OpenSecurity/bin/ui/configure_dialog.py
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 25 Jun 2014 20:46:31 +0200
changeset 203 0cc33b647a4e
parent 199 26b9a95b0da1
child 204 0c3136908f4f
permissions -rwxr-xr-x
machine configuration tab working
     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.btnRefresh.clicked.connect(self.clicked_refresh)
   117         self._file_watcher.timeout.connect(self.update_progress)
   118 
   119         # call first refresh immediately
   120         QtCore.QTimer.singleShot(0, self.clicked_refresh)
   121         self._file_watcher.start(100)
   122 
   123 
   124     def clicked_about(self):
   125 
   126         """About button has been clicked."""
   127         self._about_dialog.exec_()
   128 
   129 
   130     def clicked_download(self):
   131 
   132         """Download button has been clicked."""
   133 
   134         # remove old stuff
   135         self._file_watched_name = ''
   136         self._file_watched_size = 0
   137         self.ui.edtProgress.clear()
   138 
   139         try:
   140 
   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'])
   144 
   145         except:
   146             pass
   147 
   148 
   149     def clicked_explorer(self):
   150 
   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])
   154 
   155 
   156     def clicked_import(self):
   157 
   158         """Import button has been clicked."""
   159 
   160         # remove old stuff
   161         self._file_watched_name = ''
   162         self._file_watched_size = 0
   163         self.ui.edtProgress.clear()
   164 
   165         try:
   166 
   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'])
   170 
   171         except:
   172             pass
   173 
   174 
   175     def clicked_refresh(self):
   176 
   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()
   183 
   184         try:
   185 
   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
   195 
   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'])
   203             
   204         except:
   205             pass
   206 
   207         # trigger machine update
   208         self.update_machines()
   209 
   210 
   211     def update_machines(self):
   212 
   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)
   221 
   222 
   223         #try:
   224 
   225         # get machines
   226         machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
   227         for m in machines:
   228             i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
   229             i.setIcon(0, self._icon_machine)
   230             i.setText(0, m)
   231 
   232             properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
   233             for p in properties:
   234                 j = QtGui.QTreeWidgetItem(i)
   235                 j.setIcon(0, self._icon_property)
   236                 j.setText(0, p)
   237                 j.setText(1, properties[p])
   238 
   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)
   242             j.setText(0, 'ip')
   243             j.setText(1, ip.read())
   244 
   245 
   246         #except:
   247         #    pass
   248 
   249 
   250 
   251     def update_progress(self):
   252         
   253         """Our log file has changed, update ui"""
   254 
   255         # we could use os.stat(PATH).st_mtime ...
   256         # 
   257         # ... but Windows does not update it frequently. -.- 
   258         #
   259         # Running a Cygwin Bash Shell script in the background
   260         # does not update mtime of the redirected stderr file.
   261         #
   262         # This is terrible. 
   263 
   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
   272         
   273         # now any processing log (download or import)
   274         if self._file_watched_name == '':
   275             return
   276 
   277         file_size = os.stat(self._file_watched_name).st_size
   278         if self._file_watched_size >= file_size:
   279             return
   280 
   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
   285 
   286 
   287 if __name__ == "__main__":
   288     a = QtGui.QApplication(sys.argv)
   289     d = ConfigureDialog()
   290     d.show()
   291     sys.exit(a.exec_())     
   292