vmware: Make deploy-as-is optional (#4901)

* [Vmware] Make deploy-as-is optional

* Do not use deployasis on create volume test

* Update api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java

Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* Update api/src/main/java/org/apache/cloudstack/api/command/user/template/RegisterTemplateCmd.java

Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* Review comments

* Refactor condition to select suitable template

Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Nicolas Vazquez 2021-04-30 01:17:50 -03:00 committed by GitHub
parent de30f3b7ee
commit 9349d20dd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 87 additions and 37 deletions

View File

@ -72,7 +72,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
private String format; private String format;
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true, description = "the target hypervisor for the template") @Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, required = true, description = "the target hypervisor for the template")
private String hypervisor; protected String hypervisor;
@Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN, description = "true if this template is a featured template, false otherwise") @Parameter(name = ApiConstants.IS_FEATURED, type = CommandType.BOOLEAN, description = "true if this template is a featured template, false otherwise")
private Boolean featured; private Boolean featured;
@ -162,6 +162,11 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
description = "true if template should bypass Secondary Storage and be downloaded to Primary Storage on deployment") description = "true if template should bypass Secondary Storage and be downloaded to Primary Storage on deployment")
private Boolean directDownload; private Boolean directDownload;
@Parameter(name=ApiConstants.DEPLOY_AS_IS,
type = CommandType.BOOLEAN,
description = "(VMware only) true if VM deployments should preserve all the configurations defined for this template", since = "4.15.1")
protected Boolean deployAsIs;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
/////////////////// Accessors /////////////////////// /////////////////// Accessors ///////////////////////
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -274,8 +279,9 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
return directDownload == null ? false : directDownload; return directDownload == null ? false : directDownload;
} }
public Boolean isDeployAsIs() { public boolean isDeployAsIs() {
return hypervisor != null && hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.VMware.toString()); return Hypervisor.HypervisorType.VMware.toString().equalsIgnoreCase(hypervisor) &&
Boolean.TRUE.equals(deployAsIs);
} }
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
@ -341,7 +347,7 @@ public class RegisterTemplateCmd extends BaseCmd implements UserCmd {
"Parameter directdownload is only allowed for KVM templates"); "Parameter directdownload is only allowed for KVM templates");
} }
if (!getHypervisor().equalsIgnoreCase(Hypervisor.HypervisorType.VMware.toString()) && osTypeId == null) { if (!isDeployAsIs() && osTypeId == null) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide a guest OS type"); throw new ServerApiException(ApiErrorCode.PARAM_ERROR, "Please provide a guest OS type");
} }
} }

View File

@ -20,6 +20,7 @@
package org.apache.cloudstack.api.command.user.template; package org.apache.cloudstack.api.command.user.template;
import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceAllocationException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.template.TemplateApiService; import com.cloud.template.TemplateApiService;
import org.apache.cloudstack.api.ApiErrorCode; import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.ServerApiException;
@ -32,7 +33,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import java.util.ArrayList; import java.util.ArrayList;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class RegisterTemplateCmdTest{ public class RegisterTemplateCmdTest {
@InjectMocks @InjectMocks
private RegisterTemplateCmd registerTemplateCmd; private RegisterTemplateCmd registerTemplateCmd;
@ -108,4 +109,34 @@ public class RegisterTemplateCmdTest{
registerTemplateCmd.zoneId = 1L; registerTemplateCmd.zoneId = 1L;
Assert.assertEquals((Long)1L,registerTemplateCmd.getZoneIds().get(0)); Assert.assertEquals((Long)1L,registerTemplateCmd.getZoneIds().get(0));
} }
private void testIsDeployAsIsBase(Hypervisor.HypervisorType hypervisorType, Boolean deployAsIsParameter, boolean expectedResult) {
registerTemplateCmd = new RegisterTemplateCmd();
registerTemplateCmd.hypervisor = hypervisorType.name();
registerTemplateCmd.deployAsIs = deployAsIsParameter;
boolean isDeployAsIs = registerTemplateCmd.isDeployAsIs();
Assert.assertEquals(expectedResult, isDeployAsIs);
}
@Test
public void testIsDeployAsIsVmwareNullAsIs() {
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, null, false);
}
@Test
public void testIsDeployAsIsVmwareNotAsIs() {
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, false, false);
}
@Test
public void testIsDeployAsIsVmwareAsIs() {
testIsDeployAsIsBase(Hypervisor.HypervisorType.VMware, true, true);
}
@Test
public void testIsDeployAsIsNonVmware() {
testIsDeployAsIsBase(Hypervisor.HypervisorType.KVM, true, false);
testIsDeployAsIsBase(Hypervisor.HypervisorType.XenServer, true, false);
testIsDeployAsIsBase(Hypervisor.HypervisorType.Any, true, false);
}
} }

View File

@ -291,7 +291,7 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
} }
Map details = cmd.getDetails(); Map details = cmd.getDetails();
if (hypervisorType == HypervisorType.VMware) { if (cmd.isDeployAsIs()) {
if (MapUtils.isNotEmpty(details)) { if (MapUtils.isNotEmpty(details)) {
if (details.containsKey(VmDetailConstants.ROOT_DISK_CONTROLLER)) { if (details.containsKey(VmDetailConstants.ROOT_DISK_CONTROLLER)) {
s_logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the template"); s_logger.info("Ignoring the rootDiskController detail provided, as we honour what is defined in the template");

View File

@ -260,8 +260,8 @@ class TestKubernetesCluster(cloudstackTestCase):
if validateList(templates)[0] != PASS: if validateList(templates)[0] != PASS:
details = None details = None
if hypervisor in ["vmware"]: if hypervisor in ["vmware"] and "details" in cks_template:
details = [{"keyboard": "us"}] details = cks_template["details"]
template = Template.register(cls.apiclient, cks_template, zoneid=cls.zone.id, hypervisor=hypervisor.lower(), randomize_name=False, details=details) template = Template.register(cls.apiclient, cks_template, zoneid=cls.zone.id, hypervisor=hypervisor.lower(), randomize_name=False, details=details)
template.download(cls.apiclient) template.download(cls.apiclient)
return template, False return template, False

View File

@ -59,6 +59,7 @@ class TestVMWareStoragePolicies(cloudstackTestCase):
cls.apiclient, cls.apiclient,
cls.zone.id, cls.zone.id,
cls.hypervisor, cls.hypervisor,
deploy_as_is=cls.hypervisor.lower() == "vmware"
) )
cls._cleanup.append(cls.network_offering) cls._cleanup.append(cls.network_offering)
return return

View File

@ -84,6 +84,7 @@ class TestCreateTemplateWithChecksum(cloudstackTestCase):
self.test_template.displaytext = 'test sha-1' self.test_template.displaytext = 'test sha-1'
self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova" self.test_template.url = "http://dl.openvm.eu/cloudstack/macchinina/x86_64/macchinina-vmware.ova"
self.test_template.format = "OVA" self.test_template.format = "OVA"
self.test_template.ostypeid = self.getOsType("Other Linux (64-bit)")
self.md5 = "27f3c56a8c7ec7b2f3ff2199f7078006" self.md5 = "27f3c56a8c7ec7b2f3ff2199f7078006"
self.sha256 = "a7b04c1eb507f3f5de844bda352df1ea5e20335b465409493ca6ae07dfd0a158" self.sha256 = "a7b04c1eb507f3f5de844bda352df1ea5e20335b465409493ca6ae07dfd0a158"

View File

@ -308,7 +308,8 @@ class TestVolumes(cloudstackTestCase):
cls.apiclient, cls.apiclient,
cls.zone.id, cls.zone.id,
cls.services["ostype"], cls.services["ostype"],
cls.hypervisor cls.hypervisor,
deploy_as_is=cls.hypervisor.lower() == "vmware"
) )
if cls.template == FAILED: if cls.template == FAILED:
assert False, "get_suitable_test_template() failed to return template with description %s" % cls.services["ostype"] assert False, "get_suitable_test_template() failed to return template with description %s" % cls.services["ostype"]

View File

@ -1403,24 +1403,22 @@ class Template:
elif "hypervisor" in services: elif "hypervisor" in services:
cmd.hypervisor = services["hypervisor"] cmd.hypervisor = services["hypervisor"]
if cmd.hypervisor.lower() not in ["vmware"]: if "ostypeid" in services:
# Since version 4.15 VMware templates honour the guest OS defined in the template cmd.ostypeid = services["ostypeid"]
if "ostypeid" in services: elif "ostype" in services:
cmd.ostypeid = services["ostypeid"] # Find OSTypeId from Os type
elif "ostype" in services: sub_cmd = listOsTypes.listOsTypesCmd()
# Find OSTypeId from Os type sub_cmd.description = services["ostype"]
sub_cmd = listOsTypes.listOsTypesCmd() ostypes = apiclient.listOsTypes(sub_cmd)
sub_cmd.description = services["ostype"]
ostypes = apiclient.listOsTypes(sub_cmd)
if not isinstance(ostypes, list): if not isinstance(ostypes, list):
raise Exception(
"Unable to find Ostype id with desc: %s" %
services["ostype"])
cmd.ostypeid = ostypes[0].id
else:
raise Exception( raise Exception(
"Unable to find Ostype is required for registering template") "Unable to find Ostype id with desc: %s" %
services["ostype"])
cmd.ostypeid = ostypes[0].id
else:
raise Exception(
"Unable to find Ostype is required for registering template")
cmd.url = services["url"] cmd.url = services["url"]
@ -1438,6 +1436,7 @@ class Template:
cmd.isdynamicallyscalable = services["isdynamicallyscalable"] if "isdynamicallyscalable" in services else False cmd.isdynamicallyscalable = services["isdynamicallyscalable"] if "isdynamicallyscalable" in services else False
cmd.passwordenabled = services[ cmd.passwordenabled = services[
"passwordenabled"] if "passwordenabled" in services else False "passwordenabled"] if "passwordenabled" in services else False
cmd.deployasis = services["deployasis"] if "deployasis" in services else False
if account: if account:
cmd.account = account cmd.account = account

View File

@ -348,7 +348,7 @@ def get_template(
return list_templatesout[0] return list_templatesout[0]
def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=None): def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=None, deploy_as_is=False):
""" """
@Name : get_test_template @Name : get_test_template
@Desc : Retrieves the test template used to running tests. When the template @Desc : Retrieves the test template used to running tests. When the template
@ -373,6 +373,8 @@ def get_test_template(apiclient, zone_id=None, hypervisor=None, test_templates=N
return FAILED return FAILED
test_template = test_templates[hypervisor] test_template = test_templates[hypervisor]
if deploy_as_is:
test_template['deployasis'] = True
cmd = listTemplates.listTemplatesCmd() cmd = listTemplates.listTemplatesCmd()
cmd.name = test_template['name'] cmd.name = test_template['name']
@ -513,7 +515,7 @@ def get_windows_template(
return FAILED return FAILED
def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor): def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor, deploy_as_is=False):
''' '''
@Name : get_suitable_test_template @Name : get_suitable_test_template
@Desc : Retrieves the test template information based upon inputs provided @Desc : Retrieves the test template information based upon inputs provided
@ -525,11 +527,12 @@ def get_suitable_test_template(apiclient, zoneid, ostypeid, hypervisor):
template Information matching the inputs template Information matching the inputs
''' '''
template = FAILED template = FAILED
if hypervisor.lower() in ["xenserver"]: if hypervisor.lower() in ["xenserver"] or (hypervisor.lower() in ["vmware"] and deploy_as_is):
template = get_test_template( template = get_test_template(
apiclient, apiclient,
zoneid, zoneid,
hypervisor) hypervisor,
deploy_as_is=deploy_as_is)
if template == FAILED: if template == FAILED:
template = get_template( template = get_template(
apiclient, apiclient,

View File

@ -715,7 +715,7 @@
"label.demote.project.owner": "Demote account to Regular role", "label.demote.project.owner": "Demote account to Regular role",
"label.demote.project.owner.user": "Demote user to Regular role", "label.demote.project.owner.user": "Demote user to Regular role",
"label.deny": "Deny", "label.deny": "Deny",
"label.deployasis":"Deploy As-Is", "label.deployasis":"Read VM settings from OVA",
"label.deploymentplanner": "Deployment planner", "label.deploymentplanner": "Deployment planner",
"label.description": "Description", "label.description": "Description",
"label.destcidr": "Destination CIDR", "label.destcidr": "Destination CIDR",

View File

@ -208,8 +208,18 @@
:default-checked="xenServerProvider" /> :default-checked="xenServerProvider" />
</a-form-item> </a-form-item>
</a-row> </a-row>
<a-form-item :label="$t('label.deployasis')" v-if="hyperVMWShow">
<a-switch
v-decorator="['deployasis', {
initialValue: false,
}]"
:checked="deployasis"
@change="val => deployasis = val"/>
</a-form-item>
<a-row :gutter="12" v-if="hyperKVMShow || hyperVMWShow"> <a-row :gutter="12" v-if="hyperKVMShow || hyperVMWShow">
<a-col :md="24" :lg="24" v-if="hyperKVMShow"> <a-col :md="24" :lg="24" v-if="hyperKVMShow || (hyperVMWShow && !deployasis)">
<a-form-item :label="$t('label.rootdiskcontrollertype')"> <a-form-item :label="$t('label.rootdiskcontrollertype')">
<a-select <a-select
v-decorator="['rootDiskControllerType', { v-decorator="['rootDiskControllerType', {
@ -230,7 +240,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item v-if="hyperVMWShow" :label="$t('label.keyboardtype')"> <a-form-item v-if="hyperVMWShow && !deployasis" :label="$t('label.keyboardtype')">
<a-select <a-select
v-decorator="['keyboardType', { v-decorator="['keyboardType', {
rules: [ rules: [
@ -248,7 +258,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<a-row :gutter="12" v-if="!hyperVMWShow"> <a-row :gutter="12" v-if="!hyperVMWShow || (hyperVMWShow && !deployasis)">
<a-col :md="24" :lg="24"> <a-col :md="24" :lg="24">
<a-form-item :label="$t('label.ostypeid')"> <a-form-item :label="$t('label.ostypeid')">
<a-select <a-select
@ -378,6 +388,7 @@ export default {
hyperKVMShow: false, hyperKVMShow: false,
hyperXenServerShow: false, hyperXenServerShow: false,
hyperVMWShow: false, hyperVMWShow: false,
deployasis: false,
zoneError: '', zoneError: '',
zoneErrorMessage: '', zoneErrorMessage: '',
loading: false, loading: false,
@ -763,6 +774,7 @@ export default {
this.hyperXenServerShow = false this.hyperXenServerShow = false
this.hyperVMWShow = false this.hyperVMWShow = false
this.hyperKVMShow = false this.hyperKVMShow = false
this.deployasis = false
this.allowDirectDownload = false this.allowDirectDownload = false
this.resetSelect() this.resetSelect()
@ -794,10 +806,6 @@ export default {
continue continue
} }
params[key] = input.join() params[key] = input.join()
} else if (key === 'zoneid') {
params[key] = input
} else if (key === 'ostypeid') {
params[key] = input
} else if (key === 'hypervisor') { } else if (key === 'hypervisor') {
params[key] = this.hyperVisor.opts[input].name params[key] = this.hyperVisor.opts[input].name
} else if (key === 'groupenabled') { } else if (key === 'groupenabled') {