OpenSecurity/bin/ui/configure_dialog.py
author Oliver Maurhart <oliver.maurhart@ait.ac.at>
Wed, 29 Oct 2014 15:18:22 +0100
changeset 240 d7ef04254e9c
parent 221 853af9cfab6a
permissions -rwxr-xr-x
lizenz fixed in all files
     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 2013-2014 X-Net and AIT Austrian Institute of Technology
    12 # 
    13 # 
    14 #     X-Net Services GmbH
    15 #     Elisabethstrasse 1
    16 #     4020 Linz
    17 #     AUSTRIA
    18 #     https://www.x-net.at
    19 # 
    20 #     AIT Austrian Institute of Technology
    21 #     Donau City Strasse 1
    22 #     1220 Wien
    23 #     AUSTRIA
    24 #     http://www.ait.ac.at
    25 # 
    26 # 
    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
    30 # 
    31 #    http://www.apache.org/licenses/LICENSE-2.0
    32 # 
    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 # ------------------------------------------------------------
    39 
    40 
    41 # ------------------------------------------------------------
    42 # for the record:
    43 #
    44 #   This script uses a QTimer (in a busy loop) for checking
    45 #   changes to the log file watched.
    46 #
    47 #   Yes, this is sure f--g ugly.
    48 #
    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.
    52 #
    53 #   There is no python native but external packages
    54 #   using pip with different qualities (and struggling).
    55 #
    56 #   Qt and as such PyQt offer the QFileSystemWatcher class
    57 #   which *could* solve this isse but
    58 #
    59 #       a) this class is somehow buggy and unstable
    60 #       b) deprecated as of Qt 5.1
    61 #
    62 #   ... and this ain't a beauty contest either, is it?
    63 # ------------------------------------------------------------
    64 
    65 
    66 # ------------------------------------------------------------
    67 # imports
    68 
    69 import json
    70 import os
    71 import subprocess
    72 import sys
    73 import urllib2
    74 
    75 from PyQt4 import QtCore
    76 from PyQt4 import QtGui
    77 
    78 from ui_ConfigureDialog import Ui_ConfigureDialog 
    79 from about_dialog import AboutDialog
    80 
    81 
    82 # ------------------------------------------------------------
    83 # code
    84 
    85 
    86 class ConfigureDialog(QtGui.QDialog):
    87 
    88     """A dialog which lets the user configure the OpenSecurity Subsystem"""
    89 
    90     def __init__(self):
    91 
    92         QtGui.QDialog.__init__(self)
    93 
    94         # setup the user interface
    95         self.ui = Ui_ConfigureDialog()
    96         self.ui.setupUi(self)
    97 
    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)
   105     
   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);
   110 
   111         # local members
   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
   118 
   119         # connectors
   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)
   128 
   129         # call first refresh immediately
   130         QtCore.QTimer.singleShot(0, self.clicked_refresh)
   131         self._file_watcher.start(100)
   132 
   133 
   134     def clicked_about(self):
   135 
   136         """About button has been clicked."""
   137         self._about_dialog.exec_()
   138 
   139 
   140     def clicked_download(self):
   141 
   142         """Download button has been clicked."""
   143 
   144         # remove old stuff
   145         self._file_watched_name = ''
   146         self._file_watched_size = 0
   147         self.ui.edtProgress.clear()
   148 
   149         try:
   150 
   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'])
   154 
   155         except:
   156             pass
   157 
   158 
   159     def clicked_explorer(self):
   160 
   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])
   164 
   165 
   166     def clicked_import(self):
   167 
   168         """Import button has been clicked."""
   169 
   170         # remove old stuff
   171         self._file_watched_name = ''
   172         self._file_watched_size = 0
   173         self.ui.edtProgress.clear()
   174 
   175         try:
   176             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
   177             self._file_watched_name = str(j['init_log'])
   178         except:
   179             pass
   180     
   181     
   182     def clicked_update(self):
   183 
   184         """Update button has been clicked."""
   185 
   186         # remove old stuff
   187         self._file_watched_name = ''
   188         self._file_watched_size = 0
   189         self.ui.edtProgress.clear()
   190 
   191         try:
   192             j = json.load(urllib2.urlopen('http://127.0.0.1:8080/update_template'))
   193             self._file_watched_name = str(j['init_log'])
   194         except:
   195             pass
   196 
   197 
   198     def clicked_refresh(self):
   199 
   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()
   206 
   207         try:
   208 
   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
   218 
   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'])
   226             
   227         except:
   228             pass
   229 
   230         # trigger machine update
   231         self.update_machines()
   232 
   233 
   234     def update_machines(self):
   235 
   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)
   244 
   245         try:
   246 
   247             # get machines
   248             machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
   249             for m in machines:
   250                 i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
   251                 i.setIcon(0, self._icon_machine)
   252                 i.setText(0, m)
   253                 i.setIcon(1, self._icon_network)
   254                 i.setText(1, machines[m])
   255 
   256 
   257                 properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
   258                 for p in properties:
   259                     j = QtGui.QTreeWidgetItem(i)
   260                     j.setIcon(0, self._icon_property)
   261                     j.setText(0, p)
   262                     j.setText(1, properties[p])
   263 
   264                 j.setIcon(0, self._icon_network)
   265                 j.setText(0, 'ip')
   266                 j.setText(1, machines[m])
   267 
   268 
   269         except:
   270             pass
   271 
   272 
   273 
   274     def update_progress(self):
   275         
   276         """Our log file has changed, update ui"""
   277 
   278         # we could use os.stat(PATH).st_mtime ...
   279         # 
   280         # ... but Windows does not update it frequently. -.- 
   281         #
   282         # Running a Cygwin Bash Shell script in the background
   283         # does not update mtime of the redirected stderr file.
   284         #
   285         # This is terrible. 
   286 
   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
   295         
   296         # now any processing log (download or import)
   297         if self._file_watched_name == '':
   298             return
   299 
   300         file_size = os.stat(self._file_watched_name).st_size
   301         if self._file_watched_size >= file_size:
   302             return
   303 
   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
   308 
   309 
   310 if __name__ == "__main__":
   311     a = QtGui.QApplication(sys.argv)
   312     d = ConfigureDialog()
   313     d.show()
   314     sys.exit(a.exec_())     
   315