def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = OneMachineConfig(sb_cfg, 'Machine') self.asscfg = AssignmentConfig(sb_cfg) self.one_server = self.machinecfg.get_one_server() self.one_credentials = self.machinecfg.get_one_credentials() self.vm_id = int(self.machinecfg.get_one_vm_id()) self.one_vm_hostname = self.machinecfg.get_one_vm_hostname() self.vm_username = self.machinecfg.guest_user() self.snapshot_id = 0 # we cannot use the revert mechanism from outside assert (False == self.asscfg.revert_to_snapshot('Assignment'))
def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = OneMachineConfig(sb_cfg, 'Machine') self.asscfg = AssignmentConfig(sb_cfg) self.one_server = self.machinecfg.get_one_server() self.one_credentials = self.machinecfg.get_one_credentials() self.vm_id = int(self.machinecfg.get_one_vm_id()) self.one_vm_hostname = self.machinecfg.get_one_vm_hostname() self.vm_username = self.machinecfg.guest_user() self.snapshot_id = 0 # we cannot use the revert mechanism from outside assert(False == self.asscfg.revert_to_snapshot('Assignment'))
def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = VmwareMachineConfig(sb_cfg, 'Machine') self.vmwarecfg = VmwareConfig(sb_cfg, 'Tester') self.asscfg = AssignmentConfig(config = sb_cfg) self.testercfg = TesterConfig(config = sb_cfg) self.vmx_path = self.machinecfg.get_vmx_path() if self.vmx_path == None: self.vmx_path = self.get_submission_vmx_file() if self.vmx_path == None: # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) vmx_prefix = self.testercfg.vm_store_path('Tester') if vmx_prefix is not None: self.vmx_path = os.path.join(vmx_prefix, self.vmx_path) try: if self.vmwarecfg.vmware_type() == 3: self.vmhost = pyvix.vix.Host() elif self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: self.vmhost = pyvix.vix.Host(self.vmwarecfg.vmware_type(), self.vmwarecfg.vmware_url(), int(self.vmwarecfg.vmware_port()), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password()) except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Connecting to the host Vmware services failed.\n' sys.exit(1) if self.vmwarecfg.vmware_register_and_unregister(): self.vmhost.registerVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) vmx_path = self.vmx_path if not os.path.isfile(vmx_path): vmx_path = self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path) if not os.path.isfile(vmx_path): # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) try: self.vminstance = self.vmhost.openVM(vmx_path) except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to open the .vmx file..\n' sys.exit(1)
class VmWareVM(VM): vmhost = None vminstance = None def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = VmwareMachineConfig(sb_cfg, 'Machine') self.vmwarecfg = VmwareConfig(sb_cfg, 'Tester') self.asscfg = AssignmentConfig(config = sb_cfg) self.testercfg = TesterConfig(config = sb_cfg) self.vmx_path = self.machinecfg.get_vmx_path() if self.vmx_path == None: self.vmx_path = self.get_submission_vmx_file() if self.vmx_path == None: # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) vmx_prefix = self.testercfg.vm_store_path('Tester') if vmx_prefix is not None: self.vmx_path = os.path.join(vmx_prefix, self.vmx_path) try: if self.vmwarecfg.vmware_type() == 3: self.vmhost = pyvix.vix.Host() elif self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: self.vmhost = pyvix.vix.Host(self.vmwarecfg.vmware_type(), self.vmwarecfg.vmware_url(), int(self.vmwarecfg.vmware_port()), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password()) except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Connecting to the host Vmware services failed.\n' sys.exit(1) if self.vmwarecfg.vmware_register_and_unregister(): self.vmhost.registerVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) vmx_path = self.vmx_path if not os.path.isfile(vmx_path): vmx_path = self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path) if not os.path.isfile(vmx_path): # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) try: self.vminstance = self.vmhost.openVM(vmx_path) except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to open the .vmx file..\n' sys.exit(1) def executeCommand(self,cmd): return self.vminstance.runProgramInGuest(self.shell,'--login -c "'+cmd+'"') def start(self): self.vminstance.powerOn() def stop(self): try: self.vminstance.powerOff() except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) if self.vmwarecfg.vmware_register_and_unregister(): try: self.vmhost.unregisterVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) def _wait_for_tools(self): """Called by the thread that waits for the VMWare Tools to start. If the Tools do not start, there is no direct way of ending the Thread. As a result, on powerOff(), the Thread would throw a VIXException on account of the VM not being powered on. """ try: self.vminstance.waitForToolsInGuest() except pyvix.vix.VIXException: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) def wait_for_tools_with_timeout(self, timeout, error_fname): """Wait for VMWare Tools to start. Returns True on success and False when the VMWare tools did not start properly in the given timeout. Writes error messages to `error_fname`. """ if timeout > 0: _logger.info('Waiting for VMWare Tools with a timeout of %d seconds' % timeout) tools_thd = Thread(target = self._wait_for_tools) tools_thd.start() # normally the thread will end before the timeout expires, so a high timeout tools_thd.join(timeout) if not tools_thd.isAlive(): return True _logger.error('Timeout waiting for VMWare Tools to start.' + 'Make sure your virtual machine boots up corectly' + 'and that you have VMWare Tools installed.') with open(error_fname, 'a') as handler: print >> handler, 'Timeout waiting for VMWare Tools to start.\n' + \ 'Make sure your virtual machine boots up corectly\n' + \ 'and that you have VMWare Tools installed.\n' return False def powerOn(self): """ see power_on_with_message_handler """ power_thd = Thread(target = self.start) power_thd.start() if self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: # VMWARE_SERVER or VMWARE_VI_SERVER # Wait for the VM to powr on in case it hangs on a message power_thd.join(VMWARE_VM_POWERON_TIMEOUT) if not power_thd.isAlive(): # vm.powerOn() didn't hang: the machine has been powered on return # Run the message handler proc = Popen(['vmchecker-message-handler', self.vmwarecfg.vmware_hostname(), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password(), self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)]) os.waitpid(proc.pid, 0) # Wait for the VM to power on again power_thd.join(VMWARE_VM_POWERON_TIMEOUT) if not power_thd.isAlive(): # vm.powerOn() didn't hang: the machine has been powered on return _logger.error('Powering on VM timed out') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Timed out while powering on.\n' sys.exit(1) else: # VMWARE_WORKSTATION # Just wait until the VM has powered on power_thd.join() def try_power_on_vm_and_login(self, revertSnapshot=None): if revertSnapshot == True or \ (revertSnapshot == None and self.asscfg.revert_to_snapshot('Assignment')): self.revert(self.vminstance.nRootSnapshots - 1) tools_timeout = self.asscfg.delay_wait_for_tools('Assignment') self.powerOn() if not self.wait_for_tools_with_timeout(tools_timeout, self.error_fname): # no tools, nothing to do. return False try: self.vminstance.loginInGuest(self.machinecfg.guest_user(), self.machinecfg.guest_pass()) except pyvix.vix.VIXSecurityException: _logger.error('Error logging in on the virtual machine.' + 'Make sure you have the accounts properly configured.') with open(error_fname, 'a') as handler: print >> handler,'Error logging in on the virtual machine.\n' + \ 'Make sure you have the user accounts properly configured.\n' return False time.sleep(self.asscfg.delay_between_tools_and_tests('Assignment')) return True def revert(self, number = None): """Revert the vminstance to the number snapshot Note: snapshots are counted from 0. """ if number==None: _logger.error('Snapshot number is needed') return if self.vminstance.nRootSnapshots <= number: err_str = ('Cannot revert to snapshot %d. Too few ' + 'snapshots (nr = %d) found on %s.' % (number, self.vminstance.nRootSnapshots, self.vminstance.vmxPath)) raise Exception(err_str) snaps = self.vminstance.rootSnapshots try: self.vminstance.revertToSnapshot(snaps[number]) except: _logger.error('Could not revert to snapshot') def copyTo(self, sourceDir, targetDir, files): """ Copy files from host(source) to guest(target) """ for f in files: host_path = os.path.join(sourceDir, f) guest_path = targetDir + f if not os.path.exists(host_path): _logger.error('host file (to send) "%s" does not exist' % host_path) return _logger.info('copy file %s from host to guest at %s' % (host_path, guest_path)) self.vminstance.copyFileFromHostToGuest(host_path, guest_path) def copyFrom(self, sourceDir, targetDir, files): """ Copy files from guest(source) to host(target) """ for f in files: host_path = os.path.join(targetDir, f) guest_path = sourceDir + f _logger.info('copy file %s from guest to host at %s' % (guest_path, host_path)) self.vminstance.copyFileFromGuestToHost(guest_path, host_path) if not os.path.exists(host_path): _logger.error('host file (received) "%s" does not exist' % host_path) def run(self, shell, executable_file, timeout): args = ' --login -c ' + '"chmod +x ' + executable_file + '; ' + executable_file + '"' self.executeCommand("chmod +x "+ executable_file) _logger.info('executing on the remote: prog=%s args=[%s] timeout=%d' % (shell, executable_file, timeout)) thd = Thread(target = self.vminstance.runProgramInGuest, args = (shell,args)) thd.start() thd.join(timeout) return thd.isAlive() def get_submission_vmx_file(self): """Unzip search the bundle_dir and locate the .vmx file, no matter in what sub-folders it is located in. If the unzipped archive has multiple .vmx files, just pick the first. """ for (root, _, files) in os.walk(self.bundle_dir): for f in files: if f.endswith(".vmx"): return os.path.join(root, f) return None def hasStarted(self): return self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_TOOLS_RUNNING != 0 def hasStopped(self): return self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_POWERED_OFF != 0
def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = VmwareMachineConfig(sb_cfg, 'Machine') self.vmwarecfg = VmwareConfig(sb_cfg, 'Tester') self.asscfg = AssignmentConfig(config = sb_cfg) self.testercfg = TesterConfig(config = sb_cfg) self.vmx_path = self.machinecfg.get_vmx_path() if self.vmx_path == None: self.vmx_path = self.get_submission_vmx_file() if self.vmx_path == None: # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) vmx_prefix = self.testercfg.vm_store_path('Tester') if vmx_prefix is not None: self.vmx_path = os.path.join(vmx_prefix, self.vmx_path) try: if self.vmwarecfg.vmware_type() == 3: self.vmhost = pyvix.vix.Host() elif self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: self.vmhost = pyvix.vix.Host(self.vmwarecfg.vmware_type(), self.vmwarecfg.vmware_url(), int(self.vmwarecfg.vmware_port()), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password()) except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Connecting to the host Vmware services failed.\n' sys.exit(1) if self.vmwarecfg.vmware_register_and_unregister(): self.vmhost.registerVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) vmx_path = self.vmx_path if not os.path.isfile(vmx_path): vmx_path = self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path) if not os.path.isfile(vmx_path): # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) try: self.vminstance = self.vmhost.openVM(vmx_path) except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to open the .vmx file..\n' sys.exit(1)
class VmWareVM(VM): vmhost = None vminstance = None def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = VmwareMachineConfig(sb_cfg, 'Machine') self.vmwarecfg = VmwareConfig(sb_cfg, 'Tester') self.asscfg = AssignmentConfig(config = sb_cfg) self.testercfg = TesterConfig(config = sb_cfg) self.vmx_path = self.machinecfg.get_vmx_path() if self.vmx_path == None: self.vmx_path = self.get_submission_vmx_file() if self.vmx_path == None: # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) vmx_prefix = self.testercfg.vm_store_path('Tester') if vmx_prefix is not None: self.vmx_path = os.path.join(vmx_prefix, self.vmx_path) try: if self.vmwarecfg.vmware_type() == 3: self.vmhost = pyvix.vix.Host() elif self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: self.vmhost = pyvix.vix.Host(self.vmwarecfg.vmware_type(), self.vmwarecfg.vmware_url(), int(self.vmwarecfg.vmware_port()), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password()) except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Connecting to the host Vmware services failed.\n' sys.exit(1) if self.vmwarecfg.vmware_register_and_unregister(): self.vmhost.registerVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) vmx_path = self.vmx_path if not os.path.isfile(vmx_path): vmx_path = self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path) if not os.path.isfile(vmx_path): # no vmx, nothing to do. _logger.error('Could not find a vmx to run') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to find .vmx file.\n' sys.exit(1) try: self.vminstance = self.vmhost.openVM(vmx_path) except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Unable to open the .vmx file..\n' sys.exit(1) def executeCommand(self,cmd): return self.vminstance.runProgramInGuest(self.shell,'--login -c "'+cmd+'"') def start(self): self.vminstance.powerOn() def stop(self): try: self.vminstance.powerOff() except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) if self.vmwarecfg.vmware_register_and_unregister(): try: self.vmhost.unregisterVM(self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)) except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) def _wait_for_tools(self): """Called by the thread that waits for the VMWare Tools to start. If the Tools do not start, there is no direct way of ending the Thread. As a result, on powerOff(), the Thread would throw a VIXException on account of the VM not being powered on. """ try: self.vminstance.waitForToolsInGuest() except pyvix.vix.VIXException as e: _logger.exception('Exception thrown: ' + type(e).__name__ + "\n" + ", ".join(e.args) + "\n" + e.__str__()) def wait_for_tools_with_timeout(self, timeout, error_fname): """Wait for VMWare Tools to start. Returns True on success and False when the VMWare tools did not start properly in the given timeout. Writes error messages to `error_fname`. """ if timeout > 0: _logger.info('Waiting for VMWare Tools with a timeout of %d seconds' % timeout) tools_thd = Thread(target = self._wait_for_tools) tools_thd.start() # normally the thread will end before the timeout expires, so a high timeout tools_thd.join(timeout) if not tools_thd.isAlive(): return True _logger.error('Timeout waiting for VMWare Tools to start. ' + 'Make sure your virtual machine boots up correctly ' + 'and that you have VMWare Tools installed.') with open(error_fname, 'a') as handler: print >> handler, 'Timeout waiting for VMWare Tools to start.\n' + \ 'Make sure your virtual machine boots up corectly\n' + \ 'and that you have VMWare Tools installed.\n' return False def powerOn(self): """ see power_on_with_message_handler """ power_thd = Thread(target = self.start) power_thd.start() if self.vmwarecfg.vmware_type() == 2 or \ self.vmwarecfg.vmware_type() == 10: # VMWARE_SERVER or VMWARE_VI_SERVER # Wait for the VM to powr on in case it hangs on a message power_thd.join(VMWARE_VM_POWERON_TIMEOUT) if not power_thd.isAlive(): # vm.powerOn() didn't hang: the machine has been powered on return # Run the message handler proc = Popen(['vmchecker-message-handler', self.vmwarecfg.vmware_hostname(), self.vmwarecfg.vmware_username(), self.vmwarecfg.vmware_password(), self.vmwarecfg.vmware_rel_vmx_path(self.vmx_path)]) os.waitpid(proc.pid, 0) # Wait for the VM to power on again power_thd.join(VMWARE_VM_POWERON_TIMEOUT) if not power_thd.isAlive(): # vm.powerOn() didn't hang: the machine has been powered on return _logger.error('Powering on VM timed out') with open(self.error_fname, 'a') as handler: print >> handler, 'Error powering on the virtual machine.\n' + \ 'Timed out while powering on.\n' sys.exit(1) else: # VMWARE_WORKSTATION # Just wait until the VM has powered on power_thd.join() def try_power_on_vm_and_login(self, revertSnapshot=None): if revertSnapshot == True or \ (revertSnapshot == None and self.asscfg.revert_to_snapshot('Assignment')): self.revert(self.vminstance.nRootSnapshots - 1) tools_timeout = self.asscfg.delay_wait_for_tools('Assignment') self.powerOn() if not self.wait_for_tools_with_timeout(tools_timeout, self.error_fname): # no tools, nothing to do. return False try: self.vminstance.loginInGuest(self.machinecfg.guest_user(), self.machinecfg.guest_pass()) except pyvix.vix.VIXSecurityException: _logger.error('Error logging in on the virtual machine.' + 'Make sure you have the accounts properly configured.') with open(error_fname, 'a') as handler: print >> handler,'Error logging in on the virtual machine.\n' + \ 'Make sure you have the user accounts properly configured.\n' return False time.sleep(self.asscfg.delay_between_tools_and_tests('Assignment')) return True def revert(self, number = None): """Revert the vminstance to the number snapshot Note: snapshots are counted from 0. """ if number==None: _logger.error('Snapshot number is needed') return if self.vminstance.nRootSnapshots <= number: err_str = ('Cannot revert to snapshot %d. Too few ' + 'snapshots (nr = %d) found on %s.' % (number, self.vminstance.nRootSnapshots, self.vminstance.vmxPath)) raise Exception(err_str) snaps = self.vminstance.rootSnapshots try: self.vminstance.revertToSnapshot(snaps[number]) except: _logger.error('Could not revert to snapshot') def copyTo(self, sourceDir, targetDir, files): """ Copy files from host(source) to guest(target) """ if self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_TOOLS_RUNNING == 0: return for f in files: host_path = os.path.join(sourceDir, f) guest_path = targetDir + f if not os.path.exists(host_path): _logger.error('host file (to send) "%s" does not exist' % host_path) return _logger.info('copy file %s from host to guest at %s' % (host_path, guest_path)) self.vminstance.copyFileFromHostToGuest(host_path, guest_path) def copyFrom(self, sourceDir, targetDir, files): """ Copy files from guest(source) to host(target) """ if self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_TOOLS_RUNNING == 0: return for f in files: host_path = os.path.join(targetDir, f) guest_path = sourceDir + f _logger.info('copy file %s from guest to host at %s' % (guest_path, host_path)) self.vminstance.copyFileFromGuestToHost(guest_path, host_path) if not os.path.exists(host_path): _logger.error('host file (received) "%s" does not exist' % host_path) def run(self, shell, executable_file, timeout): args = ' --login -c ' + '"chmod +x ' + executable_file + '; ' + executable_file + '"' self.executeCommand("chmod +x "+ executable_file) _logger.info('executing on the remote: prog=%s args=[%s] timeout=%d' % (shell, executable_file, timeout)) thd = Thread(target = self.vminstance.runProgramInGuest, args = (shell,args)) thd.start() thd.join(timeout) return thd.isAlive() def get_submission_vmx_file(self): """Unzip search the bundle_dir and locate the .vmx file, no matter in what sub-folders it is located in. If the unzipped archive has multiple .vmx files, just pick the first. """ for (root, _, files) in os.walk(self.bundle_dir): for f in files: if f.endswith(".vmx"): return os.path.join(root, f) return None def hasStarted(self): return self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_TOOLS_RUNNING != 0 def hasStopped(self): return self.vminstance[VIX_PROPERTY_VM_POWER_STATE] & VIX_POWERSTATE_POWERED_OFF != 0
class OneVM(VM): # this module works with the assumtipon that there is a snapshot that we can use # start means resume to snapshot # stop means resume to snapshot # resume means resume (but) it should not be used from outside # start and stop operations are blocking (i.e. we wait for the machine to # be up again) def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = OneMachineConfig(sb_cfg, 'Machine') self.asscfg = AssignmentConfig(sb_cfg) self.one_server = self.machinecfg.get_one_server() self.one_credentials = self.machinecfg.get_one_credentials() self.vm_id = int(self.machinecfg.get_one_vm_id()) self.one_vm_hostname = self.machinecfg.get_one_vm_hostname() self.vm_username = self.machinecfg.guest_user() self.snapshot_id = 0 # we cannot use the revert mechanism from outside assert(False == self.asscfg.revert_to_snapshot('Assignment')) def start(self): # assume that the vm has been already suspended in a good state _logger.info("starting vm %d" % self.vm_id) self.revert(self.snapshot_id) while not self.hasStarted(): time.sleep(1) _logger.info("start wait for %d" % self.vm_id) def stop(self): # cleanup the work (do not suspend) _logger.info("stopping vm %d" % self.vm_id) self.revert(self.snapshot_id) while not self.hasStarted(): time.sleep(1) _logger.info("stop wait for %d" % self.vm_id) def hasStarted(self): state, state_ext = self._get_state() if state == 3 and state_ext == 3: return True return False def executeCommand(self, cmd): _logger.debug("execute on vm %d: %s" % \ (self.vm_id, cmd)) client = self._create_ssh_connection() try: # this doesn't waits for the commands (I think) stdin, stdout, stderr = client.exec_command(cmd) stdin.close() stdout.close() stderr.close() finally: client.close() def revert(self, number = None): if not number: number = self.snapshot_id _logger.info("doing revert to snapshot id %d" % number) REVERT_TIMEOUT = 300 cnt = 0 while not self.hasStarted() and cnt < REVERT_TIMEOUT: cnt += 1 time.sleep(1) _logger.info("revert wait for %d" % self.vm_id) if cnt == REVERT_TIMEOUT: _logger.warning("probably failing") self._rpc('one.vm.snapshotrevert', self.vm_id, number) def copyTo(self, sourceDir, targetDir, files): _logger.info("copy to vm %d, %s->%s (%s)" % \ (self.vm_id, sourceDir, targetDir, files)) t, sftp = self._create_sftp_connection_to_vm() try: for f in files: src_f = os.path.join(sourceDir, f) # assume remote path delim == host path delim dst_f = os.path.join(targetDir, f) sftp.put(src_f, dst_f, confirm=True) finally: t.close() def copyFrom(self, sourceDir, targetDir, files): _logger.info("copy from vm %d, %s->%s (%s)" % \ (self.vm_id, sourceDir, targetDir, files)) t, sftp = self._create_sftp_connection_to_vm() try: for f in files: src_f = os.path.join(sourceDir, f) # assume remote path delim == host path delim dst_f = os.path.join(targetDir, f) sftp.get(src_f, dst_f) finally: t.close() def run(self, shell, executable_file, timeout): _logger.info("run on vm %d: %s %s" % \ (self.vm_id, shell, executable_file)) cmd = shell+' '+executable_file+' '+str(timeout) client = self._create_ssh_connection() try: stdin, stdout, stderr = client.exec_command(cmd) while timeout > 0 and not stdout.channel.exit_status_ready(): time.sleep(1) timeout -= 1 _logger.debug('wait for cmd to finish: [%s]' % cmd) stdin.close() stdout.close() stderr.close() finally: client.close() def _create_ssh_connection(self): client = paramiko.SSHClient() try: # XXX: we should use a more strict policy client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(self.one_vm_hostname, username=self.vm_username) except: client.close() raise return client def _create_sftp_connection_to_vm(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip = socket.gethostbyname(self.one_vm_hostname) sock.connect((ip, 22)) t = paramiko.Transport(sock) try: t.start_client() sftp = None key = paramiko.RSAKey.from_private_key_file(\ os.path.join(os.environ['HOME'], '.ssh/id_rsa')) t.auth_publickey(self.vm_username, key) sftp = paramiko.SFTPClient.from_transport(t) except: t.close() t = None sftp = None raise return (t, sftp) def _get_state(self): # http://docs.opennebula.org/4.4/integration/system_interfaces/api.html#one-vm-info # INIT = 0 # PENDING = 1 # HOLD = 2 # ACTIVE = 3 # STOPPED = 4 # SUSPENDED = 5 # DONE = 6 # FAILED = 7 # POWEROFF = 8 # UNDEPLOYED = 9 #LCM_INIT = 0, #PROLOG = 1, #BOOT = 2, #RUNNING = 3, #MIGRATE = 4, #SAVE_STOP = 5, #SAVE_SUSPEND = 6, #SAVE_MIGRATE = 7, #PROLOG_MIGRATE = 8, #PROLOG_RESUME = 9, #EPILOG_STOP = 10, #EPILOG = 11, #SHUTDOWN = 12, #CANCEL = 13, #FAILURE = 14, #CLEANUP_RESUBMIT = 15, #UNKNOWN = 16, #HOTPLUG = 17, #SHUTDOWN_POWEROFF = 18, #BOOT_UNKNOWN = 19, #BOOT_POWEROFF = 20, #BOOT_SUSPENDED = 21, #BOOT_STOPPED = 22, #CLEANUP_DELETE = 23, #HOTPLUG_SNAPSHOT = 24, #HOTPLUG_NIC = 25, #HOTPLUG_SAVEAS = 26, #HOTPLUG_SAVEAS_POWEROFF = 27, #HOTPLUG_SAVEAS_SUSPENDED = 28, #SHUTDOWN_UNDEPLOY = 29, #EPILOG_UNDEPLOY = 30, #PROLOG_UNDEPLOY = 31, #BOOT_UNDEPLOY = 32 _, info, _ = self._rpc('one.vm.info', self.vm_id) xmldoc = minidom.parseString(info) state = int(xmldoc.getElementsByTagName('STATE')[0].firstChild.nodeValue) state_ext = int(xmldoc.getElementsByTagName('LCM_STATE')[0].firstChild.nodeValue) if state != 3: state_ext = None _logger.debug("state form vm %d is (%s:%s)" % (self.vm_id, state, state_ext)) return (state, state_ext) def _get_proxy(self): return xmlrpclib.ServerProxy(self.one_server) def _rpc(self, *kargs): p = self._get_proxy() method = getattr(p, kargs[0]) ret = method(self.one_credentials, *kargs[1:]) #_logger.debug("%s" % str(ret)) if not ret[0]: raise OneVMException("One RPC: %s" % ret[1]) return ret
class OneVM(VM): # this module works with the assumtipon that there is a snapshot that we can use # start means resume to snapshot # stop means resume to snapshot # resume means resume (but) it should not be used from outside # start and stop operations are blocking (i.e. we wait for the machine to # be up again) def __init__(self, host, bundle_dir, sb_cfg): VM.__init__(self, host, bundle_dir, sb_cfg) self.machinecfg = OneMachineConfig(sb_cfg, 'Machine') self.asscfg = AssignmentConfig(sb_cfg) self.one_server = self.machinecfg.get_one_server() self.one_credentials = self.machinecfg.get_one_credentials() self.vm_id = int(self.machinecfg.get_one_vm_id()) self.one_vm_hostname = self.machinecfg.get_one_vm_hostname() self.vm_username = self.machinecfg.guest_user() self.snapshot_id = 0 # we cannot use the revert mechanism from outside assert (False == self.asscfg.revert_to_snapshot('Assignment')) def start(self): # assume that the vm has been already suspended in a good state _logger.info("starting vm %d" % self.vm_id) self.revert(self.snapshot_id) while not self.hasStarted(): time.sleep(1) _logger.info("start wait for %d" % self.vm_id) def stop(self): # cleanup the work (do not suspend) _logger.info("stopping vm %d" % self.vm_id) self.revert(self.snapshot_id) while not self.hasStarted(): time.sleep(1) _logger.info("stop wait for %d" % self.vm_id) def hasStarted(self): state, state_ext = self._get_state() if state == 3 and state_ext == 3: return True return False def executeCommand(self, cmd): _logger.debug("execute on vm %d: %s" % \ (self.vm_id, cmd)) client = self._create_ssh_connection() try: # this doesn't waits for the commands (I think) stdin, stdout, stderr = client.exec_command(cmd) stdin.close() stdout.close() stderr.close() finally: client.close() def revert(self, number=None): if not number: number = self.snapshot_id _logger.info("doing revert to snapshot id %d" % number) REVERT_TIMEOUT = 300 cnt = 0 while not self.hasStarted() and cnt < REVERT_TIMEOUT: cnt += 1 time.sleep(1) _logger.info("revert wait for %d" % self.vm_id) if cnt == REVERT_TIMEOUT: _logger.warning("probably failing") self._rpc('one.vm.snapshotrevert', self.vm_id, number) def copyTo(self, sourceDir, targetDir, files): _logger.info("copy to vm %d, %s->%s (%s)" % \ (self.vm_id, sourceDir, targetDir, files)) t, sftp = self._create_sftp_connection_to_vm() try: for f in files: src_f = os.path.join(sourceDir, f) # assume remote path delim == host path delim dst_f = os.path.join(targetDir, f) sftp.put(src_f, dst_f, confirm=True) finally: t.close() def copyFrom(self, sourceDir, targetDir, files): _logger.info("copy from vm %d, %s->%s (%s)" % \ (self.vm_id, sourceDir, targetDir, files)) t, sftp = self._create_sftp_connection_to_vm() try: for f in files: src_f = os.path.join(sourceDir, f) # assume remote path delim == host path delim dst_f = os.path.join(targetDir, f) sftp.get(src_f, dst_f) finally: t.close() def run(self, shell, executable_file, timeout): _logger.info("run on vm %d: %s %s" % \ (self.vm_id, shell, executable_file)) cmd = shell + ' ' + executable_file + ' ' + str(timeout) client = self._create_ssh_connection() try: stdin, stdout, stderr = client.exec_command(cmd) while timeout > 0 and not stdout.channel.exit_status_ready(): time.sleep(1) timeout -= 1 _logger.debug('wait for cmd to finish: [%s]' % cmd) stdin.close() stdout.close() stderr.close() finally: client.close() def _create_ssh_connection(self): client = paramiko.SSHClient() try: # XXX: we should use a more strict policy client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(self.one_vm_hostname, username=self.vm_username) except: client.close() raise return client def _create_sftp_connection_to_vm(self): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ip = socket.gethostbyname(self.one_vm_hostname) sock.connect((ip, 22)) t = paramiko.Transport(sock) try: t.start_client() sftp = None key = paramiko.RSAKey.from_private_key_file(\ os.path.join(os.environ['HOME'], '.ssh/id_rsa')) t.auth_publickey(self.vm_username, key) sftp = paramiko.SFTPClient.from_transport(t) except: t.close() t = None sftp = None raise return (t, sftp) def _get_state(self): # http://docs.opennebula.org/4.4/integration/system_interfaces/api.html#one-vm-info # INIT = 0 # PENDING = 1 # HOLD = 2 # ACTIVE = 3 # STOPPED = 4 # SUSPENDED = 5 # DONE = 6 # FAILED = 7 # POWEROFF = 8 # UNDEPLOYED = 9 #LCM_INIT = 0, #PROLOG = 1, #BOOT = 2, #RUNNING = 3, #MIGRATE = 4, #SAVE_STOP = 5, #SAVE_SUSPEND = 6, #SAVE_MIGRATE = 7, #PROLOG_MIGRATE = 8, #PROLOG_RESUME = 9, #EPILOG_STOP = 10, #EPILOG = 11, #SHUTDOWN = 12, #CANCEL = 13, #FAILURE = 14, #CLEANUP_RESUBMIT = 15, #UNKNOWN = 16, #HOTPLUG = 17, #SHUTDOWN_POWEROFF = 18, #BOOT_UNKNOWN = 19, #BOOT_POWEROFF = 20, #BOOT_SUSPENDED = 21, #BOOT_STOPPED = 22, #CLEANUP_DELETE = 23, #HOTPLUG_SNAPSHOT = 24, #HOTPLUG_NIC = 25, #HOTPLUG_SAVEAS = 26, #HOTPLUG_SAVEAS_POWEROFF = 27, #HOTPLUG_SAVEAS_SUSPENDED = 28, #SHUTDOWN_UNDEPLOY = 29, #EPILOG_UNDEPLOY = 30, #PROLOG_UNDEPLOY = 31, #BOOT_UNDEPLOY = 32 _, info, _ = self._rpc('one.vm.info', self.vm_id) xmldoc = minidom.parseString(info) state = int( xmldoc.getElementsByTagName('STATE')[0].firstChild.nodeValue) state_ext = int( xmldoc.getElementsByTagName('LCM_STATE')[0].firstChild.nodeValue) if state != 3: state_ext = None _logger.debug("state form vm %d is (%s:%s)" % (self.vm_id, state, state_ext)) return (state, state_ext) def _get_proxy(self): return xmlrpclib.ServerProxy(self.one_server) def _rpc(self, *kargs): p = self._get_proxy() method = getattr(p, kargs[0]) ret = method(self.one_credentials, *kargs[1:]) #_logger.debug("%s" % str(ret)) if not ret[0]: raise OneVMException("One RPC: %s" % ret[1]) return ret