OpenSecurity/bin/ui/configure_dialog.py
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 25 Jun 2014 19:21:04 +0200
changeset 199 26b9a95b0da1
parent 192 0776e0f171f8
child 203 0cc33b647a4e
permissions -rwxr-xr-x
explorer button in configuration 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         self.ui.tvMachines.clear()
   184 
   185         try:
   186 
   187             # get general server info
   188             j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
   189             self.ui.edtStatus.setText(j['os_server']['status message'])
   190             self.ui.edtStatus.setEnabled(True)
   191             self.ui.edtVersion.setText(j['os_server']['version'])
   192             self.ui.edtVersion.setEnabled(True)
   193             self._service_log_path = j['os_server']['current log folder']
   194             self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
   195             self._service_log_size = 0
   196 
   197             # get initial template info
   198             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
   199             i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
   200             i.setText(0, j['initial_template']['name'])
   201             i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
   202             i.setText(2, str(j['initial_template']['size']))
   203             i.setText(3, j['initial_template']['path'])
   204             
   205             # get machines
   206             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/vms'))
   207             for m in j:
   208                 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
   209                 i.setText(0, m)
   210 
   211         except:
   212             pass
   213 
   214 
   215     def update_progress(self):
   216         
   217         """Our log file has changed, update ui"""
   218 
   219         # we could use os.stat(PATH).st_mtime ...
   220         # 
   221         # ... but Windows does not update it frequently. -.- 
   222         #
   223         # Running a Cygwin Bash Shell script in the background
   224         # does not update mtime of the redirected stderr file.
   225         #
   226         # This is terrible. 
   227 
   228         # first the service log
   229         if self._service_log_file != '':
   230             file_size = os.stat(self._service_log_file).st_size
   231             if file_size > self._service_log_size:
   232                 f = open(self._service_log_file, 'r')
   233                 f.seek(self._service_log_size)
   234                 self.ui.edtLog.appendPlainText(f.read())
   235                 self._service_log_size = file_size
   236         
   237         # now any processing log (download or import)
   238         if self._file_watched_name == '':
   239             return
   240 
   241         file_size = os.stat(self._file_watched_name).st_size
   242         if self._file_watched_size >= file_size:
   243             return
   244 
   245         f = open(self._file_watched_name, 'r')
   246         self.ui.edtProgress.setPlainText(f.read())
   247         self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
   248         self._file_watched_size = file_size
   249 
   250 
   251 if __name__ == "__main__":
   252     a = QtGui.QApplication(sys.argv)
   253     d = ConfigureDialog()
   254     d.show()
   255     sys.exit(a.exec_())     
   256