OpenSecurity/bin/vmmanager.pyw
changeset 176 32c895509a2a
parent 172 3d2812a07881
child 180 444525c7f32c
     1.1 --- a/OpenSecurity/bin/vmmanager.pyw	Mon Jun 02 17:08:11 2014 +0100
     1.2 +++ b/OpenSecurity/bin/vmmanager.pyw	Wed Jun 04 16:42:37 2014 +0100
     1.3 @@ -24,6 +24,7 @@
     1.4  import win32api
     1.5  import win32con
     1.6  import win32security
     1.7 +import win32wnet
     1.8  import urllib
     1.9  import urllib2
    1.10  DEBUG = True
    1.11 @@ -70,6 +71,7 @@
    1.12      _instance = None
    1.13      machineFolder = ''
    1.14      rsdHandler = None
    1.15 +    hostonlyIFs = None
    1.16      browsingManager = None
    1.17      status_message = 'Starting up...'
    1.18  
    1.19 @@ -78,7 +80,7 @@
    1.20  
    1.21          self.systemProperties = self.getSystemProperties()
    1.22          self.machineFolder = self.systemProperties["Default machine folder"]
    1.23 -
    1.24 +        self.hostonlyIFs = self.getHostOnlyIFs()
    1.25          # only proceed if we have a working background environment
    1.26          if self.backend_ok():
    1.27              self.cleanup()
    1.28 @@ -93,6 +95,27 @@
    1.29              VMManager._instance = VMManager()
    1.30          return VMManager._instance
    1.31      
    1.32 +    #list the hostonly IFs exposed by the VBox host
    1.33 +    @staticmethod    
    1.34 +    def getHostOnlyIFs():
    1.35 +        result = Cygwin.vboxExecute('list hostonlyifs')[1]
    1.36 +        if result=='':
    1.37 +            return None
    1.38 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
    1.39 +        return props    
    1.40 +        
    1.41 +    # return hosty system properties
    1.42 +    @staticmethod
    1.43 +    def getSystemProperties():
    1.44 +        result = Cygwin.checkResult(Cygwin.vboxExecute('list systemproperties'))
    1.45 +        if result[1]=='':
    1.46 +            return None
    1.47 +        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    1.48 +        return props
    1.49 +    
    1.50 +    # return the folder containing the guest VMs     
    1.51 +    def getMachineFolder(self):
    1.52 +        return self.machineFolder
    1.53  
    1.54      def backend_ok(self):
    1.55  
    1.56 @@ -145,33 +168,15 @@
    1.57  
    1.58      def cleanup(self):
    1.59          self.stop()
    1.60 -        drives = self.getNetworkDrives()
    1.61 -        for drive in drives.keys():
    1.62 -            try:
    1.63 -                result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+drive).readline()
    1.64 -            except urllib2.URLError:
    1.65 -                logger.info("Network drive disconnect skipped. OpenSecurity Tray client not started yet.")
    1.66 +        ip = self.getHostOnlyIP(None)
    1.67 +        try:
    1.68 +            result = urllib2.urlopen('http://127.0.0.1:8090/netcleanup?'+'hostonly_ip='+ip).readline()
    1.69 +        except urllib2.URLError:
    1.70 +            logger.info("Network drive cleanup all skipped. OpenSecurity Tray client not started yet.")
    1.71              
    1.72 -        #TODO://continue here
    1.73 -        #self.removeSnapshots('SecurityDVM')
    1.74 -        
    1.75          for vm in self.listSDVM():
    1.76              self.poweroffVM(vm)
    1.77              self.removeVM(vm)
    1.78 -        
    1.79 -        
    1.80 -        
    1.81 -    # return hosty system properties
    1.82 -    def getSystemProperties(self):
    1.83 -        result = Cygwin.checkResult(Cygwin.vboxExecute('list systemproperties'))
    1.84 -        if result[1]=='':
    1.85 -            return None
    1.86 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result[1].strip().splitlines()))
    1.87 -        return props
    1.88 -    
    1.89 -    # return the folder containing the guest VMs     
    1.90 -    def getMachineFolder(self):
    1.91 -        return self.machineFolder
    1.92  
    1.93      # list all existing VMs registered with VBox
    1.94      def listVM(self):
    1.95 @@ -474,21 +479,12 @@
    1.96          logger.info('Powering off ' + vm_name)
    1.97          return Cygwin.checkResult(Cygwin.vboxExecute('controlvm ' + vm_name + ' poweroff'))
    1.98      
    1.99 -    #list the hostonly IFs exposed by the VBox host
   1.100 -    @staticmethod    
   1.101 -    def getHostOnlyIFs():
   1.102 -        result = Cygwin.vboxExecute('list hostonlyifs')[1]
   1.103 -        if result=='':
   1.104 -            return None
   1.105 -        props = dict((k.strip(),v.strip().strip('"')) for k,v in (line.split(':', 1) for line in result.strip().splitlines()))
   1.106 -        return props
   1.107 -    
   1.108 -    # return the hostOnly IP for a running guest or the host
   1.109 -    @staticmethod    
   1.110 -    def getHostOnlyIP(vm_name):
   1.111 +    # return the hostOnly IP for a running guest or the host    
   1.112 +    def getHostOnlyIP(self, vm_name):
   1.113          if vm_name == None:
   1.114              logger.info('Getting hostOnly IP address for Host')
   1.115 -            return VMManager.getHostOnlyIFs()['IPAddress']
   1.116 +            #TODO:// optimise to store on init local variable and return that value (avoid calling list hostonlyifs)
   1.117 +            return self.hostonlyIFs['IPAddress']
   1.118          else:
   1.119              logger.info('Getting hostOnly IP address ' + vm_name)
   1.120              result = Cygwin.checkResult(Cygwin.vboxExecute('guestproperty get ' + vm_name + ' /VirtualBox/GuestInfo/Net/0/V4/IP'))
   1.121 @@ -535,7 +531,7 @@
   1.122      # wait for machine to come up
   1.123      def waitStartup(self, vm_name, timeout_ms = 30000):
   1.124          Cygwin.checkResult(Cygwin.vboxExecute('guestproperty wait ' + vm_name + ' SDVMStarted --timeout ' + str(timeout_ms) + ' --fail-on-timeout'))
   1.125 -        return VMManager.getHostOnlyIP(vm_name)
   1.126 +        return self.getHostOnlyIP(vm_name)
   1.127      
   1.128      # wait for machine to shutdown
   1.129      def waitShutdown(self, vm_name):
   1.130 @@ -548,50 +544,29 @@
   1.131          result = Cygwin.checkResult(Cygwin.cmdExecute('dir ' + path + ' | FIND ".."'))
   1.132          return string.find(result[1], 'DIR',)
   1.133      
   1.134 -    def getNetworkDrives(self):
   1.135 -        ip = VMManager.getHostOnlyIP(None)
   1.136 -        ip = ip[:ip.rindex('.')]
   1.137 -        drives = dict()    
   1.138 -        result = Cygwin.checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   1.139 -
   1.140 -        #logger.info( result[1] )
   1.141 -        for line in result[1].splitlines():
   1.142 -            if ip in line:
   1.143 -                parts = line.split()
   1.144 -                drives[parts[1]] = parts[2]
   1.145 -
   1.146 -        return drives
   1.147 -
   1.148 -    def getNetworkDrive(self, vm_name):
   1.149 -        ip = self.getHostOnlyIP(vm_name)
   1.150 -        if ip == None:
   1.151 -            return None
   1.152 -        result = Cygwin.checkResult(Cygwin.execute('C:\\Windows\\system32\\net.exe', 'USE'))
   1.153 -        for line in result[1].splitlines():
   1.154 -            if line != None and ip in line:
   1.155 -                parts = line.split()
   1.156 -                return parts[1]
   1.157 -    
   1.158      def genNetworkDrive(self):
   1.159 -        network_drives = self.getNetworkDrives()
   1.160 -        logger.info("Used network drive letters: "+ str(network_drives.keys()).strip('[]') ) 
   1.161          logical_drives = VMManager.getLogicalDrives()
   1.162          logger.info("Used logical drive letters: "+ str(logical_drives).strip('[]') )
   1.163          drives = list(map(chr, range(68, 91)))  
   1.164          for drive in drives:
   1.165 -            if drive+':' not in network_drives and drive not in logical_drives:
   1.166 -                return drive+':'
   1.167 +            if drive not in logical_drives:
   1.168 +                return drive
   1.169              
   1.170      @staticmethod
   1.171      def getLogicalDrives():
   1.172          drive_bitmask = ctypes.cdll.kernel32.GetLogicalDrives()
   1.173 -        return list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   1.174 +        drives = list(itertools.compress(string.ascii_uppercase,  map(lambda x:ord(x) - ord('0'), bin(drive_bitmask)[:1:-1])))
   1.175 +        return drives
   1.176      
   1.177      @staticmethod
   1.178      def getDriveType(drive):
   1.179          return ctypes.cdll.kernel32.GetDriveTypeW(u"%s:\\"%drive)
   1.180      
   1.181      @staticmethod
   1.182 +    def getNetworkPath(drive):
   1.183 +        return win32wnet.WNetGetConnection(drive+':')
   1.184 +    
   1.185 +    @staticmethod
   1.186      def getVolumeInfo(drive):
   1.187          volumeNameBuffer = ctypes.create_unicode_buffer(1024)
   1.188          fileSystemNameBuffer = ctypes.create_unicode_buffer(1024)
   1.189 @@ -600,7 +575,6 @@
   1.190          file_system_flags = None
   1.191          
   1.192          rc = ctypes.cdll.kernel32.GetVolumeInformationW(
   1.193 -            #ctypes.c_wchar_p("F:\\"),
   1.194              u"%s:\\"%drive,
   1.195              volumeNameBuffer,
   1.196              ctypes.sizeof(volumeNameBuffer),
   1.197 @@ -610,9 +584,38 @@
   1.198              fileSystemNameBuffer,
   1.199              ctypes.sizeof(fileSystemNameBuffer)
   1.200          )
   1.201 -        
   1.202          return volumeNameBuffer.value, fileSystemNameBuffer.value
   1.203      
   1.204 +    def getNetworkDrive(self, vm_name):
   1.205 +        ip = self.getHostOnlyIP(vm_name)
   1.206 +        if ip == None:
   1.207 +            logger.error("Failed getting hostonly IP for " + vm_name)
   1.208 +            return None
   1.209 +        logger.info("Got IP address for " + vm_name + ': ' + ip)
   1.210 +        for drive in VMManager.getLogicalDrives():
   1.211 +            #if is a network drive
   1.212 +            if VMManager.getDriveType(drive) == 4:
   1.213 +                network_path = VMManager.getNetworkPath(drive)
   1.214 +                if ip in network_path:
   1.215 +                    return drive
   1.216 +        return None
   1.217 +    
   1.218 +    def getNetworkDrives(self):
   1.219 +        ip = self.getHostOnlyIP(None)
   1.220 +        if ip == None:
   1.221 +            logger.error("Failed getting hostonly IP for system")
   1.222 +            return None
   1.223 +        logger.info("Got IP address for system: " + ip)
   1.224 +        ip = ip[:ip.rindex('.')]
   1.225 +        network_drives = dict()
   1.226 +        for drive in VMManager.getLogicalDrives():
   1.227 +            #if is a network drive
   1.228 +            if VMManager.getDriveType(drive) == 4:
   1.229 +                network_path = VMManager.getNetworkPath(drive)
   1.230 +                if ip in network_path:
   1.231 +                    network_drives[drive] = network_path  
   1.232 +        return network_drives
   1.233 +    
   1.234      # handles browsing request    
   1.235      def handleBrowsingRequest(self):
   1.236          handler = BrowsingHandler(self)
   1.237 @@ -670,10 +673,6 @@
   1.238      def run(self):
   1.239          #browser = '\\\"/usr/bin/chromium; pidof dbus-launch | xargs kill\\\"'
   1.240          browser = '\\\"/usr/bin/chromium\\\"'
   1.241 -        #if not Cygwin.is_X11_running():
   1.242 -        #    self.vmm.browsingManager.restart.set()
   1.243 -        #    return
   1.244 -        
   1.245          try:
   1.246              self.vmm.browsingManager.started.wait() 
   1.247              result = Cygwin.checkResult(Cygwin.sshExecuteX11(browser, self.vmm.browsingManager.ip_addr, 'osecuser', Cygwin.cygPath(self.vmm.getMachineFolder()) + '/' + self.vmm.browsingManager.vm_name + '/dvm_key'))
   1.248 @@ -691,7 +690,7 @@
   1.249      restart = None
   1.250      ip_addr = None
   1.251      vm_name = None
   1.252 -    drive = None
   1.253 +    net_resource = None
   1.254      appDataDir = None
   1.255      
   1.256      def __init__(self, vmmanager):
   1.257 @@ -709,14 +708,14 @@
   1.258              self.restart.clear()
   1.259              self.started.clear()
   1.260              
   1.261 -            if self.drive == None:
   1.262 -                logger.info("Missing browsing SDVM's network drive letter. Skipping disconnect")
   1.263 +            if self.net_resource == None:
   1.264 +                logger.info("Missing browsing SDVM's network share. Skipping disconnect")
   1.265              else:
   1.266                  try:
   1.267 -                    browsing_vm = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+self.drive).readline()
   1.268 -                    self.drive = None
   1.269 +                    browsing_vm = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'net_resource='+self.net_resource).readline()
   1.270 +                    self.net_resource = None
   1.271                  except urllib2.URLError:
   1.272 -                    logger.error("Network drive disconnect failed. OpenSecurity Tray client not running.")
   1.273 +                    logger.error("Network share disconnect failed. OpenSecurity Tray client not running.")
   1.274                      continue
   1.275              
   1.276              self.ip_addr = None
   1.277 @@ -738,19 +737,12 @@
   1.278                  else:
   1.279                      logger.info("Got IP address for " + self.vm_name + ' ' + self.ip_addr)
   1.280                  
   1.281 -                self.drive = self.vmm.genNetworkDrive()
   1.282 -                if self.drive == None:
   1.283 -                    logger.error("Failed to assign Network drive letter")
   1.284 -                    continue
   1.285 -                else:
   1.286 -                    logger.info("Assigned drive " + self.drive + " to " + self.vm_name)
   1.287 -                
   1.288                  try:
   1.289 -                    net_resource = '\\\\' + self.ip_addr + '\\Download'
   1.290 -                    result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'drive_letter='+self.drive+'&net_resource='+net_resource).readline()
   1.291 +                    self.net_resource = '\\\\' + self.ip_addr + '\\Download'
   1.292 +                    result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'net_resource='+self.net_resource).readline()
   1.293                  except urllib2.URLError:
   1.294                      logger.error("Network drive connect failed. OpenSecurity Tray client not running.")
   1.295 -                    self.drive = None
   1.296 +                    self.net_resource = None
   1.297                      continue
   1.298                  
   1.299                  user = self.vmm.getActiveUserName()
   1.300 @@ -802,19 +794,27 @@
   1.301          self.running = False
   1.302          
   1.303      def run(self):
   1.304 -        self.existingRSDs = self.vmm.getExistingRSDs()
   1.305 +        
   1.306 +        self.existingRSDs = dict()
   1.307          self.attachedRSDs = self.vmm.getAttachedRSDs()
   1.308          
   1.309          while self.running:
   1.310              tmp_rsds = self.vmm.getExistingRSDs()
   1.311 +            if tmp_rsds.keys() == self.existingRSDs.keys():
   1.312 +                logger.debug("Nothing's changed. sleep(3)")
   1.313 +                time.sleep(3)
   1.314 +                continue
   1.315 +            
   1.316 +            logger.info("Something's changed")     
   1.317              for vm_name in self.attachedRSDs.keys():
   1.318                  if self.attachedRSDs[vm_name] not in tmp_rsds.values():
   1.319 -                    drive = self.vmm.getNetworkDrive(vm_name)
   1.320 +                    ip = self.vmm.getHostOnlyIP(vm_name)
   1.321 +                    if ip == None:
   1.322 +                        logger.error("Failed getting hostonly IP for " + vm_name)
   1.323 +                        continue
   1.324                      try:
   1.325 -                        if drive != None:
   1.326 -                            result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'drive_letter='+drive).readline()
   1.327 -                        else:
   1.328 -                            logger.error("Error getting SDVM's network drive letter.")
   1.329 +                        net_resource = '\\\\' + ip + '\\USB'
   1.330 +                        result = urllib2.urlopen('http://127.0.0.1:8090/netumount?'+'net_resource='+net_resource).readline()
   1.331                      except urllib2.URLError:
   1.332                          logger.error("Network drive disconnect failed. OpenSecurity Tray client not running.")
   1.333                          continue
   1.334 @@ -824,22 +824,11 @@
   1.335                      del self.attachedRSDs[vm_name]
   1.336                      self.vmm.poweroffVM(vm_name)
   1.337                      self.vmm.removeVM(vm_name)
   1.338 -                    break
   1.339 +                    #break
   1.340                      
   1.341 -            if tmp_rsds.keys() == self.existingRSDs.keys():
   1.342 -                logger.debug("Nothing's changed. sleep(3)")
   1.343 -                time.sleep(3)
   1.344 -                continue
   1.345 -            
   1.346 -            logger.info("Something's changed")          
   1.347 -            self.existingRSDs = tmp_rsds
   1.348 -           
   1.349 -            #create new vm for attached device if any
   1.350 -            #self.attachedRSDs = self.vmm.getAttachedRSDs()
   1.351 -            #self.connectedRSDs = self.vmm.getExistingRSDs()
   1.352 -            
   1.353 +            #create new vms for new devices if any
   1.354              new_ip = None
   1.355 -            for new_device in self.existingRSDs.values():
   1.356 +            for new_device in tmp_rsds.values():
   1.357                  if (self.attachedRSDs and False) or (new_device not in self.attachedRSDs.values()):
   1.358                      new_sdvm = self.vmm.newSDVM()
   1.359                      self.vmm.storageAttach(new_sdvm)
   1.360 @@ -860,18 +849,16 @@
   1.361                          self.vmm.poweroffVM(new_sdvm)
   1.362                          self.vmm.removeVM(new_sdvm)
   1.363                          continue
   1.364 -                    drive = self.vmm.genNetworkDrive()
   1.365 -                    if drive == None:
   1.366 -                        logger.error("Error getting drive letter for network drive.")
   1.367 -                        continue
   1.368                      try:
   1.369                          net_resource = '\\\\' + new_ip + '\\USB'
   1.370 -                        result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'drive_letter='+drive+'&net_resource='+net_resource).readline()
   1.371 +                        result = urllib2.urlopen('http://127.0.0.1:8090/netmount?'+'net_resource='+net_resource).readline()
   1.372                      except urllib2.URLError:
   1.373                          logger.error("Network drive connect failed (tray client not accessible). Cleaning up.")
   1.374                          self.vmm.poweroffVM(new_sdvm)
   1.375                          self.vmm.removeVM(new_sdvm)
   1.376                          continue
   1.377 +                    
   1.378 +            self.existingRSDs = tmp_rsds
   1.379                          
   1.380  
   1.381  if __name__ == '__main__':
   1.382 @@ -891,6 +878,7 @@
   1.383      print drives
   1.384      print VMManager.getDriveType("E")
   1.385      print VMManager.getVolumeInfo("E")
   1.386 +    print VMManager.getNetworkPath("E")
   1.387      
   1.388      #vmm.backupFile()
   1.389      #for device in devices.values():