OpenSecurity/bin/ui/configure_dialog.py
author BarthaM@N3SIM1218.D03.arc.local
Fri, 29 Aug 2014 11:44:45 +0100
changeset 220 f5805ee62d80
parent 207 ae931a692b54
child 221 853af9cfab6a
permissions -rwxr-xr-x
Added temporary Initialize button to Tray. has to be clicked after import to start the system.
Rewrite of the init.sh script in progress.
     1 #!/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 # ------------------------------------------------------------
     5 # configure_dialog.pyw
     6 # 
     7 # let the user configure the opensecurity system
     8 #
     9 # Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
    10 #
    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
    15 #
    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.
    19 # 
    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.
    24 # 
    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 # ------------------------------------------------------------
    30 
    31 
    32 # ------------------------------------------------------------
    33 # for the record:
    34 #
    35 #   This script uses a QTimer (in a busy loop) for checking
    36 #   changes to the log file watched.
    37 #
    38 #   Yes, this is sure f--g ugly.
    39 #
    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.
    43 #
    44 #   There is no python native but external packages
    45 #   using pip with different qualities (and struggling).
    46 #
    47 #   Qt and as such PyQt offer the QFileSystemWatcher class
    48 #   which *could* solve this isse but
    49 #
    50 #       a) this class is somehow buggy and unstable
    51 #       b) deprecated as of Qt 5.1
    52 #
    53 #   ... and this ain't a beauty contest either, is it?
    54 # ------------------------------------------------------------
    55 
    56 
    57 # ------------------------------------------------------------
    58 # imports
    59 
    60 import json
    61 import os
    62 import subprocess
    63 import sys
    64 import urllib2
    65 
    66 from PyQt4 import QtCore
    67 from PyQt4 import QtGui
    68 
    69 from ui_ConfigureDialog import Ui_ConfigureDialog 
    70 from about_dialog import AboutDialog
    71 
    72 
    73 # ------------------------------------------------------------
    74 # code
    75 
    76 
    77 class ConfigureDialog(QtGui.QDialog):
    78 
    79     """A dialog which lets the user configure the OpenSecurity Subsystem"""
    80 
    81     def __init__(self):
    82 
    83         QtGui.QDialog.__init__(self)
    84 
    85         # setup the user interface
    86         self.ui = Ui_ConfigureDialog()
    87         self.ui.setupUi(self)
    88 
    89         # monospace font fix for windows systems
    90         font = QtGui.QFont("Monospace [Courier]")
    91         font.setPointSize(8);
    92         font.setStyleHint(QtGui.QFont.TypeWriter)
    93         font.setStyleStrategy(QtGui.QFont.PreferAntialias)
    94         self.ui.edtProgress.setFont(font)
    95         self.ui.edtLog.setFont(font)
    96     
    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);
   101 
   102         # local members
   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
   109 
   110         # connectors
   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.btnInitialize.clicked.connect(self.clicked_initialize)
   117         self.ui.btnRefresh.clicked.connect(self.clicked_refresh)
   118         self._file_watcher.timeout.connect(self.update_progress)
   119 
   120         # call first refresh immediately
   121         QtCore.QTimer.singleShot(0, self.clicked_refresh)
   122         self._file_watcher.start(100)
   123 
   124 
   125     def clicked_about(self):
   126 
   127         """About button has been clicked."""
   128         self._about_dialog.exec_()
   129 
   130 
   131     def clicked_download(self):
   132 
   133         """Download button has been clicked."""
   134 
   135         # remove old stuff
   136         self._file_watched_name = ''
   137         self._file_watched_size = 0
   138         self.ui.edtProgress.clear()
   139 
   140         try:
   141 
   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'])
   145 
   146         except:
   147             pass
   148 
   149 
   150     def clicked_explorer(self):
   151 
   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])
   155 
   156 
   157     def clicked_import(self):
   158 
   159         """Import button has been clicked."""
   160 
   161         # remove old stuff
   162         self._file_watched_name = ''
   163         self._file_watched_size = 0
   164         self.ui.edtProgress.clear()
   165 
   166         try:
   167 
   168             # get general server info
   169             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
   170             self._file_watched_name = str(j['init_log'])
   171 
   172         except:
   173             pass
   174     
   175     def clicked_initialize(self):
   176 
   177         """Import button has been clicked."""
   178 
   179         # remove old stuff
   180         self._file_watched_name = ''
   181         self._file_watched_size = 0
   182         self.ui.edtProgress.clear()
   183 
   184         try:
   185 
   186             json.load(urllib2.urlopen('http://127.0.0.1:8080/initialize'))
   187 
   188         except:
   189             pass
   190 
   191 
   192     def clicked_refresh(self):
   193 
   194         """Refresh button has been clicked."""
   195         self.ui.edtStatus.setText('<not evaluated yet>')
   196         self.ui.edtVersion.setText('<not evaluated yet>')
   197         self.ui.edtStatus.setEnabled(False);
   198         self.ui.edtVersion.setEnabled(False);
   199         self.ui.tvTemplate.clear()
   200 
   201         try:
   202 
   203             # get general server info
   204             j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
   205             self.ui.edtStatus.setText(j['os_server']['status message'])
   206             self.ui.edtStatus.setEnabled(True)
   207             self.ui.edtVersion.setText(j['os_server']['version'])
   208             self.ui.edtVersion.setEnabled(True)
   209             self._service_log_path = j['os_server']['current log folder']
   210             self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
   211             self._service_log_size = 0
   212 
   213             # get initial template info
   214             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
   215             i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
   216             i.setText(0, j['initial_template']['name'])
   217             i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
   218             i.setText(2, str(j['initial_template']['size']))
   219             i.setText(3, j['initial_template']['path'])
   220             
   221         except:
   222             pass
   223 
   224         # trigger machine update
   225         self.update_machines()
   226 
   227 
   228     def update_machines(self):
   229 
   230         """Update the machines view"""
   231         self.ui.tvMachines.clear()
   232         self._icon_machine = QtGui.QIcon()
   233         self._icon_machine.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/cpu.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
   234         self._icon_property = QtGui.QIcon()
   235         self._icon_property.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/configure.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
   236         self._icon_network = QtGui.QIcon()
   237         self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
   238 
   239         try:
   240 
   241             # get machines
   242             machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
   243             for m in machines:
   244                 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
   245                 i.setIcon(0, self._icon_machine)
   246                 i.setText(0, m)
   247                 i.setIcon(1, self._icon_network)
   248                 i.setText(1, machines[m])
   249 
   250 
   251                 properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
   252                 for p in properties:
   253                     j = QtGui.QTreeWidgetItem(i)
   254                     j.setIcon(0, self._icon_property)
   255                     j.setText(0, p)
   256                     j.setText(1, properties[p])
   257 
   258                 j.setIcon(0, self._icon_network)
   259                 j.setText(0, 'ip')
   260                 j.setText(1, machines[m])
   261 
   262 
   263         except:
   264             pass
   265 
   266 
   267 
   268     def update_progress(self):
   269         
   270         """Our log file has changed, update ui"""
   271 
   272         # we could use os.stat(PATH).st_mtime ...
   273         # 
   274         # ... but Windows does not update it frequently. -.- 
   275         #
   276         # Running a Cygwin Bash Shell script in the background
   277         # does not update mtime of the redirected stderr file.
   278         #
   279         # This is terrible. 
   280 
   281         # first the service log
   282         if self._service_log_file != '':
   283             file_size = os.stat(self._service_log_file).st_size
   284             if file_size > self._service_log_size:
   285                 f = open(self._service_log_file, 'r')
   286                 f.seek(self._service_log_size)
   287                 self.ui.edtLog.appendPlainText(f.read())
   288                 self._service_log_size = file_size
   289         
   290         # now any processing log (download or import)
   291         if self._file_watched_name == '':
   292             return
   293 
   294         file_size = os.stat(self._file_watched_name).st_size
   295         if self._file_watched_size >= file_size:
   296             return
   297 
   298         f = open(self._file_watched_name, 'r')
   299         self.ui.edtProgress.setPlainText(f.read())
   300         self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
   301         self._file_watched_size = file_size
   302 
   303 
   304 if __name__ == "__main__":
   305     a = QtGui.QApplication(sys.argv)
   306     d = ConfigureDialog()
   307     d.show()
   308     sys.exit(a.exec_())     
   309