[Multi-Arch] Select Template Arch when creating template from volume (#11068)

Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
Co-authored-by: Vishesh <vishesh92@gmail.com>
This commit is contained in:
Nicolas Vazquez 2025-07-29 06:41:43 -03:00 committed by GitHub
parent 82396b621e
commit 8756be5c18
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 3 deletions

View File

@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.cloud.cpu.CPU;
import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiCommandResourceType;
@ -148,6 +149,11 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
since = "4.19.0") since = "4.19.0")
private String accountName; private String accountName;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "the CPU arch of the template. Valid options are: x86_64, aarch64. Defaults to x86_64",
since = "4.20.2")
private String arch;
// /////////////////////////////////////////////////// // ///////////////////////////////////////////////////
// ///////////////// Accessors /////////////////////// // ///////////////// Accessors ///////////////////////
// /////////////////////////////////////////////////// // ///////////////////////////////////////////////////
@ -234,6 +240,10 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd implements UserCmd {
return accountName; return accountName;
} }
public CPU.CPUArch getArch() {
return CPU.CPUArch.fromType(arch);
}
// /////////////////////////////////////////////////// // ///////////////////////////////////////////////////
// ///////////// API Implementation/////////////////// // ///////////// API Implementation///////////////////
// /////////////////////////////////////////////////// // ///////////////////////////////////////////////////

View File

@ -1831,6 +1831,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId + throw new InvalidParameterValueException("Failed to create private template record, please specify only one of volume ID (" + volumeId +
") and snapshot ID (" + snapshotId + ")"); ") and snapshot ID (" + snapshotId + ")");
} }
CPU.CPUArch arch = cmd.getArch();
HypervisorType hyperType; HypervisorType hyperType;
VolumeVO volume = null; VolumeVO volume = null;
@ -1923,7 +1924,6 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
String description = cmd.getDisplayText(); String description = cmd.getDisplayText();
boolean isExtractable = false; boolean isExtractable = false;
Long sourceTemplateId = null; Long sourceTemplateId = null;
CPU.CPUArch arch = CPU.CPUArch.amd64;
if (volume != null) { if (volume != null) {
VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId()); VMTemplateVO template = ApiDBUtils.findTemplateById(volume.getTemplateId());
isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM; isExtractable = template != null && template.isExtractable() && template.getTemplateType() != Storage.TemplateType.SYSTEM;

View File

@ -129,6 +129,25 @@
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item
name="arch"
ref="arch">
<template #label>
<tooltip-label :title="$t('label.arch')" :tooltip="apiParams.arch.description"/>
</template>
<a-select
showSearch
optionFilterProp="label"
:filterOption="(input, option) => {
return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}"
v-model:value="form.arch"
:placeholder="apiParams.arch.description">
<a-select-option v-for="opt in architectureTypes.opts" :key="opt.id">
{{ opt.name || opt.description }}
</a-select-option>
</a-select>
</a-form-item>
<a-row :gutter="12"> <a-row :gutter="12">
<a-col :md="24" :lg="12"> <a-col :md="24" :lg="12">
<a-form-item ref="isdynamicallyscalable" name="isdynamicallyscalable"> <a-form-item ref="isdynamicallyscalable" name="isdynamicallyscalable">
@ -163,7 +182,7 @@
<tooltip-label :title="$t('label.isfeatured')" :tooltip="apiParams.isfeatured.description"/> <tooltip-label :title="$t('label.isfeatured')" :tooltip="apiParams.isfeatured.description"/>
</template> </template>
<a-switch v-model:checked="form.isfeatured" /> <a-switch v-model:checked="form.isfeatured" />
</a-form-item> </a-form-item>
</a-col> </a-col>
</a-row> </a-row>
<div :span="24" class="action-button"> <div :span="24" class="action-button">
@ -204,7 +223,8 @@ export default {
accounts: [], accounts: [],
domainLoading: false, domainLoading: false,
domainid: null, domainid: null,
account: null account: null,
architectureTypes: {}
} }
}, },
computed: { computed: {
@ -239,6 +259,7 @@ export default {
if ('listDomains' in this.$store.getters.apis) { if ('listDomains' in this.$store.getters.apis) {
this.fetchDomains() this.fetchDomains()
} }
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
}, },
fetchOsTypes () { fetchOsTypes () {
this.osTypes.opts = [] this.osTypes.opts = []