This is an automated email from the ASF dual-hosted git repository.
dahn pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new 8756be5c187 [Multi-Arch] Select Template Arch when creating template
from volume (#11068)
8756be5c187 is described below
commit 8756be5c18796469f6d480d3bebdde983e6a2a53
Author: Nicolas Vazquez <[email protected]>
AuthorDate: Tue Jul 29 06:41:43 2025 -0300
[Multi-Arch] Select Template Arch when creating template from volume
(#11068)
Co-authored-by: Abhishek Kumar <[email protected]>
Co-authored-by: Suresh Kumar Anaparti <[email protected]>
Co-authored-by: Vishesh <[email protected]>
---
.../command/user/template/CreateTemplateCmd.java | 10 +++++++++
.../com/cloud/template/TemplateManagerImpl.java | 2 +-
ui/src/views/storage/CreateTemplate.vue | 25 ++++++++++++++++++++--
3 files changed, 34 insertions(+), 3 deletions(-)
diff --git
a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
index 0a7bf291843..5f09ac6698d 100644
---
a/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
+++
b/api/src/main/java/org/apache/cloudstack/api/command/user/template/CreateTemplateCmd.java
@@ -20,6 +20,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
+import com.cloud.cpu.CPU;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
@@ -148,6 +149,11 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd
implements UserCmd {
since = "4.19.0")
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 ///////////////////////
// ///////////////////////////////////////////////////
@@ -234,6 +240,10 @@ public class CreateTemplateCmd extends BaseAsyncCreateCmd
implements UserCmd {
return accountName;
}
+ public CPU.CPUArch getArch() {
+ return CPU.CPUArch.fromType(arch);
+ }
+
// ///////////////////////////////////////////////////
// ///////////// API Implementation///////////////////
// ///////////////////////////////////////////////////
diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
index 9f23bdef142..cf88ccec919 100755
--- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
@@ -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 +
") and snapshot ID (" + snapshotId + ")");
}
+ CPU.CPUArch arch = cmd.getArch();
HypervisorType hyperType;
VolumeVO volume = null;
@@ -1923,7 +1924,6 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
String description = cmd.getDisplayText();
boolean isExtractable = false;
Long sourceTemplateId = null;
- CPU.CPUArch arch = CPU.CPUArch.amd64;
if (volume != null) {
VMTemplateVO template =
ApiDBUtils.findTemplateById(volume.getTemplateId());
isExtractable = template != null && template.isExtractable() &&
template.getTemplateType() != Storage.TemplateType.SYSTEM;
diff --git a/ui/src/views/storage/CreateTemplate.vue
b/ui/src/views/storage/CreateTemplate.vue
index 65941d39a9d..d974092a5f8 100644
--- a/ui/src/views/storage/CreateTemplate.vue
+++ b/ui/src/views/storage/CreateTemplate.vue
@@ -129,6 +129,25 @@
</a-select-option>
</a-select>
</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-col :md="24" :lg="12">
<a-form-item ref="isdynamicallyscalable"
name="isdynamicallyscalable">
@@ -163,7 +182,7 @@
<tooltip-label :title="$t('label.isfeatured')"
:tooltip="apiParams.isfeatured.description"/>
</template>
<a-switch v-model:checked="form.isfeatured" />
- </a-form-item>
+ </a-form-item>
</a-col>
</a-row>
<div :span="24" class="action-button">
@@ -204,7 +223,8 @@ export default {
accounts: [],
domainLoading: false,
domainid: null,
- account: null
+ account: null,
+ architectureTypes: {}
}
},
computed: {
@@ -239,6 +259,7 @@ export default {
if ('listDomains' in this.$store.getters.apis) {
this.fetchDomains()
}
+ this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
},
fetchOsTypes () {
this.osTypes.opts = []