vmware: Fix VMware OVF properties copy from template (#4738)

* Fix VMware OVF properties copy from template

* Fix vapp marvin test

* Remove unused code

* Fix check for deploy as is details

* Access class fields
This commit is contained in:
Nicolas Vazquez 2021-04-12 09:34:58 -03:00 committed by GitHub
parent a64ad9d9b7
commit 9cf1e0e869
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 54 deletions

View File

@ -59,6 +59,7 @@ import org.apache.cloudstack.storage.to.VolumeObjectTO;
import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo; import org.apache.cloudstack.utils.volume.VirtualMachineDiskInfo;
import org.apache.cloudstack.vm.UnmanagedInstanceTO; import org.apache.cloudstack.vm.UnmanagedInstanceTO;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
@ -2336,7 +2337,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
configBasicExtraOption(extraOptions, vmSpec); configBasicExtraOption(extraOptions, vmSpec);
if (deployAsIs) { if (deployAsIs) {
setDeployAsIsProperties(vmMo, deployAsIsInfo, vmConfigSpec); setDeployAsIsProperties(vmMo, deployAsIsInfo, vmConfigSpec, hyperHost);
} }
configNvpExtraOption(extraOptions, vmSpec, nicUuidToDvSwitchUuid); configNvpExtraOption(extraOptions, vmSpec, nicUuidToDvSwitchUuid);
@ -2563,12 +2564,12 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
* Set OVF properties (if available) * Set OVF properties (if available)
*/ */
private void setDeployAsIsProperties(VirtualMachineMO vmMo, DeployAsIsInfoTO deployAsIsInfo, private void setDeployAsIsProperties(VirtualMachineMO vmMo, DeployAsIsInfoTO deployAsIsInfo,
VirtualMachineConfigSpec vmConfigSpec) throws Exception { VirtualMachineConfigSpec vmConfigSpec, VmwareHypervisorHost hyperHost) throws Exception {
if (deployAsIsInfo != null) { if (deployAsIsInfo != null && MapUtils.isNotEmpty(deployAsIsInfo.getProperties())) {
Map<String, String> properties = deployAsIsInfo.getProperties(); Map<String, String> properties = deployAsIsInfo.getProperties();
VmConfigInfo vAppConfig = vmMo.getConfigInfo().getVAppConfig(); VmConfigInfo vAppConfig = vmMo.getConfigInfo().getVAppConfig();
s_logger.info("Copying OVF properties to the values the user provided"); s_logger.info("Copying OVF properties to the values the user provided");
setVAppPropertiesToConfigSpec(vAppConfig, properties, vmConfigSpec); setVAppPropertiesToConfigSpec(vAppConfig, properties, vmConfigSpec, hyperHost);
} }
} }
@ -2660,13 +2661,13 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
/** /**
* Set the ovf section spec from existing vApp configuration * Set the ovf section spec from existing vApp configuration
*/ */
protected List<VAppOvfSectionSpec> copyVAppConfigOvfSectionFromOVF(VmConfigInfo vAppConfig) { protected List<VAppOvfSectionSpec> copyVAppConfigOvfSectionFromOVF(VmConfigInfo vAppConfig, boolean useEdit) {
List<VAppOvfSectionInfo> ovfSection = vAppConfig.getOvfSection(); List<VAppOvfSectionInfo> ovfSection = vAppConfig.getOvfSection();
List<VAppOvfSectionSpec> specs = new ArrayList<>(); List<VAppOvfSectionSpec> specs = new ArrayList<>();
for (VAppOvfSectionInfo info : ovfSection) { for (VAppOvfSectionInfo info : ovfSection) {
VAppOvfSectionSpec spec = new VAppOvfSectionSpec(); VAppOvfSectionSpec spec = new VAppOvfSectionSpec();
spec.setInfo(info); spec.setInfo(info);
spec.setOperation(ArrayUpdateOperation.ADD); spec.setOperation(useEdit ? ArrayUpdateOperation.EDIT : ArrayUpdateOperation.ADD);
specs.add(spec); specs.add(spec);
} }
return specs; return specs;
@ -2694,7 +2695,8 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
/** /**
* Set the properties section from existing vApp configuration and values set on ovfProperties * Set the properties section from existing vApp configuration and values set on ovfProperties
*/ */
protected List<VAppPropertySpec> copyVAppConfigPropertySectionFromOVF(VmConfigInfo vAppConfig, Map<String, String> ovfProperties) { protected List<VAppPropertySpec> copyVAppConfigPropertySectionFromOVF(VmConfigInfo vAppConfig, Map<String, String> ovfProperties,
boolean useEdit) {
List<VAppPropertyInfo> productFromOvf = vAppConfig.getProperty(); List<VAppPropertyInfo> productFromOvf = vAppConfig.getProperty();
List<VAppPropertySpec> specs = new ArrayList<>(); List<VAppPropertySpec> specs = new ArrayList<>();
for (VAppPropertyInfo info : productFromOvf) { for (VAppPropertyInfo info : productFromOvf) {
@ -2702,9 +2704,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
if (ovfProperties.containsKey(info.getId())) { if (ovfProperties.containsKey(info.getId())) {
String value = ovfProperties.get(info.getId()); String value = ovfProperties.get(info.getId());
info.setValue(value); info.setValue(value);
s_logger.info("Setting OVF property ID = " + info.getId() + " VALUE = " + value);
} }
spec.setInfo(info); spec.setInfo(info);
spec.setOperation(ArrayUpdateOperation.ADD); spec.setOperation(useEdit ? ArrayUpdateOperation.EDIT : ArrayUpdateOperation.ADD);
specs.add(spec); specs.add(spec);
} }
return specs; return specs;
@ -2713,13 +2716,14 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
/** /**
* Set the product section spec from existing vApp configuration * Set the product section spec from existing vApp configuration
*/ */
protected List<VAppProductSpec> copyVAppConfigProductSectionFromOVF(VmConfigInfo vAppConfig) { protected List<VAppProductSpec> copyVAppConfigProductSectionFromOVF(VmConfigInfo vAppConfig, boolean useEdit) {
List<VAppProductInfo> productFromOvf = vAppConfig.getProduct(); List<VAppProductInfo> productFromOvf = vAppConfig.getProduct();
List<VAppProductSpec> specs = new ArrayList<>(); List<VAppProductSpec> specs = new ArrayList<>();
for (VAppProductInfo info : productFromOvf) { for (VAppProductInfo info : productFromOvf) {
VAppProductSpec spec = new VAppProductSpec(); VAppProductSpec spec = new VAppProductSpec();
spec.setInfo(info); spec.setInfo(info);
spec.setOperation(ArrayUpdateOperation.ADD); s_logger.info("Procuct info KEY " + info.getKey());
spec.setOperation(useEdit ? ArrayUpdateOperation.EDIT : ArrayUpdateOperation.ADD);
specs.add(spec); specs.add(spec);
} }
return specs; return specs;
@ -2731,16 +2735,19 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa
*/ */
protected void setVAppPropertiesToConfigSpec(VmConfigInfo vAppConfig, protected void setVAppPropertiesToConfigSpec(VmConfigInfo vAppConfig,
Map<String, String> ovfProperties, Map<String, String> ovfProperties,
VirtualMachineConfigSpec vmConfig) throws Exception { VirtualMachineConfigSpec vmConfig, VmwareHypervisorHost hyperHost) throws Exception {
VmConfigSpec vmConfigSpec = new VmConfigSpec(); VmConfigSpec vmConfigSpec = new VmConfigSpec();
vmConfigSpec.getEula().addAll(vAppConfig.getEula()); vmConfigSpec.getEula().addAll(vAppConfig.getEula());
vmConfigSpec.setInstallBootStopDelay(vAppConfig.getInstallBootStopDelay()); vmConfigSpec.setInstallBootStopDelay(vAppConfig.getInstallBootStopDelay());
vmConfigSpec.setInstallBootRequired(vAppConfig.isInstallBootRequired()); vmConfigSpec.setInstallBootRequired(vAppConfig.isInstallBootRequired());
vmConfigSpec.setIpAssignment(vAppConfig.getIpAssignment()); vmConfigSpec.setIpAssignment(vAppConfig.getIpAssignment());
vmConfigSpec.getOvfEnvironmentTransport().addAll(vAppConfig.getOvfEnvironmentTransport()); vmConfigSpec.getOvfEnvironmentTransport().addAll(vAppConfig.getOvfEnvironmentTransport());
vmConfigSpec.getProduct().addAll(copyVAppConfigProductSectionFromOVF(vAppConfig));
vmConfigSpec.getProperty().addAll(copyVAppConfigPropertySectionFromOVF(vAppConfig, ovfProperties)); // For backward compatibility, prior to Vmware 6.5 use EDIT operation instead of ADD
vmConfigSpec.getOvfSection().addAll(copyVAppConfigOvfSectionFromOVF(vAppConfig)); boolean useEditOperation = hyperHost.getContext().getServiceContent().getAbout().getApiVersion().compareTo("6.5") < 1;
vmConfigSpec.getProduct().addAll(copyVAppConfigProductSectionFromOVF(vAppConfig, useEditOperation));
vmConfigSpec.getProperty().addAll(copyVAppConfigPropertySectionFromOVF(vAppConfig, ovfProperties, useEditOperation));
vmConfigSpec.getOvfSection().addAll(copyVAppConfigOvfSectionFromOVF(vAppConfig, useEditOperation));
vmConfig.setVAppConfig(vmConfigSpec); vmConfig.setVAppConfig(vmConfigSpec);
} }

View File

@ -61,7 +61,6 @@ from operator import itemgetter
_multiprocess_shared_ = True _multiprocess_shared_ = True
class TestDeployVM(cloudstackTestCase): class TestDeployVM(cloudstackTestCase):
@classmethod @classmethod
@ -1750,9 +1749,6 @@ class TestVAppsVM(cloudstackTestCase):
cls.l2_network_offering cls.l2_network_offering
] ]
# Uncomment when tests are finished, to cleanup the test templates
for template in cls.templates:
cls._cleanup.append(template)
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):
@ -1774,21 +1770,21 @@ class TestVAppsVM(cloudstackTestCase):
def get_ova_parsed_information_from_template(self, template): def get_ova_parsed_information_from_template(self, template):
if not template: if not template:
return None return None
details = template.details.__dict__ details = template.deployasisdetails.__dict__
configurations = [] configurations = []
disks = [] disks = []
isos = [] isos = []
networks = [] networks = []
for propKey in details: for propKey in details:
if propKey.startswith('ACS-configuration'): if propKey.startswith('configuration'):
configurations.append(json.loads(details[propKey])) configurations.append(json.loads(details[propKey]))
elif propKey.startswith('ACS-disk'): elif propKey.startswith('disk'):
detail = json.loads(details[propKey]) detail = json.loads(details[propKey])
if detail['isIso'] == True: if detail['isIso'] == True:
isos.append(detail) isos.append(detail)
else: else:
disks.append(detail) disks.append(detail)
elif propKey.startswith('ACS-network'): elif propKey.startswith('network'):
networks.append(json.loads(details[propKey])) networks.append(json.loads(details[propKey]))
return configurations, disks, isos, networks return configurations, disks, isos, networks
@ -1818,32 +1814,6 @@ class TestVAppsVM(cloudstackTestCase):
msg="VM NIC(InstanceID: {}) network mismatch, expected = {}, result = {}".format(nic_network["nic"], nic_network["network"], nic.networkid) msg="VM NIC(InstanceID: {}) network mismatch, expected = {}, result = {}".format(nic_network["nic"], nic_network["network"], nic.networkid)
) )
def verify_disks(self, template_disks, vm_id):
cmd = listVolumes.listVolumesCmd()
cmd.virtualmachineid = vm_id
cmd.listall = True
vm_volumes = self.apiclient.listVolumes(cmd)
self.assertEqual(
isinstance(vm_volumes, list),
True,
"Check listVolumes response returns a valid list"
)
self.assertEqual(
len(template_disks),
len(vm_volumes),
msg="VM volumes count is different, expected = {}, result = {}".format(len(template_disks), len(vm_volumes))
)
template_disks.sort(key=itemgetter('diskNumber'))
vm_volumes.sort(key=itemgetter('deviceid'))
for j in range(len(vm_volumes)):
volume = vm_volumes[j]
disk = template_disks[j]
self.assertEqual(
volume.size,
disk["virtualSize"],
msg="VM Volume(diskNumber: {}) network mismatch, expected = {}, result = {}".format(disk["diskNumber"], disk["virtualSize"], volume.size)
)
@attr(tags=["advanced", "advancedns", "smoke", "sg", "dev"], required_hardware="false") @attr(tags=["advanced", "advancedns", "smoke", "sg", "dev"], required_hardware="false")
@skipTestIf("hypervisorNotSupported") @skipTestIf("hypervisorNotSupported")
def test_01_vapps_vm_cycle(self): def test_01_vapps_vm_cycle(self):
@ -1944,8 +1914,6 @@ class TestVAppsVM(cloudstackTestCase):
# Verify nics # Verify nics
self.verify_nics(nicnetworklist, vm.id) self.verify_nics(nicnetworklist, vm.id)
# Verify disks
self.verify_disks(disks, vm.id)
# Verify properties # Verify properties
original_properties = vm_service['properties'] original_properties = vm_service['properties']
vm_properties = get_vm_vapp_configs(self.apiclient, self.config, self.zone, vm.instancename) vm_properties = get_vm_vapp_configs(self.apiclient, self.config, self.zone, vm.instancename)

View File

@ -429,21 +429,21 @@ def get_test_ovf_templates(apiclient, zone_id=None, test_ovf_templates=None, hyp
template = Template.register(apiclient, test_template, zoneid=zone_id, hypervisor=hypervisor.lower(), randomize_name=False) template = Template.register(apiclient, test_template, zoneid=zone_id, hypervisor=hypervisor.lower(), randomize_name=False)
template.download(apiclient) template.download(apiclient)
retries = 3 retries = 3
while (template.details == None or len(template.details.__dict__) == 0) and retries > 0: while (not hasattr(template, 'deployasisdetails') or len(template.deployasisdetails.__dict__) == 0) and retries > 0:
time.sleep(10) time.sleep(10)
template_list = Template.list(apiclient, id=template.id, zoneid=zone_id, templatefilter='all') template_list = Template.list(apiclient, id=template.id, zoneid=zone_id, templatefilter='all')
if isinstance(template_list, list): if isinstance(template_list, list):
template = Template(template_list[0].__dict__) template = Template(template_list[0].__dict__)
retries = retries - 1 retries = retries - 1
if template.details == None or len(template.details.__dict__) == 0: if not hasattr(template, 'deployasisdetails') or len(template.deployasisdetails.__dict__) == 0:
template.delete(apiclient) template.delete(apiclient)
else: else:
result.append(template) result.append(template)
if templates: if templates:
for template in templates: for template in templates:
if template.isready and template.ispublic and template.details != None and len(template.details.__dict__) > 0: if template.isready and template.ispublic and template.deployasisdetails and len(template.deployasisdetails.__dict__) > 0:
result.append(template.__dict__) result.append(template)
return result return result