oliver@83
|
1 |
#!/bin/env python
|
oliver@83
|
2 |
# -*- coding: utf-8 -*-
|
oliver@83
|
3 |
|
oliver@83
|
4 |
# ------------------------------------------------------------
|
oliver@83
|
5 |
# download-osec-vm-image
|
oliver@83
|
6 |
#
|
oliver@83
|
7 |
# download the initial OsecVM.ova image
|
oliver@83
|
8 |
#
|
oliver@240
|
9 |
# Copyright 2013-2014 X-Net and AIT Austrian Institute of Technology
|
oliver@83
|
10 |
#
|
oliver@83
|
11 |
#
|
oliver@240
|
12 |
# X-Net Services GmbH
|
oliver@240
|
13 |
# Elisabethstrasse 1
|
oliver@240
|
14 |
# 4020 Linz
|
oliver@240
|
15 |
# AUSTRIA
|
oliver@240
|
16 |
# https://www.x-net.at
|
oliver@240
|
17 |
#
|
oliver@240
|
18 |
# AIT Austrian Institute of Technology
|
oliver@240
|
19 |
# Donau City Strasse 1
|
oliver@240
|
20 |
# 1220 Wien
|
oliver@240
|
21 |
# AUSTRIA
|
oliver@240
|
22 |
# http://www.ait.ac.at
|
oliver@240
|
23 |
#
|
oliver@240
|
24 |
#
|
oliver@240
|
25 |
# Licensed under the Apache License, Version 2.0 (the "License");
|
oliver@240
|
26 |
# you may not use this file except in compliance with the License.
|
oliver@240
|
27 |
# You may obtain a copy of the License at
|
oliver@240
|
28 |
#
|
oliver@240
|
29 |
# http://www.apache.org/licenses/LICENSE-2.0
|
oliver@240
|
30 |
#
|
oliver@240
|
31 |
# Unless required by applicable law or agreed to in writing, software
|
oliver@240
|
32 |
# distributed under the License is distributed on an "AS IS" BASIS,
|
oliver@240
|
33 |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
oliver@240
|
34 |
# See the License for the specific language governing permissions and
|
oliver@240
|
35 |
# limitations under the License.
|
oliver@83
|
36 |
# ------------------------------------------------------------
|
oliver@83
|
37 |
|
oliver@83
|
38 |
|
oliver@83
|
39 |
# ------------------------------------------------------------
|
oliver@83
|
40 |
# imports
|
oliver@83
|
41 |
|
oliver@86
|
42 |
import errno
|
oliver@83
|
43 |
import os
|
oliver@83
|
44 |
import sys
|
oliver@83
|
45 |
import urllib2
|
oliver@83
|
46 |
|
oliver@83
|
47 |
from PyQt4 import QtCore
|
oliver@83
|
48 |
from PyQt4 import QtGui
|
oliver@83
|
49 |
|
oliver@83
|
50 |
# local
|
oliver@83
|
51 |
from environment import Environment
|
oliver@83
|
52 |
|
oliver@83
|
53 |
|
oliver@83
|
54 |
# ------------------------------------------------------------
|
oliver@86
|
55 |
# global vars
|
oliver@86
|
56 |
|
oliver@86
|
57 |
|
oliver@86
|
58 |
vm_path = os.path.normpath(os.path.join(sys.path[0], '..', 'vm'))
|
oliver@86
|
59 |
|
oliver@86
|
60 |
|
oliver@86
|
61 |
# ------------------------------------------------------------
|
oliver@83
|
62 |
# code
|
oliver@83
|
63 |
|
oliver@83
|
64 |
|
oliver@83
|
65 |
class DownloadDialog(QtGui.QDialog):
|
oliver@83
|
66 |
|
oliver@83
|
67 |
"""Download the initial OsecVM image dialog."""
|
oliver@83
|
68 |
|
oliver@83
|
69 |
def __init__(self, parent = None, flags = QtCore.Qt.WindowFlags(0)):
|
oliver@83
|
70 |
|
oliver@83
|
71 |
# super call and widget init
|
oliver@83
|
72 |
super(DownloadDialog, self).__init__(parent, flags)
|
oliver@83
|
73 |
self.setWindowTitle('Download initial OpenSecurity VM image')
|
oliver@83
|
74 |
self.setup_ui()
|
oliver@83
|
75 |
|
oliver@83
|
76 |
# setup download thread
|
oliver@83
|
77 |
self._downloader = Downloader()
|
oliver@83
|
78 |
self._downloader.downloaded.connect(self.downloader_update)
|
oliver@83
|
79 |
self._thread = QtCore.QThread()
|
oliver@83
|
80 |
self._downloader.moveToThread(self._thread)
|
oliver@83
|
81 |
self._downloader.finished.connect(self._thread.quit)
|
oliver@83
|
82 |
self._thread.started.connect(self._downloader.work)
|
oliver@83
|
83 |
self._thread.finished.connect(self.finished_downloader)
|
oliver@83
|
84 |
self._thread.start()
|
oliver@83
|
85 |
|
oliver@83
|
86 |
|
oliver@83
|
87 |
def clicked_cancel(self):
|
oliver@83
|
88 |
|
oliver@83
|
89 |
"""button cancel clicked"""
|
oliver@83
|
90 |
|
oliver@83
|
91 |
# tell download thread to stop
|
oliver@83
|
92 |
self._downloader.stop = True
|
oliver@83
|
93 |
|
oliver@83
|
94 |
|
oliver@83
|
95 |
def downloader_update(self, current, total):
|
oliver@83
|
96 |
|
oliver@83
|
97 |
"""New download values present"""
|
oliver@83
|
98 |
if self.pbDownload.minimum() != 0:
|
oliver@83
|
99 |
self.pbDownload.setMinimum(0)
|
oliver@83
|
100 |
if self.pbDownload.maximum() != total:
|
oliver@83
|
101 |
self.pbDownload.setMaximum(total)
|
oliver@83
|
102 |
self.pbDownload.setValue(current)
|
oliver@83
|
103 |
|
oliver@83
|
104 |
|
oliver@83
|
105 |
def finished_downloader(self):
|
oliver@83
|
106 |
|
oliver@83
|
107 |
"""Download thread has finished (either success or abort)"""
|
oliver@83
|
108 |
if not self._downloader.error is None:
|
oliver@83
|
109 |
QtGui.QMessageBox.critical(None, 'OpenSecurity Download VM image error', self._downloader.error)
|
oliver@83
|
110 |
|
oliver@83
|
111 |
self.accept();
|
oliver@83
|
112 |
|
oliver@83
|
113 |
|
oliver@83
|
114 |
def setup_ui(self):
|
oliver@83
|
115 |
|
oliver@83
|
116 |
"""Create the widgets."""
|
oliver@83
|
117 |
|
oliver@83
|
118 |
lyMain = QtGui.QVBoxLayout(self)
|
oliver@83
|
119 |
lyMain.setContentsMargins(8, 8, 8, 8)
|
oliver@83
|
120 |
|
oliver@83
|
121 |
lbTitle = QtGui.QLabel('Downloading OpenSecurity VM image')
|
oliver@83
|
122 |
lyMain.addWidget(lbTitle)
|
oliver@83
|
123 |
self.pbDownload = QtGui.QProgressBar()
|
oliver@83
|
124 |
self.pbDownload.setTextVisible(True)
|
oliver@83
|
125 |
lyMain.addWidget(self.pbDownload)
|
oliver@83
|
126 |
|
oliver@83
|
127 |
# buttons
|
oliver@83
|
128 |
lyButton = QtGui.QHBoxLayout()
|
oliver@83
|
129 |
lyMain.addLayout(lyButton)
|
oliver@83
|
130 |
|
oliver@83
|
131 |
lyButton.addStretch(1)
|
oliver@83
|
132 |
btnCancel = QtGui.QPushButton('&Cancel', self)
|
oliver@83
|
133 |
btnCancel.setMinimumWidth(100)
|
oliver@83
|
134 |
lyButton.addWidget(btnCancel)
|
oliver@83
|
135 |
|
oliver@83
|
136 |
# connectors
|
oliver@83
|
137 |
btnCancel.clicked.connect(self.clicked_cancel)
|
oliver@83
|
138 |
|
oliver@83
|
139 |
# reduce to the max
|
oliver@83
|
140 |
self.setMinimumWidth(400)
|
oliver@83
|
141 |
self.resize(lyMain.minimumSize())
|
oliver@83
|
142 |
|
oliver@83
|
143 |
|
oliver@83
|
144 |
class Downloader(QtCore.QObject):
|
oliver@83
|
145 |
|
oliver@83
|
146 |
"""This is the worker thread when downloading"""
|
oliver@83
|
147 |
|
oliver@83
|
148 |
downloaded = QtCore.pyqtSignal(int, int)
|
oliver@83
|
149 |
finished = QtCore.pyqtSignal()
|
oliver@83
|
150 |
|
oliver@83
|
151 |
def __init__(self):
|
oliver@83
|
152 |
|
oliver@83
|
153 |
# super call
|
oliver@83
|
154 |
super(Downloader, self).__init__()
|
oliver@83
|
155 |
self.error = None
|
oliver@83
|
156 |
self.stop = False
|
oliver@83
|
157 |
|
oliver@83
|
158 |
# place to store the OsecVM image
|
oliver@86
|
159 |
if not os.path.exists(vm_path):
|
oliver@86
|
160 |
os.mkdir(vm_path)
|
oliver@83
|
161 |
|
oliver@83
|
162 |
|
oliver@83
|
163 |
def work(self):
|
oliver@83
|
164 |
|
oliver@83
|
165 |
"""Thread method: download until finished or stopped"""
|
oliver@83
|
166 |
|
oliver@83
|
167 |
url = "http://service.x-net.at/opensecurity/OsecVM_latest.ova"
|
oliver@83
|
168 |
|
oliver@86
|
169 |
filename_download = os.path.join(vm_path, 'OsecVM_latest.ova')
|
oliver@86
|
170 |
filename_target = os.path.join(vm_path, 'OsecVM.ova')
|
oliver@83
|
171 |
|
oliver@83
|
172 |
# open URL
|
oliver@83
|
173 |
try:
|
oliver@83
|
174 |
resp = urllib2.urlopen(url)
|
oliver@83
|
175 |
except urllib2.URLError as e:
|
oliver@83
|
176 |
self.error = 'URLError: ' + str(e.reason)
|
oliver@83
|
177 |
self.finished.emit()
|
oliver@83
|
178 |
return
|
oliver@83
|
179 |
except urllib2.HTTPError as e:
|
oliver@83
|
180 |
self.error = 'HTTPError: ' + str(e.reason)
|
oliver@83
|
181 |
self.finished.emit()
|
oliver@83
|
182 |
return
|
oliver@83
|
183 |
|
oliver@83
|
184 |
# download a CHUNK of data and then update the GUI
|
oliver@83
|
185 |
totalSize = int(resp.info().getheader('Content-Length').strip())
|
oliver@83
|
186 |
currentSize = 0
|
oliver@83
|
187 |
CHUNK_SIZE = 32768
|
oliver@83
|
188 |
self.downloaded.emit(currentSize, totalSize)
|
oliver@83
|
189 |
|
oliver@83
|
190 |
f = open(filename_download, 'w')
|
oliver@83
|
191 |
while (not self.stop) and (currentSize < totalSize):
|
oliver@83
|
192 |
data = resp.read(CHUNK_SIZE)
|
oliver@83
|
193 |
currentSize += len(data)
|
oliver@83
|
194 |
f.write(data)
|
oliver@83
|
195 |
self.downloaded.emit(currentSize, totalSize)
|
oliver@83
|
196 |
|
oliver@83
|
197 |
f.flush()
|
oliver@83
|
198 |
f.close()
|
oliver@83
|
199 |
|
oliver@83
|
200 |
# rename the download to OsecVM.ova
|
oliver@83
|
201 |
if os.path.exists(filename_target):
|
oliver@83
|
202 |
os.remove(filename_target)
|
oliver@83
|
203 |
os.rename(filename_download, filename_target)
|
oliver@83
|
204 |
|
oliver@83
|
205 |
self.finished.emit()
|
oliver@83
|
206 |
|
oliver@83
|
207 |
|
oliver@83
|
208 |
def main():
|
oliver@83
|
209 |
|
oliver@83
|
210 |
"""entry point"""
|
oliver@83
|
211 |
|
oliver@83
|
212 |
# launch Qt
|
oliver@83
|
213 |
global app
|
oliver@83
|
214 |
app = QtGui.QApplication(sys.argv)
|
oliver@83
|
215 |
|
oliver@83
|
216 |
# prebuild the pixmap cache: fetch all jpg, png and jpeg images and load them
|
oliver@83
|
217 |
image_path = os.path.join(sys.path[0], '..', 'gfx')
|
oliver@83
|
218 |
for file in os.listdir(image_path):
|
oliver@83
|
219 |
if file.lower().rpartition('.')[2] in ('jpg', 'png', 'jpeg'):
|
oliver@83
|
220 |
QtGui.QPixmapCache.insert(file.lower().rpartition('.')[0], QtGui.QPixmap(os.path.join(image_path, file)))
|
oliver@83
|
221 |
|
oliver@83
|
222 |
# we should have now our application icon
|
oliver@83
|
223 |
app.setWindowIcon(QtGui.QIcon(QtGui.QPixmapCache.find('opensecurity_icon_64')))
|
oliver@83
|
224 |
|
oliver@86
|
225 |
# check essential permissions
|
oliver@86
|
226 |
try:
|
oliver@86
|
227 |
f = open(os.path.join(vm_path, '.x'), 'w')
|
oliver@86
|
228 |
f.write('test')
|
oliver@86
|
229 |
f.flush()
|
oliver@86
|
230 |
f.close()
|
oliver@86
|
231 |
os.remove(os.path.join(vm_path, '.x'))
|
oliver@86
|
232 |
except IOError as e:
|
oliver@86
|
233 |
if e.errno == errno.EACCES:
|
oliver@86
|
234 |
QtGui.QMessageBox.critical(None, 'OpenSecurity Download VM image error', 'No write access to "' + str(vm_path) + '"\nIs this run as Administrator?')
|
oliver@86
|
235 |
sys.exit(1)
|
oliver@86
|
236 |
else:
|
oliver@86
|
237 |
QtGui.QMessageBox.critical(None, 'OpenSecurity Download VM image error', 'Error occured.\nErrno: ' + str(e.errno))
|
oliver@86
|
238 |
sys.exit(1)
|
oliver@86
|
239 |
|
oliver@86
|
240 |
# open download dialog
|
oliver@83
|
241 |
w = DownloadDialog()
|
oliver@83
|
242 |
w.show()
|
oliver@83
|
243 |
|
oliver@83
|
244 |
# on with the show
|
oliver@83
|
245 |
sys.exit(app.exec_())
|
oliver@83
|
246 |
|
oliver@83
|
247 |
|
oliver@83
|
248 |
# start
|
oliver@83
|
249 |
if __name__ == "__main__":
|
oliver@83
|
250 |
main()
|
oliver@83
|
251 |
|