2 # -*- coding: utf-8 -*-
4 # ------------------------------------------------------------
7 # let the user configure the opensecurity system
9 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
11 # Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
18 # https://www.x-net.at
20 # AIT Austrian Institute of Technology
21 # Donau City Strasse 1
24 # http://www.ait.ac.at
27 # Licensed under the Apache License, Version 2.0 (the "License");
28 # you may not use this file except in compliance with the License.
29 # You may obtain a copy of the License at
31 # http://www.apache.org/licenses/LICENSE-2.0
33 # Unless required by applicable law or agreed to in writing, software
34 # distributed under the License is distributed on an "AS IS" BASIS,
35 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
36 # See the License for the specific language governing permissions and
37 # limitations under the License.
38 # ------------------------------------------------------------
41 # ------------------------------------------------------------
44 # This script uses a QTimer (in a busy loop) for checking
45 # changes to the log file watched.
47 # Yes, this is sure f--g ugly.
49 # Thing is: there is no real good cross-platform in
50 # doing this nicely. And here we solve this problem
51 # neither. See doc in update_progress method.
53 # There is no python native but external packages
54 # using pip with different qualities (and struggling).
56 # Qt and as such PyQt offer the QFileSystemWatcher class
57 # which *could* solve this isse but
59 # a) this class is somehow buggy and unstable
60 # b) deprecated as of Qt 5.1
62 # ... and this ain't a beauty contest either, is it?
63 # ------------------------------------------------------------
66 # ------------------------------------------------------------
75 from PyQt4 import QtCore
76 from PyQt4 import QtGui
78 from ui_ConfigureDialog import Ui_ConfigureDialog
79 from about_dialog import AboutDialog
82 # ------------------------------------------------------------
86 class ConfigureDialog(QtGui.QDialog):
88 """A dialog which lets the user configure the OpenSecurity Subsystem"""
92 QtGui.QDialog.__init__(self)
94 # setup the user interface
95 self.ui = Ui_ConfigureDialog()
98 # monospace font fix for windows systems
99 font = QtGui.QFont("Monospace [Courier]")
100 font.setPointSize(8);
101 font.setStyleHint(QtGui.QFont.TypeWriter)
102 font.setStyleStrategy(QtGui.QFont.PreferAntialias)
103 self.ui.edtProgress.setFont(font)
104 self.ui.edtLog.setFont(font)
106 self.ui.edtStatus.setText('<not evaluated yet>')
107 self.ui.edtVersion.setText('<not evaluated yet>')
108 self.ui.edtStatus.setEnabled(False);
109 self.ui.edtVersion.setEnabled(False);
112 self._about_dialog = AboutDialog()
113 self._file_watched_name = ''
114 self._file_watched_size = 0
115 self._file_watcher = QtCore.QTimer(self)
116 self._service_log_file = ''
117 self._service_log_size = 0
120 self.ui.btnAbout.clicked.connect(self.clicked_about)
121 self.ui.btnClose.clicked.connect(self.accept)
122 self.ui.btnDownload.clicked.connect(self.clicked_download)
123 self.ui.btnExplorer.clicked.connect(self.clicked_explorer)
124 self.ui.btnImport.clicked.connect(self.clicked_import)
125 self.ui.btnUpdate.clicked.connect(self.clicked_update)
126 self.ui.btnRefresh.clicked.connect(self.clicked_refresh)
127 self._file_watcher.timeout.connect(self.update_progress)
129 # call first refresh immediately
130 QtCore.QTimer.singleShot(0, self.clicked_refresh)
131 self._file_watcher.start(100)
134 def clicked_about(self):
136 """About button has been clicked."""
137 self._about_dialog.exec_()
140 def clicked_download(self):
142 """Download button has been clicked."""
145 self._file_watched_name = ''
146 self._file_watched_size = 0
147 self.ui.edtProgress.clear()
151 # get general server info
152 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/fetch_initial_image'))
153 self._file_watched_name = str(j['fetch_log'])
159 def clicked_explorer(self):
161 """Explorer button has been clicked."""
162 if sys.platform == 'win32' or sys.platform == 'cygwin':
163 subprocess.Popen([os.path.join(os.environ['WINDIR'], 'explorer.exe'), self._service_log_path])
166 def clicked_import(self):
168 """Import button has been clicked."""
171 self._file_watched_name = ''
172 self._file_watched_size = 0
173 self.ui.edtProgress.clear()
176 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
177 self._file_watched_name = str(j['init_log'])
182 def clicked_update(self):
184 """Update button has been clicked."""
187 self._file_watched_name = ''
188 self._file_watched_size = 0
189 self.ui.edtProgress.clear()
192 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/update_template'))
193 self._file_watched_name = str(j['init_log'])
198 def clicked_refresh(self):
200 """Refresh button has been clicked."""
201 self.ui.edtStatus.setText('<not evaluated yet>')
202 self.ui.edtVersion.setText('<not evaluated yet>')
203 self.ui.edtStatus.setEnabled(False);
204 self.ui.edtVersion.setEnabled(False);
205 self.ui.tvTemplate.clear()
209 # get general server info
210 j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
211 self.ui.edtStatus.setText(j['os_server']['status message'])
212 self.ui.edtStatus.setEnabled(True)
213 self.ui.edtVersion.setText(j['os_server']['version'])
214 self.ui.edtVersion.setEnabled(True)
215 self._service_log_path = j['os_server']['current log folder']
216 self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
217 self._service_log_size = 0
219 # get initial template info
220 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
221 i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
222 i.setText(0, j['initial_template']['name'])
223 i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
224 i.setText(2, str(j['initial_template']['size']))
225 i.setText(3, j['initial_template']['path'])
230 # trigger machine update
231 self.update_machines()
234 def update_machines(self):
236 """Update the machines view"""
237 self.ui.tvMachines.clear()
238 self._icon_machine = QtGui.QIcon()
239 self._icon_machine.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/cpu.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
240 self._icon_property = QtGui.QIcon()
241 self._icon_property.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/configure.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
242 self._icon_network = QtGui.QIcon()
243 self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
248 machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
250 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
251 i.setIcon(0, self._icon_machine)
253 i.setIcon(1, self._icon_network)
254 i.setText(1, machines[m])
257 properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
259 j = QtGui.QTreeWidgetItem(i)
260 j.setIcon(0, self._icon_property)
262 j.setText(1, properties[p])
264 j.setIcon(0, self._icon_network)
266 j.setText(1, machines[m])
274 def update_progress(self):
276 """Our log file has changed, update ui"""
278 # we could use os.stat(PATH).st_mtime ...
280 # ... but Windows does not update it frequently. -.-
282 # Running a Cygwin Bash Shell script in the background
283 # does not update mtime of the redirected stderr file.
287 # first the service log
288 if self._service_log_file != '':
289 file_size = os.stat(self._service_log_file).st_size
290 if file_size > self._service_log_size:
291 f = open(self._service_log_file, 'r')
292 f.seek(self._service_log_size)
293 self.ui.edtLog.appendPlainText(f.read())
294 self._service_log_size = file_size
296 # now any processing log (download or import)
297 if self._file_watched_name == '':
300 file_size = os.stat(self._file_watched_name).st_size
301 if self._file_watched_size >= file_size:
304 f = open(self._file_watched_name, 'r')
305 self.ui.edtProgress.setPlainText(f.read())
306 self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
307 self._file_watched_size = file_size
310 if __name__ == "__main__":
311 a = QtGui.QApplication(sys.argv)
312 d = ConfigureDialog()