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
oliver@100
     1
#!/bin/env python
oliver@100
     2
# -*- coding: utf-8 -*-
oliver@100
     3
oliver@100
     4
# ------------------------------------------------------------
oliver@100
     5
# configure_dialog.pyw
oliver@100
     6
# 
oliver@100
     7
# let the user configure the opensecurity system
oliver@100
     8
#
oliver@100
     9
# Autor: Oliver Maurhart, <oliver.maurhart@ait.ac.at>
oliver@100
    10
#
oliver@100
    11
# Copyright (C) 2014 AIT Austrian Institute of Technology
oliver@100
    12
# AIT Austrian Institute of Technology GmbH
oliver@100
    13
# Donau-City-Strasse 1 | 1220 Vienna | Austria
oliver@100
    14
# http://www.ait.ac.at
oliver@100
    15
#
oliver@100
    16
# This program is free software; you can redistribute it and/or
oliver@100
    17
# modify it under the terms of the GNU General Public License
oliver@100
    18
# as published by the Free Software Foundation version 2.
oliver@100
    19
# 
oliver@100
    20
# This program is distributed in the hope that it will be useful,
oliver@100
    21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
oliver@100
    22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
oliver@100
    23
# GNU General Public License for more details.
oliver@100
    24
# 
oliver@100
    25
# You should have received a copy of the GNU General Public License
oliver@100
    26
# along with this program; if not, write to the Free Software
oliver@100
    27
# Foundation, Inc., 51 Franklin Street, Fifth Floor, 
oliver@100
    28
# Boston, MA  02110-1301, USA.
oliver@100
    29
# ------------------------------------------------------------
oliver@100
    30
oliver@100
    31
oliver@100
    32
# ------------------------------------------------------------
oliver@116
    33
# for the record:
oliver@116
    34
#
oliver@116
    35
#   This script uses a QTimer (in a busy loop) for checking
oliver@116
    36
#   changes to the log file watched.
oliver@116
    37
#
oliver@116
    38
#   Yes, this is sure f--g ugly.
oliver@116
    39
#
oliver@116
    40
#   Thing is: there is no real good cross-platform in
oliver@116
    41
#   doing this nicely. And here we solve this problem
oliver@116
    42
#   neither. See doc in update_progress method.
oliver@116
    43
#
oliver@116
    44
#   There is no python native but external packages
oliver@116
    45
#   using pip with different qualities (and struggling).
oliver@116
    46
#
oliver@116
    47
#   Qt and as such PyQt offer the QFileSystemWatcher class
oliver@116
    48
#   which *could* solve this isse but
oliver@116
    49
#
oliver@116
    50
#       a) this class is somehow buggy and unstable
oliver@116
    51
#       b) deprecated as of Qt 5.1
oliver@116
    52
#
oliver@116
    53
#   ... and this ain't a beauty contest either, is it?
oliver@116
    54
# ------------------------------------------------------------
oliver@116
    55
oliver@116
    56
oliver@116
    57
# ------------------------------------------------------------
oliver@100
    58
# imports
oliver@100
    59
oliver@107
    60
import json
oliver@116
    61
import os
oliver@199
    62
import subprocess
oliver@100
    63
import sys
oliver@107
    64
import urllib2
oliver@100
    65
oliver@100
    66
from PyQt4 import QtCore
oliver@100
    67
from PyQt4 import QtGui
oliver@100
    68
oliver@100
    69
from ui_ConfigureDialog import Ui_ConfigureDialog 
oliver@100
    70
from about_dialog import AboutDialog
oliver@100
    71
oliver@100
    72
oliver@100
    73
# ------------------------------------------------------------
oliver@100
    74
# code
oliver@100
    75
oliver@100
    76
oliver@100
    77
class ConfigureDialog(QtGui.QDialog):
oliver@100
    78
oliver@100
    79
    """A dialog which lets the user configure the OpenSecurity Subsystem"""
oliver@100
    80
oliver@100
    81
    def __init__(self):
oliver@100
    82
oliver@100
    83
        QtGui.QDialog.__init__(self)
oliver@100
    84
oliver@100
    85
        # setup the user interface
oliver@100
    86
        self.ui = Ui_ConfigureDialog()
oliver@100
    87
        self.ui.setupUi(self)
oliver@116
    88
oliver@116
    89
        # monospace font fix for windows systems
oliver@116
    90
        font = QtGui.QFont("Monospace [Courier]")
oliver@191
    91
        font.setPointSize(8);
oliver@116
    92
        font.setStyleHint(QtGui.QFont.TypeWriter)
oliver@116
    93
        font.setStyleStrategy(QtGui.QFont.PreferAntialias)
oliver@116
    94
        self.ui.edtProgress.setFont(font)
oliver@191
    95
        self.ui.edtLog.setFont(font)
oliver@100
    96
    
oliver@106
    97
        self.ui.edtStatus.setText('<not evaluated yet>')
oliver@106
    98
        self.ui.edtVersion.setText('<not evaluated yet>')
oliver@106
    99
        self.ui.edtStatus.setEnabled(False);
oliver@106
   100
        self.ui.edtVersion.setEnabled(False);
oliver@106
   101
oliver@100
   102
        # local members
oliver@100
   103
        self._about_dialog = AboutDialog()
oliver@116
   104
        self._file_watched_name = ''
oliver@116
   105
        self._file_watched_size = 0
oliver@116
   106
        self._file_watcher = QtCore.QTimer(self)
oliver@199
   107
        self._service_log_file = ''
oliver@188
   108
        self._service_log_size = 0
oliver@100
   109
oliver@100
   110
        # connectors
oliver@100
   111
        self.ui.btnAbout.clicked.connect(self.clicked_about)
oliver@100
   112
        self.ui.btnClose.clicked.connect(self.accept)
oliver@100
   113
        self.ui.btnDownload.clicked.connect(self.clicked_download)
oliver@199
   114
        self.ui.btnExplorer.clicked.connect(self.clicked_explorer)
oliver@100
   115
        self.ui.btnImport.clicked.connect(self.clicked_import)
oliver@100
   116
        self.ui.btnRefresh.clicked.connect(self.clicked_refresh)
oliver@116
   117
        self._file_watcher.timeout.connect(self.update_progress)
oliver@100
   118
oliver@107
   119
        # call first refresh immediately
oliver@107
   120
        QtCore.QTimer.singleShot(0, self.clicked_refresh)
oliver@116
   121
        self._file_watcher.start(100)
oliver@107
   122
oliver@100
   123
oliver@100
   124
    def clicked_about(self):
oliver@100
   125
oliver@100
   126
        """About button has been clicked."""
oliver@106
   127
        self._about_dialog.exec_()
oliver@100
   128
oliver@100
   129
oliver@100
   130
    def clicked_download(self):
oliver@100
   131
oliver@100
   132
        """Download button has been clicked."""
oliver@115
   133
oliver@116
   134
        # remove old stuff
oliver@116
   135
        self._file_watched_name = ''
oliver@116
   136
        self._file_watched_size = 0
oliver@115
   137
        self.ui.edtProgress.clear()
oliver@115
   138
oliver@115
   139
        try:
oliver@116
   140
oliver@116
   141
            # get general server info
oliver@116
   142
            j = json.load(urllib2.urlopen('http://127.0.0.1:8080/fetch_initial_image'))
oliver@116
   143
            self._file_watched_name = str(j['fetch_log'])
oliver@115
   144
oliver@115
   145
        except:
oliver@115
   146
            pass
oliver@115
   147
oliver@100
   148
oliver@199
   149
    def clicked_explorer(self):
oliver@199
   150
oliver@199
   151
        """Explorer button has been clicked."""
oliver@199
   152
        if sys.platform == 'win32' or sys.platform == 'cygwin':
oliver@199
   153
            subprocess.Popen([os.path.join(os.environ['WINDIR'], 'explorer.exe'), self._service_log_path])
oliver@199
   154
oliver@199
   155
oliver@100
   156
    def clicked_import(self):
oliver@100
   157
oliver@100
   158
        """Import button has been clicked."""
oliver@119
   159
oliver@119
   160
        # remove old stuff
oliver@119
   161
        self._file_watched_name = ''
oliver@119
   162
        self._file_watched_size = 0
oliver@119
   163
        self.ui.edtProgress.clear()
oliver@119
   164
oliver@119
   165
        try:
oliver@119
   166
oliver@119
   167
            # get general server info
oliver@119
   168
            j = json.load(urllib2.urlopen('http://127.0.0.1:8080/init'))
oliver@119
   169
            self._file_watched_name = str(j['init_log'])
oliver@119
   170
oliver@119
   171
        except:
oliver@119
   172
            pass
oliver@100
   173
oliver@100
   174
oliver@100
   175
    def clicked_refresh(self):
oliver@100
   176
oliver@100
   177
        """Refresh button has been clicked."""
oliver@107
   178
        self.ui.edtStatus.setText('<not evaluated yet>')
oliver@107
   179
        self.ui.edtVersion.setText('<not evaluated yet>')
oliver@107
   180
        self.ui.edtStatus.setEnabled(False);
oliver@107
   181
        self.ui.edtVersion.setEnabled(False);
oliver@112
   182
        self.ui.tvTemplate.clear()
oliver@107
   183
oliver@107
   184
        try:
oliver@112
   185
oliver@112
   186
            # get general server info
oliver@107
   187
            j = json.load(urllib2.urlopen('http://127.0.0.1:8080'))
oliver@132
   188
            self.ui.edtStatus.setText(j['os_server']['status message'])
oliver@107
   189
            self.ui.edtStatus.setEnabled(True)
oliver@107
   190
            self.ui.edtVersion.setText(j['os_server']['version'])
oliver@107
   191
            self.ui.edtVersion.setEnabled(True)
oliver@199
   192
            self._service_log_path = j['os_server']['current log folder']
oliver@199
   193
            self._service_log_file = os.path.join(self._service_log_path, 'OpenSecurity.log')
oliver@188
   194
            self._service_log_size = 0
oliver@112
   195
oliver@112
   196
            # get initial template info
oliver@112
   197
            j = json.load(urllib2.urlopen('http://127.0.0.1:8080/initial_image'))
oliver@112
   198
            i = QtGui.QTreeWidgetItem(self.ui.tvTemplate)
oliver@112
   199
            i.setText(0, j['initial_template']['name'])
oliver@112
   200
            i.setText(1, QtCore.QDateTime.fromTime_t(int(j['initial_template']['date'])).toString(QtCore.Qt.SystemLocaleShortDate))
oliver@112
   201
            i.setText(2, str(j['initial_template']['size']))
oliver@112
   202
            i.setText(3, j['initial_template']['path'])
oliver@107
   203
            
oliver@107
   204
        except:
oliver@107
   205
            pass
oliver@100
   206
oliver@203
   207
        # trigger machine update
oliver@203
   208
        self.update_machines()
oliver@203
   209
oliver@203
   210
oliver@203
   211
    def update_machines(self):
oliver@203
   212
oliver@203
   213
        """Update the machines view"""
oliver@203
   214
        self.ui.tvMachines.clear()
oliver@203
   215
        self._icon_machine = QtGui.QIcon()
oliver@203
   216
        self._icon_machine.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/cpu.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@203
   217
        self._icon_property = QtGui.QIcon()
oliver@203
   218
        self._icon_property.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/configure.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@203
   219
        self._icon_network = QtGui.QIcon()
oliver@203
   220
        self._icon_network.addPixmap(QtGui.QPixmap(":/opensecurity/gfx/network-workgroup.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
oliver@203
   221
oliver@203
   222
oliver@203
   223
        #try:
oliver@203
   224
oliver@203
   225
        # get machines
oliver@203
   226
        machines = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms'))
oliver@203
   227
        for m in machines:
oliver@203
   228
            i = QtGui.QTreeWidgetItem(self.ui.tvMachines)
oliver@203
   229
            i.setIcon(0, self._icon_machine)
oliver@203
   230
            i.setText(0, m)
oliver@203
   231
oliver@203
   232
            properties = json.load(urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m))
oliver@203
   233
            for p in properties:
oliver@203
   234
                j = QtGui.QTreeWidgetItem(i)
oliver@203
   235
                j.setIcon(0, self._icon_property)
oliver@203
   236
                j.setText(0, p)
oliver@203
   237
                j.setText(1, properties[p])
oliver@203
   238
oliver@203
   239
            ip = urllib2.urlopen('http://127.0.0.1:8080/sdvms/' + m + '/ip')   
oliver@203
   240
            j = QtGui.QTreeWidgetItem(i)
oliver@203
   241
            j.setIcon(0, self._icon_network)
oliver@203
   242
            j.setText(0, 'ip')
oliver@203
   243
            j.setText(1, ip.read())
oliver@203
   244
oliver@203
   245
oliver@203
   246
        #except:
oliver@203
   247
        #    pass
oliver@203
   248
oliver@203
   249
oliver@116
   250
oliver@116
   251
    def update_progress(self):
oliver@116
   252
        
oliver@116
   253
        """Our log file has changed, update ui"""
oliver@116
   254
oliver@116
   255
        # we could use os.stat(PATH).st_mtime ...
oliver@116
   256
        # 
oliver@116
   257
        # ... but Windows does not update it frequently. -.- 
oliver@116
   258
        #
oliver@116
   259
        # Running a Cygwin Bash Shell script in the background
oliver@116
   260
        # does not update mtime of the redirected stderr file.
oliver@116
   261
        #
oliver@116
   262
        # This is terrible. 
oliver@116
   263
oliver@188
   264
        # first the service log
oliver@199
   265
        if self._service_log_file != '':
oliver@199
   266
            file_size = os.stat(self._service_log_file).st_size
oliver@188
   267
            if file_size > self._service_log_size:
oliver@199
   268
                f = open(self._service_log_file, 'r')
oliver@191
   269
                f.seek(self._service_log_size)
oliver@191
   270
                self.ui.edtLog.appendPlainText(f.read())
oliver@188
   271
                self._service_log_size = file_size
oliver@188
   272
        
oliver@188
   273
        # now any processing log (download or import)
oliver@188
   274
        if self._file_watched_name == '':
oliver@188
   275
            return
oliver@188
   276
oliver@116
   277
        file_size = os.stat(self._file_watched_name).st_size
oliver@116
   278
        if self._file_watched_size >= file_size:
oliver@116
   279
            return
oliver@116
   280
oliver@191
   281
        f = open(self._file_watched_name, 'r')
oliver@199
   282
        self.ui.edtProgress.setPlainText(f.read())
oliver@199
   283
        self.ui.edtProgress.verticalScrollBar().setValue(self.ui.edtProgress.verticalScrollBar().maximum())
oliver@116
   284
        self._file_watched_size = file_size
oliver@116
   285
oliver@116
   286
oliver@100
   287
if __name__ == "__main__":
oliver@113
   288
    a = QtGui.QApplication(sys.argv)
oliver@113
   289
    d = ConfigureDialog()
oliver@113
   290
    d.show()
oliver@113
   291
    sys.exit(a.exec_())     
oliver@100
   292