2 # -*- coding: utf-8 -*-
4 # ------------------------------------------------------------
7 # let the user configure the opensecurity system
9 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
11 # Copyright (C) 2014 AIT Austrian Institute of Technology
12 # AIT Austrian Institute of Technology GmbH
13 # Donau-City-Strasse 1 | 1220 Vienna | Austria
14 # http://www.ait.ac.at
16 # This program is free software; you can redistribute it and/or
17 # modify it under the terms of the GNU General Public License
18 # as published by the Free Software Foundation version 2.
20 # This program is distributed in the hope that it will be useful,
21 # but WITHOUT ANY WARRANTY; without even the implied warranty of
22 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 # GNU General Public License for more details.
25 # You should have received a copy of the GNU General Public License
26 # along with this program; if not, write to the Free Software
27 # Foundation, Inc., 51 Franklin Street, Fifth Floor,
28 # Boston, MA 02110-1301, USA.
29 # ------------------------------------------------------------
32 # ------------------------------------------------------------
35 # This script uses a QTimer (in a busy loop) for checking
36 # changes to the log file watched.
38 # Yes, this is sure f--g ugly.
40 # Thing is: there is no real good cross-platform in
41 # doing this nicely. And here we solve this problem
42 # neither. See doc in update_progress method.
44 # There is no python native but external packages
45 # using pip with different qualities (and struggling).
47 # Qt and as such PyQt offer the QFileSystemWatcher class
48 # which *could* solve this isse but
50 # a) this class is somehow buggy and unstable
51 # b) deprecated as of Qt 5.1
53 # ... and this ain't a beauty contest either, is it?
54 # ------------------------------------------------------------
57 # ------------------------------------------------------------
66 from PyQt4 import QtCore
67 from PyQt4 import QtGui
69 from ui_ConfigureDialog import Ui_ConfigureDialog
70 from about_dialog import AboutDialog
73 # ------------------------------------------------------------
77 class ConfigureDialog(QtGui.QDialog):
79 """A dialog which lets the user configure the OpenSecurity Subsystem"""
83 QtGui.QDialog.__init__(self)
85 # setup the user interface
86 self.ui = Ui_ConfigureDialog()
89 # monospace font fix for windows systems
90 font = QtGui.QFont("Monospace [Courier]")
92 font.setStyleHint(QtGui.QFont.TypeWriter)
93 font.setStyleStrategy(QtGui.QFont.PreferAntialias)
94 self.ui.edtProgress.setFont(font)
95 self.ui.edtLog.setFont(font)
97 self.ui.edtStatus.setText('<not evaluated yet>')
98 self.ui.edtVersion.setText('<not evaluated yet>')
99 self.ui.edtStatus.setEnabled(False);
100 self.ui.edtVersion.setEnabled(False);
103 self._about_dialog = AboutDialog()
104 self._file_watched_name = ''
105 self._file_watched_size = 0
106 self._file_watcher = QtCore.QTimer(self)
107 self._service_log_file = ''
108 self._service_log_size = 0
111 self.ui.btnAbout.clicked.connect(self.clicked_about)
112 self.ui.btnClose.clicked.connect(self.accept)
113 self.ui.btnDownload.clicked.connect(self.clicked_download)
114 self.ui.btnExplorer.clicked.connect(self.clicked_explorer)
115 self.ui.btnImport.clicked.connect(self.clicked_import)
116 self.ui.btnUpdate.clicked.connect(self.clicked_update)
117 self.ui.btnRefresh.clicked.connect(self.clicked_refresh)
118 self._file_watcher.timeout.connect(self.update_progress)
120 # call first refresh immediately
121 QtCore.QTimer.singleShot(0, self.clicked_refresh)
122 self._file_watcher.start(100)
125 def clicked_about(self):
127 """About button has been clicked."""
128 self._about_dialog.exec_()
131 def clicked_download(self):
133 """Download button has been clicked."""
136 self._file_watched_name = ''
137 self._file_watched_size = 0
138 self.ui.edtProgress.clear()
142 # get general server info
143 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/fetch_initial_image'))
144 self._file_watched_name = str(j['fetch_log'])
150 def clicked_explorer(self):
152 """Explorer button has been clicked."""
153 if sys.platform == 'win32' or sys.platform == 'cygwin':
154 subprocess.Popen([os.path.join(os.environ['WINDIR'], 'explorer.exe'), self._service_log_path])
157 def clicked_import(self):
159 """Import button has been clicked."""
162 self._file_watched_name = ''
163 self._file_watched_size = 0
164 self.ui.edtProgress.clear()
167 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
168 self._file_watched_name = str(j['init_log'])
173 def clicked_update(self):
175 """Update button has been clicked."""
178 self._file_watched_name = ''
179 self._file_watched_size = 0
180 self.ui.edtProgress.clear()
183 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/update_template'))
184 self._file_watched_name = str(j['init_log'])
189 def clicked_refresh(self):
191 """Refresh button has been clicked."""
192 self.ui.edtStatus.setText('<not evaluated yet>')
193 self.ui.edtVersion.setText('<not evaluated yet>')
194 self.ui.edtStatus.setEnabled(False);
195 self.ui.edtVersion.setEnabled(False);
196 self.ui.tvTemplate.clear()
200 # get general server info
201 j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
202 self.ui.edtStatus.setText(j['os_server']['status message'])
203 self.ui.edtStatus.setEnabled(True)
204 self.ui.edtVersion.setText(j['os_server']['version'])
205 self.ui.edtVersion.setEnabled(True)
206 self._service_log_path = j['os_server']['current log folder']
207 self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
208 self._service_log_size = 0
210 # get initial template info
211 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
212 i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
213 i.setText(0, j['initial_template']['name'])
214 i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
215 i.setText(2, str(j['initial_template']['size']))
216 i.setText(3, j['initial_template']['path'])
221 # trigger machine update
222 self.update_machines()
225 def update_machines(self):
227 """Update the machines view"""
228 self.ui.tvMachines.clear()
229 self._icon_machine = QtGui.QIcon()
230 self._icon_machine.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/cpu.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
231 self._icon_property = QtGui.QIcon()
232 self._icon_property.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/configure.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
233 self._icon_network = QtGui.QIcon()
234 self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
239 machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
241 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
242 i.setIcon(0, self._icon_machine)
244 i.setIcon(1, self._icon_network)
245 i.setText(1, machines[m])
248 properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
250 j = QtGui.QTreeWidgetItem(i)
251 j.setIcon(0, self._icon_property)
253 j.setText(1, properties[p])
255 j.setIcon(0, self._icon_network)
257 j.setText(1, machines[m])
265 def update_progress(self):
267 """Our log file has changed, update ui"""
269 # we could use os.stat(PATH).st_mtime ...
271 # ... but Windows does not update it frequently. -.-
273 # Running a Cygwin Bash Shell script in the background
274 # does not update mtime of the redirected stderr file.
278 # first the service log
279 if self._service_log_file != '':
280 file_size = os.stat(self._service_log_file).st_size
281 if file_size > self._service_log_size:
282 f = open(self._service_log_file, 'r')
283 f.seek(self._service_log_size)
284 self.ui.edtLog.appendPlainText(f.read())
285 self._service_log_size = file_size
287 # now any processing log (download or import)
288 if self._file_watched_name == '':
291 file_size = os.stat(self._file_watched_name).st_size
292 if self._file_watched_size >= file_size:
295 f = open(self._file_watched_name, 'r')
296 self.ui.edtProgress.setPlainText(f.read())
297 self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
298 self._file_watched_size = file_size
301 if __name__ == "__main__":
302 a = QtGui.QApplication(sys.argv)
303 d = ConfigureDialog()