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.btnRefresh.clicked.connect(self.clicked_refresh)
117 self._file_watcher.timeout.connect(self.update_progress)
119 # call first refresh immediately
120 QtCore.QTimer.singleShot(0, self.clicked_refresh)
121 self._file_watcher.start(100)
124 def clicked_about(self):
126 """About button has been clicked."""
127 self._about_dialog.exec_()
130 def clicked_download(self):
132 """Download button has been clicked."""
135 self._file_watched_name = ''
136 self._file_watched_size = 0
137 self.ui.edtProgress.clear()
141 # get general server info
142 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/fetch_initial_image'))
143 self._file_watched_name = str(j['fetch_log'])
149 def clicked_explorer(self):
151 """Explorer button has been clicked."""
152 if sys.platform == 'win32' or sys.platform == 'cygwin':
153 subprocess.Popen([os.path.join(os.environ['WINDIR'], 'explorer.exe'), self._service_log_path])
156 def clicked_import(self):
158 """Import button has been clicked."""
161 self._file_watched_name = ''
162 self._file_watched_size = 0
163 self.ui.edtProgress.clear()
167 # get general server info
168 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
169 self._file_watched_name = str(j['init_log'])
175 def clicked_refresh(self):
177 """Refresh button has been clicked."""
178 self.ui.edtStatus.setText('<not evaluated yet>')
179 self.ui.edtVersion.setText('<not evaluated yet>')
180 self.ui.edtStatus.setEnabled(False);
181 self.ui.edtVersion.setEnabled(False);
182 self.ui.tvTemplate.clear()
186 # get general server info
187 j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
188 self.ui.edtStatus.setText(j['os_server']['status message'])
189 self.ui.edtStatus.setEnabled(True)
190 self.ui.edtVersion.setText(j['os_server']['version'])
191 self.ui.edtVersion.setEnabled(True)
192 self._service_log_path = j['os_server']['current log folder']
193 self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
194 self._service_log_size = 0
196 # get initial template info
197 j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
198 i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
199 i.setText(0, j['initial_template']['name'])
200 i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
201 i.setText(2, str(j['initial_template']['size']))
202 i.setText(3, j['initial_template']['path'])
207 # trigger machine update
208 self.update_machines()
211 def update_machines(self):
213 """Update the machines view"""
214 self.ui.tvMachines.clear()
215 self._icon_machine = QtGui.QIcon()
216 self._icon_machine.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/cpu.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
217 self._icon_property = QtGui.QIcon()
218 self._icon_property.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/configure.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
219 self._icon_network = QtGui.QIcon()
220 self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
226 machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
228 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
229 i.setIcon(0, self._icon_machine)
232 properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
234 j = QtGui.QTreeWidgetItem(i)
235 j.setIcon(0, self._icon_property)
237 j.setText(1, properties[p])
239 ip = urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m + '/ip')
240 j = QtGui.QTreeWidgetItem(i)
241 j.setIcon(0, self._icon_network)
243 j.setText(1, ip.read())
251 def update_progress(self):
253 """Our log file has changed, update ui"""
255 # we could use os.stat(PATH).st_mtime ...
257 # ... but Windows does not update it frequently. -.-
259 # Running a Cygwin Bash Shell script in the background
260 # does not update mtime of the redirected stderr file.
264 # first the service log
265 if self._service_log_file != '':
266 file_size = os.stat(self._service_log_file).st_size
267 if file_size > self._service_log_size:
268 f = open(self._service_log_file, 'r')
269 f.seek(self._service_log_size)
270 self.ui.edtLog.appendPlainText(f.read())
271 self._service_log_size = file_size
273 # now any processing log (download or import)
274 if self._file_watched_name == '':
277 file_size = os.stat(self._file_watched_name).st_size
278 if self._file_watched_size >= file_size:
281 f = open(self._file_watched_name, 'r')
282 self.ui.edtProgress.setPlainText(f.read())
283 self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
284 self._file_watched_size = file_size
287 if __name__ == "__main__":
288 a = QtGui.QApplication(sys.argv)
289 d = ConfigureDialog()