Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui,server: add s390x architecture selection #10556

Draft
wants to merge 35 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e7ff4ed
wip
shwstppr Jan 28, 2025
67042ce
ui: multi-arch improvements
shwstppr Jan 28, 2025
126dfa9
api,ui: filter resources by arch
shwstppr Jan 29, 2025
8f48da3
ui: show arch tag in infocard
shwstppr Jan 29, 2025
13f3f14
ui: add arch display and filter for kubernetes iso
shwstppr Jan 29, 2025
b017025
simulator: allow adding hosts with arch
shwstppr Jan 29, 2025
ee59e61
api,ui: allow filtering vms by arch
shwstppr Jan 29, 2025
13ced5e
ui: make arch filter a list
shwstppr Jan 29, 2025
16282dd
wip
shwstppr Feb 4, 2025
bed9666
wip
shwstppr Feb 5, 2025
969660a
change for downloading templates if allowed
shwstppr Feb 20, 2025
f74355f
move download method to httputils
shwstppr Feb 20, 2025
9073ec1
remove unnecssary
shwstppr Feb 21, 2025
48c9d29
fix build
shwstppr Feb 21, 2025
bc5f734
fix
shwstppr Feb 22, 2025
60dc9d9
remove unnecessary change
shwstppr Feb 22, 2025
0ac96d6
fixes
shwstppr Mar 6, 2025
33bb563
wip: try system vm deployment with different arch templates
shwstppr Mar 6, 2025
42598f7
fix checkstyle
shwstppr Mar 6, 2025
59f2608
wip: try VR deployment with arch specific template
shwstppr Mar 6, 2025
a2a7f5d
fix systemvm deployment retry
shwstppr Mar 10, 2025
582187a
preferred arch config
shwstppr Mar 11, 2025
6c95e90
ui: changes for arch auto selection in deploy vm
shwstppr Mar 11, 2025
3069929
CPUArch as an enum, make config select
shwstppr Mar 11, 2025
c98ef69
fix persiting ilbvm
shwstppr Mar 11, 2025
ce43205
refactor to use searchbuilder/critera for distinct pair
shwstppr Mar 12, 2025
5d696f0
cpu test
shwstppr Mar 12, 2025
0552e27
Merge remote-tracking branch 'apache/main' into 4.21-multiarch-changes
shwstppr Mar 12, 2025
a6bdd52
refactor fetch arch types
shwstppr Mar 12, 2025
99bc651
Merge branch 'multiarchzones-improvements' into 4.21-multiarch-changes
shwstppr Mar 12, 2025
87b792e
ui,server: add s390x architecture selection
shwstppr Mar 12, 2025
499b861
fix
shwstppr Mar 12, 2025
90f9459
Merge branch 'multiarchzones-improvements' into 4.21-multiarch-changes
shwstppr Mar 12, 2025
a6f41ef
ui build fix
shwstppr Mar 12, 2025
b0cf095
fix test
shwstppr Mar 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions api/src/main/java/com/cloud/cpu/CPU.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,52 @@
// under the License.
package com.cloud.cpu;

import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.lang3.StringUtils;

import java.util.LinkedHashMap;
import java.util.Map;

public class CPU {
public enum CPUArch {
x86("i686", 32),
amd64("x86_64", 64),
arm64("aarch64", 64),
s390x("s390x", 64);

public static final String archX86Identifier = "i686";
public static final String archX86_64Identifier = "x86_64";
public static final String archARM64Identifier = "aarch64";

public static class CPUArch {
private static final Map<String, CPUArch> cpuArchMap = new LinkedHashMap<>();

public static final CPUArch archX86 = new CPUArch(archX86Identifier, 32);
public static final CPUArch amd64 = new CPUArch(archX86_64Identifier, 64);
public static final CPUArch arm64 = new CPUArch(archARM64Identifier, 64);

private String type;
private int bits;
private final String type;
private final int bits;

public CPUArch(String type, int bits) {
CPUArch(String type, int bits) {
this.type = type;
this.bits = bits;
cpuArchMap.put(type, this);
}

public String getType() {
return this.type;
return type;
}

public int getBits() {
return this.bits;
return bits;
}

public static CPUArch fromType(String type) {
if (StringUtils.isBlank(type)) {
return amd64;
return amd64; // Default architecture
}
for (CPUArch arch : values()) {
if (arch.type.equals(type)) {
return arch;
}
}
throw new IllegalArgumentException("Unsupported arch type: " + type);
}

public static String getTypesAsCSV() {
StringBuilder sb = new StringBuilder();
for (CPUArch arch : values()) {
sb.append(arch.getType()).append(",");
}
switch (type) {
case archX86Identifier: return archX86;
case archX86_64Identifier: return amd64;
case archARM64Identifier: return arm64;
default: throw new CloudRuntimeException(String.format("Unsupported arch type: %s", type));
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the clusters")
private Boolean showCapacities;

@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the clusters",
since = "4.20.1")
private String arch;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -112,6 +117,10 @@
return showCapacities;
}

public String getArch() {
return arch;
}

Check warning on line 122 in api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/admin/cluster/ListClustersCmd.java#L120-L122

Added lines #L120 - L122 were not covered by tests

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
@Parameter(name = ApiConstants.MANAGEMENT_SERVER_ID, type = CommandType.UUID, entityType = ManagementServerResponse.class, description = "the id of the management server", since="4.21.0")
private Long managementServerId;

@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING, description = "CPU Arch of the host", since = "4.20.1")
private String arch;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -193,6 +196,10 @@
return outOfBandManagementPowerState;
}

public String getArch() {
return arch;
}

Check warning on line 201 in api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/admin/host/ListHostsCmd.java#L199-L201

Added lines #L199 - L201 were not covered by tests

public Long getManagementServerId() {
return managementServerId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@
@Parameter(name = ApiConstants.USER_DATA, type = CommandType.BOOLEAN, description = "Whether to return the VMs' user data or not. By default, user data will not be returned.", since = "4.18.0.0")
private Boolean showUserData;

@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the VM",
since = "4.20.1")
private String arch;

/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
Expand Down Expand Up @@ -284,6 +289,10 @@
return isVnf;
}

public String getArch() {
return arch;
}

Check warning on line 294 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/ListVMsCmd.java#L292-L294

Added lines #L292 - L294 were not covered by tests

/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
import org.apache.cloudstack.api.EntityReference;
import org.apache.commons.collections.CollectionUtils;

import com.cloud.network.router.VirtualRouter;
import com.cloud.serializer.Param;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;
import com.google.gson.annotations.SerializedName;
import org.apache.commons.collections.CollectionUtils;

@SuppressWarnings("unused")
@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
Expand Down Expand Up @@ -396,6 +396,10 @@
@Param(description = "User VM type", since = "4.20.0")
private String vmType;

@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the VM", since = "4.20.1")
private String arch;

public UserVmResponse() {
securityGroupList = new LinkedHashSet<>();
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
Expand Down Expand Up @@ -1169,4 +1173,12 @@
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}

public String getArch() {
return arch;
}

Check warning on line 1179 in api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java#L1177-L1179

Added lines #L1177 - L1179 were not covered by tests

public void setArch(String arch) {

Check warning on line 1181 in api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/response/UserVmResponse.java#L1181

Added line #L1181 was not covered by tests
this.arch = arch;
}
}
67 changes: 67 additions & 0 deletions api/src/test/java/com/cloud/cpu/CPUTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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.cpu;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import org.junit.Test;

public class CPUTest {
@Test
public void testCPUArchGetType() {
assertEquals("i686", CPU.CPUArch.x86.getType());
assertEquals("x86_64", CPU.CPUArch.amd64.getType());
assertEquals("aarch64", CPU.CPUArch.arm64.getType());
}

@Test
public void testCPUArchGetBits() {
assertEquals(32, CPU.CPUArch.x86.getBits());
assertEquals(64, CPU.CPUArch.amd64.getBits());
assertEquals(64, CPU.CPUArch.arm64.getBits());
}

@Test
public void testCPUArchFromTypeWithValidValues() {
assertEquals(CPU.CPUArch.x86, CPU.CPUArch.fromType("i686"));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType("x86_64"));
assertEquals(CPU.CPUArch.arm64, CPU.CPUArch.fromType("aarch64"));
}

@Test
public void testCPUArchFromTypeWithDefaultForBlankOrNull() {
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(""));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(" "));
assertEquals(CPU.CPUArch.amd64, CPU.CPUArch.fromType(null));
}

@Test
public void testCPUArchFromTypeWithInvalidValue() {
Exception exception = assertThrows(IllegalArgumentException.class, () -> {
CPU.CPUArch.fromType("unsupported");
});
assertTrue(exception.getMessage().contains("Unsupported arch type: unsupported"));
}

@Test
public void testCPUArchGetTypesAsCSV() {
String expectedCSV = "i686,x86_64,aarch64,s390x";
assertEquals(expectedCSV, CPU.CPUArch.getTypesAsCSV());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -309,4 +309,8 @@ static String getHypervisorHostname(String name) {

Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds);

void checkDeploymentPlan(VirtualMachine virtualMachine, VirtualMachineTemplate template,
ServiceOffering serviceOffering, Account systemAccount, DeploymentPlan plan)
throws InsufficientServerCapacityException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.VgpuTypesInfo;
import com.cloud.agent.api.to.GPUDeviceTO;
import com.cloud.cpu.CPU;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.dc.PodCluster;
Expand Down Expand Up @@ -61,6 +62,17 @@ public interface ResourceManager extends ResourceService, Configurable {
+ "To force-stop VMs, choose 'ForceStop' strategy",
true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "Error,Migration,ForceStop");

ConfigKey<String> SystemVmPreferredArchitecture = new ConfigKey<>(
String.class,
"system.vm.preferred.architecture",
"Advanced",
"",
"Preferred architecture for the system VMs including virtual routers",
true,
ConfigKey.Scope.Global, null, null, null, null, null,
ConfigKey.Kind.Select,
"," + CPU.CPUArch.getTypesAsCSV());

/**
* Register a listener for different types of resource life cycle events.
* There can only be one type of listener per type of host.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6084,4 +6084,18 @@
}
return result;
}

@Override
public void checkDeploymentPlan(VirtualMachine virtualMachine, VirtualMachineTemplate template,
ServiceOffering serviceOffering, Account systemAccount, DeploymentPlan plan)
throws InsufficientServerCapacityException {
final VirtualMachineProfileImpl vmProfile =

Check warning on line 6092 in engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

View check run for this annotation

Codecov / codecov/patch

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java#L6091-L6092

Added lines #L6091 - L6092 were not covered by tests
new VirtualMachineProfileImpl(virtualMachine, template, serviceOffering, systemAccount, null);
DeployDestination destination =
_dpMgr.planDeployment(vmProfile, plan, new DeploymentPlanner.ExcludeList(), null);

Check warning on line 6095 in engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

View check run for this annotation

Codecov / codecov/patch

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java#L6094-L6095

Added lines #L6094 - L6095 were not covered by tests
if (destination == null) {
throw new InsufficientServerCapacityException(String.format("Unable to create a deployment for %s",
vmProfile), DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile));

Check warning on line 6098 in engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

View check run for this annotation

Codecov / codecov/patch

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java#L6097-L6098

Added lines #L6097 - L6098 were not covered by tests
}
}

Check warning on line 6100 in engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java

View check run for this annotation

Codecov / codecov/patch

engine/orchestration/src/main/java/com/cloud/vm/VirtualMachineManagerImpl.java#L6100

Added line #L6100 was not covered by tests
}
6 changes: 2 additions & 4 deletions engine/schema/src/main/java/com/cloud/dc/dao/ClusterDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,23 @@

import java.util.List;
import java.util.Map;
import java.util.Set;

import com.cloud.cpu.CPU;
import com.cloud.dc.ClusterVO;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDao;

public interface ClusterDao extends GenericDao<ClusterVO, Long> {
List<ClusterVO> listByPodId(long podId);

ClusterVO findBy(String name, long podId);

List<ClusterVO> listByHyTypeWithoutGuid(String hyType);

List<ClusterVO> listByZoneId(long zoneId);

List<HypervisorType> getAvailableHypervisorInZone(Long zoneId);

Set<HypervisorType> getDistinctAvailableHypervisorsAcrossClusters();
List<Pair<HypervisorType, String>> listDistinctHypervisorsArchAcrossClusters(Long zoneId);

List<ClusterVO> listByDcHyType(long dcId, String hyType);

Expand Down
24 changes: 12 additions & 12 deletions engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.inject.Inject;
Expand All @@ -39,6 +37,7 @@
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.org.Grouping;
import com.cloud.org.Managed;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.JoinBuilder;
Expand Down Expand Up @@ -148,14 +147,6 @@
return findOneBy(sc);
}

@Override
public List<ClusterVO> listByHyTypeWithoutGuid(String hyType) {
SearchCriteria<ClusterVO> sc = HyTypeWithoutGuidSearch.create();
sc.setParameters("hypervisorType", hyType);

return listBy(sc);
}

@Override
public List<ClusterVO> listByDcHyType(long dcId, String hyType) {
SearchCriteria<ClusterVO> sc = ZoneHyTypeSearch.create();
Expand All @@ -178,8 +169,17 @@
}

@Override
public Set<HypervisorType> getDistinctAvailableHypervisorsAcrossClusters() {
return new HashSet<>(getAvailableHypervisorInZone(null));
public List<Pair<HypervisorType, String>> listDistinctHypervisorsArchAcrossClusters(Long zoneId) {
SearchBuilder<ClusterVO> sb = createSearchBuilder();
sb.select(null, Func.DISTINCT_PAIR, sb.entity().getHypervisorType(), sb.entity().getArch());
sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<ClusterVO> sc = sb.create();
sc.setParameters("zoneId", zoneId);
final List<ClusterVO> clusters = search(sc, null);
return clusters.stream()
.map(c -> new Pair<>(c.getHypervisorType(), c.getArch().getType()))
.collect(Collectors.toList());

Check warning on line 182 in engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java

View check run for this annotation

Codecov / codecov/patch

engine/schema/src/main/java/com/cloud/dc/dao/ClusterDaoImpl.java#L172-L182

Added lines #L172 - L182 were not covered by tests
}

@Override
Expand Down
Loading
Loading