diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java index 986000aa938..64ca4067cee 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/guru/VMwareGuru.java @@ -31,13 +31,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; import org.apache.cloudstack.framework.config.ConfigKey; import org.apache.cloudstack.framework.config.Configurable; -import org.apache.cloudstack.framework.config.dao.ConfigurationDao; import org.apache.cloudstack.storage.command.CopyCommand; import org.apache.cloudstack.storage.command.DeleteCommand; import org.apache.cloudstack.storage.command.StorageSubSystemCommand; import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao; import org.apache.cloudstack.storage.datastore.db.StoragePoolVO; import org.apache.cloudstack.storage.to.VolumeObjectTO; +import org.apache.commons.lang.BooleanUtils; import org.apache.log4j.Logger; import com.cloud.agent.api.BackupSnapshotCommand; @@ -57,7 +57,6 @@ import com.cloud.agent.api.to.DiskTO; import com.cloud.agent.api.to.NicTO; import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.cluster.ClusterManager; -import com.cloud.configuration.Config; import com.cloud.exception.InsufficientAddressCapacityException; import com.cloud.host.Host; import com.cloud.host.HostVO; @@ -127,8 +126,6 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co @Inject private NetworkModel _networkMgr; @Inject - private ConfigurationDao _configDao; - @Inject private NicDao _nicDao; @Inject private PhysicalNetworkTrafficTypeDao _physicalNetworkTrafficTypeDao; @@ -155,6 +152,12 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co "Specify whether or not to reserve memory when not overprovisioning, In case of memory overprovisioning we will always reserve memory.", true, ConfigKey.Scope.Cluster, null); + protected ConfigKey VmwareEnableNestedVirtualization = new ConfigKey(Boolean.class, "vmware.nested.virtualization", "Advanced", "false", + "When set to true this will enable nested virtualization when this is supported by the hypervisor", true, ConfigKey.Scope.Global, null); + + protected ConfigKey VmwareEnableNestedVirtualizationPerVM = new ConfigKey(Boolean.class, "vmware.nested.virtualization.perVM", "Advanced", "false", + "When set to true this will enable nested virtualization per vm", true, ConfigKey.Scope.Global, null); + @Override public HypervisorType getHypervisorType() { return HypervisorType.VMware; @@ -306,13 +309,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co // Don't do this if the virtual machine is one of the special types // Should only be done on user machines if (userVm) { - String nestedVirt = _configDao.getValue(Config.VmwareEnableNestedVirtualization.key()); - if (nestedVirt != null) { - s_logger.debug("Nested virtualization requested, adding flag to vm configuration"); - details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, nestedVirt); - to.setDetails(details); - - } + configureNestedVirtualization(details, to); } // Determine the VM's OS description GuestOSVO guestOS = _guestOsDao.findByIdIncludingRemoved(vm.getVirtualMachine().getGuestOSId()); @@ -331,6 +328,50 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co return to; } + /** + * Decide in which cases nested virtualization should be enabled based on (1){@code globalNestedV}, (2){@code globalNestedVPerVM}, (3){@code localNestedV}
+ * Nested virtualization should be enabled when one of this cases: + *
    + *
  • (1)=TRUE, (2)=TRUE, (3) is NULL (missing)
  • + *
  • (1)=TRUE, (2)=TRUE, (3)=TRUE
  • + *
  • (1)=TRUE, (2)=FALSE
  • + *
  • (1)=FALSE, (2)=TRUE, (3)=TRUE
  • + *
+ * In any other case, it shouldn't be enabled + * @param globalNestedV value of {@code 'vmware.nested.virtualization'} global config + * @param globalNestedVPerVM value of {@code 'vmware.nested.virtualization.perVM'} global config + * @param localNestedV value of {@code 'nestedVirtualizationFlag'} key in vm details if present, null if not present + * @return "true" for cases in which nested virtualization is enabled, "false" if not + */ + protected Boolean shouldEnableNestedVirtualization(Boolean globalNestedV, Boolean globalNestedVPerVM, String localNestedV){ + if (globalNestedV == null || globalNestedVPerVM == null) { + return false; + } + boolean globalNV = globalNestedV.booleanValue(); + boolean globalNVPVM = globalNestedVPerVM.booleanValue(); + + if (globalNVPVM){ + return (localNestedV == null && globalNV) || BooleanUtils.toBoolean(localNestedV); + } + return globalNV; + } + + /** + * Adds {@code 'nestedVirtualizationFlag'} value to {@code details} due to if it should be enabled or not + * @param details vm details + * @param to vm to + */ + protected void configureNestedVirtualization(Map details, VirtualMachineTO to) { + Boolean globalNestedV = VmwareEnableNestedVirtualization.value(); + Boolean globalNestedVPerVM = VmwareEnableNestedVirtualizationPerVM.value(); + String localNestedV = details.get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG); + + Boolean shouldEnableNestedVirtualization = shouldEnableNestedVirtualization(globalNestedV, globalNestedVPerVM, localNestedV); + s_logger.debug("Nested virtualization requested, adding flag to vm configuration"); + details.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Boolean.toString(shouldEnableNestedVirtualization)); + to.setDetails(details); + } + private long getClusterId(long vmId) { long clusterId; Long hostId; @@ -525,7 +566,7 @@ public class VMwareGuru extends HypervisorGuruBase implements HypervisorGuru, Co @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {VmwareReserveCpu, VmwareReserveMemory}; + return new ConfigKey[] {VmwareReserveCpu, VmwareReserveMemory, VmwareEnableNestedVirtualization, VmwareEnableNestedVirtualizationPerVM}; } @Override diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 522b8ae0440..9f38cae8fd9 100644 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -2208,7 +2208,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return new Pair(vmInternalCSName, vmNameOnVcenter); } - private static void configNestedHVSupport(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec) throws Exception { + protected void configNestedHVSupport(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec) throws Exception { VmwareContext context = vmMo.getContext(); if ("true".equals(vmSpec.getDetails().get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG))) { diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/guru/VMwareGuruTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/guru/VMwareGuruTest.java new file mode 100755 index 00000000000..77042fd8307 --- /dev/null +++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/guru/VMwareGuruTest.java @@ -0,0 +1,157 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.hypervisor.guru; + +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.inOrder; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.cloudstack.framework.config.ConfigKey; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.cloud.agent.api.to.VirtualMachineTO; +import com.cloud.vm.VmDetailConstants; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({ConfigKey.class, VMwareGuru.class}) +@ContextConfiguration(loader = AnnotationConfigContextLoader.class) +public class VMwareGuruTest { + + @Mock(name="VmwareEnableNestedVirtualization") + private ConfigKey vmwareNestedVirtualizationConfig; + + @Mock(name="VmwareEnableNestedVirtualizationPerVM") + private ConfigKey vmwareNestedVirtualizationPerVmConfig; + + @Spy + @InjectMocks + private VMwareGuru _guru = new VMwareGuru(); + + @Mock + VirtualMachineTO vmTO; + + private Map vmDetails = new HashMap(); + + @Before + public void testSetUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + private void setConfigValues(Boolean globalNV, Boolean globalNVPVM, String localNV){ + when(vmwareNestedVirtualizationConfig.value()).thenReturn(globalNV); + when(vmwareNestedVirtualizationPerVmConfig.value()).thenReturn(globalNVPVM); + if (localNV != null) { + vmDetails.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, localNV); + } + } + + private void executeAndVerifyTest(Boolean globalNV, Boolean globalNVPVM, String localNV, Boolean expectedResult){ + Boolean result = _guru.shouldEnableNestedVirtualization(globalNV, globalNVPVM, localNV); + assertEquals(expectedResult, result); + } + + @Test + public void testConfigureNestedVirtualization(){ + setConfigValues(true, true, null); + _guru.configureNestedVirtualization(vmDetails, vmTO); + + InOrder inOrder = inOrder(_guru, vmTO); + inOrder.verify(_guru).shouldEnableNestedVirtualization(true, true, null); + inOrder.verify(vmTO).setDetails(vmDetails); + + assertTrue(vmDetails.containsKey(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG)); + assertEquals(Boolean.toString(true), vmDetails.get(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG)); + + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMTrueLocalNVNull(){ + executeAndVerifyTest(true, true, null, true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMTrueLocalNVTrue(){ + executeAndVerifyTest(true, true, "true", true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMTrueLocalNVFalse(){ + executeAndVerifyTest(true, true, "false", false); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMFalseLocalNVNull(){ + executeAndVerifyTest(true, false, null, true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMFalseLocalNVTrue(){ + executeAndVerifyTest(true, false, "true", true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVTrueGlobalNVPVMFalseLocalNVNFalse(){ + executeAndVerifyTest(true, false, "false", true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMTrueLocalNVNull(){ + executeAndVerifyTest(false, true, null, false); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMTrueLocalNVTrue(){ + executeAndVerifyTest(false, true, "true", true); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMTrueLocalNVFalse(){ + executeAndVerifyTest(false, true, "false", false); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMFalseLocalNVNull(){ + executeAndVerifyTest(false, false, null, false); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMFalseLocalNVTrue(){ + executeAndVerifyTest(false, false, "true", false); + } + + @Test + public void testEnableNestedVirtualizationCaseGlobalNVFalseGlobalNVPVMFalseLocalNVFalse(){ + executeAndVerifyTest(false, false, "false", false); + } + +} diff --git a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java index 6f411dcca39..744c93aa403 100644 --- a/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java +++ b/plugins/hypervisors/vmware/test/com/cloud/hypervisor/vmware/resource/VmwareResourceTest.java @@ -51,7 +51,9 @@ import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; +import com.vmware.vim25.HostCapability; import com.vmware.vim25.ManagedObjectReference; +import com.vmware.vim25.VimPortType; import com.vmware.vim25.VirtualDevice; import com.vmware.vim25.VirtualDeviceConfigSpec; import com.vmware.vim25.VirtualMachineConfigSpec; @@ -65,9 +67,12 @@ import com.cloud.agent.api.to.VirtualMachineTO; import com.cloud.agent.api.to.VolumeTO; import com.cloud.hypervisor.vmware.mo.DatacenterMO; import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.hypervisor.vmware.mo.HostMO; import com.cloud.hypervisor.vmware.mo.VirtualMachineMO; import com.cloud.hypervisor.vmware.mo.VmwareHypervisorHost; +import com.cloud.hypervisor.vmware.util.VmwareClient; import com.cloud.hypervisor.vmware.util.VmwareContext; +import com.cloud.vm.VmDetailConstants; import com.cloud.storage.resource.VmwareStorageProcessor; import com.cloud.storage.resource.VmwareStorageSubsystemCommandHandler; import com.cloud.storage.resource.VmwareStorageProcessor.VmwareStorageProcessorConfigurableFields; @@ -135,6 +140,20 @@ public class VmwareResourceTest { DataTO destDataTO; @Mock PrimaryDataStoreTO destDataStoreTO; + @Mock + HostMO host; + @Mock + ManagedObjectReference hostRef; + @Mock + ManagedObjectReference computeRef; + @Mock + ManagedObjectReference envRef; + @Mock + VmwareClient client; + @Mock + VimPortType vimService; + @Mock + HostCapability hostCapability; CopyCommand storageCmd; EnumMap params = new EnumMap(VmwareStorageProcessorConfigurableFields.class); @@ -145,6 +164,8 @@ public class VmwareResourceTest { private static final long VIDEO_CARD_MEMORY_SIZE = 65536l; private static final Boolean FULL_CLONE_FLAG = true; + private Map specsArray = new HashMap(); + @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); @@ -163,6 +184,17 @@ public class VmwareResourceTest { when(destDataTO.getDataStore()).thenReturn(destDataStoreTO); when(destDataStoreTO.isFullCloneFlag()).thenReturn(FULL_CLONE_FLAG); when(volume.getPath()).thenReturn(VOLUME_PATH); + when(vmSpec.getDetails()).thenReturn(specsArray); + + when(vmMo.getContext()).thenReturn(context); + when(vmMo.getRunningHost()).thenReturn(host); + when(host.getMor()).thenReturn(hostRef); + when(context.getVimClient()).thenReturn(client); + when(client.getMoRefProp(hostRef, "parent")).thenReturn(computeRef); + when(client.getMoRefProp(computeRef, "environmentBrowser")).thenReturn(envRef); + when(context.getService()).thenReturn(vimService); + when(vimService.queryTargetCapabilities(envRef, hostRef)).thenReturn(hostCapability); + when(hostCapability.isNestedHVSupported()).thenReturn(true); } //Test successful scaling up the vm @@ -348,4 +380,28 @@ public class VmwareResourceTest { VirtualMachineMO result = _resource.findVmOnDatacenter(context, hyperHost, volume); assertEquals(vmMo, result); } + + @Test + public void testConfigNestedHVSupportFlagTrue() throws Exception{ + specsArray.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, "true"); + _resource.configNestedHVSupport(vmMo, vmSpec, vmConfigSpec); + verify(vmMo).getRunningHost(); + verify(host).getMor(); + verify(context, times(2)).getVimClient(); + verify(client).getMoRefProp(hostRef, "parent"); + verify(client).getMoRefProp(computeRef, "environmentBrowser"); + verify(context).getService(); + verify(vimService).queryTargetCapabilities(envRef, hostRef); + verify(hostCapability).isNestedHVSupported(); + + verify(vmConfigSpec).setNestedHVEnabled(true); + } + + @Test + public void testConfigNestedHVSupportFlagFalse() throws Exception{ + specsArray.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, "false"); + _resource.configNestedHVSupport(vmMo, vmSpec, vmConfigSpec); + verify(vmMo, never()).getRunningHost(); + } + } diff --git a/server/src/com/cloud/configuration/Config.java b/server/src/com/cloud/configuration/Config.java index ed7f1619879..851b868c2d8 100644 --- a/server/src/com/cloud/configuration/Config.java +++ b/server/src/com/cloud/configuration/Config.java @@ -1220,14 +1220,6 @@ public enum Config { "Specify whether or not to recycle hung worker VMs", null), VmwareHungWorkerTimeout("Advanced", ManagementServer.class, Long.class, "vmware.hung.wokervm.timeout", "7200", "Worker VM timeout in seconds", null), - VmwareEnableNestedVirtualization( - "Advanced", - ManagementServer.class, - Boolean.class, - "vmware.nested.virtualization", - "false", - "When set to true this will enable nested virtualization when this is supported by the hypervisor", - null), VmwareVcenterSessionTimeout("Advanced", ManagementServer.class, Long.class, "vmware.vcenter.session.timeout", "1200", "VMware client timeout in seconds", null), // Midonet diff --git a/test/integration/smoke/test_nested_virtualization.py b/test/integration/smoke/test_nested_virtualization.py new file mode 100755 index 00000000000..3b03f776cad --- /dev/null +++ b/test/integration/smoke/test_nested_virtualization.py @@ -0,0 +1,152 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" Tests for Nested Virtualization +""" +#Import Local Modules +from marvin.codes import FAILED +from marvin.cloudstackTestCase import cloudstackTestCase +from marvin.lib.utils import (cleanup_resources, + get_hypervisor_type, + get_process_status) +from marvin.lib.base import (Account, + ServiceOffering, + NetworkOffering, + Configurations, + VirtualMachine, + Network) +from marvin.lib.common import (get_zone, + get_domain, + get_template) +from nose.plugins.attrib import attr +from marvin.sshClient import SshClient +import logging + +class TestNestedVirtualization(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + testClient = super(TestNestedVirtualization, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + cls.logger = logging.getLogger('TestNestedVirtualization') + cls.stream_handler = logging.StreamHandler() + cls.logger.setLevel(logging.DEBUG) + cls.logger.addHandler(cls.stream_handler) + + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + cls.services["isolated_network"]["zoneid"] = cls.zone.id + cls.domain = get_domain(cls.apiclient) + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offerings"]["tiny"] + ) + cls.account = Account.create(cls.apiclient, services=cls.services["account"]) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.hypervisor = get_hypervisor_type(cls.apiclient) + + cls.isolated_network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["isolated_network_offering"]) + # Enable Isolated Network offering + cls.isolated_network_offering.update(cls.apiclient, state='Enabled') + + if cls.template == FAILED: + assert False, "get_template() failed to return template with description %s" % cls.services["ostype"] + + cls.services["small"]["zoneid"] = cls.zone.id + cls.services["small"]["template"] = cls.template.id + + cls.cleanup = [cls.account] + + @attr(tags=["advanced"], required_hardware="true") + def test_nested_virtualization_vmware(self): + """Test nested virtualization on Vmware hypervisor""" + if self.hypervisor.lower() not in ["vmware"]: + self.skipTest("Skipping test because suitable hypervisor/host not present") + + # 1) Update nested virtualization configurations, if needed + configs = Configurations.list(self.apiclient, name="vmware.nested.virtualization") + rollback_nv = False + rollback_nv_per_vm = False + for conf in configs: + if (conf.name == "vmware.nested.virtualization" and conf.value == "false"): + config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization", "true") + self.logger.debug("Updated global setting vmware.nested.virtualization to true") + rollback_nv = True + elif (conf.name == "vmware.nested.virtualization.perVM" and conf.value == "false"): + config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization.perVM", "true") + self.logger.debug("Updated global setting vmware.nested.virtualization.perVM to true") + rollback_nv_per_vm = True + + # 2) Deploy a vm + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["small"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + mode=self.services['mode'] + ) + self.assert_(virtual_machine is not None, "VM failed to deploy") + self.assert_(virtual_machine.state == 'Running', "VM is not running") + self.logger.debug("Deployed vm: %s" % virtual_machine.id) + + isolated_network = Network.create( + self.apiclient, + self.services["isolated_network"], + self.account.name, + self.account.domainid, + networkofferingid=self.isolated_network_offering.id) + + virtual_machine.add_nic(self.apiclient, isolated_network.id) + + # 3) SSH into vm + ssh_client = virtual_machine.get_ssh_client() + + if ssh_client: + # run ping test + result = ssh_client.execute("cat /proc/cpuinfo | grep flags") + self.logger.debug(result) + else: + self.fail("Failed to setup ssh connection to %s" % virtual_machine.public_ip) + + # 4) Revert configurations, if needed + if rollback_nv: + config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization", "false") + self.logger.debug("Reverted global setting vmware.nested.virtualization back to false") + if rollback_nv_per_vm: + config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization", "false") + self.logger.debug("Reverted global setting vmware.nested.virtualization.perVM back to false") + + #5) Check for CPU flags: vmx for Intel and svm for AMD indicates nested virtualization is enabled + self.assert_(result is not None, "Empty result for CPU flags") + res = str(result) + self.assertTrue('vmx' in res or 'svm' in res) + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.apiclient, cls.cleanup) + except Exception, e: + raise Exception("Cleanup failed with %s" % e) + \ No newline at end of file