OpenSecurity/bin/vmmanager.pyw
author mb
Thu, 27 Feb 2014 11:39:37 +0100
changeset 81 84663db906d7
parent 79 617009c32da0
child 87 d5b04809faca
permissions -rwxr-xr-x
corrected forgotten notification remove call
     1 '''
     2 Created on Nov 19, 2013
     3 
     4 @author: BarthaM
     5 '''
     6 import os
     7 import os.path
     8 from subprocess import Popen, PIPE, call, STARTUPINFO, _subprocess
     9 import sys
    10 import re
    11 
    12 from cygwin import Cygwin
    13 from environment import Environment
    14 import threading
    15 import time
    16 import string
    17 
    18 import shutil
    19 import stat
    20 import tempfile
    21 from opensecurity_util import logger, setupLogger, OpenSecurityException
    22 import ctypes
    23 import itertools
    24 DEBUG = True
    25 
    26 class VMManagerException(Exception):
    27     def __init__(self, value):
    28         self.value = value
    29     def __str__(self):
    30         return repr(self.value)
    31 
    32 class USBFilter:
    33     vendorid = ""
    34     productid = ""
    35     revision = ""
    36     
    37     def __init__(self, vendorid, productid, revision):
    38         self.vendorid = vendorid.lower()
    39         self.productid = productid.lower()
    40         self.revision = revision.lower()
    41         return
    42     
    43     def __eq__(self, other):
    44         return self.vendorid == other.vendorid and self.productid == other.productid and self.revision == other.revision
    45     
    46     def __hash__(self):
    47         return hash(self.vendorid) ^ hash(self.productid) ^ hash(self.revision)
    48     
    49     def __repr__(self):
    50         return "VendorId = \'" + str(self.vendorid) + "\' ProductId = \'" + str(self.productid) + "\' Revision = \'" + str(self.revision) + "\'"
    51  
    52 class VMManager(object):
    53     vmRootName = "SecurityDVM"
    54     systemProperties = None
    55     _instance = None
    56     machineFolder = ''
    57     rsdHandler = None
    58     
    59     def __init__(self):
    60         self.systemProperties = self.getSystemProperties()
    61         self.machineFolder = self.systemProperties["Default machine folder"]
    62         self.cleanup()
    63         self.rsdHandler = DeviceHandler(self)
    64         self.rsdHandler.start()
    65         return
    66     
    67     @staticmethod
    68     def getInstance():
    69         if VMManager._instance == None:
    70             VMManager._instance = VMManager()
    71         return VMManager._instance
    72     
    73     def cleanup(self):
    74         if self.rsdHandler != None:
    75             self.rsdHandler.stop()
    76             self.rsdHandler.join()
    77         drives = self.getNetworkDrives()
    78         for drive in drives.keys():
    79             self.unmapNetworkDrive(drive)
    80         for vm in self.listSDVM():
    81             self.poweroffVM(vm)
    82             self.removeVM(vm)
    83         
    84     # return hosty system properties
    85     def getSystemProperties(self):
    86         result = Cygwin.vboxExecute('list systemproperties')
    87         if result[1]=='':
    88             return None
    89         props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    90         #logger.debug(props)
    91         return props
    92     
    93     # return the folder containing the guest VMs     
    94     def getMachineFolder(self):
    95         return self.machineFolder
    96 
    97     # list all existing VMs registered with VBox
    98     def listVM(self):
    99         result = Cygwin.vboxExecute('list vms')[1]
   100         vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   101         return vms
   102     
   103     # list running VMs
   104     def listRunningVMS(self):
   105         result = Cygwin.vboxExecute('list runningvms')[1]
   106         vms = list(k.strip().strip('"') for k,_ in (line.split(' ') for line in result.splitlines()))
   107         return vms
   108     
   109     # list existing SDVMs
   110     def listSDVM(self):
   111         vms = self.listVM()
   112         svdms = []
   113         for vm in vms:
   114             if vm.startswith(self.vmRootName) and vm != self.vmRootName:
   115                 svdms.append(vm)
   116         return svdms
   117     
   118     # generate valid (not already existing SDVM name). necessary for creating a new VM
   119     def generateSDVMName(self):
   120         vms = self.listVM()
   121         for i in range(0,999):
   122             if(not self.vmRootName+str(i) in vms):
   123                 return self.vmRootName+str(i)
   124         return ''
   125     
   126     # return the RSDs connected to the host
   127     def getConnectedRSDS(self):
   128         results = Cygwin.vboxExecute('list usbhost')[1]
   129         results = results.split('Host USB Devices:')[1].strip()
   130         
   131         items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   132         rsds = dict()   
   133         for item in items:
   134             props = dict()
   135             for line in item.splitlines():
   136                 if line != "":         
   137                     k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   138                     props[k] = v
   139             
   140             if 'Product' in props.keys() and props['Product'] == 'Mass Storage':
   141                 usb_filter = USBFilter( re.search(r"\((?P<vid>[0-9A-Fa-f]+)\)", props['VendorId']).groupdict()['vid'], 
   142                                         re.search(r"\((?P<pid>[0-9A-Fa-f]+)\)", props['ProductId']).groupdict()['pid'],
   143                                         re.search(r"\((?P<rev>[0-9A-Fa-f]+)\)", props['Revision']).groupdict()['rev'] )
   144                 rsds[props['UUID']] = usb_filter;
   145                 logger.debug(usb_filter)
   146         return rsds
   147     
   148     # return the RSDs attached to all existing SDVMs
   149     def getAttachedRSDs(self):
   150         vms = self.listSDVM()
   151         attached_devices = dict()
   152         for vm in vms:
   153             rsd_filter = self.getUSBFilter(vm)
   154             if rsd_filter != None:
   155                 attached_devices[vm] = rsd_filter
   156         return attached_devices
   157     
   158     # configures hostonly networking and DHCP server. requires admin rights
   159     def configureHostNetworking(self):
   160         #cmd = 'vboxmanage list hostonlyifs'
   161         #Cygwin.vboxExecute(cmd)
   162         #cmd = 'vboxmanage hostonlyif remove \"VirtualBox Host-Only Ethernet Adapter\"'
   163         #Cygwin.vboxExecute(cmd)
   164         #cmd = 'vboxmanage hostonlyif create'
   165         #Cygwin.vboxExecute(cmd)
   166         Cygwin.vboxExecute('hostonlyif ipconfig \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.1 --netmask 255.255.255.0')
   167         #cmd = 'vboxmanage dhcpserver add'
   168         #Cygwin.vboxExecute(cmd)
   169         Cygwin.vboxExecute('dhcpserver modify --ifname \"VirtualBox Host-Only Ethernet Adapter\" --ip 192.168.56.100 --netmask 255.255.255.0 --lowerip 192.168.56.101 --upperip 192.168.56.200')
   170     
   171     #create new virtual machine instance based on template vm named SecurityDVM (\SecurityDVM\SecurityDVM.vmdk)
   172     def createVM(self, vm_name):
   173         hostonly_if = self.getHostOnlyIFs()
   174         Cygwin.vboxExecute('createvm --name ' + vm_name + ' --ostype Debian --register')
   175         Cygwin.vboxExecute('modifyvm ' + vm_name + ' --memory 512 --vram 10 --cpus 1 --usb on --usbehci on --nic1 hostonly --hostonlyadapter1 \"' + hostonly_if['Name'] + '\" --nic2 nat')
   176         Cygwin.vboxExecute('storagectl ' + vm_name + ' --name SATA --add sata --portcount 2')
   177         return
   178     
   179     # attach storage image to controller
   180     def storageAttach(self, vm_name):
   181         if self.isStorageAttached(vm_name):
   182             self.storageDetach(vm_name)
   183         Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium \"'+ self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk\"')
   184         return
   185     
   186     # return true if storage is attached 
   187     def isStorageAttached(self, vm_name):
   188         info = self.getVMInfo(vm_name)
   189         return (info['SATA-0-0']!='none')
   190     
   191     # detach storage from controller
   192     def storageDetach(self, vm_name):
   193         if self.isStorageAttached(vm_name):
   194             Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 0 --device 0 --type hdd --medium none')
   195         return
   196     
   197     def changeStorageType(self, filename, storage_type):
   198         Cygwin.vboxExecute('modifyhd \"' + filename + '\" --type ' + storage_type)
   199         return
   200     
   201     # list storage snaphots for VM
   202     def updateTemplate(self):
   203         self.cleanup()
   204         self.poweroffVM('SecurityDVM')
   205         self.waitShutdown('SecurityDVM')
   206         
   207         # check for updates
   208         self.genCertificateISO('SecurityDVM')
   209         self.attachCertificateISO('SecurityDVM')
   210         
   211         self.storageDetach('SecurityDVM')
   212         results = Cygwin.vboxExecute('list hdds')[1]
   213         results = results.replace('Parent UUID', 'Parent')
   214         items = list( "UUID:"+result for result in results.split('UUID:') if result != '')
   215         
   216         snaps = dict()   
   217         for item in items:
   218             props = dict()
   219             for line in item.splitlines():
   220                 if line != "":         
   221                     k,v = line[:line.index(':')].strip(), line[line.index(':')+1:].strip()
   222                     props[k] = v;
   223             snaps[props['UUID']] = props
   224         
   225         
   226         template_storage = self.machineFolder + '\SecurityDVM\SecurityDVM.vmdk'
   227         
   228         # find template uuid
   229         template_uuid = ''
   230         for hdd in snaps.values():
   231             if hdd['Location'] == template_storage:
   232                 template_uuid = hdd['UUID']
   233         logger.debug('found parent uuid ' + template_uuid)
   234         
   235         # remove snapshots 
   236         for hdd in snaps.values():
   237             if hdd['Parent'] == template_uuid:
   238                 #template_uuid = hdd['UUID']
   239                 logger.debug('removing snapshot ' + hdd['UUID'])
   240                 results = Cygwin.vboxExecute('closemedium disk {' + hdd['UUID'] + '} --delete')[1]
   241                 # parse result 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
   242         
   243         self.changeStorageType(template_storage,'normal')
   244         self.storageAttach('SecurityDVM')
   245         self.startVM('SecurityDVM')
   246         self.waitStartup('SecurityDVM')
   247         Cygwin.sshExecute('"sudo apt-get -y update"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'  )
   248         Cygwin.sshExecute('"sudo apt-get -y upgrade"', VMManager.getHostOnlyIP('SecurityDVM'), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + 'SecurityDVM' + '/dvm_key'  )
   249         #self.stopVM('SecurityDVM')
   250         self.hibernateVM('SecurityDVM')
   251         self.waitShutdown('SecurityDVM')
   252         self.storageDetach('SecurityDVM')
   253         self.changeStorageType(template_storage,'immutable')
   254         self.storageAttach('SecurityDVM')
   255         self.rsdHandler = DeviceHandler(self)
   256         self.rsdHandler.start()
   257     
   258     #remove VM from the system. should be used on VMs returned by listSDVMs    
   259     def removeVM(self, vm_name):
   260         logger.info('Removing ' + vm_name)
   261         Cygwin.vboxExecute('unregistervm ' + vm_name + ' --delete')
   262         machineFolder = Cygwin.cygPath(self.machineFolder)
   263         Cygwin.bashExecute('"/usr/bin/rm -rf ' + machineFolder + '/' + vm_name + '"')
   264     
   265     # start VM
   266     def startVM(self, vm_name):
   267         logger.info('Starting ' +  vm_name)
   268         result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless' )
   269         while not string.find(str(result), 'successfully started',):
   270             logger.error("Failed to start SDVM: " + vm_name + " retrying")
   271             time.sleep(1)
   272             result = Cygwin.vboxExecute('startvm ' + vm_name + ' --type headless')
   273         return result[0]
   274     
   275     # return wether VM is running or not
   276     def isVMRunning(self, vm_name):
   277         return vm_name in self.listRunningVMS()    
   278     
   279     # stop VM
   280     def stopVM(self, vm_name):
   281         logger.info('Sending shutdown signal to ' + vm_name)
   282         Cygwin.sshExecute( '"sudo shutdown -h now"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key' )
   283     
   284     # stop VM
   285     def hibernateVM(self, vm_name):
   286         logger.info('Sending shutdown signal to ' + vm_name)
   287         Cygwin.sshExecute( '"sudo hibernate-disk&"', VMManager.getHostOnlyIP(vm_name), 'osecuser', Cygwin.cygPath(self.machineFolder) + '/' + vm_name + '/dvm_key', wait_return=False )
   288             
   289     # poweroff VM
   290     def poweroffVM(self, vm_name):
   291         if not self.isVMRunning(vm_name):
   292             return
   293         logger.info('Powering off ' + vm_name)
   294         return Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff')
   295     
   296     #list the hostonly IFs exposed by the VBox host
   297     @staticmethod    
   298     def getHostOnlyIFs():
   299         result = Cygwin.vboxExecute('list hostonlyifs')[1]
   300         if result=='':
   301             return None
   302         props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   303         return props
   304     
   305     # return the hostOnly IP for a running guest or the host
   306     @staticmethod    
   307     def getHostOnlyIP(vm_name):
   308         if vm_name == None:
   309             logger.info('Gettting hostOnly IP address for Host')
   310             return VMManager.getHostOnlyIFs()['IPAddress']
   311         else:
   312             logger.info('Gettting hostOnly IP address ' + vm_name)
   313             result = Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP')
   314             if result=='':
   315                 return None
   316             result = result[1]
   317             if result.startswith('No value set!'):
   318                 return None
   319             return result[result.index(':')+1:].strip()
   320             
   321     # attach removable storage device to VM by provision of filter
   322     def attachRSD(self, vm_name, rsd_filter):
   323         return Cygwin.vboxExecute('usbfilter add 0 --target ' + vm_name + ' --name OpenSecurityRSD --vendorid ' + rsd_filter.vendorid + ' --productid ' + rsd_filter.productid + ' --revision ' + rsd_filter.revision)
   324     
   325     # detach removable storage from VM by 
   326     def detachRSD(self, vm_name):
   327         return Cygwin.vboxExecute('usbfilter remove 0 --target ' + vm_name )
   328         
   329     
   330     # return the description set for an existing VM
   331     def getVMInfo(self, vm_name):
   332         results = Cygwin.vboxExecute('showvminfo ' + vm_name + ' --machinereadable')[1]
   333         props = dict((k.strip().strip('"'),v.strip().strip('"')) for k,v in (line.split('=', 1) for line in results.splitlines()))
   334         #logger.debug(props)
   335         return props
   336     
   337     # return the configured USB filter for an existing VM 
   338     def getUSBFilter(self, vm_name):
   339         props = self.getVMInfo(vm_name)
   340         keys = set(['USBFilterVendorId1', 'USBFilterProductId1', 'USBFilterRevision1'])
   341         keyset = set(props.keys())
   342         usb_filter = None
   343         if keyset.issuperset(keys):
   344             usb_filter = USBFilter(props['USBFilterVendorId1'], props['USBFilterProductId1'], props['USBFilterRevision1'])
   345         return usb_filter
   346     
   347     #generates ISO containing authorized_keys for use with guest VM
   348     def genCertificateISO(self, vm_name):
   349         machineFolder = Cygwin.cygPath(self.machineFolder)
   350         # remove .ssh folder if exists
   351         cmd = '\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"'
   352         Cygwin.bashExecute(cmd)
   353         # remove .ssh folder if exists
   354         Cygwin.bashExecute('\"/usr/bin/rm -rf \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"')
   355         # create .ssh folder in vm_name
   356         Cygwin.bashExecute('\"/usr/bin/mkdir -p \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"')
   357         # generate dvm_key pair in vm_name / .ssh     
   358         Cygwin.bashExecute('\"/usr/bin/ssh-keygen -q -t rsa -N \\"\\" -C \\\"' + vm_name + '\\\" -f \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\"\"')
   359         # move out private key
   360         Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key\\\" \\\"' + machineFolder + '/' + vm_name + '\\\"')
   361         # set permissions for private key
   362         Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/dvm_key\\\"\"')
   363         # rename public key to authorized_keys
   364         Cygwin.bashExecute('\"/usr/bin/mv \\\"' + machineFolder + '/' + vm_name + '/.ssh/dvm_key.pub\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"')
   365         # set permissions for authorized_keys
   366         Cygwin.bashExecute('\"/usr/bin/chmod 500 \\\"' + machineFolder + '/' + vm_name + '/.ssh/authorized_keys\\\"\"')
   367         # generate iso image with .ssh/authorized keys
   368         Cygwin.bashExecute('\"/usr/bin/genisoimage -J -R -o \\\"' + machineFolder + '/' + vm_name + '/'+ vm_name + '.iso\\\" \\\"' + machineFolder + '/' + vm_name + '/.ssh\\\"\"')
   369     
   370     # attaches generated ssh public cert to guest vm
   371     def attachCertificateISO(self, vm_name):
   372         result = Cygwin.vboxExecute('storageattach ' + vm_name + ' --storagectl SATA --port 1 --device 0 --type dvddrive --mtype readonly --medium \"' + self.machineFolder + '\\' + vm_name + '\\'+ vm_name + '.iso\"')
   373         return result
   374     
   375     # wait for machine to come up
   376     def waitStartup(self, vm_name, timeout_ms = 30000):
   377         result = Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout')
   378         return VMManager.getHostOnlyIP(vm_name)
   379     
   380     # wait for machine to shutdown
   381     def waitShutdown(self, vm_name):
   382         while vm_name in self.listRunningVMS():
   383             time.sleep(1)
   384         return
   385         
   386     # handles browsing request    
   387     def handleBrowsingRequest(self):
   388         if VMManager.handleDeviceChangeLock.acquire(True):
   389             new_sdvm = self.generateSDVMName()
   390             self.createVM(new_sdvm)
   391             self.storageAttach(new_sdvm)
   392             self.genCertificateISO(new_sdvm)
   393             self.attachCertificateISO(new_sdvm)
   394             self.startVM(new_sdvm)
   395             new_ip = self.waitStartup(new_sdvm)
   396             if new_ip != None:
   397                 self.mapNetworkDrive('g:', '\\\\' + new_ip + '\\Download', None, None)
   398             #TODO: cleanup notifications somwhere else (eg. machine shutdown)
   399             VMManager.handleDeviceChangeLock.release()
   400         return new_sdvm
   401     
   402     #Small function to check the availability of network resource.
   403     #def isAvailable(self, path):
   404         #return os.path.exists(path)
   405         #result = Cygwin.cmdExecute('IF EXIST "' + path + '" echo YES')
   406         #return string.find(result[1], 'YES',)
   407     
   408     #Small function to check if the mention location is a directory
   409     def isDirectory(self, path):
   410         result = Cygwin.cmdExecute('dir ' + path + ' | FIND ".."')
   411         return string.find(result[1], 'DIR',)
   412 
   413     def mapNetworkDrive(self, drive, networkPath, user, password):
   414         self.unmapNetworkDrive(drive)
   415         #Check for drive availability
   416         if os.path.exists(drive):
   417             logger.error("Drive letter is already in use: " + drive)
   418             return -1
   419         #Check for network resource availability
   420         while not os.path.exists(networkPath):
   421             time.sleep(1)
   422             logger.info("Path not accessible: " + networkPath + " retrying")
   423             #return -1
   424     
   425         command = 'USE ' + drive + ' ' + networkPath + ' /PERSISTENT:NO'
   426         if user != None:
   427             command += ' ' + password + ' /User' + user
   428     
   429         #TODO: Execute 'NET USE' command with authentication
   430         result = Cygwin.execute('C:\\Windows\\system32\\net.exe', command)
   431         if string.find(result[1], 'successfully',) == -1:
   432             logger.error("Failed: NET " + command)
   433             return -1
   434         return 1
   435     
   436     def unmapNetworkDrive(self, drive):
   437         drives = self.getNetworkDrives()
   438         if drive not in drives.keys():
   439             return 1 
   440         result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE ' + drive + ' /DELETE /YES')
   441         if string.find(str(result[1]), 'successfully',) == -1:
   442             logger.error(result[2])
   443             return -1
   444         return 1
   445     
   446     def getNetworkDrives(self):
   447         ip = VMManager.getHostOnlyIP(None)
   448         ip = ip[:ip.rindex('.')]
   449         drives = dict()    
   450         result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE')
   451         for line in result[1].splitlines():
   452             if ip in line:
   453                 parts = line.split()
   454                 drives[parts[1]] = parts[2]
   455         return drives
   456             
   457     def genNetworkDrive(self):
   458         network_drives = self.getNetworkDrives()
   459         logical_drives = self.getLogicalDrives()
   460         drives = list(map(chr, range(68, 91)))  
   461         for drive in drives:
   462             if drive+':' not in network_drives and drive not in logical_drives:
   463                 return drive+':'
   464 
   465     def getNetworkDrive(self, vm_name):
   466         ip = self.getHostOnlyIP(vm_name)
   467         result = Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE')
   468         for line in result[1].splitlines():
   469             if ip in line:
   470                 parts = line.split()
   471                 return parts[0]
   472     
   473     def getLogicalDrives(self):
   474         drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   475         return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   476                     
   477         #vms = self.listSDVM()
   478         #for vm in vms:
   479         #    ip = self.getHostOnlyIP(vm)
   480         
   481 class DeviceHandler(threading.Thread): 
   482     vmm = None
   483     #handleDeviceChangeLock = threading.Lock()
   484     attachedRSDs = None  
   485     connectedRSDs = None
   486     running = True
   487     def __init__(self, vmmanger): 
   488         threading.Thread.__init__(self)
   489         self.vmm = vmmanger
   490  
   491     def stop(self):
   492         self.running = False
   493         
   494     def run(self):
   495         self.connectedRSDs = dict()#self.vmm.getConnectedRSDS()
   496         self.attachedRSDs = self.vmm.getAttachedRSDs()
   497         while self.running:
   498             tmp_rsds = self.vmm.getConnectedRSDS()
   499             if tmp_rsds.keys() == self.connectedRSDs.keys():
   500                 logger.debug("Nothing's changed. sleep(3)")
   501                 time.sleep(3)
   502                 continue
   503             
   504             logger.info("Something's changed")          
   505             
   506             self.connectedRSDs = tmp_rsds
   507             self.attachedRSDs = self.vmm.getAttachedRSDs()
   508             
   509             
   510             for vm_name in self.attachedRSDs.keys():
   511                 if self.attachedRSDs[vm_name] not in self.connectedRSDs.values():
   512                     drive = self.vmm.getNetworkDrive(vm_name)
   513                     self.vmm.unmapNetworkDrive(drive)
   514                     #self.stopVM(vm_name)
   515                     self.vmm.detachRSD(vm_name)
   516                     self.vmm.poweroffVM(vm_name)
   517                     self.vmm.removeVM(vm_name)
   518             #create new vm for attached device if any
   519             self.attachedRSDs = self.vmm.getAttachedRSDs()
   520             self.connectedRSDs = self.vmm.getConnectedRSDS()
   521             
   522             new_ip = None
   523             for connected_device in self.connectedRSDs.values():
   524                 if (self.attachedRSDs and False) or (connected_device not in self.attachedRSDs.values()):
   525                     new_sdvm = self.vmm.generateSDVMName()
   526                     self.vmm.createVM(new_sdvm)
   527                     self.vmm.storageAttach(new_sdvm)
   528                     self.vmm.attachRSD(new_sdvm, connected_device)
   529                     self.vmm.startVM(new_sdvm)
   530                     new_ip = self.vmm.waitStartup(new_sdvm)
   531                     drive = self.vmm.genNetworkDrive()
   532                     if new_ip != None:
   533                         self.vmm.mapNetworkDrive(drive, '\\\\' + new_ip + '\\USB', None, None)
   534                     #TODO: cleanup notifications somwhere else (eg. machine shutdown)
   535             #self.handleDeviceChangeLock.release()
   536                 
   537 
   538 if __name__ == '__main__':
   539     #man = VMManager.getInstance()
   540     #man.listVM()
   541     #print man.getConnectedRSDs()
   542     #print man.getNetworkDrives()
   543     #man.genNetworkDrive()
   544     drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   545     print list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   546     #print list(map(chr, range(68, 91))) 
   547     
   548     #time.sleep(-1)
   549     #man.listVM()
   550     #man.listVM()
   551     #man.listVM()
   552     #man.listVM()
   553     #man.genCertificateISO('SecurityDVM0')
   554     #man.guestExecute('SecurityDVM0', '/bin/ls -la')
   555     #logger = setupLogger('VMManager')
   556     #c = Cygwin()
   557     
   558     #man.sshExecute('/bin/ls -la', 'SecurityDVM0')
   559     #man.sshExecuteX11('/usr/bin/iceweasel', 'SecurityDVM0')
   560     #man.removeVM('SecurityDVM0')
   561     #man.netUse('192.168.56.134', 'USB\\')
   562     #ip = '192.168.56.139'
   563     
   564     #man.cygwin_path = 'c:\\cygwin64\\bin\\'
   565     #man.handleDeviceChange()
   566     #print man.listSDVM()
   567     #man.configureHostNetworking()
   568     #new_vm = man.generateSDVMName()
   569     #man.createVM(new_vm)
   570     
   571     #print Cygwin.cmd()
   572     #man.isAvailable('c:')
   573     #ip = man.getHostOnlyIP('SecurityDVM0')
   574     #man.mapNetworkDrive('h:', '\\\\' + ip + '\Download', None, None)
   575     
   576     #man.genCertificateISO(new_vm)
   577     #man.attachCertificateISO(new_vm)
   578     
   579     #man.attachCertificateISO(vm_name)
   580     #man.guestExecute(vm_name, "ls")
   581     #man.sshGuestX11Execute('SecurityDVM1', '/usr/bin/iceweasel')
   582     #time.sleep(60)
   583     #print man.cygwinPath("C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\.ssh\*")
   584     #man.genCertificateISO('SecurityDVM')
   585     #man.attachCertificateISO('SecurityDVM')
   586     #man.isStorageAttached('SecurityDVM')
   587     #man.guestExecute('SecurityDVM', 'sudo apt-get -y update')
   588     #man.guestExecute('SecurityDVM', 'sudo apt-get -y upgrade' )
   589     
   590     #man.stopVM('SecurityDVM')
   591     #man.storageDetach('SecurityDVM')
   592     #man.changeStorageType('C:\Users\BarthaM\VirtualBox VMs\SecurityDVM\SecurityDVM.vmdk','immutable')
   593     #man.storageAttach('SecurityDVM')
   594     
   595     
   596     #cmd = "c:\\cygwin64\\bin\\bash.exe --login -c \"/bin/ls\""
   597     #man.execute(cmd)
   598