1.1 --- a/OpenSecurity/bin/vmmanager.pyw Tue Feb 18 14:38:24 2014 +0100
1.2 +++ b/OpenSecurity/bin/vmmanager.pyw Fri Feb 21 11:04:04 2014 +0100
1.3 @@ -55,11 +55,15 @@
1.4 startNotifications = list()
1.5 _instance = None
1.6 machineFolder = ''
1.7 + attachedRSDs = None
1.8 + connectedRSDs = None
1.9
1.10 def __init__(self):
1.11 self.systemProperties = self.getSystemProperties()
1.12 self.machineFolder = self.systemProperties["Default machine folder"]
1.13 self.cleanup()
1.14 + self.attachedRSDs = self.getAttachedRSDs()
1.15 + self.connectedRSDs = self.getConnectedRSDS()
1.16 return
1.17
1.18 @staticmethod
1.19 @@ -87,7 +91,7 @@
1.20 if result[1]=='':
1.21 return None
1.22 props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
1.23 - logger.debug(props)
1.24 + #logger.debug(props)
1.25 return props
1.26
1.27 # return the folder containing the guest VMs
1.28 @@ -101,27 +105,6 @@
1.29 return None
1.30 props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
1.31 return props
1.32 -
1.33 - def listRSDS(self):
1.34 - results = Cygwin.vboxExecute('list usbhost')[1]
1.35 - results = results.split('Host USB Devices:')[1].strip()
1.36 -
1.37 - items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
1.38 - rsds = dict()
1.39 - for item in items:
1.40 - props = dict()
1.41 - for line in item.splitlines():
1.42 - if line != "":
1.43 - k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
1.44 - props[k] = v
1.45 -
1.46 - if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
1.47 - usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'],
1.48 - re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
1.49 - re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
1.50 - rsds[props['UUID']] = usb_filter;
1.51 - logger.debug(usb_filter)
1.52 - return rsds
1.53
1.54 # list all existing VMs registered with VBox
1.55 def listVM(self):
1.56 @@ -152,6 +135,28 @@
1.57 return self.vmRootName+str(i)
1.58 return ''
1.59
1.60 + # return the RSDs connected to the host
1.61 + def getConnectedRSDS(self):
1.62 + results = Cygwin.vboxExecute('list usbhost')[1]
1.63 + results = results.split('Host USB Devices:')[1].strip()
1.64 +
1.65 + items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
1.66 + rsds = dict()
1.67 + for item in items:
1.68 + props = dict()
1.69 + for line in item.splitlines():
1.70 + if line != "":
1.71 + k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
1.72 + props[k] = v
1.73 +
1.74 + if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
1.75 + usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'],
1.76 + re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
1.77 + re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
1.78 + rsds[props['UUID']] = usb_filter;
1.79 + logger.debug(usb_filter)
1.80 + return rsds
1.81 +
1.82 # return the RSDs attached to all existing SDVMs
1.83 def getAttachedRSDs(self):
1.84 vms = self.listSDVM()
1.85 @@ -207,6 +212,7 @@
1.86
1.87 # list storage snaphots for VM
1.88 def updateTemplate(self):
1.89 + self.cleanup()
1.90 self.poweroffVM('SecurityDVM')
1.91 self.waitShutdown('SecurityDVM')
1.92
1.93 @@ -250,13 +256,15 @@
1.94 self.storageAttach('SecurityDVM')
1.95 self.startVM('SecurityDVM')
1.96 self.waitStartup('SecurityDVM')
1.97 - Cygwin.sshExecute('sudo apt-get -y update', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key' )
1.98 - Cygwin.sshExecute('sudo apt-get -y upgrade', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key' )
1.99 + Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key' )
1.100 + Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key' )
1.101 self.stopVM('SecurityDVM')
1.102 + #self.hibernateVM('SecurityDVM')
1.103 self.waitShutdown('SecurityDVM')
1.104 self.storageDetach('SecurityDVM')
1.105 self.changeStorageType(template_storage,'immutable')
1.106 self.storageAttach('SecurityDVM')
1.107 + self.handleDeviceChange()
1.108
1.109 #remove VM from the system. should be used on VMs returned by listSDVMs
1.110 def removeVM(self, vm_name):
1.111 @@ -282,7 +290,12 @@
1.112 # stop VM
1.113 def stopVM(self, vm_name):
1.114 logger.info('Sending shutdown signal to ' + vm_name)
1.115 - Cygwin.sshExecute( 'sudo shutdown -h now', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' )
1.116 + Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' )
1.117 +
1.118 + # stop VM
1.119 + def hibernateVM(self, vm_name):
1.120 + logger.info('Sending shutdown signal to ' + vm_name)
1.121 + Cygwin.sshExecute( '"sudo hibernate-disk"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' )
1.122
1.123 # poweroff VM
1.124 def poweroffVM(self, vm_name):
1.125 @@ -316,7 +329,7 @@
1.126 def getVMInfo(self, vm_name):
1.127 results = Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable')[1]
1.128 props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
1.129 - logger.debug(props)
1.130 + #logger.debug(props)
1.131 return props
1.132
1.133 # return the configured USB filter for an existing VM
1.134 @@ -357,33 +370,56 @@
1.135 result = Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + self.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"')
1.136 return result
1.137
1.138 +
1.139 handleDeviceChangeLock = threading.Lock()
1.140 -
1.141 + trigger = False
1.142 # handles device change events
1.143 def handleDeviceChange(self):
1.144 if VMManager.handleDeviceChangeLock.acquire(True):
1.145 + #logger.debug("triggered")
1.146 + #VMManager.handleDeviceChangeLock.release()
1.147 + #return
1.148 #destroy unused vms
1.149 - new_ip = None
1.150 - attached_devices = self.getAttachedRSDs()
1.151 - connected_devices = self.listRSDS()
1.152 - for vm_name in attached_devices.keys():
1.153 - if attached_devices[vm_name] not in connected_devices.values():
1.154 + #diff = DictDiffer(self.connectedRSDs, tmp_conn)
1.155 + retry = 0
1.156 + while retry < 30:
1.157 + if self.getConnectedRSDS().keys() == self.connectedRSDs.keys():
1.158 + logger.info("Nothing's changed. Waiting for VBox USB sub-system to update...")
1.159 + else:
1.160 + self.connectedRSDs = self.getConnectedRSDS()
1.161 + break
1.162 + time.sleep(1)
1.163 + retry+=1
1.164 +
1.165 + if retry == 30:
1.166 + VMManager.handleDeviceChangeLock.release()
1.167 + return None
1.168 +
1.169 + logger.info("Something's changed")
1.170 +
1.171 + self.attachedRSDs = self.getAttachedRSDs()
1.172 +
1.173 + for vm_name in self.attachedRSDs.keys():
1.174 + if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
1.175 self.unmapNetworkDrive('h:')
1.176 #self.stopVM(vm_name)
1.177 self.detachRSD(vm_name)
1.178 self.poweroffVM(vm_name)
1.179 self.removeVM(vm_name)
1.180 #create new vm for attached device if any
1.181 - attached_devices = self.getAttachedRSDs()
1.182 - connected_devices = self.listRSDS()
1.183 - for connected_device in connected_devices.values():
1.184 - if (attached_devices and False) or (connected_device not in attached_devices.values()):
1.185 + self.attachedRSDs = self.getAttachedRSDs()
1.186 + self.connectedRSDs = self.getConnectedRSDS()
1.187 +
1.188 + new_ip = None
1.189 + for connected_device in self.connectedRSDs.values():
1.190 + if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
1.191 new_sdvm = self.generateSDVMName()
1.192 self.createVM(new_sdvm)
1.193 self.storageAttach(new_sdvm)
1.194 self.attachRSD(new_sdvm, connected_device)
1.195 self.startVM(new_sdvm)
1.196 new_ip = self.waitStartup(new_sdvm)
1.197 +
1.198 if new_ip != None:
1.199 self.mapNetworkDrive('h:', '\\\\' + new_ip + '\\USB', None, None)
1.200 #TODO: cleanup notifications somwhere else (eg. machine shutdown)
1.201 @@ -425,9 +461,10 @@
1.202 return new_sdvm
1.203
1.204 #Small function to check the availability of network resource.
1.205 - def isAvailable(self, path):
1.206 - result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
1.207 - return string.find(result[1], 'YES',)
1.208 + #def isAvailable(self, path):
1.209 + #return os.path.exists(path)
1.210 + #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
1.211 + #return string.find(result[1], 'YES',)
1.212
1.213 #Small function to check if the mention location is a directory
1.214 def isDirectory(self, path):
1.215 @@ -437,11 +474,11 @@
1.216 def mapNetworkDrive(self, drive, networkPath, user, password):
1.217 self.unmapNetworkDrive(drive)
1.218 #Check for drive availability
1.219 - if self.isAvailable(drive) > -1:
1.220 + if os.path.exists(drive):
1.221 logger.error("Drive letter is already in use: " + drive)
1.222 return -1
1.223 #Check for network resource availability
1.224 - while self.isAvailable(networkPath) == -1:
1.225 + while not os.path.exists(networkPath):
1.226 time.sleep(1)
1.227 logger.info("Path not accessible: " + networkPath + " retrying")
1.228 #return -1
1.229 @@ -458,18 +495,34 @@
1.230 return 1
1.231
1.232 def unmapNetworkDrive(self, drive):
1.233 - if self.isAvailable(drive) == -1:
1.234 + if not os.path.exists(drive):
1.235 return -1
1.236 result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES')
1.237 if string.find(str(result), 'successfully',) == -1:
1.238 + logger.error(result[2])
1.239 return -1
1.240 return 1
1.241
1.242 +class DeviceHandler(threading.Thread):
1.243 + vmm = None
1.244 + triggered = False
1.245 + def __init__(self, zahl):
1.246 + threading.Thread.__init__(self)
1.247 + self.vmm = None
1.248 +
1.249 + def run(self):
1.250 + while True:
1.251 + if self.triggered:
1.252 + logger.debug("triggered")
1.253 + triggered = False
1.254 + else:
1.255 + time.sleep(1)
1.256 +
1.257
1.258 if __name__ == '__main__':
1.259 man = VMManager.getInstance()
1.260 #man.listVM()
1.261 - print man.listRSDS()
1.262 + print man.getConnectedRSDs()
1.263
1.264 #man.listVM()
1.265 #man.listVM()