def WaitForPowerState(vm, si, powerState, nsec = 20): saveSi = connect.GetSi() connect.SetSi(si) for i in range(nsec): if vm.GetRuntime().GetPowerState() != powerState: time.sleep(1) if vm.GetRuntime().GetPowerState() != powerState: raise Exception("VM did not transition to expected power state!") connect.SetSi(saveSi)
def ReloadSecondary(si, vm1): with LogSelfOp() as logOp: curSi = connect.GetSi() connect.SetSi(si) vmname = vm1.GetConfig().GetName() Log("Reloading secondary VM") vm1.Reload() vm2 = folder.Find(vmname) if vm2 == None: raise Exception("Reload caused the VM to go invalid") connect.SetSi(curSi)
def WaitForPowerState(vm, si, powerState, nsec=40): with LogSelfOp() as logOp: saveSi = connect.GetSi() connect.SetSi(si) for i in range(nsec): if vm.GetRuntime().GetPowerState() != powerState: time.sleep(1) if vm.GetRuntime().GetPowerState() != powerState: raise Exception("%s: VM did not transition to expected power state!" % \ DescribeVm(vm)) connect.SetSi(saveSi)
def setUp(self): """ Connects to the host and creates test VM. """ self._host = vimhost.Host() connect.SetSi(self._host._si) # Create dummy test VM self._vmname = "ttt.%s" % str(self.__class__.__module__) if (self._vmname is None): raise self.failureException( "Test VM name is not a valid path name. %s" % (self._vmname)) try: self.destroyTestVM(self._vmname) envBrowser = invt.GetEnv() cfgTarget = envBrowser.QueryConfigTarget(None) if len(cfgTarget.GetDatastore()) == 0: cm = host.GetHostConfigManager(self._si) dsm = cm.GetDatastoreSystem() # todo is this going to work on vmkernel dsm.CreateLocalDatastore("tttds1", "/var/tmp") # create a quick dummy test VM with one SCSI disk self._vm = vm.CreateQuickDummy(self._vmname, 1) vm1 = vm.VM(self._vm, None, None) if (not vm1.IsPoweredOff()): raise self.failureException( "Newly created test VM should be powered off.") except Exception as msg: raise self.failureException( "Failed to create test VM \"%s\" on host=\"%s\": %s" % (self._vmname, self._host, msg)) print("INFO: created vm %s " % (self._vmname))
def CheckFTState(vm, state, si = None, isPrimary = True): prevSi = None if si != None: prevSi = connect.GetSi() connect.SetSi(si) ftState = vm.GetRuntime().GetFaultToleranceState() if ftState != state: raise Exception( "Runtime FT state " + str(ftState) + " not set to " + str(state)) Log("Verified runtime fault tolerance state as " + str(state))
def main(): supportedArgs = [ (["P:", "primary host="], "localhost", "Primary host name", "primaryHost"), (["S:", "secondary host="], "localhost", "Secondary host name", "secondaryHost"), (["d:", "shared datastore name="], "storage1", "shared datastore name", "dsName"), (["k:", "keep="], "0", "Keep configs", "keep"), (["u:", "user="******"root", "User name", "user"), (["p:", "pwd="], "", "Password", "pwd"), (["v:", "vmname="], "vmFT", "Name of the virtual machine", "vmname"), (["i:", "numiter="], "1", "Number of iterations", "iter"), (["t:", "FT type="], "up", "Type of fault tolerance [up|smp]", "ftType"), ] supportedToggles = [(["usage", "help"], False, "Show usage information", "usage")] args = arguments.Arguments(sys.argv, supportedArgs, supportedToggles) if args.GetKeyValue("usage") == True: args.Usage() sys.exit(0) # Process command line vmname = args.GetKeyValue("vmname") numiter = int(args.GetKeyValue("iter")) keep = int(args.GetKeyValue("keep")) dsName = args.GetKeyValue("dsName") primaryHost = args.GetKeyValue("primaryHost") secondaryHost = args.GetKeyValue("secondaryHost") ftType = args.GetKeyValue("ftType") numCPU = 2 if ftType == "smp" else 1 memSize = 64 for i in range(numiter): primaryVm = None primarySi = None secondarySi = None try: # Connect to primary host primarySi = SmartConnect(host=primaryHost, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to Primary host") # Cleanup from previous runs try: CleanupVm(vmname) except vim.fault.InvalidOperationOnSecondaryVm: pass # Connect to secondary host secondarySi = SmartConnect(host=secondaryHost, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to Secondary host") for si in [primarySi, secondarySi]: if len(FindNicType(si, ftLoggingNicType)) == 0: SelectVnic(si, "vmk0", ftLoggingNicType) if len(FindNicType(si, vmotionNicType)) == 0: SelectVnic(si, "vmk0", vmotionNicType) ftMgrDst = host.GetFaultToleranceMgr(secondarySi) # Cleanup from previous runs CleanupVm(vmname) CleanupVm(vmname, True) connect.SetSi(primarySi) CleanupDir(dsName, vmname) if ftType == "smp": CleanupDir(dsName, "%s_shared" % vmname) # Create new VM Log("Creating primary VM " + vmname) primaryVm = vm.CreateQuickDummy(vmname, guest="winNetEnterpriseGuest", numScsiDisks=2, scrubDisks=True, memory=memSize, datastoreName=dsName) primaryUuid = primaryVm.GetConfig().GetInstanceUuid() primaryCfgPath = primaryVm.GetConfig().GetFiles().GetVmPathName() primaryDir = primaryCfgPath[:primaryCfgPath.rfind("/")] ftMetadataDir = GetSharedPath(primarySi, primaryVm) Log("Using VM : " + primaryVm.GetName() + " with instanceUuid " + primaryUuid) ftMetadataDir = GetSharedPath(primarySi, primaryVm) cSpec = vim.vm.ConfigSpec() if ftType != "smp": # Enable record/replay for the primaryVm # See PR 200254 flags = vim.vm.FlagInfo(recordReplayEnabled=True) cSpec.SetFlags(flags) task = primaryVm.Reconfigure(cSpec) WaitForTask(task) Log("Enabled record/replay for Primary VM.") CheckFTState( primaryVm, vim.VirtualMachine.FaultToleranceState.notConfigured) else: cSpec.files = vim.vm.FileInfo( ftMetadataDirectory=ftMetadataDir) cSpec.numCPUs = numCPU task = primaryVm.Reconfigure(cSpec) WaitForTask(task) # Create secondary VM connect.SetSi(secondarySi) Log("Creating secondary VM " + vmname) secondaryVm = vm.CreateQuickSecondary(vmname, primaryVm, ftType=ftType, scrubDisks=True, numScsiDisks=2, datastoreName=dsName, ftMetadataDir=ftMetadataDir) if secondaryVm == None: raise "Secondary VM creation failed" secondaryUuid = secondaryVm.GetConfig().GetInstanceUuid() secondaryCfgPath = secondaryVm.GetConfig().GetFiles( ).GetVmPathName() Log("Created secondary VM " + secondaryVm.GetName()) Log("Secondry VM: instanceUuid " + secondaryUuid) Log("Secondary cfg path: " + secondaryCfgPath) ## Configure some additional config variables needed for FT ## This should eventually be done automatically at FT Vmotion time Log("Setting up extra config settings for the primary VM...") cSpec = vim.Vm.ConfigSpec() extraCfgs = [] if ftType == "smp": # some of these options are temporary cSpec.flags = vim.vm.FlagInfo( faultToleranceType=FTType.checkpointing) AddExtraConfig(extraCfgs, "ftcpt.maxDiskBufferPages", "0") AddExtraConfig(extraCfgs, "sched.mem.pshare.enable", "FALSE") AddExtraConfig(extraCfgs, "sched.mem.fullreservation", "TRUE") AddExtraConfig(extraCfgs, "monitor_control.disable_mmu_largepages", "TRUE") AddExtraConfig(extraCfgs, "sched.mem.min", memSize) AddExtraConfig(extraCfgs, "migration.dataTimeout", "2000") cSpec.files = vim.vm.FileInfo( ftMetadataDirectory=ftMetadataDir) else: cSpec.flags = vim.vm.FlagInfo( faultToleranceType=FTType.recordReplay) AddExtraConfig(extraCfgs, "replay.allowBTOnly", "TRUE") cSpec.SetExtraConfig(extraCfgs) WaitForTask(primaryVm.Reconfigure(cSpec)) # Register secondary VM Log("Register secondary VM with the primary") ftMgr = host.GetFaultToleranceMgr(primarySi) connect.SetSi(primarySi) task = ftMgr.RegisterSecondary(primaryVm, secondaryUuid, secondaryCfgPath) WaitForTask(task) Log("Secondary VM registered successfully") # Verify FT role & state CheckFTRole(primaryVm, 1) CheckFTState(primaryVm, vim.VirtualMachine.FaultToleranceState.enabled) Log("FT configured successfully.") # PowerOn FT VM Log("Powering on Primary VM") vm.PowerOn(primaryVm) if ftType == "smp": # some of these options are temporary task = primaryVm.CreateSnapshot("snap-early", "before secondary starts", memory=False, quiesce=True) WaitForTask(task) # Perform the FT VMotion Log("Calling StartSecondary on remote host...") primaryThumbprint = GetHostThumbprint(primaryHost) secondaryThumbprint = GetHostThumbprint(secondaryHost) Log("Primary thumbprint: %s" % primaryThumbprint) Log("Secondary thumbprint: %s" % secondaryThumbprint) secondaryHostSystem = secondarySi.content.rootFolder.childEntity[ 0].hostFolder.childEntity[0].host[0] sslThumbprintInfo = vim.host.SslThumbprintInfo( ownerTag='hostd-test', principal='vpxuser') sslThumbprintInfo.sslThumbprints = [primaryThumbprint] secondaryHostSystem.UpdateSslThumbprintInfo( sslThumbprintInfo, "add") sslThumbprintInfo.sslThumbprints = [secondaryThumbprint] primaryHostSystem = primarySi.content.rootFolder.childEntity[ 0].hostFolder.childEntity[0].host[0] primaryHostSystem.UpdateSslThumbprintInfo(sslThumbprintInfo, "add") task = ftMgr.StartSecondaryOnRemoteHost(primaryVm, secondaryCfgPath, secondaryHost, 80, secondaryThumbprint) WaitForTask(task) Log("Start secondary done.") if ftType == "smp": # Verify snapshot is gone if primaryVm.snapshot is not None: raise Exception("Snapshot still exists on primary") task = primaryVm.CreateSnapshot("snap", "without memory snapshot", memory=False, quiesce=True) WaitForTask(task) if not primaryVm.snapshot or not primaryVm.snapshot.currentSnapshot: raise Exception("Snapshot was not created") else: Log("Snapshot %s exists as expected" % primaryVm.snapshot.currentSnapshot) # Retrieve reference to new secondary VM connect.SetSi(secondarySi) secondaryVm = folder.FindCfg(secondaryCfgPath) connect.SetSi(primarySi) # FT state check CheckFTState(primaryVm, vim.VirtualMachine.FaultToleranceState.running) CheckFTState(secondaryVm, vim.VirtualMachine.FaultToleranceState.running) Log("Start secondary done.") # allows some time for FT to run and checkpoint before failing # over. This seems more necessary on nested VM environments # than physical time.sleep(20) Log("Failing over to the secondary.") WaitForTask(ftMgr.MakePrimary(primaryVm, secondaryUuid)) WaitForPowerState(primaryVm, primarySi, vim.VirtualMachine.PowerState.poweredOff) Log("Verified primary power state is off.") WaitForFTState(secondaryVm, FTState.needSecondary) Log("Starting secondary.") task = ftMgrDst.StartSecondaryOnRemoteHost(secondaryVm, primaryCfgPath, primaryHost, 80, primaryThumbprint) WaitForTask(task) # Verify snapshot is gone if primaryVm.snapshot is not None: raise Exception("Snapshot still exists on old primary") Log("Failing over to the old-primary.") WaitForTask(ftMgrDst.MakePrimary(secondaryVm, secondaryUuid)) WaitForPowerState(secondaryVm, secondarySi, vim.VirtualMachine.PowerState.poweredOff) Log("Verified primary power state is off.") WaitForFTState(primaryVm, FTState.needSecondary) task = ftMgr.StartSecondaryOnRemoteHost(primaryVm, secondaryCfgPath, secondaryHost, 80, secondaryThumbprint) WaitForTask(task) # PowerOff FT VMs Log("Power off Primary VM") vm.PowerOff(primaryVm) connect.SetSi(secondarySi) for i in range(10): if secondaryVm.GetRuntime().GetPowerState( ) == vim.VirtualMachine.PowerState.poweredOn: time.sleep(1) if secondaryVm.GetRuntime().GetPowerState( ) == vim.VirtualMachine.PowerState.poweredOn: raise Exception("Secondary VM is still powered on!") Log("Verified secondary power state.") Log("Unregistering secondary VM " + vmname) ftMgrDst.Unregister(secondaryVm) # Cleanup if not keep: connect.SetSi(primarySi) CleanupVm(vmname) CleanupDir(dsName, vmname) if ftType == "smp": CleanupDir(dsName, "%s_shared" % vmname) connect.SetSi(secondarySi) CleanupVm(vmname, True) except Exception as e: Log("Caught exception : %s" % e) stackTrace = " ".join( traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])) Log(stackTrace) global status status = "FAIL" Disconnect(primarySi) Disconnect(secondarySi) return Disconnect(primarySi) Disconnect(secondarySi)
def main(): supportedArgs = [ (["1:", "host1="], "localhost", "Host name", "host1"), (["2:", "host2="], "localhost", "Host name", "host2"), (["u:", "user="******"root", "User name", "user"), (["p:", "pwd="], "ca$hc0w", "Password", "pwd"), (["v:", "vmname="], "CreateTest", "Name of the virtual machine", "vmname"), (["t:", "vmotionType="], "vmotion", "VMotion type", "vmotionType"), (["d:", "destDs="], None, "Target datastore for storage VMotions", "destDs"), (["e:", "encrypt="], False, "Whether to use encryption", "encrypt") ] supportedToggles = [(["usage", "help"], False, "Show usage information", "usage")] args = arguments.Arguments(sys.argv, supportedArgs, supportedToggles) if args.GetKeyValue("usage") == True: args.Usage() sys.exit(0) host1 = args.GetKeyValue("host1") host2 = args.GetKeyValue("host2") encrypt = bool(args.GetKeyValue("encrypt")) vmotionType = args.GetKeyValue("vmotionType") destDs = args.GetKeyValue("destDs") supportedTypes = vmotion.GetSupportedVMotionTypes() if vmotionType not in supportedTypes: print "Unsupported vmotion type '%s'" % vmotionType print "Supported values are %s" % ", ".join(supportedTypes) sys.exit(-1) print "Using vmotion type: " + vmotionType # Connect to hosts print "Host 1: " + host1 primarySi = connect.SmartConnect(host=host1, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) secondarySi = primarySi if vmotionType != Vim.Host.VMotionManager.VMotionType.disks_only: print "Host 2: " + host2 secondarySi = connect.SmartConnect(host=host2, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) connect.SetSi(primarySi) print "Use encryption: " + str(encrypt) vmname = args.GetKeyValue("vmname") vm1 = folder.Find(vmname) if vm1 == None: print "Couldnt find the specified virtual machine " + vmname \ + ". Check that the vm exists on host 1" sys.exit(-1) vm.Migrate(vm1, primarySi, secondarySi, vmotionType=vmotionType, encrypt=encrypt, destDs=destDs)
def main(): global status supportedArgs = [ (["H:", "host="], "localhost", "Host name", "host"), (["k:", "keep="], "0", "Keep configs", "keep"), (["e:", "useExisting="], False, "Use existing VM", "useExistingVm"), (["u:", "user="******"root", "User name", "user"), (["p:", "pwd="], "", "Password", "pwd"), (["v:", "VM name="], "vmotionErrs", "Name of the virtual machine", "vmname"), (["d:", "dsName="], None, "Target datastore for storage VMotions", "dsName"), (["i:", "numiter="], "1", "Number of iterations", "iter"), ] supportedToggles = [ (["usage", "help"], False, "Show usage information", "usage"), ] args = arguments.Arguments(sys.argv, supportedArgs, supportedToggles) if args.GetKeyValue("usage") == True: args.Usage() sys.exit(0) # Process command line host = args.GetKeyValue("host") vmname = args.GetKeyValue("vmname") numiter = int(args.GetKeyValue("iter")) keep = int(args.GetKeyValue("keep")) useExistingVm = bool(args.GetKeyValue("useExistingVm")) dsName = args.GetKeyValue("dsName") for i in range(numiter): si = None try: # Connect to host si = SmartConnect(host=host, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to Host") dsName = GetDatastore(si, dsName) Log('Using datastore: %s' % dsName) # Cleanup from previous runs if not useExistingVm: CleanupVm(vmname) CleanDirs(si, dsName, vmname) # Create new VM connect.SetSi(si) theVm = None if useExistingVm: theVm = folder.Find(vmname) if theVm == None: raise Exception("No VM with name %s found!" % vmname) Log("Using VM %s" % vmname) else: Log("Creating VM %s" % vmname) # Short delay to avoid colliding with a cleanup. time.sleep(1) # XXX numScsiDisks=0. vm.Migrate() doesn't know about # xvmotion, so it fails to set up the disk copy spec theVm = vm.CreateQuickDummy(vmname, guest="winXPProGuest", memory=4, cdrom=0, numScsiDisks=0, datastoreName=dsName) if theVm.GetRuntime().GetPowerState() == PowerState.poweredOff: Log("Powering on VM.") vm.PowerOn(theVm) else: Log("VM already powered on.") srcDir = os.path.dirname(theVm.config.files.vmPathName) tests = [ TestVmxFailTo, TestVmxFailToEvent, TestVmxFailInit, TestVmxFailFrom, TestVmxFailPrepareDst, TestVmxFailStart, TestVmxSuccess, # Must be last: does not switch back to source ] for testClass in tests: Log("Creating dummy dest") dstPath = os.path.join(srcDir, testClass.name, vmname + ".vmx") dummySpec = vm.CreateQuickDummySpec(vmname, guest="winXPProGuest", memory=4, cdrom=0, numScsiDisks=0, datastoreName=dsName) dummySpec.GetFiles().SetVmPathName(dstPath) dstVm = vm.CreateFromSpec(dummySpec) # Core of running an individual test theTest = testClass(theVm, dstVm) theTest.setup() Log("Attempt to vMotion with test '%s'" % str(theTest)) try: vm.Migrate(theVm, si, si, vmotionType='vmotion', unsharedSwap=True, dstPath=dstPath) except Exception as e: theTest.gotFailure(e) else: theTest.gotSuccess() theTest.cleanup() if not useExistingVm: CleanupVm(vmname) except Exception as e: Log("Caught exception : %s" % e) excType, excValue, excTB = sys.exc_info() stackTrace = " ".join( traceback.format_exception(excType, excValue, excTB)) Log(stackTrace) status = "FAIL" Disconnect(si) if IsTestEsx(): ReportFiles('/vmfs/volumes/%s/%s' % (dsName, vmname)) return if status == "PASS" and IsTestEsx( ) and 'test-esx-vmotionErrs' in vmname: CleanDirs(si, dsName, vmname) Disconnect(si)
def main(): supportedArgs = [ (["P:", "primary host="], "localhost", "Primary host name", "primaryHost"), (["S:", "secondary host="], "localhost", "Secondary host name", "secondaryHost"), (["T:", "tertiary host="], "", "Third host name for VMotion test", "tertiaryHost"), (["d:", "shared datastore name="], "storage1", "shared datastore name", "dsName"), (["u:", "user="******"root", "User name", "user"), (["p:", "pwd="], "ca$hc0w", "Password", "pwd"), (["e:", "useExisting="], False, "Use existing VM", "useExistingVm"), (["v:", "VM name="], "vmFT", "Name of the virtual machine", "vmname"), (["i:", "numiter="], "1", "Number of iterations", "iter") ] supportedToggles = [ (["usage", "help"], False, "Show usage information", "usage")] args = arguments.Arguments(sys.argv, supportedArgs, supportedToggles) if args.GetKeyValue("usage") == True: args.Usage() sys.exit(0) # Process command line primaryName = args.GetKeyValue("vmname") numiter = int(args.GetKeyValue("iter")) dsName = args.GetKeyValue("dsName") primaryHost = args.GetKeyValue("primaryHost") secondaryHost = args.GetKeyValue("secondaryHost") tertiaryHost = args.GetKeyValue("tertiaryHost") useExisting = bool(args.GetKeyValue("useExistingVm")) if primaryHost == secondaryHost: secondaryName = "_" + primaryName else: secondaryName = primaryName for i in range(numiter): primaryVm = None primarySi = None secondarySi = None tertiarySi = None try: # Connect to tertiary host, if provided. if tertiaryHost != "": tertiarySi = SmartConnect(host=tertiaryHost, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to VMotion test host, VMotion will be tested") if not useExisting: CleanupVm(primaryName) CleanupVm(secondaryName, True) # Connect to primary host primarySi = SmartConnect(host=primaryHost, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to Primary host") # Cleanup from previous runs if not useExisting: CleanupVm(primaryName) CleanupVm(secondaryName, True) # Connect to secondary host secondarySi = SmartConnect(host=secondaryHost, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd")) Log("Connected to Secondary host") # Cleanup from previous runs if not useExisting: CleanupVm(primaryName) CleanupVm(secondaryName, True) # Create new VM connect.SetSi(primarySi) primaryVm = None if useExisting: primaryVm = folder.Find(primaryName) if primaryVm == None: raise Exception("No primary VM with name " + primaryName + " found!") Log("Using primary VM " + primaryName) else: Log("Creating primary VM " + primaryName) primaryVm = vm.CreateQuickDummy(primaryName, guest = "winXPProGuest", cdrom = 1, numScsiDisks = 1, scrubDisks = True, datastoreName = dsName) # Get details about primary VM primaryUuid = primaryVm.GetConfig().GetInstanceUuid() primaryCfgPath = primaryVm.GetConfig().GetFiles().GetVmPathName() primaryDir = primaryCfgPath[:primaryCfgPath.rfind("/")] Log("Using VM : " + primaryVm.GetName() + " with instanceUuid " + primaryUuid) if useExisting: ftState = Vim.VirtualMachine.FaultToleranceState.running else: ftState = Vim.VirtualMachine.FaultToleranceState.notConfigured CheckFTState(primaryVm, ftState) # Create secondary VM connect.SetSi(secondarySi) if useExisting: secondaryVm = folder.Find(secondaryName) if secondaryVm == None: raise Exception("No secondary VM with name " + secondaryName + " found!") Log("Using secondary VM " + secondaryName) else: Log("Creating secondary VM " + secondaryName) secondaryVm = vm.CreateQuickSecondary(secondaryName, primaryUuid, primaryCfgPath, primaryDir) if secondaryVm == None: raise "Secondary VM creation failed" Log("Created secondary VM " + secondaryVm.GetName()) secondaryUuid = secondaryVm.GetConfig().GetInstanceUuid() secondaryCfgPath = secondaryVm.GetConfig().GetFiles().GetVmPathName() Log("Secondry VM: instanceUuid " + secondaryUuid) Log("Secondary cfg path: " + secondaryCfgPath) primaryFTMgr = host.GetFaultToleranceMgr(primarySi) if not useExisting: ## Configure some additional config variables needed for FT ## This should eventually be done automatically at FT Vmotion time Log("Setting up extra config settings for the primary VM...") connect.SetSi(primarySi) extraCfgs = primaryVm.GetConfig().GetExtraConfig() AddExtraConfig(extraCfgs, "replay.allowBTOnly", "TRUE") AddExtraConfig(extraCfgs, "replay.allowFT", "TRUE") if primaryName != secondaryName: AddExtraConfig(extraCfgs, "ft.allowUniqueName", "TRUE") cSpec = Vim.Vm.ConfigSpec() cSpec.SetExtraConfig(extraCfgs) task = primaryVm.Reconfigure(cSpec) WaitForTask(task) # Register secondary VM Log("Register secondary VM with the powered off primary") task = primaryFTMgr.RegisterSecondary(primaryVm, secondaryUuid, secondaryCfgPath) WaitForTask(task) Log("Secondary VM registered successfully") # Verify FT state CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.enabled) Log("FT configured successfully.") # PowerOn FT VM Log("Powering on Primary VM") vm.PowerOn(primaryVm) # Perform FT VMotion to setup protection Log("Migrating state from primary to secondary VM.") vm.Migrate(primaryVm, primarySi, secondarySi, secondaryCfgPath, True, Vim.Host.VMotionManager.VMotionType.fault_tolerance) CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.running) CheckFTState(secondaryVm, Vim.VirtualMachine.FaultToleranceState.running, secondarySi, False) Log("VMs are running with FT protection.") # Test VM component health exchanges secondaryFTMgr = host.GetFaultToleranceMgr(secondarySi) health = Vim.Host.FaultToleranceManager.ComponentHealthInfo() health.SetIsStorageHealthy(True) health.SetIsNetworkHealthy(True) Log("Testing VM health exchange from primary to secondary: all healthy") TestComponentHealthInfo(primaryFTMgr, secondaryFTMgr, primaryVm, secondaryVm, health) Log("Testing VM health exchange from primary to secondary: storage unhealthy") health.SetIsStorageHealthy(False) TestComponentHealthInfo(primaryFTMgr, secondaryFTMgr, primaryVm, secondaryVm, health) Log("Testing VM health exchange from secondary to primary: network unhealthy") health.SetIsStorageHealthy(True) health.SetIsNetworkHealthy(False) TestComponentHealthInfo(secondaryFTMgr, primaryFTMgr, secondaryVm, primaryVm, health) # Making peer go live Log("Making FT primary go live from secondary") secondaryFTMgr.GoLivePeerVM(secondaryVm) time.sleep(5) CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.needSecondary, primarySi) WaitForPowerState(secondaryVm, secondarySi, Vim.VirtualMachine.PowerState.poweredOff) # Set local VM storage and network health Log("Setting primary VM as unhealthy") health.SetIsStorageHealthy(False) health.SetIsNetworkHealthy(False) primaryFTMgr.SetLocalVMComponentHealth(primaryVm, health) # Restart secondary VM. It should still show storage unhealthy Log("Restarting secondary VM.") vm.Migrate(primaryVm, primarySi, secondarySi, secondaryCfgPath, True, Vim.Host.VMotionManager.VMotionType.fault_tolerance) CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.running) CheckFTState(secondaryVm, Vim.VirtualMachine.FaultToleranceState.running, secondarySi, False) Log("VMs are running with FT protection.") # Verify health has propagated to the new secondary health2 = secondaryFTMgr.GetPeerVMComponentHealth(secondaryVm) if health.isStorageHealthy != health2.isStorageHealthy or \ health.isNetworkHealthy != health2.isNetworkHealthy: Log("Got peer health information : " + str(health2)) raise Exception("Peer health information does not match") # Test VMotion of primary and secondary, if a third host is given if tertiarySi != None: # Mark secondary as unhealthy health.SetIsStorageHealthy(True) health.SetIsNetworkHealthy(False) secondaryFTMgr.SetLocalVMComponentHealth(secondaryVm, health) Log("VMotion primary to tertiary host") vm.Migrate(primaryVm, primarySi, tertiarySi, primaryCfgPath, False) primaryFTMgr = host.GetFaultToleranceMgr(tertiarySi) connect.SetSi(tertiarySi) primaryVm = folder.Find(primaryName) CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.running, tertiarySi) CheckFTState(secondaryVm, Vim.VirtualMachine.FaultToleranceState.running, secondarySi, False) # Verify secondary health has propagated to primary on new host health2 = primaryFTMgr.GetPeerVMComponentHealth(primaryVm) if health.isStorageHealthy != health2.isStorageHealthy or \ health.isNetworkHealthy != health2.isNetworkHealthy: Log("Got peer health information : " + str(health2)) raise Exception("Peer health information does not match") # Mark primary as unhealthy health.SetIsStorageHealthy(False) health.SetIsNetworkHealthy(True) primaryFTMgr.SetLocalVMComponentHealth(primaryVm, health) Log("VMotion secondary to tertiary host") vm.Migrate(secondaryVm, secondarySi, tertiarySi, secondaryCfgPath, False) secondaryFTMgr = host.GetFaultToleranceMgr(tertiarySi) connect.SetSi(tertiarySi) secondaryVm = folder.Find(secondaryName) CheckFTState(primaryVm, Vim.VirtualMachine.FaultToleranceState.running, tertiarySi) CheckFTState(secondaryVm, Vim.VirtualMachine.FaultToleranceState.running, tertiarySi, False) # Verify primary health has propagated to secondary on new host health2 = secondaryFTMgr.GetPeerVMComponentHealth(secondaryVm) if health.isStorageHealthy != health2.isStorageHealthy or \ health.isNetworkHealthy != health2.isNetworkHealthy: Log("Got peer health information : " + str(health2)) raise Exception("Peer health information does not match") Log("Power off Primary VM") connect.SetSi(tertiarySi) vm.PowerOff(primaryVm) WaitForPowerState(primaryVm, tertiarySi, Vim.VirtualMachine.PowerState.poweredOff) WaitForPowerState(secondaryVm, primarySi, Vim.VirtualMachine.PowerState.poweredOff) if not useExisting: Log("Cleaning up VMs") CleanupVm(primaryName) CleanupVm(secondaryName, True) else: # Skipped VMotion test Log("Power off Primary VM") connect.SetSi(primarySi) vm.PowerOff(primaryVm) WaitForPowerState(primaryVm, primarySi, Vim.VirtualMachine.PowerState.poweredOff) WaitForPowerState(secondaryVm, secondarySi, Vim.VirtualMachine.PowerState.poweredOff) if not useExisting: Log("Cleaning up VMs") CleanupVm(primaryName) connect.SetSi(secondarySi) CleanupVm(secondaryName, True) except Exception as e: Log("Caught exception : " + str(e)) global status status = "FAIL" Disconnect(primarySi) Disconnect(secondarySi) return Disconnect(primarySi) Disconnect(secondarySi)
def main(): supportedArgs = [ (["H:", "hosts="], "", "List of hosts (comma separated)", "hosts"), (["D:", "dcName="], "Datacenter", "datacenter name", "dcName"), (["d:", "dsName="], "storage1", "shared datastore name", "dsName"), (["dsMount="], "", "server:path of datastore to mount", "dsMount"), (["k:", "keep="], "0", "Keep configs", "keep"), (["l:", "leaveRunning="], False, "Leave FT VMs running", "leaveRunning"), (["L:", "leaveRegistered="], False, "Leave FT VMs configured but not powered on", "leaveRegistered"), (["e:", "useExistingVm="], False, "Use existing VM", "useExistingVm"), (["r:", "checkRRState="], "True", "Validate Record/Replay states", "checkRRState"), (["V:", "vc="], "", "VC Server name", "vc"), (["u:", "user="******"root", "User name", "user"), (["p:", "pwd="], "vmware", "Password", "pwd"), (["v:", "vmname="], "vmFT", "Name of the virtual machine", "vmname") ] supportedToggles = [(["usage", "help"], False, "Show usage information", "usage")] args = arguments.Arguments(sys.argv, supportedArgs, supportedToggles) if args.GetKeyValue("usage") == True: args.Usage() sys.exit(0) # Process command line primaryName = args.GetKeyValue("vmname") keep = int(args.GetKeyValue("keep")) vc = args.GetKeyValue("vc") leaveRegistered = bool(args.GetKeyValue("leaveRegistered")) leaveRunning = bool(args.GetKeyValue("leaveRunning")) useExistingVm = bool(args.GetKeyValue("useExistingVm")) global checkRRState checkRRState = eval(args.GetKeyValue("checkRRState")) dsName = args.GetKeyValue("dsName") dsMount = args.GetKeyValue("dsMount") dcName = args.GetKeyValue("dcName") hostList = args.GetKeyValue("hosts") hosts = re.split('\s*,\s*', hostList) hostSystems = [] # Connect to VC server global si Log("Connecting to %s" % vc) si = connect.Connect(host=vc, user=args.GetKeyValue("user"), pwd=args.GetKeyValue("pwd"), version=newestVersions.get('vim')) if si is None: raise Exception("Failed to connect to VC") connect.SetSi(si) Log("Connected to VC Server") dc = CreateOrUseDC(si, dcName) cluster = CreateOrUseCluster(dc, "HA") for host in hosts: hostSystem = GetHostByName(si, host) if hostSystem is not None and hostSystem.runtime.connectionState != "connected": task.WaitForTask(hostSystem.Destroy()) hostSystem = None if hostSystem == None: Log("Failed to find %s" % host) hostSystem = AddHostToCluster(si, cluster, host) hostSystems.append(hostSystem) if len(FindNicType(si, hostSystem, ftLoggingNicType)) == 0: SelectVnic(si, hostSystem, "vmk0", ftLoggingNicType) if len(FindNicType(si, hostSystem, vmotionNicType)) == 0: SelectVnic(si, hostSystem, "vmk0", vmotionNicType) ds = FindDS(hostSystem, dsName) if ds is None and dsMount: MountNas(hostSystem, dsName, dsMount, accessMode="readWrite") secondaryName = primaryName orphanedSecondaryName = primaryName + "_orphaned" global primaryVm global secondaryVm primaryVm = None si = None try: CleanupVm(primaryName) # Create new VM primaryVm = None if useExistingVm: primaryVm = folder.Find(primaryName) if primaryVm == None: raise Exception("No primary VM with name " + primaryName + " found!") Log("Using primary VM " + primaryName) else: Log("Creating primary VM " + primaryName) # Short delay to avoid colliding with a cleanup. time.sleep(5) primaryVm = vm.CreateQuickDummy(primaryName, guest="winXPProGuest", cdrom=0, numScsiDisks=2, scrubDisks=False, datastoreName=dsName, vmxVersion="vmx-09", dc=dcName) spec = vim.vm.ConfigSpec(numCPUs=2) task.WaitForTask(primaryVm.Reconfigure(spec)) # Get details about primary VM primaryUuid = primaryVm.GetConfig().GetInstanceUuid() primaryCfgPath = primaryVm.GetConfig().GetFiles().GetVmPathName() primaryDir = primaryCfgPath[:primaryCfgPath.rfind("/")] Log("Using VM : " + primaryVm.GetName() + " with instanceUuid " + primaryUuid) CheckFTState(primaryVm, FTState.notConfigured) # Create secondary VM Log("Creating secondary VM " + secondaryName) HandleAction("on") if secondaryVm == None: raise "Secondary VM creation failed" ## Configure some additional config variables needed for FT ## This should eventually be done automatically at FT Vmotion time Log("Setting up extra config settings for the primary VM...") extraCfgs = primaryVm.GetConfig().GetExtraConfig() # AddExtraConfig(extraCfgs, "replay.allowBTOnly", "TRUE") # AddExtraConfig(extraCfgs, "replay.allowFT", "TRUE") cSpec = vim.Vm.ConfigSpec() cSpec.SetExtraConfig(extraCfgs) task.WaitForTask(primaryVm.Reconfigure(cSpec)) Log("FT configured successfully.") # Test snapshot #SnapshotTests(primaryVm) Log("PowerOn") task.WaitForTask(primaryVm.PowerOn()) WaitForRunning() time.sleep(5) # We are now in a good known state, start random testing while True: action = random.choice(ACTION_LIST) revAction = REV_ACTION[action] HandleActions(action, revAction) except Exception as e: Log("Caught exception : " + str(e)) traceback.print_exc() global status status = "FAIL" finally: connect.Disconnect(si)