def wait_for_task(task, raiseOnError=True, si=None, pc=None): if si is None: si = GetSi() if pc is None: sc = si.RetrieveContent() pc = sc.propertyCollector # First create the object specification as the task object. objspec = vmodl.Query.PropertyCollector.ObjectSpec() objspec.SetObj(task) # Next, create the property specification as the state. propspec = vmodl.Query.PropertyCollector.PropertySpec() propspec.SetType(vim.Task) propspec.SetPathSet(["info.state"]) propspec.SetAll(True) # Create a filter spec with the specified object and property spec. filterspec = vmodl.Query.PropertyCollector.FilterSpec() filterspec.SetObjectSet([objspec]) filterspec.SetPropSet([propspec]) # Create the filter filter = pc.CreateFilter(filterspec, True) # Loop looking for updates till the state moves to a completed state. taskName = task.GetInfo().GetName() update = pc.WaitForUpdates(None) state = task.GetInfo().GetState() while state != vim.TaskInfo.State.success and \ state != vim.TaskInfo.State.error: if (state == 'running') and (taskName.info.name != "Destroy"): # check to see if VM needs to ask a question, thow exception vm = task.GetInfo().GetEntity() if vm is not None and isinstance(vm, vim.VirtualMachine): qst = vm.GetRuntime().GetQuestion() if qst is not None: raise Exception("Task blocked, User Intervention required") update = pc.WaitForUpdates(update.GetVersion()) state = task.GetInfo().GetState() filter.Destroy() if state == "error" and raiseOnError: raise task.GetInfo().GetError() return state
def wait_for_task(task, *args, **kwargs): def no_op(task, *args): pass queued_callback = kwargs.get('queued', no_op) running_callback = kwargs.get('running', no_op) success_callback = kwargs.get('success', no_op) error_callback = kwargs.get('error', no_op) si = GetSi() pc = si.content.propertyCollector obj_spec = [vmodl.query.PropertyCollector.ObjectSpec(obj=task)] prop_spec = vmodl.query.PropertyCollector.PropertySpec(type=vim.Task, pathSet=[], all=True) filter_spec = vmodl.query.PropertyCollector.FilterSpec() filter_spec.objectSet = obj_spec filter_spec.propSet = [prop_spec] filter = pc.CreateFilter(filter_spec, True) try: version, state = None, None # Loop looking for updates till the state moves to a completed state. waiting = True while waiting: update = pc.WaitForUpdates(version) version = update.version for filterSet in update.filterSet: for objSet in filterSet.objectSet: task = objSet.obj for change in objSet.changeSet: if change.name == 'info': state = change.val.state elif change.name == 'info.state': state = change.val else: continue if state == vim.TaskInfo.State.success: success_callback(task, *args) waiting = False elif state == vim.TaskInfo.State.queued: queued_callback(task, *args) elif state == vim.TaskInfo.State.running: running_callback(task, *args) elif state == vim.TaskInfo.State.error: error_callback(task, *args) raise task.info.error finally: if filter: filter.Destroy()
def get_service_instance(host, username=None, password=None, protocol=None, port=None, mechanism='userpass', principal=None, domain=None): ''' Authenticate with a vCenter server or ESX/ESXi host and return the service instance object. host The location of the vCenter server or ESX/ESXi host. username The username used to login to the vCenter server or ESX/ESXi host. Required if mechanism is ``userpass`` password The password used to login to the vCenter server or ESX/ESXi host. Required if mechanism is ``userpass`` protocol Optionally set to alternate protocol if the vCenter server or ESX/ESXi host is not using the default protocol. Default protocol is ``https``. port Optionally set to alternate port if the vCenter server or ESX/ESXi host is not using the default port. Default port is ``443``. mechanism pyVmomi connection mechanism. Can either be ``userpass`` or ``sspi``. Default mechanism is ``userpass``. principal Kerberos service principal. Required if mechanism is ``sspi`` domain Kerberos user domain. Required if mechanism is ``sspi`` ''' if protocol is None: protocol = 'https' if port is None: port = 443 service_instance = GetSi() if service_instance: stub = GetStub() if salt.utils.is_proxy() or (hasattr( stub, 'host') and stub.host != ':'.join([host, str(port)])): # Proxies will fork and mess up the cached service instance. # If this is a proxy or we are connecting to a different host # invalidate the service instance to avoid a potential memory leak # and reconnect Disconnect(service_instance) service_instance = None else: return service_instance if not service_instance: service_instance = _get_service_instance(host, username, password, protocol, port, mechanism, principal, domain) # Test if data can actually be retrieved or connection has gone stale log.trace('Checking connection is still authenticated') try: service_instance.CurrentTime() except vim.fault.NotAuthenticated: log.trace('Session no longer authenticating. Reconnecting') Disconnect(service_instance) service_instance = _get_service_instance(host, username, password, protocol, port, mechanism, principal, domain) return service_instance
curr = curr.GetParent() vmFolder = curr.GetVmFolder() # Create the vm cspec = vm.CreateQuickDummySpec(vmname, numScsiDisks=1, memory=4, envBrowser=cr.GetEnvironmentBrowser(), datastoreName=ds.GetSummary().GetName()) try: vimutil.InvokeAndTrack(vmFolder.CreateVm, cspec, cr.GetResourcePool(), src) except Exception, e: raise vmotionVM = None searchIndex = GetSi().RetrieveContent().GetSearchIndex() vmotionVM = searchIndex.FindChild(vmFolder, vmname) if vmotionVM == None: logging.error("Unexpected error!") sys.exit(-1) return vmotionVM def doVmotion(vm1, dest, destName, priority, rp): logging.debug("Migrating to: " + destName) start = datetime.datetime.now() task = vm1.Migrate(rp, dest, priority, Vim.VirtualMachine.PowerState.poweredOn) try: WaitForTask(task)
def get_service_instance(host, username, password, protocol=None, port=None): ''' Authenticate with a vCenter server or ESX/ESXi host and return the service instance object. host The location of the vCenter server or ESX/ESXi host. username The username used to login to the vCenter server or ESX/ESXi host. password The password used to login to the vCenter server or ESX/ESXi host. protocol Optionally set to alternate protocol if the vCenter server or ESX/ESXi host is not using the default protocol. Default protocol is ``https``. port Optionally set to alternate port if the vCenter server or ESX/ESXi host is not using the default port. Default port is ``443``. ''' if protocol is None: protocol = 'https' if port is None: port = 443 service_instance = GetSi() if service_instance: if service_instance._GetStub().host == ':'.join([host, str(port)]): service_instance._GetStub().GetConnection() return service_instance Disconnect(service_instance) try: service_instance = SmartConnect(host=host, user=username, pwd=password, protocol=protocol, port=port) except Exception as exc: default_msg = 'Could not connect to host \'{0}\'. ' \ 'Please check the debug log for more information.'.format(host) try: if (isinstance(exc, vim.fault.HostConnectFault) and '[SSL: CERTIFICATE_VERIFY_FAILED]' in exc.msg ) or '[SSL: CERTIFICATE_VERIFY_FAILED]' in str(exc): import ssl default_context = ssl._create_default_https_context ssl._create_default_https_context = ssl._create_unverified_context service_instance = SmartConnect(host=host, user=username, pwd=password, protocol=protocol, port=port) ssl._create_default_https_context = default_context elif ( isinstance(exc, vim.fault.HostConnectFault) and 'SSL3_GET_SERVER_CERTIFICATE\', \'certificate verify failed' in exc.msg ) or 'SSL3_GET_SERVER_CERTIFICATE\', \'certificate verify failed' in str( exc): import ssl default_context = ssl._create_default_https_context ssl._create_default_https_context = ssl._create_unverified_context service_instance = SmartConnect(host=host, user=username, pwd=password, protocol=protocol, port=port) ssl._create_default_https_context = default_context else: err_msg = exc.msg if hasattr(exc, 'msg') else default_msg log.debug(exc) raise SaltSystemExit(err_msg) except Exception as exc: if 'certificate verify failed' in str(exc): import ssl context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) context.verify_mode = ssl.CERT_NONE service_instance = SmartConnect(host=host, user=username, pwd=password, protocol=protocol, port=port, sslContext=context) else: err_msg = exc.msg if hasattr(exc, 'msg') else default_msg log.debug(exc) raise SaltSystemExit(err_msg) atexit.register(Disconnect, service_instance) return service_instance
def RunTests(argv): global about parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-h', '--host', default='localhost', help='Host name') parser.add_argument('-u', '--user', default='root', help='User name') parser.add_argument('-p', '--pwd', default='', help='Password') parser.add_argument('-o', '--port', default=443, type=int, help='Port') parser.add_argument('-i', '--numiter', default=1, type=int, help='Iterations') parser.add_argument('-d', '--datastore', help='Datastore') parser.add_argument('-v', '--volume', help='VMFS volume') parser.add_argument('-c', '--cleanup', default=False, action='store_true', help='Try to clean up test VMS from prvious runs') parser.add_argument('-?', '--help', action='help', help='Usage') options = parser.parse_args(argv) # Connect si = SmartConnect(host=options.host, user=options.user, pwd=options.pwd, port=options.port) atexit.register(Disconnect, si) about = si.content.about status = "PASS" if about.productLineId == 'ws': Log('This test is ESX only') sys.exit(-1) if host.IsHostMockup(GetSi()): Log('This test does not support mockup hosts') sys.exit(1) # Determine the datastore name if options.datastore and options.volume: Log("Cannot specify both datastore and volume") sys.exit(-1) elif options.datastore: datastore = options.datastore Log("Using specified datastore: '%s'" % datastore) elif options.volume: # Convert absolute volume path to (dsName, relPath) tuple to get dsName Log("Trying to determine datastore name for volume: '%s'" % options.volume) try: datastore = path.FsPathToTuple(options.volume)[0] Log("Using datastore: '%s'" % datastore) except path.FilePathError as e: Log("Could not determine datastore name for volume: '%s'" % options.volume) sys.exit(-1) else: Log("No datastore or volume specified, test will choose one") datastore = None # To avoid confusion with other 'vmware' modules, set sys.path temporarily origPath = sys.path sys.path = [ '/lib64/python3.5', '/lib64/python3.5/plat-linux2', '/lib64/python3.5/lib-tk', '/lib64/python3.5/lib-old', '/lib64/python3.5/lib-dynload', '/lib64/python3.5/site-packages/setuptools-0.6c11-py2.6.egg', '/lib64/python3.5/site-packages' ] global vsi import vmware.vsi as vsi sys.path = origPath Log("Hostd memory : %d KB" % HostdMemSize(si)) resultsArray = [] for i in range(options.numiter): bigClock = StopWatch() try: try: # Find the vm without tools newName = VM_NAME_PREFIX + '_' + str(i) vm2 = folder.Find(newName) if vm2 != None: if options.cleanup: Log("Cleaning up old vm with name: " + newName) try: vm.PowerOff(vm2) except: pass vm.Destroy(vm2) else: Log("Please cleanup unit test vms from previous runs") sys.exit(-1) ph = Phase() # Create a simple vm vm2 = vm.CreateQuickDummy(newName, 1, datastoreName=datastore) ph.SetPhase("Create VM on " + newName) TestInitialFilePolicy(vm2, datastore) ph.SetPhase("Initial file policy tests") TestOnlineReconfigure(vm2, datastore) ph.SetPhase("Online reconfigure tests") TestLinkedClone(vm2, datastore) ph.SetPhase("Linked clone tests") vm2 = TestIllegalOptions(vm2) ph.SetPhase("Illegal options tests") vm.Destroy(vm2) ph.SetPhase("Destroy vm called " + newName) status = "PASS" finally: bigClock.finish("iteration " + str(i)) Log("Hostd memory after iteration %d : %d KB" % \ (i, HostdMemSize(si))) except Exception as e: Log("Caught exception : " + str(e)) traceback.print_exc() status = "FAIL" Log("TEST RUN COMPLETE: " + status) resultsArray.append(status) return_code = 0 Log("Results for each iteration: ") for i in range(len(resultsArray)): if resultsArray[i] == "FAIL": return_code = -1 Log("Iteration " + str(i) + ": " + resultsArray[i]) return return_code
def TestOnlineReconfigure(vm1, datastore=None): domainName = 'hostd' + str(vm1._GetMoId()) vmxPath = vm1.GetSummary().GetConfig().GetVmPathName() toolsIso = '/vmimages/tools-isoimages/linux.iso' if os.path.isfile(toolsIso): Log('Test hot-adding a CDROM backed by an ISO') toolsIsoRP = os.path.realpath(toolsIso) assert (not CheckInPolicy(domainName, [(toolsIsoRP, 1)])) vm.PowerOn(vm1) cdromDev, ctlr = AddCdromISO(vm1, toolsIso) found = CheckInPolicy(domainName, [(toolsIsoRP, 1)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find cdrom image permission') # Remove cdrom device cspec = Vim.Vm.ConfigSpec() vmconfig.RemoveDeviceFromSpec(cspec, cdromDev) vm.Reconfigure(vm1, cspec) found = CheckInPolicy(domainName, [(toolsIsoRP, 1)], True) if len(found) > 0: DumpFilePolicy(domainName) raise Exception('Found unexpected cdrom image permission') vm.PowerOff(vm1) cspec = Vim.Vm.ConfigSpec() vmconfig.RemoveDeviceFromSpec(cspec, ctlr) vm.Reconfigure(vm1, cspec) Log('Test hot-adding a serial device backed by a symlink') pathBase = os.path.dirname(vmxPath) serialDev = AddSerialPipeBacked(vm1) vm.PowerOn(vm1) origPolicy = RetrieveFilePolicy(domainName) serialDev, serialPath, symlink = AddEditSerialSymlinkFile( vm1, pathBase, serialDev) assert (serialPath not in origPolicy) found = CheckInPolicy(domainName, [(serialPath, 3)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find serial log permission') # Change backing of serial device cspec = Vim.Vm.ConfigSpec() backing = Vim.Vm.Device.VirtualSerialPort.FileBackingInfo() backing.SetFileName(pathBase + "/newSerial.log") serialDev.SetBacking(backing) vmconfig.AddDeviceToSpec(cspec, serialDev, Vim.Vm.Device.VirtualDeviceSpec.Operation.edit) vm.Reconfigure(vm1, cspec) found = CheckInPolicy(domainName, [(serialPath, 3)], True) if len(found) > 0: DumpFilePolicy(domainName) raise Exception('Found unexpected serial log permission') vm.PowerOff(vm1) # Remove serial device cspec = Vim.Vm.ConfigSpec() vmconfig.RemoveDeviceFromSpec(cspec, serialDev) vm.Reconfigure(vm1, cspec) os.unlink(symlink) try: os.unlink(serialPath) except OSError as e: if e.errno == errno.ENOENT: pass Log('Test hot adding a new disk in a different directory') vm.PowerOn(vm1) origPolicy = RetrieveFilePolicy(domainName) diskDev, diskDir = AddDiskExternalDir(vm1, pathBase, datastore) diskFullPath = ResolveDsPath(vm1, diskDir) assert (diskFullPath not in origPolicy) found = CheckInPolicy(domainName, [(diskFullPath, 3)]) if len(found) != 1: raise Exception('Did not find all expected permissions. Found: %s' % ', '.join(found)) # Remove added disk and clean up directory cspec = Vim.Vm.ConfigSpec() fileOp = Vim.Vm.Device.VirtualDeviceSpec.FileOperation.destroy vmconfig.RemoveDeviceFromSpec(cspec, diskDev, fileOp) vm.Reconfigure(vm1, cspec) found = CheckInPolicy(domainName, [(diskFullPath, 3)]) if len(found) > 0: DumpFilePolicy(domainName) raise Exception('Found unexpected disk path permission', True) vm.PowerOff(vm1) fileManager = GetSi().RetrieveContent().GetFileManager() try: vimutil.InvokeAndTrack(fileManager.Delete, datastorePath=diskDir, fileType=Vim.FileManager.FileType.File) except Vim.fault.FileNotFound: pass
def TestInitialFilePolicy(vm1, datastore=None): # Basic dummy VM should at least have permission for its home directory domainName = 'hostd' + str(vm1._GetMoId()) vm.PowerOn(vm1) vmxPath = vm1.GetSummary().GetConfig().GetVmPathName() vmdir = os.path.dirname(ResolveDsPath(vm1, vmxPath)) found = CheckInPolicy(domainName, [(vmdir, 3)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find VM home directory policy after power-on') vm.PowerOff(vm1) if FindDomain(domainName): raise Exception('Domain %s has not been cleaned up' % domainName) Log('Test setting nvram_default in global config') globalConf = '/etc/vmware/config' nvramPath = '/vmfs/volumes/testVol1/non_existent_nvram' shutil.copy2(globalConf, globalConf + '.backup') with open(globalConf, 'a') as f: f.write('nvram_default = "' + nvramPath + '"' + '\n') vm.PowerOn(vm1) shutil.move(globalConf + '.backup', globalConf) found = CheckInPolicy(domainName, [(nvramPath, 1)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find permission for nvram_default path') vm.PowerOff(vm1) toolsIso = '/vmimages/tools-isoimages/linux.iso' if os.path.isfile(toolsIso): Log('Test CDROM image config option') cdromDev, ctlr = AddCdromISO(vm1, toolsIso) vm.PowerOn(vm1) toolsIsoRP = os.path.realpath(toolsIso) found = CheckInPolicy(domainName, [(toolsIsoRP, 1)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find cdrom image permission') vm.PowerOff(vm1) # Remove cdrom device cspec = Vim.Vm.ConfigSpec() vmconfig.RemoveDeviceFromSpec(cspec, cdromDev) vmconfig.RemoveDeviceFromSpec(cspec, ctlr) vm.Reconfigure(vm1, cspec) Log('Test symlink serial backing file') pathBase = os.path.dirname(vmxPath) serialDev, fullPath, symlink = AddEditSerialSymlinkFile(vm1, pathBase) vm.PowerOn(vm1) found = CheckInPolicy(domainName, [(fullPath, 3)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find serial log permission') vm.PowerOff(vm1) # Remove serial device cspec = Vim.Vm.ConfigSpec() vmconfig.RemoveDeviceFromSpec(cspec, serialDev) vm.Reconfigure(vm1, cspec) os.unlink(symlink) Log('Test log file path with environment variables') logDir = pathBase + '-root' CreateDirectory(logDir) logDirPath = ResolveDsPath(vm1, logDir) logFullPath = re.sub(r'-root', '-$USER', logDirPath) + 'vmx-$PID.log' vmxLogOpt = Vim.Option.OptionValue(key='vmx.fileTrack.logFile', value=logFullPath) cspec = Vim.Vm.ConfigSpec(extraConfig=[vmxLogOpt]) vm.Reconfigure(vm1, cspec) vm.PowerOn(vm1) found = CheckInPolicy(domainName, [(logDirPath, 3)]) if len(found) != 1: DumpFilePolicy(domainName) raise Exception('Did not find log file permission') vm.PowerOff(vm1) vmxLogOpt = Vim.Option.OptionValue(key='vmx.fileTrack.logFile', value='') cspec = Vim.Vm.ConfigSpec(extraConfig=[vmxLogOpt]) vm.Reconfigure(vm1, cspec) fileManager = GetSi().RetrieveContent().GetFileManager() vimutil.InvokeAndTrack(fileManager.Delete, datastorePath=logDir, fileType=Vim.FileManager.FileType.File) Log('Test setting workingDir') workingDir = pathBase + '-workingDir' workingDirFullPath = ResolveDsPath(vm1, workingDir) workingDirSymPath = ResolveDsPath(vm1, workingDir, True) CreateDirectory(workingDir) vmxFullPath = ResolveDsPath(vm1, vmxPath) shutil.copy2(vmxFullPath, vmxFullPath + '.backup') vmxOut = codecs.open(vmxFullPath, mode='w+', encoding='utf_8') with codecs.open(vmxFullPath + '.backup', encoding='utf_8') as vmxIn: for line in vmxIn: if 'migrate.hostlog' not in line: vmxOut.write(line) vmxOut.write('workingDir = "%s"\n' % workingDirSymPath) vmxOut.close() vm.PowerOn(vm1) found = CheckInPolicy(domainName, [(workingDirFullPath, 3)]) filesFound = os.listdir(workingDirFullPath) if len(filesFound) == 0: raise Exception('No files found in working directory %s' % workingDirFullPath) vm.PowerOff(vm1) # Power cycle to verify VM is still in a valid state vm.PowerOn(vm1) vm.PowerOff(vm1) shutil.move(vmxFullPath + '.backup', vmxFullPath) fileManager = GetSi().RetrieveContent().GetFileManager() vimutil.InvokeAndTrack(fileManager.Delete, datastorePath=workingDir, fileType=Vim.FileManager.FileType.File) vm.PowerOn(vm1) vm.PowerOff(vm1) # Create suspend directory, additional disk directory Log('Test setting suspend directory and adding a new disk') suspendDir = AddSuspendDirectory(vm1, pathBase) diskDev, diskDir = AddDiskExternalDir(vm1, pathBase, datastore) Log('Set suspend directory to %s and added disk in %s' % (suspendDir, diskDir)) vm.PowerOn(vm1) suspendFullPath = ResolveDsPath(vm1, suspendDir) diskFullPath = ResolveDsPath(vm1, diskDir) found = CheckInPolicy(domainName, [(suspendFullPath, 3), (diskFullPath, 3)]) if len(found) != 2: raise Exception('Did not find all expected permissions. Found: %s' % ', '.join(found)) Log('Suspending VM') vm.Suspend(vm1) suspendFiles = os.listdir(suspendFullPath) if len(suspendFiles) == 0: raise Exception('Did not find suspend image in %s' % suspendFullPath) Log('Resume VM, power off and clean up') vm.PowerOn(vm1) vm.PowerOff(vm1) # Reset suspend directory, remove added disk and clean up directories cspec = Vim.Vm.ConfigSpec() files = Vim.Vm.FileInfo() files.SetSuspendDirectory('ds://') cspec.SetFiles(files) fileOp = Vim.Vm.Device.VirtualDeviceSpec.FileOperation.destroy vmconfig.RemoveDeviceFromSpec(cspec, diskDev, fileOp) vm.Reconfigure(vm1, cspec) for directory in (suspendDir, diskDir): try: vimutil.InvokeAndTrack(fileManager.Delete, datastorePath=directory, fileType=Vim.FileManager.FileType.File) except Vim.fault.FileNotFound: pass
def CreateDirectory(directory): fileManager = GetSi().RetrieveContent().GetFileManager() try: fileManager.MakeDirectory(directory) except Vim.fault.FileAlreadyExists: pass