2
2
3
3
import datetime
4
4
import json
5
+ import logging
5
6
import os
6
7
import shutil
7
8
import signal
19
20
BRLASER_DRIVER = "/usr/share/cups/drv/brlaser.drv"
20
21
BRLASER_PPD = "/usr/share/cups/model/br7030.ppd"
21
22
23
+ logger = logging .getLogger (__name__ )
24
+
22
25
23
26
class Metadata (object ):
24
27
"""
@@ -40,20 +43,40 @@ def __init__(self, archive_path):
40
43
41
44
try :
42
45
with open (self .metadata_path ) as f :
46
+ logging .info ('Parsing archive metadata' )
43
47
json_config = json .loads (f .read ())
44
48
self .export_method = json_config .get ("device" , None )
45
49
self .encryption_method = json_config .get ("encryption_method" , None )
46
- self .encryption_key = json_config .get ("encryption_key" , None )
50
+ self .encryption_key = json_config .get (
51
+ "encryption_key" , None
52
+ )
53
+ logging .info (
54
+ 'Exporting to device {} with encryption_method {}' .format (
55
+ self .export_method , self .encryption_method
56
+ )
57
+ )
47
58
48
59
except Exception :
60
+ logging .error ('Metadata parsing failure' )
49
61
raise
50
62
51
63
def is_valid (self ):
64
+ logging .info ('Validating metadata contents' )
52
65
if self .export_method not in self .SUPPORTED_EXPORT_METHODS :
66
+ logging .error (
67
+ 'Archive metadata: Export method {} is not supported' .format (
68
+ self .export_method
69
+ )
70
+ )
53
71
return False
54
72
55
73
if self .export_method == "disk" :
56
74
if self .encryption_method not in self .SUPPORTED_ENCRYPTION_METHODS :
75
+ logging .error (
76
+ 'Archive metadata: Encryption method {} is not supported' .format (
77
+ self .encryption_method
78
+ )
79
+ )
57
80
return False
58
81
return True
59
82
@@ -79,11 +102,15 @@ def __init__(self, archive, config_path):
79
102
80
103
try :
81
104
with open (config_path ) as f :
105
+ logging .info ('Retrieving VM configuration' )
82
106
json_config = json .loads (f .read ())
83
107
self .pci_bus_id = json_config .get ("pci_bus_id" , None )
108
+ logging .info ('pci_bus_id is {}' .format (self .pci_bus_id ))
84
109
if self .pci_bus_id is None :
85
- raise
110
+ logging .error ('pci_bus_id is not set in VM configuration' )
111
+ raise
86
112
except Exception :
113
+ logger .error ("error parsing VM configuration." )
87
114
self .exit_gracefully ("ERROR_CONFIG" )
88
115
89
116
def exit_gracefully (self , msg , e = False ):
@@ -95,12 +122,14 @@ def exit_gracefully(self, msg, e=False):
95
122
"""
96
123
sys .stderr .write (msg )
97
124
sys .stderr .write ("\n " )
125
+ logger .info ('Exiting with message: {}' .format (msg ))
98
126
if e :
99
127
try :
100
128
# If the file archive was extracted, delete before returning
101
129
if os .path .isdir (self .tmpdir ):
102
130
shutil .rmtree (self .tmpdir )
103
131
e_output = e .output
132
+ logger .error (e_output )
104
133
except Exception :
105
134
e_output = "<unknown exception>"
106
135
sys .stderr .write (e_output )
@@ -127,6 +156,7 @@ def popup_message(self, msg):
127
156
128
157
def extract_tarball (self ):
129
158
try :
159
+ logging .info ('Extracting tarball {} into {}' .format (self .archive , self .tmpdir ))
130
160
with tarfile .open (self .archive ) as tar :
131
161
tar .extractall (self .tmpdir )
132
162
except Exception :
@@ -137,18 +167,22 @@ def check_usb_connected(self):
137
167
138
168
# If the USB is not attached via qvm-usb attach, lsusb will return empty string and a
139
169
# return code of 1
170
+ logging .info ('Performing usb preflight' )
140
171
try :
141
- p = subprocess .check_output (["lsusb" , "-s" , "{}:" .format (self .pci_bus_id )])
172
+ p = subprocess .check_output (["lsusb" , "-s" , "{}:" .format (self .pci_bus_id )])
173
+ logging .info ("lsusb -s {} : {}" .format (self .pci_bus_id , p .decode ("utf-8" )))
142
174
except subprocess .CalledProcessError :
143
175
msg = "ERROR_USB_CONFIGURATION"
144
176
self .exit_gracefully (msg )
145
177
n_usb = len (p .decode ("utf-8" ).rstrip ().split ("\n " ))
146
178
# If there is one device, it is the root hub.
147
179
if n_usb == 1 :
180
+ logging .info ('usb preflight - no external devices connected' )
148
181
msg = "USB_NOT_CONNECTED"
149
182
self .exit_gracefully (msg )
150
183
# If there are two devices, it's the root hub and another device (presumably for export)
151
184
elif n_usb == 2 :
185
+ logging .info ('usb preflight - external device connected' )
152
186
msg = "USB_CONNECTED"
153
187
self .exit_gracefully (msg )
154
188
# Else the result is unexpected
@@ -157,10 +191,11 @@ def check_usb_connected(self):
157
191
self .exit_gracefully (msg )
158
192
159
193
def check_luks_volume (self ):
194
+ logging .info ('Checking if volume is luks-encrypted' )
160
195
try :
161
196
# cryptsetup isLuks returns 0 if the device is a luks volume
162
197
# subprocess with throw if the device is not luks (rc !=0)
163
- p = subprocess .check_call (["sudo" , "cryptsetup" , "isLuks" , DEVICE ])
198
+ subprocess .check_call (["sudo" , "cryptsetup" , "isLuks" , DEVICE ])
164
199
msg = "USB_ENCRYPTED"
165
200
self .exit_gracefully (msg )
166
201
except subprocess .CalledProcessError :
@@ -169,16 +204,19 @@ def check_luks_volume(self):
169
204
170
205
def unlock_luks_volume (self , encryption_key ):
171
206
# the luks device is not already unlocked
207
+ logging .info ('Unlocking luks volume {}' .format (self .encrypted_device ))
172
208
if not os .path .exists (os .path .join ("/dev/mapper/" , self .encrypted_device )):
173
209
p = subprocess .Popen (
174
210
["sudo" , "cryptsetup" , "luksOpen" , self .device , self .encrypted_device ],
175
211
stdin = subprocess .PIPE ,
176
212
stdout = subprocess .PIPE ,
177
- stderr = subprocess .PIPE ,
213
+ stderr = subprocess .PIPE
178
214
)
215
+ logging .info ('Passing key' )
179
216
p .communicate (input = str .encode (encryption_key , "utf-8" ))
180
217
rc = p .returncode
181
218
if rc != 0 :
219
+ logging .error ('Bad phassphrase for {}' .format (self .encrypted_device ))
182
220
msg = "USB_BAD_PASSPHRASE"
183
221
self .exit_gracefully (msg )
184
222
@@ -187,6 +225,7 @@ def mount_volume(self):
187
225
if not os .path .exists (self .mountpoint ):
188
226
subprocess .check_call (["sudo" , "mkdir" , self .mountpoint ])
189
227
try :
228
+ logging .info ('Mounting {} to {}' .format (self .encrypted_device , self .mountpoint ))
190
229
subprocess .check_call (
191
230
[
192
231
"sudo" ,
@@ -198,6 +237,8 @@ def mount_volume(self):
198
237
subprocess .check_call (["sudo" , "chown" , "-R" , "user:user" , self .mountpoint ])
199
238
except subprocess .CalledProcessError :
200
239
# clean up
240
+ logging .error ('Error mounting {} to {}' .format (self .encrypted_device , self .mountpoint ))
241
+ logging .info ('Locking luks volume {}' .format (self .encrypted_device ))
201
242
subprocess .check_call (
202
243
["sudo" , "cryptsetup" , "luksClose" , self .encrypted_device ]
203
244
)
@@ -210,19 +251,25 @@ def copy_submission(self):
210
251
target_path = os .path .join (self .mountpoint , self .target_dirname )
211
252
subprocess .check_call (["mkdir" , target_path ])
212
253
export_data = os .path .join (self .tmpdir , "export_data/" )
254
+ logging .info ('Copying file to {}' .format (self .target_dirname ))
213
255
subprocess .check_call (["cp" , "-r" , export_data , target_path ])
256
+ logging .info ('File copied successfully to {}' .format (self .target_dirname ))
214
257
self .popup_message ("Files exported successfully to disk." )
215
258
except (subprocess .CalledProcessError , OSError ):
216
259
msg = "ERROR_USB_WRITE"
217
260
self .exit_gracefully (msg )
218
261
finally :
219
262
# Finally, we sync the filesystem, unmount the drive and lock the
220
263
# luks volume, and exit 0
264
+ logging .info ('Syncing filesystems' )
221
265
subprocess .check_call (["sync" ])
266
+ logging .info ('Unmounting drive from {}' .format (self .mountpoint ))
222
267
subprocess .check_call (["sudo" , "umount" , self .mountpoint ])
268
+ logging .info ('Locking luks volume {}' .format (self .encrypted_device ))
223
269
subprocess .check_call (
224
270
["sudo" , "cryptsetup" , "luksClose" , self .encrypted_device ]
225
271
)
272
+ logging .info ('Deleting temporary directory {}' .format (self .tmpdir ))
226
273
subprocess .check_call (["rm" , "-rf" , self .tmpdir ])
227
274
sys .exit (0 )
228
275
@@ -234,15 +281,18 @@ def wait_for_print(self):
234
281
printer_idle_string = "printer {} is idle" .format (self .printer_name )
235
282
while True :
236
283
try :
284
+ logging .info ('Running lpstat waiting for printer {}' .format (self .printer_name ))
237
285
output = subprocess .check_output (["lpstat" , "-p" , self .printer_name ])
238
286
if printer_idle_string in output .decode ("utf-8" ):
287
+ logging .info ('Print completed' )
239
288
return True
240
289
else :
241
290
time .sleep (5 )
242
291
except subprocess .CalledProcessError :
243
292
msg = "ERROR_PRINT"
244
293
self .exit_gracefully (msg )
245
294
except TimeoutException :
295
+ logging .error ('Timeout waiting for printer {}' .format (self .printer_name ))
246
296
msg = "ERROR_PRINT"
247
297
self .exit_gracefully (msg )
248
298
return True
@@ -260,15 +310,19 @@ def get_printer_uri(self):
260
310
for line in output .split ():
261
311
if "usb://" in line .decode ("utf-8" ):
262
312
printer_uri = line .decode ("utf-8" )
313
+ logging .info ('lpinfo usb printer: {}' .format (printer_uri ))
263
314
264
315
# verify that the printer is supported, else exit
265
316
if printer_uri == "" :
266
317
# No usb printer is connected
318
+ logging .info ('No usb printers connected' )
267
319
self .exit_gracefully ("ERROR_PRINTER_NOT_FOUND" )
268
320
elif "Brother" in printer_uri :
321
+ logging .info ('Printer {} is supported' .format (printer_uri ))
269
322
return printer_uri
270
323
else :
271
324
# printer url is a make that is unsupported
325
+ logging .info ('Printer {} is unsupported' .format (printer_uri ))
272
326
self .exit_gracefully ("ERROR_PRINTER_NOT_SUPPORTED" )
273
327
274
328
def install_printer_ppd (self , uri ):
@@ -349,22 +403,24 @@ def is_open_office_file(self, filename):
349
403
350
404
def print_file (self , file_to_print ):
351
405
try :
352
- # if the file to print is an (open)office document, we need to call unoconf to convert
353
- # the file to pdf as printer drivers do not immediately support this format out of the box
406
+ # If the file to print is an (open)office document, we need to call unoconf to
407
+ # convert the file to pdf as printer drivers do not support this format
354
408
if self .is_open_office_file (file_to_print ):
409
+ logging .info ('Converting Office document to pdf' .format (self .printer_name ))
355
410
folder = os .path .dirname (file_to_print )
356
411
converted_filename = file_to_print + ".pdf"
357
412
converted_path = os .path .join (folder , converted_filename )
358
413
subprocess .check_call (["unoconv" , "-o" , converted_path , file_to_print ])
359
414
file_to_print = converted_path
360
415
416
+ logging .info ('Sending file to printer {}:{}' .format (self .printer_name ))
361
417
subprocess .check_call (["xpp" , "-P" , self .printer_name , file_to_print ])
362
418
except subprocess .CalledProcessError :
363
419
msg = "ERROR_PRINT"
364
420
self .exit_gracefully (msg )
365
421
366
422
367
- ## class ends here
423
+ # class ends here
368
424
class TimeoutException (Exception ):
369
425
pass
370
426
0 commit comments