This commit is contained in:
Pearl Dsilva 2025-04-28 12:15:48 +05:30
commit 2df1ac5106
135 changed files with 4026 additions and 1737 deletions

View File

@ -16,52 +16,55 @@
// 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);
public static final String archX86Identifier = "i686";
public static final String archX86_64Identifier = "x86_64";
public static final String archARM64Identifier = "aarch64";
private final String type;
private final int bits;
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;
public CPUArch(String type, int bits) {
CPUArch(String type, int bits) {
this.type = type;
this.bits = bits;
cpuArchMap.put(type, this);
}
public static CPUArch getDefault() {
return amd64;
}
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;
}
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));
return getDefault();
}
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(",");
}
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
}
}

View File

@ -101,4 +101,13 @@ public interface VmDetailConstants {
String VMWARE_HOST_NAME = String.format("%s-host", VMWARE_TO_KVM_PREFIX);
String VMWARE_DISK = String.format("%s-disk", VMWARE_TO_KVM_PREFIX);
String VMWARE_MAC_ADDRESSES = String.format("%s-mac-addresses", VMWARE_TO_KVM_PREFIX);
// TPM
String VIRTUAL_TPM_ENABLED = "virtual.tpm.enabled";
String VIRTUAL_TPM_MODEL = "virtual.tpm.model";
String VIRTUAL_TPM_VERSION = "virtual.tpm.version";
// CPU mode and model, ADMIN only
String GUEST_CPU_MODE = "guest.cpu.mode";
String GUEST_CPU_MODEL = "guest.cpu.model";
}

View File

@ -485,12 +485,11 @@ public class ApiConstants {
public static final String STATE = "state";
public static final String STATS = "stats";
public static final String STATUS = "status";
public static final String STORAGE_TYPE = "storagetype";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_CAPABILITIES = "storagecapabilities";
public static final String STORAGE_CUSTOM_STATS = "storagecustomstats";
public static final String STORAGE_MOTION_ENABLED = "storagemotionenabled";
public static final String STORAGE_POLICY = "storagepolicy";
public static final String STORAGE_POOL = "storagepool";
public static final String STORAGE_TYPE = "storagetype";
public static final String SUBNET = "subnet";
public static final String OWNER = "owner";
public static final String SWAP_OWNER = "swapowner";

View File

@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.cluster;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.BaseListCmd;
@ -28,7 +27,9 @@ import org.apache.cloudstack.api.response.ClusterResponse;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.org.Cluster;
import com.cloud.utils.Pair;
@ -68,6 +69,11 @@ public class ListClustersCmd extends BaseListCmd {
@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 ///////////////////////
/////////////////////////////////////////////////////
@ -112,6 +118,10 @@ public class ListClustersCmd extends BaseListCmd {
return showCapacities;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -21,7 +21,6 @@ import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -35,7 +34,9 @@ import org.apache.cloudstack.api.response.ManagementServerResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
@ -109,6 +110,9 @@ public class ListHostsCmd extends BaseListCmd {
@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 ///////////////////////
/////////////////////////////////////////////////////
@ -197,6 +201,10 @@ public class ListHostsCmd extends BaseListCmd {
return managementServerId;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -16,8 +16,6 @@
// under the License.
package org.apache.cloudstack.api.command.admin.router;
import org.apache.commons.lang.BooleanUtils;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -32,7 +30,10 @@ import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.vm.VirtualMachine;
@ -86,6 +87,11 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
description = "if true is passed for this parameter, also fetch last executed health check results for the router. Default is false")
private Boolean fetchHealthCheckResults;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the router",
since = "4.20.1")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -146,6 +152,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
return BooleanUtils.isTrue(fetchHealthCheckResults);
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////

View File

@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.systemvm;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
@ -31,7 +30,9 @@ import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.response.StoragePoolResponse;
import org.apache.cloudstack.api.response.SystemVmResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.utils.Pair;
import com.cloud.vm.VirtualMachine;
@ -74,6 +75,11 @@ public class ListSystemVMsCmd extends BaseListCmd {
since = "3.0.1")
private Long storageId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the system VM",
since = "4.20.1")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -110,6 +116,10 @@ public class ListSystemVMsCmd extends BaseListCmd {
return storageId;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -46,9 +46,11 @@ import org.apache.cloudstack.api.response.UserResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.api.response.VpcResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.cpu.CPU;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.server.ResourceIcon;
import com.cloud.server.ResourceTag;
@ -153,6 +155,11 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
@Parameter(name = ApiConstants.USER_DATA_ID, type = CommandType.UUID, entityType = UserDataResponse.class, required = false, description = "the instances by userdata", since = "4.20.1")
private Long userdataId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "CPU arch of the VM",
since = "4.20.1")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -292,6 +299,10 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
return isVnf;
}
public CPU.CPUArch getArch() {
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -245,6 +245,10 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
@Param(description = "the version of the code / software in the router")
private String softwareVersion;
@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the router", since = "4.20.1")
private String arch;
public DomainRouterResponse() {
nics = new LinkedHashSet<NicResponse>();
}
@ -518,4 +522,8 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
public void setSoftwareVersion(String softwareVersion) {
this.softwareVersion = softwareVersion;
}
public void setArch(String arch) {
this.arch = arch;
}
}

View File

@ -152,7 +152,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
@Deprecated
@SerializedName("memoryallocated")
@Param(description = "the amount of the host's memory currently allocated")
private Long memoryAllocated;
private long memoryAllocated;
@SerializedName("memoryallocatedpercentage")
@Param(description = "the amount of the host's memory currently allocated in percentage")
@ -415,7 +415,7 @@ public class HostResponse extends BaseResponseWithAnnotations {
this.memWithOverprovisioning=memWithOverprovisioning;
}
public void setMemoryAllocated(Long memoryAllocated) {
public void setMemoryAllocated(long memoryAllocated) {
this.memoryAllocated = memoryAllocated;
}
@ -703,8 +703,8 @@ public class HostResponse extends BaseResponseWithAnnotations {
return memoryTotal;
}
public Long getMemoryAllocated() {
return memoryAllocated == null ? 0 : memoryAllocated;
public long getMemoryAllocated() {
return memoryAllocated;
}
public void setMemoryAllocatedPercentage(String memoryAllocatedPercentage) {

View File

@ -186,6 +186,10 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
@Param(description = "the name of the service offering of the system virtual machine.")
private String serviceOfferingName;
@SerializedName(ApiConstants.ARCH)
@Param(description = "CPU arch of the system VM", since = "4.20.1")
private String arch;
@Override
public String getObjectId() {
return this.getId();
@ -490,4 +494,8 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
public void setServiceOfferingName(String serviceOfferingName) {
this.serviceOfferingName = serviceOfferingName;
}
public void setArch(String arch) {
this.arch = arch;
}
}

View File

@ -31,13 +31,13 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
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})
@ -396,6 +396,10 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
@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())));
@ -1169,4 +1173,12 @@ public class UserVmResponse extends BaseResponseWithTagInformation implements Co
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getArch() {
return arch;
}
public void setArch(String arch) {
this.arch = arch;
}
}

View File

@ -16,6 +16,7 @@
// under the License.
package org.apache.cloudstack.query;
import java.util.Arrays;
import java.util.List;
import org.apache.cloudstack.affinity.AffinityGroupResponse;
@ -97,6 +98,7 @@ import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.exception.PermissionDeniedException;
import com.cloud.vm.VmDetailConstants;
/**
* Service used for list api query.
@ -104,6 +106,8 @@ import com.cloud.exception.PermissionDeniedException;
*/
public interface QueryService {
List<String> RootAdminOnlyVmSettings = Arrays.asList(VmDetailConstants.GUEST_CPU_MODE, VmDetailConstants.GUEST_CPU_MODEL);
// Config keys
ConfigKey<Boolean> AllowUserViewDestroyedVM = new ConfigKey<>("Advanced", Boolean.class, "allow.user.view.destroyed.vm", "false",
"Determines whether users can view their destroyed or expunging vm ", true, ConfigKey.Scope.Account);

View File

@ -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";
assertEquals(expectedCSV, CPU.CPUArch.getTypesAsCSV());
}
}

View File

@ -56,6 +56,8 @@ if [ "$1" = configure ]; then
chmod 0640 ${CONFDIR}/${DBPROPS}
chgrp cloud ${CONFDIR}/${DBPROPS}
chown -R cloud:cloud /var/log/cloudstack/management
chown -R cloud:cloud /usr/share/cloudstack-management/templates
find /usr/share/cloudstack-management/templates -type d -exec chmod 0770 {} \;
ln -sf ${CONFDIR}/log4j-cloud.xml ${CONFDIR}/log4j2.xml

View File

@ -309,4 +309,8 @@ public interface VirtualMachineManager extends Manager {
Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds);
void checkDeploymentPlan(VirtualMachine virtualMachine, VirtualMachineTemplate template,
ServiceOffering serviceOffering, Account systemAccount, DeploymentPlan plan)
throws InsufficientServerCapacityException;
}

View File

@ -25,14 +25,16 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import com.cloud.network.Network;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.events.Event;
import org.apache.cloudstack.framework.events.EventBus;
import org.apache.cloudstack.framework.events.EventDistributor;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
@ -243,4 +245,22 @@ public class UsageEventUtils {
static final String Name = "management-server";
public static void publishNetworkCreation(Network network) {
publishUsageEvent(EventTypes.EVENT_NETWORK_CREATE, network.getAccountId(), network.getDataCenterId(),
network.getId(), network.getName(), network.getNetworkOfferingId(), null, null, null, network.getState().name(),
network.getUuid());
}
public static void publishNetworkUpdate(Network network) {
publishUsageEvent(EventTypes.EVENT_NETWORK_UPDATE, network.getAccountId(), network.getDataCenterId(),
network.getId(), network.getName(), network.getNetworkOfferingId(), null, network.getState().name(),
Network.class.getName(), network.getUuid(), true);
}
public static void publishNetworkDeletion(Network network) {
publishUsageEvent(EventTypes.EVENT_NETWORK_DELETE, network.getAccountId(), network.getDataCenterId(),
network.getId(), network.getName(), network.getNetworkOfferingId(), null, null, null,
Network.class.getName(), network.getUuid());
}
}

View File

@ -28,6 +28,7 @@ import com.cloud.agent.api.StartupCommand;
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;
@ -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",
CPU.CPUArch.getDefault().getType(),
"Preferred architecture for the system VMs including virtual routers",
true,
ConfigKey.Scope.Zone, 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.

View File

@ -6083,4 +6083,18 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
}
return result;
}
@Override
public void checkDeploymentPlan(VirtualMachine virtualMachine, VirtualMachineTemplate template,
ServiceOffering serviceOffering, Account systemAccount, DeploymentPlan plan)
throws InsufficientServerCapacityException {
final VirtualMachineProfileImpl vmProfile =
new VirtualMachineProfileImpl(virtualMachine, template, serviceOffering, systemAccount, null);
DeployDestination destination =
_dpMgr.planDeployment(vmProfile, plan, new DeploymentPlanner.ExcludeList(), null);
if (destination == null) {
throw new InsufficientServerCapacityException(String.format("Unable to create a deployment for %s",
vmProfile), DataCenter.class, plan.getDataCenterId(), areAffinityGroupsAssociated(vmProfile));
}
}
}

View File

@ -1528,8 +1528,6 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (isNetworkImplemented(network)) {
logger.debug("Network {} is already implemented", network);
implemented.set(guru, network);
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_UPDATE, network.getAccountId(), network.getDataCenterId(), network.getId(),
network.getName(), network.getNetworkOfferingId(), null, network.getState().name(), Network.class.getName(), network.getUuid(), true);
return implemented;
}
@ -1585,9 +1583,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
network.setRestartRequired(false);
_networksDao.update(network.getId(), network);
UsageEventUtils.publishNetworkUpdate(network);
implemented.set(guru, network);
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_CREATE, network.getAccountId(), network.getDataCenterId(), network.getId(),
network.getName(), network.getNetworkOfferingId(), null, null, null, network.getState().name(), network.getUuid());
return implemented;
} catch (final NoTransitionException e) {
logger.error(e.getMessage());
@ -3087,6 +3084,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
if (updateResourceCount) {
_resourceLimitMgr.incrementResourceCount(owner.getId(), ResourceType.network, isDisplayNetworkEnabled);
}
UsageEventUtils.publishNetworkCreation(network);
return network;
}
@ -3168,13 +3166,14 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
logger.debug("Lock is acquired for network {} as a part of network shutdown", network);
if (network.getState() == Network.State.Allocated) {
logger.debug("Network is already shutdown: {}", network);
final Network.State initialState = network.getState();
if (initialState == Network.State.Allocated) {
logger.debug(String.format("Network [%s] is in Allocated state, no need to shutdown.", network));
return true;
}
if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Shutdown) {
logger.debug("Network is not implemented: {}", network);
if (initialState != Network.State.Implemented && initialState != Network.State.Shutdown) {
logger.debug("Network is not implemented: " + network);
return false;
}
@ -3218,6 +3217,9 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
}
_networksDao.update(networkFinal.getId(), networkFinal);
_networksDao.clearCheckForGc(networkId);
if (initialState == Network.State.Implemented) {
UsageEventUtils.publishNetworkUpdate(networkFinal);
}
result = true;
} else {
try {
@ -3469,8 +3471,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
final Pair<Class<?>, Long> networkMsg = new Pair<Class<?>, Long>(Network.class, networkFinal.getId());
_messageBus.publish(_name, EntityManager.MESSAGE_REMOVE_ENTITY_EVENT, PublishScope.LOCAL, networkMsg);
}
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_DELETE, network.getAccountId(), network.getDataCenterId(), network.getId(),
network.getName(), network.getNetworkOfferingId(), null, null, null, Network.class.getName(), network.getUuid());
UsageEventUtils.publishNetworkDeletion(network);
return true;
} catch (final CloudRuntimeException e) {
logger.error("Failed to delete network", e);

View File

@ -891,7 +891,7 @@ public class NetworkOrchestratorTest extends TestCase {
boolean shutdownNetworkStatus = testOrchestrator.shutdownNetwork(networkId, reservationContext, false);
Assert.assertFalse(shutdownNetworkStatus);
verify(network, times(3)).getState();
verify(network).getState();
verify(testOrchestrator._networksDao, times(1)).acquireInLockTable(networkId, NetworkLockTimeout.value());
verify(testOrchestrator._networksDao, times(1)).releaseFromLockTable(networkId);
}

View File

@ -165,6 +165,15 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<test.mode>true</test.mode>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
<profiles>

View File

@ -18,11 +18,11 @@ package com.cloud.dc.dao;
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> {
@ -30,13 +30,11 @@ public interface ClusterDao extends GenericDao<ClusterVO, Long> {
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, CPU.CPUArch>> listDistinctHypervisorsArchAcrossClusters(Long zoneId);
List<ClusterVO> listByDcHyType(long dcId, String hyType);

View File

@ -21,10 +21,8 @@ import java.sql.ResultSet;
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;
@ -39,6 +37,7 @@ import com.cloud.dc.HostPodVO;
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;
@ -148,14 +147,6 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
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();
@ -178,8 +169,19 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
}
@Override
public Set<HypervisorType> getDistinctAvailableHypervisorsAcrossClusters() {
return new HashSet<>(getAvailableHypervisorInZone(null));
public List<Pair<HypervisorType, CPU.CPUArch>> 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();
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
final List<ClusterVO> clusters = search(sc, null);
return clusters.stream()
.map(c -> new Pair<>(c.getHypervisorType(), c.getArch()))
.collect(Collectors.toList());
}
@Override

View File

@ -19,6 +19,7 @@ package com.cloud.host.dao;
import java.util.Date;
import java.util.List;
import com.cloud.cpu.CPU;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
@ -212,5 +213,9 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
List<HypervisorType> listDistinctHypervisorTypes(final Long zoneId);
List<Pair<HypervisorType, CPU.CPUArch>> listDistinctHypervisorArchTypes(final Long zoneId);
List<CPU.CPUArch> listDistinctArchTypes(final Long clusterId);
List<HostVO> listByIds(final List<Long> ids);
}

View File

@ -42,6 +42,7 @@ import com.cloud.agent.api.VgpuTypesInfo;
import com.cloud.cluster.agentlb.HostTransferMapVO;
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
import com.cloud.configuration.ManagementServiceConfiguration;
import com.cloud.cpu.CPU;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.gpu.dao.HostGpuGroupsDao;
@ -1795,17 +1796,52 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
@Override
public List<HypervisorType> listDistinctHypervisorTypes(final Long zoneId) {
GenericSearchBuilder<HostVO, HypervisorType> sb = createSearchBuilder(HypervisorType.class);
GenericSearchBuilder<HostVO, String> sb = createSearchBuilder(String.class);
sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.select(null, Func.DISTINCT, sb.entity().getHypervisorType());
sb.done();
SearchCriteria<HypervisorType> sc = sb.create();
SearchCriteria<String> sc = sb.create();
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
sc.setParameters("type", Type.Routing);
return customSearch(sc, null);
List<String> hypervisorString = customSearch(sc, null);
return hypervisorString.stream().map(HypervisorType::getType).collect(Collectors.toList());
}
@Override
public List<Pair<HypervisorType, CPU.CPUArch>> listDistinctHypervisorArchTypes(final Long zoneId) {
SearchBuilder<HostVO> sb = createSearchBuilder();
sb.select(null, Func.DISTINCT_PAIR, sb.entity().getHypervisorType(), sb.entity().getArch());
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.and("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<HostVO> sc = sb.create();
sc.setParameters("type", Type.Routing);
if (zoneId != null) {
sc.setParameters("zoneId", zoneId);
}
final List<HostVO> hosts = search(sc, null);
return hosts.stream()
.map(h -> new Pair<>(h.getHypervisorType(), h.getArch()))
.collect(Collectors.toList());
}
@Override
public List<CPU.CPUArch> listDistinctArchTypes(final Long clusterId) {
GenericSearchBuilder<HostVO, String> sb = createSearchBuilder(String.class);
sb.and("clusterId", sb.entity().getClusterId(), SearchCriteria.Op.EQ);
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
sb.select(null, Func.DISTINCT, sb.entity().getArch());
sb.done();
SearchCriteria<String> sc = sb.create();
if (clusterId != null) {
sc.setParameters("clusterId", clusterId);
}
sc.setParameters("type", Type.Routing);
List<String> archStrings = customSearch(sc, null);
return archStrings.stream().map(CPU.CPUArch::fromType).collect(Collectors.toList());
}
@Override

View File

@ -19,6 +19,7 @@ package com.cloud.storage.dao;
import java.util.List;
import java.util.Map;
import com.cloud.cpu.CPU;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateVO;
@ -73,9 +74,13 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType);
List<VMTemplateVO> findSystemVMReadyTemplates(long zoneId, HypervisorType hypervisorType, String preferredArch);
VMTemplateVO findRoutingTemplate(HypervisorType type, String templateName);
VMTemplateVO findLatestTemplateByTypeAndHypervisor(HypervisorType hypervisorType, Storage.TemplateType type);
List<VMTemplateVO> findRoutingTemplates(HypervisorType type, String templateName, String preferredArch);
VMTemplateVO findLatestTemplateByTypeAndHypervisorAndArch(HypervisorType hypervisorType, CPU.CPUArch arch, Storage.TemplateType type);
public Long countTemplatesForAccount(long accountId);
@ -87,7 +92,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
List<VMTemplateVO> listByParentTemplatetId(long parentTemplatetId);
VMTemplateVO findLatestTemplateByName(String name);
VMTemplateVO findLatestTemplateByName(String name, CPU.CPUArch arch);
List<VMTemplateVO> findTemplatesLinkedToUserdata(long userdataId);

View File

@ -18,7 +18,9 @@ package com.cloud.storage.dao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -28,8 +30,10 @@ import javax.naming.ConfigurationException;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import com.cloud.cpu.CPU;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.dao.DomainDao;
import com.cloud.host.Host;
@ -47,6 +51,7 @@ import com.cloud.storage.VMTemplateZoneVO;
import com.cloud.tags.ResourceTagVO;
import com.cloud.tags.dao.ResourceTagDao;
import com.cloud.template.VirtualMachineTemplate;
import com.cloud.utils.Pair;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.GenericDaoBase;
@ -111,6 +116,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
LatestTemplateByHypervisorTypeSearch = createSearchBuilder();
LatestTemplateByHypervisorTypeSearch.and("hypervisorType", LatestTemplateByHypervisorTypeSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ);
LatestTemplateByHypervisorTypeSearch.and("templateType", LatestTemplateByHypervisorTypeSearch.entity().getTemplateType(), SearchCriteria.Op.EQ);
LatestTemplateByHypervisorTypeSearch.and("arch", LatestTemplateByHypervisorTypeSearch.entity().getArch(), SearchCriteria.Op.EQ);
LatestTemplateByHypervisorTypeSearch.and("removed", LatestTemplateByHypervisorTypeSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
}
@ -238,10 +244,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
@Override
public VMTemplateVO findLatestTemplateByName(String name) {
SearchCriteria<VMTemplateVO> sc = createSearchCriteria();
sc.addAnd("name", SearchCriteria.Op.EQ, name);
sc.addAnd("removed", SearchCriteria.Op.NULL);
public VMTemplateVO findLatestTemplateByName(String name, CPU.CPUArch arch) {
SearchBuilder<VMTemplateVO> sb = createSearchBuilder();
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
sb.and("arch", sb.entity().getArch(), SearchCriteria.Op.EQ);
sb.done();
SearchCriteria<VMTemplateVO> sc = sb.create();
sc.setParameters("name", name);
if (arch != null) {
sc.setParameters("arch", arch);
}
Filter filter = new Filter(VMTemplateVO.class, "id", false, null, 1L);
List<VMTemplateVO> templates = listBy(sc, filter);
if ((templates != null) && !templates.isEmpty()) {
@ -580,6 +592,59 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
.orElse(null);
}
protected List<VMTemplateVO> getSortedTemplatesListWithPreferredArch(
Map<Pair<HypervisorType, CPU.CPUArch>, VMTemplateVO> uniqueTemplates, String preferredArch) {
List<VMTemplateVO> result = new ArrayList<>(uniqueTemplates.values());
if (StringUtils.isNotBlank(preferredArch)) {
result.sort((t1, t2) -> {
boolean t1Preferred = t1.getArch().getType().equalsIgnoreCase(preferredArch);
boolean t2Preferred = t2.getArch().getType().equalsIgnoreCase(preferredArch);
if (t1Preferred && !t2Preferred) {
return -1; // t1 comes before t2
} else if (!t1Preferred && t2Preferred) {
return 1; // t2 comes before t1
} else {
// Both are either preferred or not preferred; use template id as a secondary sorting key.
return Long.compare(t1.getId(), t2.getId());
}
});
} else {
result.sort(Comparator.comparing(VMTemplateVO::getId).reversed());
}
return result;
}
@Override
public List<VMTemplateVO> findSystemVMReadyTemplates(long zoneId, HypervisorType hypervisorType,
String preferredArch) {
List<Pair<HypervisorType, CPU.CPUArch>> availableHypervisors = _hostDao.listDistinctHypervisorArchTypes(zoneId);
if (CollectionUtils.isEmpty(availableHypervisors)) {
return Collections.emptyList();
}
SearchCriteria<VMTemplateVO> sc = readySystemTemplateSearch.create();
sc.setParameters("templateType", Storage.TemplateType.SYSTEM);
sc.setParameters("state", VirtualMachineTemplate.State.Active);
if (hypervisorType != null && !HypervisorType.Any.equals(hypervisorType)) {
sc.setParameters("hypervisorType", List.of(hypervisorType).toArray());
} else {
sc.setParameters("hypervisorType",
availableHypervisors.stream().map(Pair::first).distinct().toArray());
}
sc.setJoinParameters("vmTemplateJoinTemplateStoreRef", "downloadState",
List.of(VMTemplateStorageResourceAssoc.Status.DOWNLOADED,
VMTemplateStorageResourceAssoc.Status.BYPASSED).toArray());
// order by descending order of id
List<VMTemplateVO> templates = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, null));
Map<Pair<HypervisorType, CPU.CPUArch>, VMTemplateVO> uniqueTemplates = new HashMap<>();
for (VMTemplateVO template : templates) {
Pair<HypervisorType, CPU.CPUArch> key = new Pair<>(template.getHypervisorType(), template.getArch());
if (availableHypervisors.contains(key) && !uniqueTemplates.containsKey(key)) {
uniqueTemplates.put(key, template);
}
}
return getSortedTemplatesListWithPreferredArch(uniqueTemplates, preferredArch);
}
@Override
public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) {
SearchCriteria<VMTemplateVO> sc = tmpltTypeHyperSearch2.create();
@ -618,10 +683,43 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
}
@Override
public VMTemplateVO findLatestTemplateByTypeAndHypervisor(HypervisorType hypervisorType, TemplateType type) {
public List<VMTemplateVO> findRoutingTemplates(HypervisorType hType, String templateName, String preferredArch) {
SearchCriteria<VMTemplateVO> sc = tmpltTypeHyperSearch2.create();
sc.setParameters("templateType", TemplateType.ROUTING);
sc.setParameters("hypervisorType", hType);
sc.setParameters("state", VirtualMachineTemplate.State.Active.toString());
if (templateName != null) {
sc.setParameters("templateName", templateName);
}
List<VMTemplateVO> templates = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1L));
if (CollectionUtils.isEmpty(templates)) {
sc = tmpltTypeHyperSearch2.create();
sc.setParameters("templateType", TemplateType.SYSTEM);
sc.setParameters("hypervisorType", hType);
sc.setParameters("state", VirtualMachineTemplate.State.Active.toString());
if (templateName != null) {
sc.setParameters("templateName", templateName);
}
templates = listBy(sc, new Filter(VMTemplateVO.class, "id", false, null, 1L));
}
Map<Pair<HypervisorType, CPU.CPUArch>, VMTemplateVO> uniqueTemplates = new HashMap<>();
for (VMTemplateVO template : templates) {
Pair<HypervisorType, CPU.CPUArch> key = new Pair<>(template.getHypervisorType(), template.getArch());
if (!uniqueTemplates.containsKey(key)) {
uniqueTemplates.put(key, template);
}
}
return getSortedTemplatesListWithPreferredArch(uniqueTemplates, preferredArch);
}
@Override
public VMTemplateVO findLatestTemplateByTypeAndHypervisorAndArch(HypervisorType hypervisorType, CPU.CPUArch arch, TemplateType type) {
SearchCriteria<VMTemplateVO> sc = LatestTemplateByHypervisorTypeSearch.create();
sc.setParameters("hypervisorType", hypervisorType);
sc.setParameters("templateType", type);
if (arch != null) {
sc.setParameters("arch", arch);
}
Filter filter = new Filter(VMTemplateVO.class, "id", false, null, 1L);
List<VMTemplateVO> templates = listBy(sc, filter);
if (templates != null && !templates.isEmpty()) {

View File

@ -16,6 +16,47 @@
// under the License.
package com.cloud.upgrade;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ini4j.Ini;
import com.cloud.cpu.CPU;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.ClusterDaoImpl;
@ -36,6 +77,7 @@ import com.cloud.template.VirtualMachineTemplate;
import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl;
import com.cloud.user.Account;
import com.cloud.utils.DateUtil;
import com.cloud.utils.HttpUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.UriUtils;
import com.cloud.utils.db.GlobalLock;
@ -46,48 +88,10 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.dao.VMInstanceDaoImpl;
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationDaoImpl;
import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDaoImpl;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDao;
import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailsDaoImpl;
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.ini4j.Ini;
import javax.inject.Inject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class SystemVmTemplateRegistration {
protected static Logger LOGGER = LogManager.getLogger(SystemVmTemplateRegistration.class);
private static final String MOUNT_COMMAND = "sudo mount -t nfs %s %s";
private static final String MOUNT_COMMAND_BASE = "sudo mount -t nfs";
private static final String UMOUNT_COMMAND = "sudo umount %s";
private static final String RELATIVE_TEMPLATE_PATH = "./engine/schema/dist/systemvm-templates/";
private static final String ABSOLUTE_TEMPLATE_PATH = "/usr/share/cloudstack-management/templates/systemvm/";
@ -102,6 +106,9 @@ public class SystemVmTemplateRegistration {
private static final Integer LINUX_7_ID = 183;
private static final Integer SCRIPT_TIMEOUT = 1800000;
private static final Integer LOCK_WAIT_TIMEOUT = 1200;
protected static final List<CPU.CPUArch> DOWNLOADABLE_TEMPLATE_ARCH_TYPES = Arrays.asList(
CPU.CPUArch.arm64
);
public static String CS_MAJOR_VERSION = null;
@ -128,6 +135,8 @@ public class SystemVmTemplateRegistration {
private String systemVmTemplateVersion;
private final File tempDownloadDir;
public SystemVmTemplateRegistration() {
dataCenterDao = new DataCenterDaoImpl();
vmTemplateDao = new VMTemplateDaoImpl();
@ -138,6 +147,7 @@ public class SystemVmTemplateRegistration {
imageStoreDetailsDao = new ImageStoreDetailsDaoImpl();
clusterDao = new ClusterDaoImpl();
configurationDao = new ConfigurationDaoImpl();
tempDownloadDir = new File(System.getProperty("java.io.tmpdir"));
}
/**
@ -149,7 +159,7 @@ public class SystemVmTemplateRegistration {
}
public static String getMountCommand(String nfsVersion, String device, String dir) {
String cmd = "sudo mount -t nfs";
String cmd = MOUNT_COMMAND_BASE;
if (StringUtils.isNotBlank(nfsVersion)) {
cmd = String.format("%s -o vers=%s", cmd, nfsVersion);
}
@ -163,6 +173,10 @@ public class SystemVmTemplateRegistration {
return systemVmTemplateVersion;
}
public File getTempDownloadDir() {
return tempDownloadDir;
}
private static class SystemVMTemplateDetails {
Long id;
String uuid;
@ -174,6 +188,7 @@ public class SystemVmTemplateRegistration {
ImageFormat format;
Integer guestOsId;
Hypervisor.HypervisorType hypervisorType;
CPU.CPUArch arch;
Long storeId;
Long size;
Long physicalSize;
@ -183,7 +198,7 @@ public class SystemVmTemplateRegistration {
SystemVMTemplateDetails(String uuid, String name, Date created, String url, String checksum,
ImageFormat format, Integer guestOsId, Hypervisor.HypervisorType hypervisorType,
Long storeId) {
CPU.CPUArch arch, Long storeId) {
this.uuid = uuid;
this.name = name;
this.created = created;
@ -192,6 +207,7 @@ public class SystemVmTemplateRegistration {
this.format = format;
this.guestOsId = guestOsId;
this.hypervisorType = hypervisorType;
this.arch = arch;
this.storeId = storeId;
}
@ -235,6 +251,10 @@ public class SystemVmTemplateRegistration {
return hypervisorType;
}
public CPU.CPUArch getArch() {
return arch;
}
public Long getStoreId() {
return storeId;
}
@ -288,18 +308,17 @@ public class SystemVmTemplateRegistration {
}
}
public static final List<Hypervisor.HypervisorType> hypervisorList = Arrays.asList(Hypervisor.HypervisorType.KVM,
Hypervisor.HypervisorType.VMware,
Hypervisor.HypervisorType.XenServer,
Hypervisor.HypervisorType.Hyperv,
Hypervisor.HypervisorType.LXC,
Hypervisor.HypervisorType.Ovm3
public static final List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorList = Arrays.asList(
new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64),
new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64),
new Pair<>(Hypervisor.HypervisorType.VMware, null),
new Pair<>(Hypervisor.HypervisorType.XenServer, null),
new Pair<>(Hypervisor.HypervisorType.Hyperv, null),
new Pair<>(Hypervisor.HypervisorType.LXC, null),
new Pair<>(Hypervisor.HypervisorType.Ovm3, null)
);
public static final Map<Hypervisor.HypervisorType, String> NewTemplateNameList = new HashMap<Hypervisor.HypervisorType, String>();
public static final Map<Hypervisor.HypervisorType, String> FileNames = new HashMap<Hypervisor.HypervisorType, String>();
public static final Map<Hypervisor.HypervisorType, String> NewTemplateUrl = new HashMap<Hypervisor.HypervisorType, String>();
public static final Map<Hypervisor.HypervisorType, String> NewTemplateChecksum = new HashMap<Hypervisor.HypervisorType, String>();
public static final Map<String, MetadataTemplateDetails> NewTemplateMap = new HashMap<>();
public static final Map<Hypervisor.HypervisorType, String> RouterTemplateConfigurationNames = new HashMap<Hypervisor.HypervisorType, String>() {
{
@ -368,56 +387,74 @@ public class SystemVmTemplateRegistration {
}
}
public Long getRegisteredTemplateId(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
VMTemplateVO vmTemplate = vmTemplateDao.findLatestTemplateByName(hypervisorAndTemplateName.second());
Long templateId = null;
if (vmTemplate != null) {
templateId = vmTemplate.getId();
private static String getHypervisorArchLog(Hypervisor.HypervisorType hypervisorType, CPU.CPUArch arch) {
StringBuilder sb = new StringBuilder("hypervisor: ").append(hypervisorType.name());
if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) {
sb.append(", arch: ").append(arch == null ? CPU.CPUArch.amd64.getType() : arch.getType());
}
return templateId;
return sb.toString();
}
private static String fetchTemplatesPath() {
String filePath = RELATIVE_TEMPLATE_PATH + METADATA_FILE_NAME;
LOGGER.debug(String.format("Looking for file [ %s ] in the classpath.", filePath));
File metaFile = new File(filePath);
String templatePath = null;
if (metaFile.exists()) {
templatePath = RELATIVE_TEMPLATE_PATH;
protected static String getHypervisorArchKey(Hypervisor.HypervisorType hypervisorType, CPU.CPUArch arch) {
if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) {
return String.format("%s-%s", hypervisorType.name().toLowerCase(),
arch == null ? CPU.CPUArch.amd64.getType() : arch.getType());
}
if (templatePath == null) {
filePath = ABSOLUTE_TEMPLATE_PATH + METADATA_FILE_NAME;
metaFile = new File(filePath);
templatePath = ABSOLUTE_TEMPLATE_PATH;
LOGGER.debug(String.format("Looking for file [ %s ] in the classpath.", filePath));
if (!metaFile.exists()) {
String errMsg = String.format("Unable to locate metadata file in your setup at %s", filePath.toString());
return hypervisorType.name().toLowerCase();
}
protected static MetadataTemplateDetails getMetadataTemplateDetails(Hypervisor.HypervisorType hypervisorType,
CPU.CPUArch arch) {
return NewTemplateMap.get(getHypervisorArchKey(hypervisorType, arch));
}
public VMTemplateVO getRegisteredTemplate(String templateName, CPU.CPUArch arch) {
return vmTemplateDao.findLatestTemplateByName(templateName, arch);
}
private static boolean isRunningInTest() {
return "true".equalsIgnoreCase(System.getProperty("test.mode"));
}
/**
* Attempts to determine the templates directory path by locating the metadata file.
* <p>
* This method checks if the application is running in a test environment by invoking
* {@code isRunningInTest()}. If so, it immediately returns the {@code RELATIVE_TEMPLATE_PATH}.
* </p>
* <p>
* Otherwise, it creates a list of candidate paths (typically including both relative and absolute
* template paths) and iterates through them. For each candidate, it constructs the metadata file
* path by appending {@code METADATA_FILE_NAME} to {@code RELATIVE_TEMPLATE_PATH} (note: the candidate
* path is not used in the file path construction in this implementation) and checks if that file exists.
* If the metadata file exists, the candidate path is returned.
* </p>
* <p>
* If none of the candidate paths contain the metadata file, the method logs an error and throws a
* {@link CloudRuntimeException}.
* </p>
*
* @return the path to the templates directory if the metadata file is found, or {@code RELATIVE_TEMPLATE_PATH}
* when running in a test environment.
* @throws CloudRuntimeException if the metadata file cannot be located in any of the candidate paths.
*/
private static String fetchTemplatesPath() {
if (isRunningInTest()) {
return RELATIVE_TEMPLATE_PATH;
}
List<String> paths = Arrays.asList(RELATIVE_TEMPLATE_PATH, ABSOLUTE_TEMPLATE_PATH);
for (String path : paths) {
String filePath = path + METADATA_FILE_NAME;
LOGGER.debug("Looking for file [ {} ] in the classpath.", filePath);
File metaFile = new File(filePath);
if (metaFile.exists()) {
return path;
}
}
String errMsg = String.format("Unable to locate metadata file in your setup at %s", StringUtils.join(paths));
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
}
return templatePath;
}
private String getHypervisorName(String name) {
if (name.equals("xenserver")) {
return "xen";
}
if (name.equals("ovm3")) {
return "ovm";
}
return name;
}
private Hypervisor.HypervisorType getHypervisorType(String hypervisor) {
if (hypervisor.equalsIgnoreCase("xen")) {
hypervisor = "xenserver";
} else if (hypervisor.equalsIgnoreCase("ovm")) {
hypervisor = "ovm3";
}
return Hypervisor.HypervisorType.getType(hypervisor);
}
private List<Long> getEligibleZoneIds() {
List<Long> zoneIds = new ArrayList<>();
@ -430,28 +467,28 @@ public class SystemVmTemplateRegistration {
return zoneIds;
}
private Pair<String, Long> getNfsStoreInZone(Long zoneId) {
String url = null;
Long storeId = null;
protected Pair<String, Long> getNfsStoreInZone(Long zoneId) {
ImageStoreVO storeVO = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs");
if (storeVO == null) {
String errMsg = String.format("Failed to fetch NFS store in zone = %s for SystemVM template registration", zoneId);
String errMsg = String.format("Failed to fetch NFS store in zone = %s for SystemVM template registration",
zoneId);
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
url = storeVO.getUrl();
storeId = storeVO.getId();
String url = storeVO.getUrl();
Long storeId = storeVO.getId();
return new Pair<>(url, storeId);
}
public static void mountStore(String storeUrl, String path, String nfsVersion) {
try {
if (storeUrl != null) {
if (storeUrl == null) {
return;
}
URI uri = new URI(UriUtils.encodeURIComponent(storeUrl));
String host = uri.getHost();
String mountPath = uri.getPath();
Script.runSimpleBashScript(getMountCommand(nfsVersion, host + ":" + mountPath, path));
}
} catch (Exception e) {
String msg = "NFS Store URL is not in the correct format";
LOGGER.error(msg, e);
@ -459,13 +496,6 @@ public class SystemVmTemplateRegistration {
}
}
private List<String> fetchAllHypervisors(Long zoneId) {
List<String> hypervisorList = new ArrayList<>();
List<Hypervisor.HypervisorType> hypervisorTypes = clusterDao.getAvailableHypervisorInZone(zoneId);
hypervisorList = hypervisorTypes.stream().distinct().map(Hypervisor.HypervisorType::name).collect(Collectors.toList());
return hypervisorList;
}
private VMTemplateVO createTemplateObjectInDB(SystemVMTemplateDetails details) {
Long templateId = vmTemplateDao.getNextInSequence(Long.class, "id");
VMTemplateVO template = new VMTemplateVO();
@ -486,6 +516,7 @@ public class SystemVmTemplateRegistration {
template.setGuestOSId(details.getGuestOsId());
template.setCrossZones(true);
template.setHypervisorType(details.getHypervisorType());
template.setArch(details.getArch());
template.setState(VirtualMachineTemplate.State.Inactive);
template.setDeployAsIs(false);
template = vmTemplateDao.persist(template);
@ -627,7 +658,7 @@ public class SystemVmTemplateRegistration {
}
}
private void setupTemplate(String templateName, Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName,
private void setupTemplate(String templateName, Hypervisor.HypervisorType hypervisor, CPU.CPUArch arch,
String destTempFolder) throws CloudRuntimeException {
String setupTmpltScript = Script.findScript(storageScriptsDir, "setup-sysvm-tmplt");
if (setupTmpltScript == null) {
@ -635,8 +666,12 @@ public class SystemVmTemplateRegistration {
}
Script scr = new Script(setupTmpltScript, SCRIPT_TIMEOUT, LOGGER);
scr.add("-u", templateName);
scr.add("-f", TEMPLATES_PATH + FileNames.get(hypervisorAndTemplateName.first()));
scr.add("-h", hypervisorAndTemplateName.first().name().toLowerCase(Locale.ROOT));
MetadataTemplateDetails templateDetails = NewTemplateMap.get(getHypervisorArchKey(hypervisor, arch));
String filePath = StringUtils.isNotBlank(templateDetails.getDownloadedFilePath()) ?
templateDetails.getDownloadedFilePath() :
templateDetails.getDefaultFilePath();
scr.add("-f", filePath);
scr.add("-h", hypervisor.name().toLowerCase(Locale.ROOT));
scr.add("-d", destTempFolder);
String result = scr.execute();
if (result != null) {
@ -644,17 +679,15 @@ public class SystemVmTemplateRegistration {
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
}
private Long performTemplateRegistrationOperations(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName,
String url, String checksum, ImageFormat format, long guestOsId,
private Long performTemplateRegistrationOperations(Hypervisor.HypervisorType hypervisor,
String name, CPU.CPUArch arch, String url, String checksum, ImageFormat format, long guestOsId,
Long storeId, Long templateId, String filePath, TemplateDataStoreVO templateDataStoreVO) {
Hypervisor.HypervisorType hypervisor = hypervisorAndTemplateName.first();
String templateName = UUID.randomUUID().toString();
Date created = new Date(DateUtil.currentGMTTime().getTime());
SystemVMTemplateDetails details = new SystemVMTemplateDetails(templateName, hypervisorAndTemplateName.second(), created,
url, checksum, format, (int) guestOsId, hypervisor, storeId);
SystemVMTemplateDetails details = new SystemVMTemplateDetails(templateName, name, created,
url, checksum, format, (int) guestOsId, hypervisor, arch, storeId);
if (templateId == null) {
VMTemplateVO template = createTemplateObjectInDB(details);
if (template == null) {
@ -671,23 +704,44 @@ public class SystemVmTemplateRegistration {
if (templateDataStoreVO == null) {
createTemplateStoreRefEntry(details);
}
setupTemplate(templateName, hypervisorAndTemplateName, destTempFolder);
setupTemplate(templateName, hypervisor, arch, destTempFolder);
readTemplateProperties(destTempFolder + "/template.properties", details);
details.setUpdated(new Date(DateUtil.currentGMTTime().getTime()));
updateTemplateDetails(details);
return templateId;
}
public void registerTemplate(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName,
Pair<String, Long> storeUrlAndId, VMTemplateVO templateVO,
TemplateDataStoreVO templateDataStoreVO, String filePath) {
public void registerTemplate(Hypervisor.HypervisorType hypervisor, String name, Long storeId,
VMTemplateVO templateVO, TemplateDataStoreVO templateDataStoreVO, String filePath) {
try {
performTemplateRegistrationOperations(hypervisor, name, templateVO.getArch(), templateVO.getUrl(),
templateVO.getChecksum(), templateVO.getFormat(), templateVO.getGuestOSId(), storeId,
templateVO.getId(), filePath, templateDataStoreVO);
} catch (Exception e) {
String errMsg = String.format("Failed to register template for hypervisor: %s", hypervisor);
LOGGER.error(errMsg, e);
updateTemplateTablesOnFailure(templateVO.getId());
cleanupStore(templateVO.getId(), filePath);
throw new CloudRuntimeException(errMsg, e);
}
}
public void registerTemplateForNonExistingEntries(Hypervisor.HypervisorType hypervisor, CPU.CPUArch arch,
String name, Pair<String, Long> storeUrlAndId, String filePath) {
Long templateId = null;
try {
templateId = templateVO.getId();
performTemplateRegistrationOperations(hypervisorAndTemplateName, templateVO.getUrl(), templateVO.getChecksum(),
templateVO.getFormat(), templateVO.getGuestOSId(), storeUrlAndId.second(), templateId, filePath, templateDataStoreVO);
MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisor, arch);
templateId = performTemplateRegistrationOperations(hypervisor, name,
templateDetails.getArch(), templateDetails.getUrl(),
templateDetails.getChecksum(), hypervisorImageFormat.get(hypervisor),
hypervisorGuestOsMap.get(hypervisor), storeUrlAndId.second(), null, filePath, null);
Map<String, String> configParams = new HashMap<>();
configParams.put(RouterTemplateConfigurationNames.get(hypervisor), templateDetails.getName());
configParams.put("minreq.sysvmtemplate.version", getSystemVmTemplateVersion());
updateConfigurationParams(configParams);
updateSystemVMEntries(templateId, hypervisor);
} catch (Exception e) {
String errMsg = String.format("Failed to register template for hypervisor: %s", hypervisorAndTemplateName.first());
String errMsg = String.format("Failed to register template for hypervisor: %s", hypervisor);
LOGGER.error(errMsg, e);
if (templateId != null) {
updateTemplateTablesOnFailure(templateId);
@ -697,28 +751,33 @@ public class SystemVmTemplateRegistration {
}
}
public void registerTemplate(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName, Pair<String, Long> storeUrlAndId, String filePath) {
Long templateId = null;
try {
Hypervisor.HypervisorType hypervisor = hypervisorAndTemplateName.first();
templateId = performTemplateRegistrationOperations(hypervisorAndTemplateName, NewTemplateUrl.get(hypervisor), NewTemplateChecksum.get(hypervisor),
hypervisorImageFormat.get(hypervisor), hypervisorGuestOsMap.get(hypervisor), storeUrlAndId.second(), null, filePath, null);
Map<String, String> configParams = new HashMap<>();
configParams.put(RouterTemplateConfigurationNames.get(hypervisorAndTemplateName.first()), hypervisorAndTemplateName.second());
configParams.put("minreq.sysvmtemplate.version", getSystemVmTemplateVersion());
updateConfigurationParams(configParams);
updateSystemVMEntries(templateId, hypervisorAndTemplateName.first());
} catch (Exception e) {
String errMsg = String.format("Failed to register template for hypervisor: %s", hypervisorAndTemplateName.first());
LOGGER.error(errMsg, e);
if (templateId != null) {
updateTemplateTablesOnFailure(templateId);
cleanupStore(templateId, filePath);
protected void validateTemplateFileForHypervisorAndArch(Hypervisor.HypervisorType hypervisor, CPU.CPUArch arch) {
MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisor, arch);
File templateFile = getTemplateFile(templateDetails);
if (templateFile == null) {
throw new CloudRuntimeException("Failed to find local template file");
}
throw new CloudRuntimeException(errMsg, e);
if (isTemplateFileChecksumDifferent(templateDetails, templateFile)) {
throw new CloudRuntimeException("Checksum failed for local template file");
}
}
public void validateAndRegisterTemplate(Hypervisor.HypervisorType hypervisor, String name, Long storeId,
VMTemplateVO templateVO, TemplateDataStoreVO templateDataStoreVO, String filePath) {
validateTemplateFileForHypervisorAndArch(hypervisor, templateVO.getArch());
registerTemplate(hypervisor, name, storeId, templateVO, templateDataStoreVO, filePath);
}
public void validateAndRegisterTemplateForNonExistingEntries(Hypervisor.HypervisorType hypervisor,
CPU.CPUArch arch, String name, Pair<String, Long> storeUrlAndId, String filePath) {
validateTemplateFileForHypervisorAndArch(hypervisor, arch);
registerTemplateForNonExistingEntries(hypervisor, arch, name, storeUrlAndId, filePath);
}
protected static String getMetadataFilePath() {
return METADATA_FILE;
}
/**
* This method parses the metadata file consisting of the systemVM templates information
* @return the version of the systemvm template that is to be used. This is done in order
@ -726,25 +785,40 @@ public class SystemVmTemplateRegistration {
* exist a template corresponding to the current code version.
*/
public static String parseMetadataFile() {
try {
Ini ini = new Ini();
ini.load(new FileReader(METADATA_FILE));
for (Hypervisor.HypervisorType hypervisorType : hypervisorList) {
String hypervisor = hypervisorType.name().toLowerCase(Locale.ROOT);
Ini.Section section = ini.get(hypervisor);
NewTemplateNameList.put(hypervisorType, section.get("templatename"));
FileNames.put(hypervisorType, section.get("filename"));
NewTemplateChecksum.put(hypervisorType, section.get("checksum"));
NewTemplateUrl.put(hypervisorType, section.get("downloadurl"));
}
Ini.Section section = ini.get("default");
return section.get("version");
} catch (Exception e) {
String errMsg = String.format("Failed to parse systemVM template metadata file: %s", METADATA_FILE);
String metadataFilePath = getMetadataFilePath();
String errMsg = String.format("Failed to parse systemVM template metadata file: %s", metadataFilePath);
final Ini ini = new Ini();
try (FileReader reader = new FileReader(metadataFilePath)) {
ini.load(reader);
} catch (IOException e) {
LOGGER.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
if (!ini.containsKey("default")) {
errMsg = String.format("%s as unable to default section", errMsg);
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
for (Pair<Hypervisor.HypervisorType, CPU.CPUArch> hypervisorType : hypervisorList) {
String key = getHypervisorArchKey(hypervisorType.first(), hypervisorType.second());
Ini.Section section = ini.get(key);
if (section == null) {
LOGGER.error("Failed to find details for {} in template metadata file: {}",
key, metadataFilePath);
continue;
}
NewTemplateMap.put(key, new MetadataTemplateDetails(
hypervisorType.first(),
section.get("templatename"),
section.get("filename"),
section.get("downloadurl"),
section.get("checksum"),
hypervisorType.second()));
}
Ini.Section defaultSection = ini.get("default");
return defaultSection.get("version").trim();
}
private static void cleanupStore(Long templateId, String filePath) {
String destTempFolder = filePath + PARTIAL_TEMPLATE_FOLDER + String.valueOf(templateId);
@ -755,31 +829,60 @@ public class SystemVmTemplateRegistration {
}
}
private void validateTemplates(Set<Hypervisor.HypervisorType> hypervisorsInUse) {
Set<String> hypervisors = hypervisorsInUse.stream().
map(Hypervisor.HypervisorType::name).map(name -> name.toLowerCase(Locale.ROOT)).map(this::getHypervisorName).collect(Collectors.toSet());
List<String> templates = new ArrayList<>();
for (Hypervisor.HypervisorType hypervisorType : hypervisorsInUse) {
templates.add(FileNames.get(hypervisorType));
protected File getTemplateFile(MetadataTemplateDetails templateDetails) {
File templateFile = new File(templateDetails.getDefaultFilePath());
if (templateFile.exists()) {
return templateFile;
}
LOGGER.debug("{} is not present", templateFile.getAbsolutePath());
if (DOWNLOADABLE_TEMPLATE_ARCH_TYPES.contains(templateDetails.getArch()) &&
StringUtils.isNotBlank(templateDetails.getUrl())) {
LOGGER.debug("Downloading the template file {} for {}",
templateDetails.getUrl(), templateDetails.getHypervisorArchLog());
Path path = Path.of(TEMPLATES_PATH);
if (!Files.isWritable(path)) {
templateFile = new File(tempDownloadDir, templateDetails.getFilename());
}
if (!templateFile.exists() &&
!HttpUtils.downloadFileWithProgress(templateDetails.getUrl(), templateFile.getAbsolutePath(),
LOGGER)) {
return null;
}
templateDetails.setDownloadedFilePath(templateFile.getAbsolutePath());
}
return templateFile;
}
protected boolean isTemplateFileChecksumDifferent(MetadataTemplateDetails templateDetails, File templateFile) {
String templateChecksum = DigestHelper.calculateChecksum(templateFile);
if (!templateChecksum.equals(templateDetails.getChecksum())) {
LOGGER.error("Checksum {} for file {} does not match checksum {} from metadata",
templateChecksum, templateFile, templateDetails.getChecksum());
return true;
}
return false;
}
protected void validateTemplates(List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorsArchInUse) {
boolean templatesFound = true;
for (String hypervisor : hypervisors) {
String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null);
for (Pair<Hypervisor.HypervisorType, CPU.CPUArch> hypervisorArch : hypervisorsArchInUse) {
MetadataTemplateDetails matchedTemplate = getMetadataTemplateDetails(hypervisorArch.first(),
hypervisorArch.second());
if (matchedTemplate == null) {
templatesFound = false;
break;
}
File tempFile = new File(TEMPLATES_PATH + matchedTemplate);
String templateChecksum = DigestHelper.calculateChecksum(tempFile);
if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) {
LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor))));
File tempFile = getTemplateFile(matchedTemplate);
if (tempFile == null) {
LOGGER.warn("Failed to download template for {}, moving ahead",
matchedTemplate.getHypervisorArchLog());
continue;
}
if (isTemplateFileChecksumDifferent(matchedTemplate, tempFile)) {
templatesFound = false;
break;
}
}
if (!templatesFound) {
String errMsg = "SystemVm template not found. Cannot upgrade system Vms";
LOGGER.error(errMsg);
@ -787,7 +890,40 @@ public class SystemVmTemplateRegistration {
}
}
public void registerTemplates(Set<Hypervisor.HypervisorType> hypervisorsInUse) {
protected void registerTemplatesForZone(long zoneId, String filePath) {
Pair<String, Long> storeUrlAndId = getNfsStoreInZone(zoneId);
String nfsVersion = getNfsVersion(storeUrlAndId.second());
mountStore(storeUrlAndId.first(), filePath, nfsVersion);
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorArchList =
clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId);
for (Pair<Hypervisor.HypervisorType, CPU.CPUArch> hypervisorArch : hypervisorArchList) {
Hypervisor.HypervisorType hypervisorType = hypervisorArch.first();
MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisorType,
hypervisorArch.second());
if (templateDetails == null) {
continue;
}
VMTemplateVO templateVO = getRegisteredTemplate(templateDetails.getName(), templateDetails.getArch());
if (templateVO != null) {
TemplateDataStoreVO templateDataStoreVO =
templateDataStoreDao.findByStoreTemplate(storeUrlAndId.second(), templateVO.getId());
if (templateDataStoreVO != null) {
String installPath = templateDataStoreVO.getInstallPath();
if (validateIfSeeded(templateDataStoreVO, storeUrlAndId.first(), installPath, nfsVersion)) {
continue;
}
}
registerTemplate(hypervisorType, templateDetails.getName(), storeUrlAndId.second(), templateVO,
templateDataStoreVO, filePath);
updateRegisteredTemplateDetails(templateVO.getId(), templateDetails);
continue;
}
registerTemplateForNonExistingEntries(hypervisorType, templateDetails.getArch(), templateDetails.getName(),
storeUrlAndId, filePath);
}
}
public void registerTemplates(List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorsArchInUse) {
GlobalLock lock = GlobalLock.getInternLock("UpgradeDatabase-Lock");
try {
LOGGER.info("Grabbing lock to register templates.");
@ -795,7 +931,7 @@ public class SystemVmTemplateRegistration {
throw new CloudRuntimeException("Unable to acquire lock to register SystemVM template.");
}
try {
validateTemplates(hypervisorsInUse);
validateTemplates(hypervisorsArchInUse);
// Perform Registration if templates not already registered
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
@ -808,32 +944,7 @@ public class SystemVmTemplateRegistration {
if (filePath == null) {
throw new CloudRuntimeException("Failed to create temporary file path to mount the store");
}
Pair<String, Long> storeUrlAndId = getNfsStoreInZone(zoneId);
String nfsVersion = getNfsVersion(storeUrlAndId.second());
mountStore(storeUrlAndId.first(), filePath, nfsVersion);
List<String> hypervisorList = fetchAllHypervisors(zoneId);
for (String hypervisor : hypervisorList) {
Hypervisor.HypervisorType name = Hypervisor.HypervisorType.getType(hypervisor);
String templateName = NewTemplateNameList.get(name);
Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName = new Pair<Hypervisor.HypervisorType, String>(name, templateName);
Long templateId = getRegisteredTemplateId(hypervisorAndTemplateName);
if (templateId != null) {
VMTemplateVO templateVO = vmTemplateDao.findById(templateId);
TemplateDataStoreVO templateDataStoreVO = templateDataStoreDao.findByStoreTemplate(storeUrlAndId.second(), templateId);
if (templateDataStoreVO != null) {
String installPath = templateDataStoreVO.getInstallPath();
if (validateIfSeeded(templateDataStoreVO, storeUrlAndId.first(), installPath, nfsVersion)) {
continue;
}
}
if (templateVO != null) {
registerTemplate(hypervisorAndTemplateName, storeUrlAndId, templateVO, templateDataStoreVO, filePath);
updateRegisteredTemplateDetails(templateId, hypervisorAndTemplateName);
continue;
}
}
registerTemplate(hypervisorAndTemplateName, storeUrlAndId, filePath);
}
registerTemplatesForZone(zoneId, filePath);
unmountStore(filePath);
} catch (Exception e) {
unmountStore(filePath);
@ -851,12 +962,7 @@ public class SystemVmTemplateRegistration {
}
}
private void updateRegisteredTemplateDetails(Long templateId, Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
Pair<Hypervisor.HypervisorType, String> entry = new Pair<>(hypervisorAndTemplateName.getKey(), hypervisorAndTemplateName.getValue());
updateRegisteredTemplateDetails(templateId, entry);
}
private void updateRegisteredTemplateDetails(Long templateId, Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
private void updateRegisteredTemplateDetails(Long templateId, MetadataTemplateDetails templateDetails) {
VMTemplateVO templateVO = vmTemplateDao.findById(templateId);
templateVO.setTemplateType(Storage.TemplateType.SYSTEM);
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
@ -865,68 +971,81 @@ public class SystemVmTemplateRegistration {
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
updateSystemVMEntries(templateId, hypervisorAndTemplateName.first());
Hypervisor.HypervisorType hypervisorType = templateDetails.getHypervisorType();
updateSystemVMEntries(templateId, hypervisorType);
// Change value of global configuration parameter router.template.* for the corresponding hypervisor and minreq.sysvmtemplate.version for the ACS version
Map<String, String> configParams = new HashMap<>();
configParams.put(RouterTemplateConfigurationNames.get(hypervisorAndTemplateName.first()), hypervisorAndTemplateName.second());
configParams.put(RouterTemplateConfigurationNames.get(hypervisorType), templateDetails.getName());
configParams.put("minreq.sysvmtemplate.version", getSystemVmTemplateVersion());
updateConfigurationParams(configParams);
}
private void updateTemplateUrlAndChecksum(VMTemplateVO templateVO, Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
templateVO.setUrl(NewTemplateUrl.get(hypervisorAndTemplateName.getKey()));
templateVO.setChecksum(NewTemplateChecksum.get(hypervisorAndTemplateName.getKey()));
private void updateTemplateUrlAndChecksum(VMTemplateVO templateVO, MetadataTemplateDetails templateDetails) {
templateVO.setUrl(templateDetails.getUrl());
templateVO.setChecksum(templateDetails.getChecksum());
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
if (!updated) {
String errMsg = String.format("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type %s", hypervisorAndTemplateName.getKey().name());
String errMsg = String.format("updateSystemVmTemplates:Exception while updating 'url' and 'checksum' for hypervisor type %s", templateDetails.getHypervisorType());
LOGGER.error(errMsg);
throw new CloudRuntimeException(errMsg);
}
}
protected boolean registerOrUpdateSystemVmTemplate(MetadataTemplateDetails templateDetails,
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorsInUse) {
LOGGER.debug("Updating System VM template for {}", templateDetails.getHypervisorArchLog());
VMTemplateVO registeredTemplate = getRegisteredTemplate(templateDetails.getName(), templateDetails.getArch());
// change template type to SYSTEM
if (registeredTemplate != null) {
updateRegisteredTemplateDetails(registeredTemplate.getId(), templateDetails);
} else {
boolean isHypervisorArchMatchMetadata = hypervisorsInUse.stream()
.anyMatch(p -> p.first().equals(templateDetails.getHypervisorType())
&& Objects.equals(p.second(), templateDetails.getArch()));
if (isHypervisorArchMatchMetadata) {
try {
registerTemplates(hypervisorsInUse);
return true;
} catch (final Exception e) {
throw new CloudRuntimeException(String.format("Failed to register %s templates for hypervisors: [%s]. " +
"Cannot upgrade system VMs",
getSystemVmTemplateVersion(),
StringUtils.join(hypervisorsInUse.stream()
.map(x -> getHypervisorArchKey(x.first(), x.second()))
.collect(Collectors.toList()), ",")), e);
}
} else {
LOGGER.warn("Cannot upgrade {} system VM template for {} as it is not used, not failing upgrade",
getSystemVmTemplateVersion(), templateDetails.getHypervisorArchLog());
VMTemplateVO templateVO = vmTemplateDao.findLatestTemplateByTypeAndHypervisorAndArch(
templateDetails.getHypervisorType(), templateDetails.getArch(), Storage.TemplateType.SYSTEM);
if (templateVO != null) {
updateTemplateUrlAndChecksum(templateVO, templateDetails);
}
}
}
return false;
}
public void updateSystemVmTemplates(final Connection conn) {
LOGGER.debug("Updating System Vm template IDs");
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(final TransactionStatus status) {
Set<Hypervisor.HypervisorType> hypervisorsListInUse = new HashSet<Hypervisor.HypervisorType>();
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorsInUse;
try {
hypervisorsListInUse = clusterDao.getDistinctAvailableHypervisorsAcrossClusters();
hypervisorsInUse = clusterDao.listDistinctHypervisorsArchAcrossClusters(null);
} catch (final Exception e) {
LOGGER.error("updateSystemVmTemplates: Exception caught while getting hypervisor types from clusters: " + e.getMessage());
throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting hypervisor types from clusters", e);
throw new CloudRuntimeException("Exception while getting hypervisor types from clusters", e);
}
for (final Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName : NewTemplateNameList.entrySet()) {
LOGGER.debug("Updating " + hypervisorAndTemplateName.getKey() + " System Vms");
Long templateId = getRegisteredTemplateId(new Pair<>(hypervisorAndTemplateName.getKey(), hypervisorAndTemplateName.getValue()));
Collection<MetadataTemplateDetails> templateEntries = NewTemplateMap.values();
for (MetadataTemplateDetails templateDetails : templateEntries) {
try {
// change template type to SYSTEM
if (templateId != null) {
updateRegisteredTemplateDetails(templateId, hypervisorAndTemplateName);
} else {
if (hypervisorsListInUse.contains(hypervisorAndTemplateName.getKey())) {
try {
registerTemplates(hypervisorsListInUse);
if (registerOrUpdateSystemVmTemplate(templateDetails, hypervisorsInUse)) {
break;
} catch (final Exception e) {
throw new CloudRuntimeException(String.format("%s %s SystemVm template not found. Cannot upgrade system Vms", getSystemVmTemplateVersion(), hypervisorAndTemplateName.getKey()));
}
} else {
LOGGER.warn(String.format("%s %s SystemVm template not found. Cannot upgrade system Vms hypervisor is not used, so not failing upgrade",
getSystemVmTemplateVersion(), hypervisorAndTemplateName.getKey()));
// Update the latest template URLs for corresponding hypervisor
VMTemplateVO templateVO = vmTemplateDao.findLatestTemplateByTypeAndHypervisor(hypervisorAndTemplateName.getKey(), Storage.TemplateType.SYSTEM);
if (templateVO != null) {
updateTemplateUrlAndChecksum(templateVO, hypervisorAndTemplateName);
}
}
}
} catch (final Exception e) {
String errMsg = "updateSystemVmTemplates:Exception while getting ids of templates";
String errMsg = "Exception while registering/updating system VM templates for hypervisors in metadata";
LOGGER.error(errMsg, e);
throw new CloudRuntimeException(errMsg, e);
}
@ -948,4 +1067,64 @@ public class SystemVmTemplateRegistration {
}
return null;
}
protected static class MetadataTemplateDetails {
private final Hypervisor.HypervisorType hypervisorType;
private final String name;
private final String filename;
private final String url;
private final String checksum;
private final CPU.CPUArch arch;
private String downloadedFilePath;
MetadataTemplateDetails(Hypervisor.HypervisorType hypervisorType, String name, String filename, String url,
String checksum, CPU.CPUArch arch) {
this.hypervisorType = hypervisorType;
this.name = name;
this.filename = filename;
this.url = url;
this.checksum = checksum;
this.arch = arch;
}
public Hypervisor.HypervisorType getHypervisorType() {
return hypervisorType;
}
public String getName() {
return name;
}
public String getFilename() {
return filename;
}
public String getUrl() {
return url;
}
public String getChecksum() {
return checksum;
}
public CPU.CPUArch getArch() {
return arch;
}
public String getDownloadedFilePath() {
return downloadedFilePath;
}
public void setDownloadedFilePath(String downloadedFilePath) {
this.downloadedFilePath = downloadedFilePath;
}
public String getDefaultFilePath() {
return TEMPLATES_PATH + filename;
}
public String getHypervisorArchLog() {
return SystemVmTemplateRegistration.getHypervisorArchLog(hypervisorType, arch);
}
}
}

View File

@ -78,7 +78,7 @@ public class Upgrade42000to42010 extends DbUpgradeAbstractImpl implements DbUpgr
try {
systemVmTemplateRegistration.updateSystemVmTemplates(conn);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)");
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)", e);
}
}

View File

@ -44,7 +44,7 @@ public interface ImageStoreDao extends GenericDao<ImageStoreVO, Long> {
List<ImageStoreVO> listStoresByZoneId(long zoneId);
List<ImageStoreVO> listAllStoresInZone(Long zoneId, String provider, DataStoreRole role);
List<ImageStoreVO> listAllStoresInZoneExceptId(Long zoneId, String provider, DataStoreRole role, long storeId);
List<ImageStoreVO> findByProtocol(String protocol);

View File

@ -41,7 +41,7 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
private SearchBuilder<ImageStoreVO> nameSearch;
private SearchBuilder<ImageStoreVO> providerSearch;
private SearchBuilder<ImageStoreVO> regionSearch;
private SearchBuilder<ImageStoreVO> storeSearch;
private SearchBuilder<ImageStoreVO> storesExceptIdSearch;
private SearchBuilder<ImageStoreVO> protocolSearch;
private SearchBuilder<ImageStoreVO> zoneProtocolSearch;
@ -88,11 +88,12 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
regionSearch.and("role", regionSearch.entity().getRole(), SearchCriteria.Op.EQ);
regionSearch.done();
storeSearch = createSearchBuilder();
storeSearch.and("providerName", storeSearch.entity().getProviderName(), SearchCriteria.Op.EQ);
storeSearch.and("role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ);
storeSearch.and("dataCenterId", storeSearch.entity().getDcId(), SearchCriteria.Op.EQ);
storeSearch.done();
storesExceptIdSearch = createSearchBuilder();
storesExceptIdSearch.and("providerName", storesExceptIdSearch.entity().getProviderName(), SearchCriteria.Op.EQ);
storesExceptIdSearch.and("role", storesExceptIdSearch.entity().getRole(), SearchCriteria.Op.EQ);
storesExceptIdSearch.and("dataCenterId", storesExceptIdSearch.entity().getDcId(), SearchCriteria.Op.EQ);
storesExceptIdSearch.and("id", storesExceptIdSearch.entity().getId(), SearchCriteria.Op.NEQ);
storesExceptIdSearch.done();
return true;
}
@ -113,11 +114,12 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
}
@Override
public List<ImageStoreVO> listAllStoresInZone(Long zoneId, String provider, DataStoreRole role) {
SearchCriteria<ImageStoreVO> sc = storeSearch.create();
public List<ImageStoreVO> listAllStoresInZoneExceptId(Long zoneId, String provider, DataStoreRole role, long id) {
SearchCriteria<ImageStoreVO> sc = storesExceptIdSearch.create();
sc.setParameters("providerName", provider);
sc.setParameters("role", role);
sc.setParameters("dataCenterId", zoneId);
sc.setParameters("id", id);
return listBy(sc);
}

View File

@ -21,7 +21,7 @@ import com.cloud.cpu.CPU;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter
@Converter(autoApply = true)
public class CPUArchConverter implements AttributeConverter<CPU.CPUArch, String> {
@Override

View File

@ -19,6 +19,12 @@
-- Schema upgrade from 4.20.0.0 to 4.20.1.0
--;
-- Delete user vm details for guest CPU mode/model which are root admin only
DELETE FROM `cloud`.`user_vm_details` WHERE `name` IN ('guest.cpu.mode','guest.cpu.model');
-- Delete template details for guest CPU mode/model which are root admin only
DELETE FROM `cloud`.`vm_template_details` WHERE `name` IN ('guest.cpu.mode','guest.cpu.model');
-- Add column api_key_access to user and account tables
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.user', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the user" AFTER `secret_key`');
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.account', 'api_key_access', 'boolean DEFAULT NULL COMMENT "is api key access allowed for the account" ');

View File

@ -58,6 +58,7 @@ select
host.resource_state host_resource_state,
vm_template.id template_id,
vm_template.uuid template_uuid,
vm_template.arch arch,
service_offering.id service_offering_id,
service_offering.uuid service_offering_uuid,
service_offering.name service_offering_name,

View File

@ -83,6 +83,7 @@ SELECT
`iso`.`uuid` AS `iso_uuid`,
`iso`.`name` AS `iso_name`,
`iso`.`display_text` AS `iso_display_text`,
`vm_template`.`arch` AS `arch`,
`service_offering`.`id` AS `service_offering_id`,
`service_offering`.`uuid` AS `service_offering_uuid`,
`disk_offering`.`uuid` AS `disk_offering_uuid`,

View File

@ -17,6 +17,7 @@
package com.cloud.dc.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
@ -36,9 +37,13 @@ import org.mockito.InjectMocks;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.cpu.CPU;
import com.cloud.dc.ClusterVO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.utils.Pair;
import com.cloud.utils.db.GenericSearchBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@RunWith(MockitoJUnitRunner.class)
public class ClusterDaoImplTest {
@ -75,4 +80,39 @@ public class ClusterDaoImplTest {
verify(clusterDao).customSearch(genericSearchBuilder.create(), null);
assertTrue(result.isEmpty());
}
@Test
public void listDistinctHypervisorsArchAcrossClusters_WithZone() {
Long zoneId = 123L;
ClusterVO cluster1 = mock(ClusterVO.class);
when(cluster1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer);
when(cluster1.getArch()).thenReturn(CPU.CPUArch.amd64);
ClusterVO cluster2 = mock(ClusterVO.class);
when(cluster2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
when(cluster2.getArch()).thenReturn(CPU.CPUArch.arm64);
List<ClusterVO> dummyHosts = Arrays.asList(cluster1, cluster2);
doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull());
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId);
assertNotNull(result);
assertEquals(2, result.size());
assertEquals(Hypervisor.HypervisorType.XenServer, result.get(0).first());
assertEquals(CPU.CPUArch.amd64, result.get(0).second());
assertEquals(Hypervisor.HypervisorType.KVM, result.get(1).first());
assertEquals(CPU.CPUArch.arm64, result.get(1).second());
}
@Test
public void listDistinctHypervisorsArchAcrossClusters_WithoutZone() {
Long zoneId = null;
ClusterVO cluster = mock(ClusterVO.class);
when(cluster.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware);
when(cluster.getArch()).thenReturn(CPU.CPUArch.amd64);
List<ClusterVO> dummyHosts = Collections.singletonList(cluster);
doReturn(dummyHosts).when(clusterDao).search(any(SearchCriteria.class), isNull());
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> result = clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId);
assertNotNull(result);
assertEquals(1, result.size());
assertEquals(Hypervisor.HypervisorType.VMware, result.get(0).first());
assertEquals(CPU.CPUArch.amd64, result.get(0).second());
}
}

View File

@ -16,7 +16,18 @@
// under the License.
package com.cloud.host.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Assert;
import org.junit.Test;
@ -26,6 +37,7 @@ import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.cpu.CPU;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
@ -52,10 +64,10 @@ public class HostDaoImplTest {
public void testCountUpAndEnabledHostsInZone() {
long testZoneId = 100L;
hostDao.HostTypeCountSearch = mockSearchBuilder;
Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
Mockito.doNothing().when(mockSearchCriteria).setParameters(Mockito.anyString(), Mockito.any());
when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
Mockito.doNothing().when(mockSearchCriteria).setParameters(Mockito.anyString(), any());
int expected = 5;
Mockito.doReturn(expected).when(hostDao).getCount(mockSearchCriteria);
doReturn(expected).when(hostDao).getCount(mockSearchCriteria);
Integer count = hostDao.countUpAndEnabledHostsInZone(testZoneId);
Assert.assertSame(expected, count);
Mockito.verify(mockSearchCriteria).setParameters("type", Host.Type.Routing);
@ -70,16 +82,16 @@ public class HostDaoImplTest {
GenericDaoBase.SumCount mockSumCount = new GenericDaoBase.SumCount();
mockSumCount.count = 10;
mockSumCount.sum = 20;
HostVO host = Mockito.mock(HostVO.class);
GenericSearchBuilder<HostVO, GenericDaoBase.SumCount> sb = Mockito.mock(GenericSearchBuilder.class);
Mockito.when(sb.entity()).thenReturn(host);
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(GenericDaoBase.SumCount.class);
SearchCriteria<GenericDaoBase.SumCount> sc = Mockito.mock(SearchCriteria.class);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.doReturn(List.of(mockSumCount)).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, GenericDaoBase.SumCount> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
doReturn(sb).when(hostDao).createSearchBuilder(GenericDaoBase.SumCount.class);
SearchCriteria<GenericDaoBase.SumCount> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
doReturn(List.of(mockSumCount)).when(hostDao).customSearch(any(SearchCriteria.class), any());
Pair<Integer, Integer> result = hostDao.countAllHostsAndCPUSocketsByType(type);
Assert.assertEquals(10, result.first().intValue());
Assert.assertEquals(20, result.second().intValue());
assertEquals(10, result.first().intValue());
assertEquals(20, result.second().intValue());
Mockito.verify(sc).setParameters("type", type);
}
@ -87,13 +99,13 @@ public class HostDaoImplTest {
public void testIsHostUp() {
long testHostId = 101L;
List<Status> statuses = List.of(Status.Up);
HostVO host = Mockito.mock(HostVO.class);
GenericSearchBuilder<HostVO, Status> sb = Mockito.mock(GenericSearchBuilder.class);
Mockito.when(sb.entity()).thenReturn(host);
SearchCriteria<Status> sc = Mockito.mock(SearchCriteria.class);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Status.class);
Mockito.doReturn(statuses).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, Status> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
SearchCriteria<Status> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
doReturn(sb).when(hostDao).createSearchBuilder(Status.class);
doReturn(statuses).when(hostDao).customSearch(any(SearchCriteria.class), any());
boolean result = hostDao.isHostUp(testHostId);
Assert.assertTrue("Host should be up", result);
Mockito.verify(sc).setParameters("id", testHostId);
@ -109,17 +121,17 @@ public class HostDaoImplTest {
List<Host.Type> types = List.of(Host.Type.Routing);
List<Hypervisor.HypervisorType> hypervisorTypes = List.of(Hypervisor.HypervisorType.KVM);
List<Long> mockResults = List.of(1001L, 1002L); // Mocked result
HostVO host = Mockito.mock(HostVO.class);
GenericSearchBuilder<HostVO, Long> sb = Mockito.mock(GenericSearchBuilder.class);
Mockito.when(sb.entity()).thenReturn(host);
SearchCriteria<Long> sc = Mockito.mock(SearchCriteria.class);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.when(sb.and()).thenReturn(sb);
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, Long> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
SearchCriteria<Long> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
when(sb.and()).thenReturn(sb);
doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
doReturn(mockResults).when(hostDao).customSearch(any(SearchCriteria.class), any());
List<Long> hostIds = hostDao.findHostIdsByZoneClusterResourceStateTypeAndHypervisorType(
zoneId, clusterId, msId, resourceStates, types, hypervisorTypes);
Assert.assertEquals(mockResults, hostIds);
assertEquals(mockResults, hostIds);
Mockito.verify(sc).setParameters("zoneId", zoneId);
Mockito.verify(sc).setParameters("clusterId", clusterId);
Mockito.verify(sc).setParameters("msId", msId);
@ -132,15 +144,16 @@ public class HostDaoImplTest {
public void testListDistinctHypervisorTypes() {
Long zoneId = 1L;
List<Hypervisor.HypervisorType> mockResults = List.of(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.XenServer);
HostVO host = Mockito.mock(HostVO.class);
GenericSearchBuilder<HostVO, Hypervisor.HypervisorType> sb = Mockito.mock(GenericSearchBuilder.class);
Mockito.when(sb.entity()).thenReturn(host);
SearchCriteria<Hypervisor.HypervisorType> sc = Mockito.mock(SearchCriteria.class);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Hypervisor.HypervisorType.class);
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, String> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
SearchCriteria<String> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
doReturn(sb).when(hostDao).createSearchBuilder(String.class);
doReturn(mockResults.stream().map(h -> h.name()).collect(Collectors.toList())).when(hostDao)
.customSearch(any(SearchCriteria.class), any());
List<Hypervisor.HypervisorType> hypervisorTypes = hostDao.listDistinctHypervisorTypes(zoneId);
Assert.assertEquals(mockResults, hypervisorTypes);
assertEquals(mockResults, hypervisorTypes);
Mockito.verify(sc).setParameters("zoneId", zoneId);
Mockito.verify(sc).setParameters("type", Host.Type.Routing);
}
@ -148,12 +161,12 @@ public class HostDaoImplTest {
@Test
public void testListByIds() {
List<Long> ids = List.of(101L, 102L);
List<HostVO> mockResults = List.of(Mockito.mock(HostVO.class), Mockito.mock(HostVO.class));
List<HostVO> mockResults = List.of(mock(HostVO.class), mock(HostVO.class));
hostDao.IdsSearch = mockSearchBuilder;
Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
Mockito.doReturn(mockResults).when(hostDao).search(Mockito.any(SearchCriteria.class), Mockito.any());
when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
doReturn(mockResults).when(hostDao).search(any(SearchCriteria.class), any());
List<HostVO> hosts = hostDao.listByIds(ids);
Assert.assertEquals(mockResults, hosts);
assertEquals(mockResults, hosts);
Mockito.verify(mockSearchCriteria).setParameters("id", ids.toArray());
Mockito.verify(hostDao).search(mockSearchCriteria, null);
}
@ -166,15 +179,15 @@ public class HostDaoImplTest {
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
Long zoneId = 1L, podId = 2L, clusterId = 3L;
List<Long> mockResults = List.of(1001L, 1002L);
HostVO host = Mockito.mock(HostVO.class);
GenericSearchBuilder<HostVO, Long> sb = Mockito.mock(GenericSearchBuilder.class);
Mockito.when(sb.entity()).thenReturn(host);
SearchCriteria<Long> sc = Mockito.mock(SearchCriteria.class);
Mockito.when(sb.create()).thenReturn(sc);
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, Long> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
SearchCriteria<Long> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
doReturn(mockResults).when(hostDao).customSearch(any(SearchCriteria.class), any());
List<Long> hostIds = hostDao.listIdsBy(type, status, resourceState, hypervisorType, zoneId, podId, clusterId);
Assert.assertEquals(mockResults, hostIds);
assertEquals(mockResults, hostIds);
Mockito.verify(sc).setParameters("type", type);
Mockito.verify(sc).setParameters("status", status);
Mockito.verify(sc).setParameters("resourceState", resourceState);
@ -183,4 +196,57 @@ public class HostDaoImplTest {
Mockito.verify(sc).setParameters("podId", podId);
Mockito.verify(sc).setParameters("clusterId", clusterId);
}
@Test
public void testListDistinctHypervisorArchTypes_WithZone() {
Long zoneId = 123L;
HostVO host1 = mock(HostVO.class);
when(host1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.XenServer);
when(host1.getArch()).thenReturn(CPU.CPUArch.amd64);
HostVO host2 = mock(HostVO.class);
when(host2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
when(host2.getArch()).thenReturn(CPU.CPUArch.arm64);
List<HostVO> dummyHosts = Arrays.asList(host1, host2);
doReturn(dummyHosts).when(hostDao).search(any(SearchCriteria.class), isNull());
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> result = hostDao.listDistinctHypervisorArchTypes(zoneId);
assertNotNull(result);
assertEquals(2, result.size());
assertEquals(Hypervisor.HypervisorType.XenServer, result.get(0).first());
assertEquals(CPU.CPUArch.amd64, result.get(0).second());
assertEquals(Hypervisor.HypervisorType.KVM, result.get(1).first());
assertEquals(CPU.CPUArch.arm64, result.get(1).second());
}
@Test
public void testListDistinctHypervisorArchTypes_WithoutZone() {
Long zoneId = null;
HostVO host1 = mock(HostVO.class);
when(host1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.VMware);
when(host1.getArch()).thenReturn(CPU.CPUArch.amd64);
List<HostVO> dummyHosts = Collections.singletonList(host1);
doReturn(dummyHosts).when(hostDao).search(any(SearchCriteria.class), isNull());
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> result = hostDao.listDistinctHypervisorArchTypes(zoneId);
assertNotNull(result);
assertEquals(1, result.size());
assertEquals(Hypervisor.HypervisorType.VMware, result.get(0).first());
assertEquals(CPU.CPUArch.amd64, result.get(0).second());
}
@Test
public void testListDistinctArchTypes() {
Long clusterId = 1L;
List<CPU.CPUArch> mockResults = List.of(CPU.CPUArch.amd64, CPU.CPUArch.arm64);
HostVO host = mock(HostVO.class);
GenericSearchBuilder<HostVO, String> sb = mock(GenericSearchBuilder.class);
when(sb.entity()).thenReturn(host);
SearchCriteria<String> sc = mock(SearchCriteria.class);
when(sb.create()).thenReturn(sc);
doReturn(sb).when(hostDao).createSearchBuilder(String.class);
doReturn(mockResults.stream().map(h -> h.getType()).collect(Collectors.toList())).when(hostDao)
.customSearch(any(SearchCriteria.class), any());
List<CPU.CPUArch> hypervisorTypes = hostDao.listDistinctArchTypes(clusterId);
assertEquals(mockResults, hypervisorTypes);
Mockito.verify(sc).setParameters("clusterId", clusterId);
Mockito.verify(sc).setParameters("type", Host.Type.Routing);
}
}

View File

@ -0,0 +1,189 @@
// 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.storage.dao;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.cpu.CPU;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateVO;
import com.cloud.utils.Pair;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
@RunWith(MockitoJUnitRunner.class)
public class VMTemplateDaoImplTest {
@Mock
HostDao hostDao;
@Spy
@InjectMocks
VMTemplateDaoImpl templateDao = new VMTemplateDaoImpl();
@Test
public void testFindLatestTemplateByName_ReturnsTemplate() {
VMTemplateVO expectedTemplate = new VMTemplateVO();
List<VMTemplateVO> returnedList = Collections.singletonList(expectedTemplate);
doReturn(returnedList).when(templateDao).listBy(any(SearchCriteria.class), any(Filter.class));
VMTemplateVO result = templateDao.findLatestTemplateByName("test", CPU.CPUArch.getDefault());
assertNotNull("Expected a non-null template", result);
assertEquals("Expected the returned template to be the first element", expectedTemplate, result);
}
@Test
public void testFindLatestTemplateByName_ReturnsNullWhenNoTemplateFound() {
List<VMTemplateVO> emptyList = Collections.emptyList();
doReturn(emptyList).when(templateDao).listBy(any(SearchCriteria.class), any(Filter.class));
VMTemplateVO result = templateDao.findLatestTemplateByName("test", CPU.CPUArch.getDefault());
assertNull("Expected null when no templates are found", result);
}
@Test
public void testFindLatestTemplateByName_NullArch() {
VMTemplateVO expectedTemplate = new VMTemplateVO();
List<VMTemplateVO> returnedList = Collections.singletonList(expectedTemplate);
doReturn(returnedList).when(templateDao).listBy(any(SearchCriteria.class), any(Filter.class));
VMTemplateVO result = templateDao.findLatestTemplateByName("test", null);
assertNotNull("Expected a non-null template even if arch is null", result);
assertEquals("Expected the returned template to be the first element", expectedTemplate, result);
}
@Test
public void testGetSortedTemplatesListWithPreferredArch_PreferredProvided() {
VMTemplateVO templatePreferred = Mockito.mock(VMTemplateVO.class);
when(templatePreferred.getArch()).thenReturn(CPU.CPUArch.amd64);
VMTemplateVO templateOther = Mockito.mock(VMTemplateVO.class);
when(templateOther.getArch()).thenReturn(CPU.CPUArch.arm64);
Map<Pair<Hypervisor.HypervisorType, CPU.CPUArch>, VMTemplateVO> uniqueTemplates = new HashMap<>();
uniqueTemplates.put(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), templatePreferred);
uniqueTemplates.put(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64), templateOther);
List<VMTemplateVO> sortedList = templateDao.getSortedTemplatesListWithPreferredArch(uniqueTemplates,
CPU.CPUArch.amd64.getType());
assertEquals(2, sortedList.size());
assertEquals(templatePreferred, sortedList.get(0));
assertEquals(templateOther, sortedList.get(1));
}
@Test
public void testGetSortedTemplatesListWithPreferredArch_NoPreferred() {
VMTemplateVO template1 = Mockito.mock(VMTemplateVO.class);
when(template1.getId()).thenReturn(1L);
VMTemplateVO template2 = Mockito.mock(VMTemplateVO.class);
when(template2.getId()).thenReturn(2L);
Map<Pair<Hypervisor.HypervisorType, CPU.CPUArch>, VMTemplateVO> uniqueTemplates = new HashMap<>();
uniqueTemplates.put(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), template1);
uniqueTemplates.put(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64), template2);
List<VMTemplateVO> sortedList = templateDao.getSortedTemplatesListWithPreferredArch(uniqueTemplates, "");
assertEquals(2, sortedList.size());
assertEquals(template2, sortedList.get(0));
assertEquals(template1, sortedList.get(1));
}
@Test
public void testFindSystemVMReadyTemplates() {
long zoneId = 1L;
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
String preferredArch = CPU.CPUArch.arm64.getType();
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> availableHypervisors = new ArrayList<>();
availableHypervisors.add(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64));
availableHypervisors.add(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64));
doReturn(availableHypervisors).when(hostDao).listDistinctHypervisorArchTypes(zoneId);
VMTemplateVO template1 = Mockito.mock(VMTemplateVO.class);
when(template1.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
when(template1.getArch()).thenReturn(CPU.CPUArch.amd64);
VMTemplateVO template2 = Mockito.mock(VMTemplateVO.class);
when(template2.getHypervisorType()).thenReturn(Hypervisor.HypervisorType.KVM);
when(template2.getArch()).thenReturn(CPU.CPUArch.arm64);
List<VMTemplateVO> templatesFromDb = Arrays.asList(template1, template2);
doReturn(templatesFromDb).when(templateDao).listBy(any(), any());
SearchBuilder<VMTemplateVO> sb = mock(SearchBuilder.class);
templateDao.readySystemTemplateSearch = sb;
when(sb.create()).thenReturn(mock(SearchCriteria.class));
List<VMTemplateVO> result = templateDao.findSystemVMReadyTemplates(zoneId, hypervisorType, preferredArch);
assertNotNull(result);
assertEquals(2, result.size());
assertEquals(template2, result.get(0));
assertEquals(template1, result.get(1));
}
@Test
public void testFindRoutingTemplates() {
Hypervisor.HypervisorType hType = Hypervisor.HypervisorType.KVM;
String templateName = "TestRouting";
String preferredArch = CPU.CPUArch.amd64.getType();
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
when(template.getArch()).thenReturn(CPU.CPUArch.amd64);
List<VMTemplateVO> templatesFromDb = Collections.singletonList(template);
doReturn(templatesFromDb).when(templateDao).listBy(any(), any());
SearchBuilder<VMTemplateVO> sb = mock(SearchBuilder.class);
when(sb.create()).thenReturn(mock(SearchCriteria.class));
templateDao.tmpltTypeHyperSearch2 = sb;
List<VMTemplateVO> result = templateDao.findRoutingTemplates(hType, templateName, preferredArch);
assertNotNull(result);
assertEquals(1, result.size());
assertEquals(template, result.get(0));
}
@Test
public void testFindLatestTemplateByTypeAndHypervisorAndArch_Found() {
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
CPU.CPUArch arch = CPU.CPUArch.amd64;
Storage.TemplateType type = Storage.TemplateType.SYSTEM;
VMTemplateVO template = Mockito.mock(VMTemplateVO.class);
List<VMTemplateVO> templatesFromDb = Collections.singletonList(template);
doReturn(templatesFromDb).when(templateDao).listBy(any(), any());
VMTemplateVO result = templateDao.findLatestTemplateByTypeAndHypervisorAndArch(hypervisorType, arch, type);
assertNotNull(result);
assertEquals(template, result);
}
@Test
public void testFindLatestTemplateByTypeAndHypervisorAndArch_NotFound() {
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
CPU.CPUArch arch = CPU.CPUArch.x86;
Storage.TemplateType type = Storage.TemplateType.SYSTEM;
doReturn(Collections.emptyList()).when(templateDao).listBy(any(), any());
VMTemplateVO result = templateDao.findLatestTemplateByTypeAndHypervisorAndArch(hypervisorType, arch, type);
assertNull(result);
}
}

View File

@ -0,0 +1,427 @@
// 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.upgrade;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.security.DigestHelper;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.cpu.CPU;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.utils.HttpUtils;
import com.cloud.utils.Pair;
import com.cloud.utils.UriUtils;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
@RunWith(MockitoJUnitRunner.class)
public class SystemVmTemplateRegistrationTest {
@Mock
ClusterDao clusterDao;
@Mock
VMTemplateDao vmTemplateDao;
@Spy
@InjectMocks
SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration();
private void setupMetadataFile(MockedStatic<SystemVmTemplateRegistration> mockedStatic, String content) {
try {
String location = "metadata.ini";
if (StringUtils.isNotBlank(content)) {
File tempFile = File.createTempFile("metadata", ".ini");
location = tempFile.getAbsolutePath();
Files.write(Paths.get(location), content.getBytes());
tempFile.deleteOnExit();
}
mockedStatic.when(SystemVmTemplateRegistration::getMetadataFilePath).thenReturn(location);
} catch (Exception e) {
fail(e.getMessage());
}
}
@Test
public void test_parseMetadataFile_noFile() {
try (MockedStatic<SystemVmTemplateRegistration> mockedStatic =
Mockito.mockStatic(SystemVmTemplateRegistration.class, Mockito.CALLS_REAL_METHODS)) {
setupMetadataFile(mockedStatic, null);
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class,
SystemVmTemplateRegistration::parseMetadataFile);
assertTrue(exception.getMessage().contains("Failed to parse systemVM template metadata file"));
}
}
@Test
public void test_parseMetadataFile_invalidContent() {
try (MockedStatic<SystemVmTemplateRegistration> mockedStatic =
Mockito.mockStatic(SystemVmTemplateRegistration.class, Mockito.CALLS_REAL_METHODS)) {
setupMetadataFile(mockedStatic, "abc");
CloudRuntimeException exception = assertThrows(CloudRuntimeException.class,
SystemVmTemplateRegistration::parseMetadataFile);
assertTrue(exception.getMessage().contains("Failed to parse systemVM template metadata file"));
}
}
@Test
public void test_parseMetadataFile_success() {
String metadataFileContent = "[default]\n" +
"version = x.y.z.0\n" +
"\n" +
"[kvm-x86_64]\n" +
"templatename = systemvm-kvm-x.y.z\n" +
"checksum = abc1\n" +
"downloadurl = https://download.cloudstack.org/systemvm/x.y/systemvmtemplate-x.y.z-kvm.qcow2.bz2\n" +
"filename = systemvmtemplate-x.y.z-kvm.qcow2.bz2\n" +
"\n" +
"[kvm-aarch64]\n" +
"templatename = systemvm-kvm-x.y.z\n" +
"checksum = abc2\n" +
"downloadurl = https://download.cloudstack.org/systemvm/x.y/systemvmtemplate-x.y.z-kvm.qcow2.bz2\n" +
"filename = systemvmtemplate-x.y.z-kvm.qcow2.bz2\n" +
"\n" +
"[vmware]\n" +
"templatename = systemvm-vmware-x.y.z\n" +
"checksum = abc3\n" +
"downloadurl = https://download.cloudstack.org/systemvm/x.y/systemvmtemplate-x.y.z-vmware.ova\n" +
"filename = systemvmtemplate-x.y.z-vmware.ova\n";
try (MockedStatic<SystemVmTemplateRegistration> mockedStatic =
Mockito.mockStatic(SystemVmTemplateRegistration.class, Mockito.CALLS_REAL_METHODS)) {
setupMetadataFile(mockedStatic, metadataFileContent);
String version = SystemVmTemplateRegistration.parseMetadataFile();
assertEquals("x.y.z.0", version);
}
assertNull(SystemVmTemplateRegistration.NewTemplateMap.get("xenserver"));
SystemVmTemplateRegistration.MetadataTemplateDetails templateDetails =
SystemVmTemplateRegistration.NewTemplateMap.get("kvm-x86_64");
assertNotNull(templateDetails);
assertEquals(CPU.CPUArch.amd64, templateDetails.getArch());
assertEquals(Hypervisor.HypervisorType.KVM, templateDetails.getHypervisorType());
templateDetails =
SystemVmTemplateRegistration.NewTemplateMap.get("kvm-aarch64");
assertNotNull(templateDetails);
assertEquals(CPU.CPUArch.arm64, templateDetails.getArch());
assertEquals(Hypervisor.HypervisorType.KVM, templateDetails.getHypervisorType());
templateDetails =
SystemVmTemplateRegistration.NewTemplateMap.get("vmware");
assertNotNull(templateDetails);
assertNull(templateDetails.getArch());
assertEquals(Hypervisor.HypervisorType.VMware, templateDetails.getHypervisorType());
}
@Test
public void testMountStore_nullStoreUrl() throws Exception {
try (MockedStatic<Script> scriptMock = Mockito.mockStatic(Script.class)) {
SystemVmTemplateRegistration.mountStore(null, "/mnt/nfs", "nfs3");
scriptMock.verifyNoInteractions();
}
}
@Test
public void testMountStore_validStoreUrl() throws Exception {
String storeUrl = "nfs://192.168.1.100/export";
String path = "/mnt/nfs";
String nfsVersion = "nfs3";
String expectedMountCommand = "expectedMountCommand";
try (MockedStatic<UriUtils> uriUtilsMock = Mockito.mockStatic(UriUtils.class);
MockedStatic<SystemVmTemplateRegistration> sysVmMock =
Mockito.mockStatic(SystemVmTemplateRegistration.class, Mockito.CALLS_REAL_METHODS);
MockedStatic<Script> scriptMock = Mockito.mockStatic(Script.class)) {
uriUtilsMock.when(() -> UriUtils.encodeURIComponent(storeUrl)).thenReturn(storeUrl);
sysVmMock.when(() -> SystemVmTemplateRegistration.getMountCommand(
eq(nfsVersion),
eq("192.168.1.100:/export"),
eq(path)
)).thenReturn(expectedMountCommand);
SystemVmTemplateRegistration.mountStore(storeUrl, path, nfsVersion);
scriptMock.verify(() -> Script.runSimpleBashScript(expectedMountCommand), times(1));
}
}
@Test
public void testValidateTemplateFile_fileNotFound() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
new SystemVmTemplateRegistration.MetadataTemplateDetails(Hypervisor.HypervisorType.KVM,
"name", "file", "url", "checksum", CPU.CPUArch.amd64);
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
details.getHypervisorType(), details.getArch()), details);
doReturn(null).when(systemVmTemplateRegistration).getTemplateFile(details);
try {
systemVmTemplateRegistration.validateTemplateFileForHypervisorAndArch(details.getHypervisorType(),
details.getArch());
fail("Expected CloudRuntimeException due to missing template file");
} catch (CloudRuntimeException e) {
assertEquals("Failed to find local template file", e.getMessage());
}
}
@Test
public void testValidateTemplateFile_checksumMismatch() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
new SystemVmTemplateRegistration.MetadataTemplateDetails(Hypervisor.HypervisorType.KVM,
"name", "file", "url", "checksum", CPU.CPUArch.amd64);
File dummyFile = new File("dummy.txt");
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
details.getHypervisorType(), details.getArch()), details);
doReturn(dummyFile).when(systemVmTemplateRegistration).getTemplateFile(details);
doReturn(true).when(systemVmTemplateRegistration).isTemplateFileChecksumDifferent(details, dummyFile);
try {
systemVmTemplateRegistration.validateTemplateFileForHypervisorAndArch(details.getHypervisorType(),
details.getArch());
fail("Expected CloudRuntimeException due to checksum failure");
} catch (CloudRuntimeException e) {
assertEquals("Checksum failed for local template file", e.getMessage());
}
}
@Test
public void testValidateTemplateFile_success() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
new SystemVmTemplateRegistration.MetadataTemplateDetails(Hypervisor.HypervisorType.KVM,
"name", "file", "url", "checksum", CPU.CPUArch.amd64);
File dummyFile = new File("dummy.txt");
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
details.getHypervisorType(), details.getArch()), details);
doReturn(dummyFile).when(systemVmTemplateRegistration).getTemplateFile(details);
doReturn(false).when(systemVmTemplateRegistration).isTemplateFileChecksumDifferent(details, dummyFile);
systemVmTemplateRegistration.validateTemplateFileForHypervisorAndArch(details.getHypervisorType(),
details.getArch());
}
@Test
public void testValidateAndRegisterTemplate() {
Hypervisor.HypervisorType hypervisor = Hypervisor.HypervisorType.KVM;
String name = "TestTemplate";
Long storeId = 123L;
VMTemplateVO templateVO = new VMTemplateVO();
templateVO.setArch(CPU.CPUArch.x86);
TemplateDataStoreVO templateDataStoreVO = new TemplateDataStoreVO();
String filePath = "/dummy/path";
doNothing().when(systemVmTemplateRegistration).validateTemplateFileForHypervisorAndArch(hypervisor, templateVO.getArch());
doNothing().when(systemVmTemplateRegistration).registerTemplate(hypervisor, name, storeId, templateVO, templateDataStoreVO, filePath);
systemVmTemplateRegistration.validateAndRegisterTemplate(hypervisor, name, storeId, templateVO, templateDataStoreVO, filePath);
verify(systemVmTemplateRegistration).validateTemplateFileForHypervisorAndArch(eq(hypervisor), eq(templateVO.getArch()));
verify(systemVmTemplateRegistration).registerTemplate(eq(hypervisor), eq(name), eq(storeId), eq(templateVO), eq(templateDataStoreVO), eq(filePath));
}
@Test
public void testValidateAndRegisterTemplateForNonExistingEntries() {
Hypervisor.HypervisorType hypervisor = Hypervisor.HypervisorType.KVM;
CPU.CPUArch arch = CPU.CPUArch.amd64;
String name = "TestTemplateNonExisting";
Pair<String, Long> storeUrlAndId = new Pair<>("nfs://dummy", 456L);
String filePath = "/dummy/path/nonexisting";
doNothing().when(systemVmTemplateRegistration).validateTemplateFileForHypervisorAndArch(hypervisor, arch);
doNothing().when(systemVmTemplateRegistration).registerTemplateForNonExistingEntries(hypervisor, arch, name, storeUrlAndId, filePath);
systemVmTemplateRegistration.validateAndRegisterTemplateForNonExistingEntries(hypervisor, arch, name, storeUrlAndId, filePath);
verify(systemVmTemplateRegistration).validateTemplateFileForHypervisorAndArch(eq(hypervisor), eq(arch));
verify(systemVmTemplateRegistration).registerTemplateForNonExistingEntries(eq(hypervisor), eq(arch), eq(name), eq(storeUrlAndId), eq(filePath));
}
@Test
public void testGetTemplateFile_fileExists() throws Exception {
File tempFile = File.createTempFile("template", ".qcow2");
tempFile.deleteOnExit();
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
when(details.getDefaultFilePath()).thenReturn(tempFile.getAbsolutePath());
File result = systemVmTemplateRegistration.getTemplateFile(details);
assertNotNull(result);
assertEquals(tempFile.getAbsolutePath(), result.getAbsolutePath());
}
@Test
public void testGetTemplateFile_fileDoesNotExist_downloadFails() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
new SystemVmTemplateRegistration.MetadataTemplateDetails(Hypervisor.HypervisorType.KVM,
"name", "nonexistent.qcow2", "http://example.com/file.qcow2",
"", CPU.CPUArch.arm64);
try (MockedStatic<Files> filesMock = Mockito.mockStatic(Files.class);
MockedStatic<HttpUtils> httpMock = Mockito.mockStatic(HttpUtils.class)) {
filesMock.when(() -> Files.isWritable(any(Path.class))).thenReturn(true);
httpMock.when(() -> HttpUtils.downloadFileWithProgress(eq(details.getUrl()), anyString(), any()))
.thenReturn(false);
File result = systemVmTemplateRegistration.getTemplateFile(details);
assertNull(result);
}
}
@Test
public void testGetTemplateFile_fileDoesNotExist_downloadSucceeds() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
new SystemVmTemplateRegistration.MetadataTemplateDetails(Hypervisor.HypervisorType.KVM,
"name", "file.qcow2", "http://example.com/file.qcow2",
"", CPU.CPUArch.arm64);
try (MockedStatic<Files> filesMock = Mockito.mockStatic(Files.class);
MockedStatic<HttpUtils> httpMock = Mockito.mockStatic(HttpUtils.class)) {
filesMock.when(() -> Files.isWritable(any(Path.class))).thenReturn(false);
File expectedFile = new File(systemVmTemplateRegistration.getTempDownloadDir(), details.getFilename());
httpMock.when(() -> HttpUtils.downloadFileWithProgress(eq(details.getUrl()), eq(expectedFile.getAbsolutePath()), any()))
.thenReturn(true);
File result = systemVmTemplateRegistration.getTemplateFile(details);
assertNotNull(result);
assertEquals(expectedFile.getAbsolutePath(), result.getAbsolutePath());
assertEquals(expectedFile.getAbsolutePath(), details.getDownloadedFilePath());
}
}
@Test
public void testIsTemplateFileChecksumDifferent_noMismatch() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
when(details.getChecksum()).thenReturn("dummyChecksum");
File file = new File("dummy.txt");
try (MockedStatic<DigestHelper> digestMock = Mockito.mockStatic(DigestHelper.class)) {
digestMock.when(() -> DigestHelper.calculateChecksum(file)).thenReturn("dummyChecksum");
boolean result = systemVmTemplateRegistration.isTemplateFileChecksumDifferent(details, file);
assertFalse(result);
}
}
@Test
public void testIsTemplateFileChecksumDifferent_mismatch() {
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
when(details.getChecksum()).thenReturn("expectedChecksum");
File file = new File("dummy.txt");
try (MockedStatic<DigestHelper> digestMock = Mockito.mockStatic(DigestHelper.class)) {
digestMock.when(() -> DigestHelper.calculateChecksum(file)).thenReturn("actualChecksum");
boolean result = systemVmTemplateRegistration.isTemplateFileChecksumDifferent(details, file);
assertTrue(result);
}
}
@Test(expected = CloudRuntimeException.class)
public void testValidateTemplates_metadataTemplateFailure() {
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> list = new ArrayList<>();
list.add(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64));
systemVmTemplateRegistration.validateTemplates(list);
}
@Test(expected = CloudRuntimeException.class)
public void testValidateTemplates_fileFailure() {
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> list = new ArrayList<>();
list.add(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64));
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), details);
File mockFile = Mockito.mock(File.class);
doReturn(mockFile).when(systemVmTemplateRegistration).getTemplateFile(details);
doReturn(true).when(systemVmTemplateRegistration).isTemplateFileChecksumDifferent(details, mockFile);
systemVmTemplateRegistration.validateTemplates(list);
}
public void testValidateTemplates_downloadableFileNotFound() {
CPU.CPUArch arch = SystemVmTemplateRegistration.DOWNLOADABLE_TEMPLATE_ARCH_TYPES.get(0);
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> list = new ArrayList<>();
list.add(new Pair<>(Hypervisor.HypervisorType.KVM, arch));
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
Hypervisor.HypervisorType.KVM, arch), details);
doReturn(null).when(systemVmTemplateRegistration).getTemplateFile(details);
systemVmTemplateRegistration.validateTemplates(list);
}
@Test
public void testValidateTemplates_success() {
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> list = new ArrayList<>();
list.add(new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64));
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
SystemVmTemplateRegistration.NewTemplateMap.put(SystemVmTemplateRegistration.getHypervisorArchKey(
Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64), details);
File mockFile = Mockito.mock(File.class);
doReturn(mockFile).when(systemVmTemplateRegistration).getTemplateFile(details);
doReturn(false).when(systemVmTemplateRegistration).isTemplateFileChecksumDifferent(details, mockFile);
systemVmTemplateRegistration.validateTemplates(list);
}
@Test
public void testRegisterTemplatesForZone() {
long zoneId = 1L;
String filePath = "dummyFilePath";
String nfsVersion = "nfs3";
Pair<String, Long> storeUrlAndId = new Pair<>("nfs://dummy", 100L);
doReturn(storeUrlAndId).when(systemVmTemplateRegistration).getNfsStoreInZone(zoneId);
doReturn(nfsVersion).when(systemVmTemplateRegistration).getNfsVersion(storeUrlAndId.second());
try (MockedStatic<SystemVmTemplateRegistration> mockedStatic = Mockito.mockStatic(
SystemVmTemplateRegistration.class)) {
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorArchList = new ArrayList<>();
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
CPU.CPUArch arch = CPU.CPUArch.getDefault();
hypervisorArchList.add(new Pair<>(hypervisorType, arch));
doReturn(hypervisorArchList).when(clusterDao).listDistinctHypervisorsArchAcrossClusters(zoneId);
SystemVmTemplateRegistration.MetadataTemplateDetails details =
Mockito.mock(SystemVmTemplateRegistration.MetadataTemplateDetails.class);
String name = "existing";
Mockito.when(details.getArch()).thenReturn(CPU.CPUArch.getDefault());
Mockito.when(details.getName()).thenReturn(name);
mockedStatic.when(() -> SystemVmTemplateRegistration.getMetadataTemplateDetails(Mockito.any(),
Mockito.any())).thenReturn(details);
when(systemVmTemplateRegistration.getRegisteredTemplate(name, arch))
.thenReturn(null);
doNothing().when(systemVmTemplateRegistration).registerTemplateForNonExistingEntries(
hypervisorType, arch,
name, storeUrlAndId, filePath);
systemVmTemplateRegistration.registerTemplatesForZone(zoneId, filePath);
mockedStatic.verify(() -> SystemVmTemplateRegistration.mountStore(storeUrlAndId.first(), filePath,
nfsVersion));
verify(systemVmTemplateRegistration).registerTemplateForNonExistingEntries(hypervisorType,
arch, name, storeUrlAndId, filePath);
}
}
}

View File

@ -58,11 +58,12 @@ function createMetadataFile() {
for template in "${templates[@]}"
do
section="${template%%:*}"
hvName=$(getGenericName $section)
sectionHv="${section%%-*}"
hvName=$(getGenericName $sectionHv)
downloadurl="${template#*:}"
arch=$(echo ${downloadurl#*"/systemvmtemplate-$VERSION-"} | cut -d'-' -f 1)
templatename="systemvm-${section%.*}-${VERSION}-${arch}"
templatename="systemvm-${sectionHv%.*}-${VERSION}-${arch}"
checksum=$(getChecksum "$fileData" "$VERSION-${arch}-$hvName")
filename=$(echo ${downloadurl##*'/'})
echo -e "["$section"]\ntemplatename = $templatename\nchecksum = $checksum\ndownloadurl = $downloadurl\nfilename = $filename\narch = $arch\n" >> $METADATAFILE
@ -71,7 +72,8 @@ function createMetadataFile() {
declare -a templates
getTemplateVersion $1
templates=( "kvm:https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-x86_64-kvm.qcow2.bz2"
templates=( "kvm-x86_64:https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-x86_64-kvm.qcow2.bz2"
"kvm-aarch64:https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-aarch64-kvm.qcow2.bz2"
"vmware:https://download.cloudstack.org/systemvm/${CS_VERSION}/systemvmtemplate-$VERSION-x86_64-vmware.ova"
"xenserver:https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-x86_64-xen.vhd.bz2"
"hyperv:https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-x86_64-hyperv.vhd.zip"

View File

@ -573,6 +573,9 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
} else {
field.set(entity, rs.getLong(index));
}
} else if (field.getDeclaredAnnotation(Convert.class) != null) {
Object val = _conversionSupport.convertToEntityAttribute(field, rs.getObject(index));
field.set(entity, val);
} else if (type.isEnum()) {
final Enumerated enumerated = field.getAnnotation(Enumerated.class);
final EnumType enumType = (enumerated == null) ? EnumType.STRING : enumerated.value();
@ -677,9 +680,6 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
}
} else if (type == byte[].class) {
field.set(entity, rs.getBytes(index));
} else if (field.getDeclaredAnnotation(Convert.class) != null) {
Object val = _conversionSupport.convertToEntityAttribute(field, rs.getObject(index));
field.set(entity, val);
} else {
field.set(entity, rs.getObject(index));
}
@ -949,7 +949,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
}
@DB()
protected List<T> listBy(SearchCriteria<T> sc, final Filter filter) {
public List<T> listBy(SearchCriteria<T> sc, final Filter filter) {
sc = checkAndSetRemovedIsNull(sc);
return listIncludingRemovedBy(sc, filter);
}

View File

@ -36,6 +36,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
/**
@ -122,7 +124,7 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
if (_entity == null) {
throw new RuntimeException("SearchBuilder cannot be modified once it has been setup");
}
if (_specifiedAttrs.size() > 1) {
if (func.getCount() <= 1 && _specifiedAttrs.size() > 1) {
throw new RuntimeException("You can't specify more than one field to search on");
}
if (func.getCount() != -1 && (func.getCount() != (params.length + 1))) {
@ -150,7 +152,7 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
}
}
final Select select = new Select(func, _specifiedAttrs.size() == 0 ? null : _specifiedAttrs.get(0), declaredField, params);
final Select select = new Select(func, _specifiedAttrs, declaredField, params);
_selects.add(select);
_specifiedAttrs.clear();
@ -185,7 +187,7 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
} catch (final SecurityException e) {
} catch (final NoSuchFieldException e) {
}
_selects.add(new Select(Func.NATIVE, attr, field, null));
_selects.add(new Select(Func.NATIVE, List.of(attr), field, null));
}
_specifiedAttrs.clear();
@ -531,16 +533,18 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
protected static class Select {
public Func func;
public Attribute attr;
public List<Attribute> attributes = new ArrayList<>();
public Object[] params;
public Field field;
protected Select() {
}
public Select(final Func func, final Attribute attr, final Field field, final Object[] params) {
public Select(final Func func, final List<Attribute> attributes, final Field field, final Object[] params) {
this.func = func;
this.attr = attr;
if (CollectionUtils.isNotEmpty(attributes)) {
this.attributes.addAll(attributes);
}
this.params = params;
this.field = field;
}

View File

@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.cloud.utils.Pair;
@ -59,7 +60,7 @@ public class SearchCriteria<K> {
}
public enum Func {
NATIVE("@", 1), MAX("MAX(@)", 1), MIN("MIN(@)", 1), FIRST("FIRST(@)", 1), LAST("LAST(@)", 1), SUM("SUM(@)", 1), COUNT("COUNT(@)", 1), DISTINCT("DISTINCT(@)", 1);
NATIVE("@", 1), MAX("MAX(@)", 1), MIN("MIN(@)", 1), FIRST("FIRST(@)", 1), LAST("LAST(@)", 1), SUM("SUM(@)", 1), COUNT("COUNT(@)", 1), DISTINCT("DISTINCT(@)", 1), DISTINCT_PAIR("DISTINCT @, @", 2);
private String func;
private int count;
@ -135,10 +136,12 @@ public class SearchCriteria<K> {
for (Select select : _selects) {
String func = select.func.toString() + ",";
if (select.attr == null) {
if (CollectionUtils.isEmpty(select.attributes)) {
func = func.replace("@", "*");
} else {
func = func.replace("@", select.attr.table + "." + select.attr.columnName);
for (Attribute attribute : select.attributes) {
func = func.replaceFirst("@", attribute.table + "." + attribute.columnName);
}
}
str.insert(insertAt, func);
insertAt += func.length();

View File

@ -470,6 +470,8 @@ if [ -f %{_sysconfdir}/sysconfig/%{name}-management ] ; then
fi
chown -R cloud:cloud /var/log/cloudstack/management
chown -R cloud:cloud /usr/share/cloudstack-management/templates
find /usr/share/cloudstack-management/templates -type d -exec chmod 0770 {} \;
systemctl daemon-reload
@ -610,6 +612,9 @@ pip3 install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%{_datadir}/%{name}-management/setup/*.sh
%{_datadir}/%{name}-management/setup/server-setup.xml
%{_datadir}/%{name}-management/webapp/*
%dir %attr(0770, cloud, cloud) %{_datadir}/%{name}-management/templates
%dir %attr(0770, cloud, cloud) %{_datadir}/%{name}-management/templates/systemvm
%attr(0644, cloud, cloud) %{_datadir}/%{name}-management/templates/systemvm/*
%attr(0755,root,root) %{_bindir}/%{name}-external-ipallocator.py
%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator

View File

@ -47,7 +47,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
private RoleService roleService;
private List<PluggableService> services;
private Map<RoleType, Set<String>> annotationRoleBasedApisMap = new HashMap<>();
private Map<RoleType, Set<String>> annotationRoleBasedApisMap = new HashMap<RoleType, Set<String>>();
private LazyCache<Long, Account> accountCache;
private LazyCache<Long, Pair<Role, List<RolePermission>>> rolePermissionsCache;
@ -56,7 +56,7 @@ public class DynamicRoleBasedAPIAccessChecker extends AdapterBase implements API
protected DynamicRoleBasedAPIAccessChecker() {
super();
for (RoleType roleType : RoleType.values()) {
annotationRoleBasedApisMap.put(roleType, new HashSet<>());
annotationRoleBasedApisMap.put(roleType, new HashSet<String>());
}
}

View File

@ -167,6 +167,7 @@ import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.RngDef.RngBackendModel;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SCSIDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.SerialDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TermPolicy;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.TpmDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.VideoDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef;
import com.cloud.hypervisor.kvm.resource.LibvirtVMDef.WatchDogDef.WatchDogAction;
@ -2671,9 +2672,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
devices.addDevice(createVideoDef(vmTO));
devices.addDevice(createConsoleDef());
devices.addDevice(createGraphicDef(vmTO));
if (!isGuestS390x()) {
devices.addDevice(createTabletInputDef());
}
TpmDef tpmDef = createTpmDef(vmTO);
if (tpmDef != null) {
devices.addDevice(tpmDef);
}
if (isGuestAarch64()) {
createArm64UsbDef(devices);
}
@ -2856,8 +2864,11 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
private CpuModeDef createCpuModeDef(VirtualMachineTO vmTO, int vcpus) {
final CpuModeDef cmd = new CpuModeDef();
cmd.setMode(guestCpuMode);
cmd.setModel(guestCpuModel);
Map<String, String> details = vmTO.getDetails();
String cpuMode = MapUtils.isNotEmpty(details) && details.get(VmDetailConstants.GUEST_CPU_MODE) != null ? details.get(VmDetailConstants.GUEST_CPU_MODE) : guestCpuMode;
String cpuModel = MapUtils.isNotEmpty(details) && details.get(VmDetailConstants.GUEST_CPU_MODEL) != null ? details.get(VmDetailConstants.GUEST_CPU_MODEL) : guestCpuModel;
cmd.setMode(cpuMode);
cmd.setModel(cpuModel);
if (VirtualMachine.Type.User.equals(vmTO.getType())) {
cmd.setFeatures(cpuFeatures);
}
@ -2866,6 +2877,19 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
return cmd;
}
protected TpmDef createTpmDef(VirtualMachineTO vmTO) {
Map<String, String> details = vmTO.getDetails();
if (MapUtils.isEmpty(details)) {
return null;
}
String tpmModel = details.get(VmDetailConstants.VIRTUAL_TPM_MODEL);
if (tpmModel == null) {
return null;
}
String tpmVersion = details.get(VmDetailConstants.VIRTUAL_TPM_VERSION);
return new TpmDef(tpmModel, tpmVersion);
}
private void configureGuestIfUefiEnabled(boolean isSecureBoot, String bootMode, GuestDef guest) {
setGuestLoader(bootMode, SECURE, guest, GuestDef.GUEST_LOADER_SECURE);
setGuestLoader(bootMode, LEGACY, guest, GuestDef.GUEST_LOADER_LEGACY);

View File

@ -18,6 +18,7 @@ package com.cloud.hypervisor.kvm.resource;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -2358,6 +2359,82 @@ public class LibvirtVMDef {
}
}
public static class TpmDef {
enum TpmModel {
TIS("tpm-tis"), // TPM Interface Specification (TIS)
CRB("tpm-crb"); // Command-Response Buffer (CRB)
final String model;
TpmModel(String model) {
this.model = model;
}
@Override
public String toString() {
return model;
}
}
enum TpmVersion {
V1_2("1.2"), // 1.2
V2_0("2.0"); // 2.0. Default version. The CRB model is only supported with version 2.0.
final String version;
TpmVersion(String version) {
this.version = version;
}
@Override
public String toString() {
return version;
}
}
private TpmModel model;
private TpmVersion version = TpmVersion.V2_0;
public TpmDef(TpmModel model, TpmVersion version) {
this.model = model;
if (version != null) {
this.version = version;
}
}
public TpmDef(String model, String version) {
this.model = Arrays.stream(TpmModel.values())
.filter(tpmModel -> tpmModel.toString().equals(model))
.findFirst()
.orElse(null);
if (version != null) {
this.version = Arrays.stream(TpmVersion.values())
.filter(tpmVersion -> tpmVersion.toString().equals(version))
.findFirst()
.orElse(this.version);;
}
}
public TpmModel getModel() {
return model;
}
public TpmVersion getVersion() {
return version;
}
@Override
public String toString() {
StringBuilder tpmBuidler = new StringBuilder();
if (model != null) {
tpmBuidler.append("<tpm model='").append(model).append("'>\n");
tpmBuidler.append("<backend type='emulator' version='").append(version).append("'/>\n");
tpmBuidler.append("</tpm>\n");
}
return tpmBuidler.toString();
}
}
public void setHvsType(String hvs) {
_hvsType = hvs;
}

View File

@ -6541,4 +6541,28 @@ public class LibvirtComputingResourceTest {
DiskDef.DiskBus diskBus = libvirtComputingResourceSpy.getDiskModelFromVMDetail(virtualMachineTO);
assertEquals(DiskDef.DiskBus.VIRTIOBLK, diskBus);
}
@Test
public void testCreateTpmDef() {
VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class);
Map<String, String> details = new HashMap<>();
details.put(VmDetailConstants.VIRTUAL_TPM_MODEL, "tpm-tis");
details.put(VmDetailConstants.VIRTUAL_TPM_VERSION, "2.0");
Mockito.when(virtualMachineTO.getDetails()).thenReturn(details);
LibvirtVMDef.TpmDef tpmDef = libvirtComputingResourceSpy.createTpmDef(virtualMachineTO);
assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel());
assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion());
}
@Test
public void testCreateTpmDefWithInvalidVersion() {
VirtualMachineTO virtualMachineTO = Mockito.mock(VirtualMachineTO.class);
Map<String, String> details = new HashMap<>();
details.put(VmDetailConstants.VIRTUAL_TPM_MODEL, "tpm-crb");
details.put(VmDetailConstants.VIRTUAL_TPM_VERSION, "3.0");
Mockito.when(virtualMachineTO.getDetails()).thenReturn(details);
LibvirtVMDef.TpmDef tpmDef = libvirtComputingResourceSpy.createTpmDef(virtualMachineTO);
assertEquals(LibvirtVMDef.TpmDef.TpmModel.CRB, tpmDef.getModel());
assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion());
}
}

View File

@ -566,9 +566,20 @@ public class LibvirtVMDefTest extends TestCase {
assertEquals("<cpu><topology sockets='4' cores='2' threads='1' /></cpu>", cpuModeDef.toString());
}
@Test
public void testTopologyNoInfo() {
LibvirtVMDef.CpuModeDef cpuModeDef = new LibvirtVMDef.CpuModeDef();
cpuModeDef.setTopology(-1, -1, 4);
assertEquals("<cpu></cpu>", cpuModeDef.toString());
}
@Test
public void testTpmModel() {
LibvirtVMDef.TpmDef tpmDef = new LibvirtVMDef.TpmDef("tpm-tis", "2.0");
assertEquals(LibvirtVMDef.TpmDef.TpmModel.TIS, tpmDef.getModel());
assertEquals(LibvirtVMDef.TpmDef.TpmVersion.V2_0, tpmDef.getVersion());
assertEquals("<tpm model='tpm-tis'>\n" +
"<backend type='emulator' version='2.0'/>\n" +
"</tpm>\n", tpmDef.toString());
}
}

View File

@ -39,6 +39,7 @@ public interface MockAgentManager extends Manager {
public static final long DEFAULT_HOST_MEM_SIZE = 8 * 1024 * 1024 * 1024L; // 8G, unit of Mbytes
public static final int DEFAULT_HOST_CPU_CORES = 4; // 2 dual core CPUs (2 x 2)
public static final int DEFAULT_HOST_SPEED_MHZ = 8000; // 1 GHz CPUs
public static final String DEFAULT_HOST_ARCH = "x86_64";
@Override
boolean configure(String name, Map<String, Object> params) throws ConfigurationException;

View File

@ -153,6 +153,7 @@ public class MockAgentManagerImpl extends ManagerBase implements MockAgentManage
long cpuSpeed = Long.parseLong((String)params.get("cpuspeed"));
long memory = Long.parseLong((String)params.get("memory"));
long localStorageSize = Long.parseLong((String)params.get("localstorage"));
String arch = (String)params.get("arch");
synchronized (this) {
long dataCenterId = Long.parseLong((String)params.get("zone"));
long podId = Long.parseLong((String)params.get("pod"));
@ -170,6 +171,7 @@ public class MockAgentManagerImpl extends ManagerBase implements MockAgentManage
mockHost.setCpuCount(cpuCore);
mockHost.setCpuSpeed(cpuSpeed);
mockHost.setMemorySize(memory);
mockHost.setArch(arch);
String guid = UUID.randomUUID().toString();
mockHost.setGuid(guid);
mockHost.setName("SimulatedAgent." + guid);

View File

@ -177,6 +177,7 @@ public class AgentRoutingResource extends AgentStorageResource {
StartupRoutingCommand cmd =
new StartupRoutingCommand((Integer)info.get(0), (Long)info.get(1), (Long)info.get(2), (Long)info.get(4), (String)info.get(3), HypervisorType.Simulator,
RouterPrivateIpStrategy.HostLocal);
cmd.setCpuArch((String)info.get(5));
Map<String, String> hostDetails = new HashMap<String, String>();
hostDetails.put(RouterPrivateIpStrategy.class.getCanonicalName(), RouterPrivateIpStrategy.DcGlobal.toString());
@ -274,12 +275,14 @@ public class AgentRoutingResource extends AgentStorageResource {
long cpus = agentHost.getCpuCount();
long ram = agentHost.getMemorySize();
long dom0Ram = agentHost.getMemorySize() / 10;
String arch = agentHost.getArch();
info.add((int)cpus);
info.add(speed);
info.add(ram);
info.add(agentHost.getCapabilities());
info.add(dom0Ram);
info.add(arch);
return info;
}

View File

@ -87,6 +87,7 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L
long cpuCores = MockAgentManager.DEFAULT_HOST_CPU_CORES;
long memory = MockAgentManager.DEFAULT_HOST_MEM_SIZE;
long localstorageSize = MockStorageManager.DEFAULT_HOST_STORAGE_SIZE;
String arch = MockAgentManager.DEFAULT_HOST_ARCH;
if (scheme.equals("http")) {
if (host == null || !host.startsWith("sim")) {
String msg = "uri is not of simulator type so we're not taking care of the discovery for this: " + uri;
@ -111,6 +112,8 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L
memory = Long.parseLong(parameter[1]);
} else if (parameter[0].equalsIgnoreCase("localstorage") && parameter[1] != null) {
localstorageSize = Long.parseLong(parameter[1]);
} else if (parameter[0].equalsIgnoreCase("arch") && parameter[1] != null) {
arch = parameter[1];
}
}
}
@ -168,6 +171,7 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L
params.put("cpucore", Long.toString(cpuCores));
params.put("memory", Long.toString(memory));
params.put("localstorage", Long.toString(localstorageSize));
params.put("arch", arch);
resources = createAgentResources(params);
return resources;

View File

@ -23,6 +23,8 @@ public interface MockHost {
public long getMemorySize();
String getArch();
public String getCapabilities();
public long getId();

View File

@ -87,6 +87,9 @@ public class MockHostVO implements MockHost, InternalIdentity {
@Column(name = "ram")
private long memorySize;
@Column(name = "arch")
private String arch;
@Column(name = "capabilities")
private String capabilities;
@ -143,6 +146,14 @@ public class MockHostVO implements MockHost, InternalIdentity {
this.memorySize = memorySize;
}
public String getArch() {
return arch;
}
public void setArch(String arch) {
this.arch = arch;
}
@Override
public String getCapabilities() {
return this.capabilities;

View File

@ -22,15 +22,12 @@ import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.dc.VsphereStoragePolicy;
import com.cloud.exception.DiscoveryException;
import com.cloud.exception.ResourceInUseException;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.storage.StoragePool;
import com.cloud.utils.Pair;
import com.cloud.utils.component.PluggableService;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcHostsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
@ -56,7 +53,5 @@ public interface VmwareDatacenterService extends PluggableService {
List<StoragePool> listVsphereStoragePolicyCompatibleStoragePools(ListVsphereStoragePolicyCompatiblePoolsCmd cmd);
List<HostMO> listHostsInDatacenter(ListVmwareDcHostsCmd cmd);
Pair<String, List<UnmanagedInstanceTO>> listVMsInDatacenter(ListVmwareDcVmsCmd cmd);
List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd);
}

View File

@ -19,12 +19,10 @@ package com.cloud.hypervisor.vmware.manager;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.time.Duration;
import java.time.Instant;
@ -45,11 +43,10 @@ import javax.inject.Inject;
import javax.naming.ConfigurationException;
import javax.persistence.EntityExistsException;
import com.cloud.hypervisor.vmware.util.VmwareClient;
import org.apache.cloudstack.api.command.admin.zone.AddVmwareDcCmd;
import org.apache.cloudstack.api.command.admin.zone.ImportVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcVmsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcHostsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcItems;
import org.apache.cloudstack.api.command.admin.zone.ListVmwareDcsCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePoliciesCmd;
import org.apache.cloudstack.api.command.admin.zone.ListVsphereStoragePolicyCompatiblePoolsCmd;
@ -89,7 +86,6 @@ import com.cloud.dc.ClusterDetailsDao;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.ClusterVSMMapVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VmwareDatacenter;
import com.cloud.dc.VsphereStoragePolicy;
import com.cloud.dc.VsphereStoragePolicyVO;
import com.cloud.dc.dao.ClusterDao;
@ -115,8 +111,7 @@ import com.cloud.hypervisor.HypervisorGuruManager;
import com.cloud.hypervisor.dao.HypervisorCapabilitiesDao;
import com.cloud.hypervisor.vmware.LegacyZoneVO;
import com.cloud.hypervisor.vmware.VmwareCleanupMaid;
import com.cloud.hypervisor.vmware.util.VmwareClient;
import com.cloud.hypervisor.vmware.util.VmwareClientException;
import com.cloud.dc.VmwareDatacenter;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.hypervisor.vmware.VmwareDatacenterZoneMap;
@ -173,16 +168,9 @@ import com.cloud.utils.ssh.SshHelper;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.dao.UserVmCloneSettingDao;
import com.cloud.vm.dao.VMInstanceDao;
// TODO move these items upstream?
import com.vmware.pbm.PbmProfile;
import com.vmware.vim25.AboutInfo;
import com.vmware.vim25.ManagedObjectReference;
import com.vmware.vim25.InvalidLocaleFaultMsg;
import com.vmware.vim25.InvalidLoginFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import org.jetbrains.annotations.NotNull;
public class VmwareManagerImpl extends ManagerBase implements VmwareManager, VmwareStorageMount, Listener, VmwareDatacenterService, Configurable {
@ -257,11 +245,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private StorageLayer _storage;
private final String _privateNetworkVSwitchName = "vSwitch0";
private final int _portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP;
private int _portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP;
private boolean _fullCloneFlag;
private boolean _instanceNameFlag;
private String _serviceConsoleName;
private String _managementPortGroupName;
private String _managemetPortGroupName;
private String _defaultSystemVmNicAdapterType = VirtualEthernetCardType.E1000.toString();
private String _recycleHungWorker = "false";
private int _additionalPortRangeStart;
@ -275,7 +263,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private final Random _rand = new Random(System.currentTimeMillis());
private static final ScheduledExecutorService templateCleanupScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-FullyClonedTemplateCheck"));
private static ScheduledExecutorService templateCleanupScheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory("Vmware-FullyClonedTemplateCheck"));;
private final VmwareStorageManager _storageMgr;
private final GlobalLock _exclusiveOpLock = GlobalLock.getInternLock("vmware.exclusive.op");
@ -359,9 +347,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
_serviceConsoleName = "Service Console";
}
_managementPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key());
if (_managementPortGroupName == null) {
_managementPortGroupName = "Management Network";
_managemetPortGroupName = _configDao.getValue(Config.VmwareManagementPortGroup.key());
if (_managemetPortGroupName == null) {
_managemetPortGroupName = "Management Network";
}
_defaultSystemVmNicAdapterType = _configDao.getValue(Config.VmwareSystemVmNicDeviceType.key());
@ -460,7 +448,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
logger.info("Preparing network on host " + hostMo.getContext().toString() + " for " + privateTrafficLabel);
VirtualSwitchType vsType = VirtualSwitchType.getType(vSwitchType);
//The management network is probably always going to be a physical network with isolation type of vlans, so assume BroadcastDomainType VLAN
//The management network is probably always going to be a physical network with islation type of vlans, so assume BroadcastDomainType VLAN
if (VirtualSwitchType.StandardVirtualSwitch == vsType) {
HypervisorHostHelper.prepareNetwork(vSwitchName, "cloud.private", hostMo, vlanId, null, null, 180000, false, BroadcastDomainType.Vlan, null, null);
}
@ -469,7 +457,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
AboutInfo about = hostMo.getHostAboutInfo();
if (about != null) {
String version = about.getApiVersion();
if (version != null && (version.equals("4.0") || version.equals("4.1")) ) { // && _portsPerDvPortGroup < DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x)
if (version != null && (version.equals("4.0") || version.equals("4.1")) && _portsPerDvPortGroup < DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x) {
portsPerDvPortGroup = DEFAULT_PORTS_PER_DV_PORT_GROUP_VSPHERE4_x;
}
}
@ -492,7 +480,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
}
URI uriForHost = new URI(UriUtils.encodeURIComponent(clusterDetails.get("url") + "/" + host.getName()));
morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), StandardCharsets.UTF_8));
morSrcHost = serviceContext.getHostMorByPath(URLDecoder.decode(uriForHost.getPath(), "UTF-8"));
if (morSrcHost == null) {
return null;
}
@ -508,18 +496,19 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
throw new CloudRuntimeException("Invalid serviceContext");
}
ManagedObjectReference mor = serviceContext.getHostMorByPath(hostInventoryPath);
String privateTrafficLabel;
String privateTrafficLabel = null;
privateTrafficLabel = serviceContext.getStockObject("privateTrafficLabel");
if (privateTrafficLabel == null) {
privateTrafficLabel = _privateNetworkVSwitchName;
}
if (mor != null) {
List<ManagedObjectReference> returnedHostList = new ArrayList<>();
List<ManagedObjectReference> returnedHostList = new ArrayList<ManagedObjectReference>();
if (mor.getType().equals("ComputeResource")) {
List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host");
assert (CollectionUtils.isNullOrEmpty(hosts));
assert (hosts != null && hosts.size() > 0);
// For ESX host, we need to enable host firewall to allow VNC access
HostMO hostMo = new HostMO(serviceContext, hosts.get(0));
@ -530,8 +519,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
List<ManagedObjectReference> hosts = serviceContext.getVimClient().getDynamicProperty(mor, "host");
assert (hosts != null);
if (!hosts.isEmpty()) {
AboutInfo about = serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product");
if (hosts.size() > 0) {
AboutInfo about = (AboutInfo)(serviceContext.getVimClient().getDynamicProperty(hosts.get(0), "config.product"));
String version = about.getApiVersion();
int maxHostsPerCluster = _hvCapabilitiesDao.getMaxHostsPerCluster(HypervisorType.VMware, version);
if (hosts.size() > maxHostsPerCluster) {
@ -625,13 +614,13 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
public String getManagementPortGroupName() {
return _managementPortGroupName;
return _managemetPortGroupName;
}
@Override
public String getManagementPortGroupByHost(HostMO hostMo) throws Exception {
if (hostMo.getHostType() == VmwareHostType.ESXi) {
return _managementPortGroupName;
return _managemetPortGroupName;
}
return _serviceConsoleName;
}
@ -641,7 +630,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
params.put("vmware.create.full.clone", _fullCloneFlag);
params.put("vm.instancename.flag", _instanceNameFlag);
params.put("service.console.name", _serviceConsoleName);
params.put("management.portgroup.name", _managementPortGroupName);
params.put("management.portgroup.name", _managemetPortGroupName);
params.put("vmware.root.disk.controller", _rootDiskController);
params.put("vmware.data.disk.controller", _dataDiskController);
params.put("vmware.recycle.hung.wokervm", _recycleHungWorker);
@ -668,23 +657,23 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return false;
}
String[] tokens = workerTag.split("-");
String tokens[] = workerTag.split("-");
if (tokens.length != 3) {
logger.error("Invalid worker VM tag " + workerTag);
return false;
}
long startTick = Long.parseLong(tokens[0]);
long msId = Long.parseLong(tokens[1]);
long runId = Long.parseLong(tokens[2]);
long msid = Long.parseLong(tokens[1]);
long runid = Long.parseLong(tokens[2]);
if (msHostPeerDao.countStateSeenInPeers(msId, runId, ManagementServerHost.State.Down) > 0) {
if (msHostPeerDao.countStateSeenInPeers(msid, runid, ManagementServerHost.State.Down) > 0) {
if (logger.isInfoEnabled())
logger.info("Worker VM's owner management server node has been detected down from peer nodes, recycle it");
return true;
}
if (runId != clusterManager.getManagementRunId(msId)) {
if (runid != clusterManager.getManagementRunId(msid)) {
if (logger.isInfoEnabled())
logger.info("Worker VM's owner management server has changed runid, recycle it");
return true;
@ -782,6 +771,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
isoFile = new File("/usr/share/cloudstack-common/vms/systemvm.iso");
}
assert (isoFile != null);
if (!isoFile.exists()) {
logger.error("Unable to locate systemvm.iso in your setup at " + isoFile);
}
@ -798,7 +788,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (keyFile == null || !keyFile.exists()) {
keyFile = new File("/usr/share/cloudstack-common/scripts/vm/systemvm/id_rsa.cloud");
}
assert (keyFile != null);
if (!keyFile.exists()) {
logger.error("Unable to locate id_rsa.cloud in your setup at " + keyFile);
}
@ -807,7 +797,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
public String getMountPoint(String storageUrl, String nfsVersion) {
String mountPoint;
String mountPoint = null;
synchronized (_storageMounts) {
mountPoint = _storageMounts.get(storageUrl);
if (mountPoint != null) {
@ -837,7 +827,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String mountPoint = null;
long mshostId = ManagementServerNode.getManagementServerId();
for (int i = 0; i < 10; i++) {
String mntPt = parent + File.separator + mshostId + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
String mntPt = parent + File.separator + String.valueOf(mshostId) + "." + Integer.toHexString(_rand.nextInt(Integer.MAX_VALUE));
File file = new File(mntPt);
if (!file.exists()) {
if (_storage.mkdir(mntPt)) {
@ -862,9 +852,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
for (String mountPoint : mounts) {
logger.info("umount NFS mount from previous session: " + mountPoint);
String result = null;
Script command = new Script(true, "umount", _timeout, logger);
command.add(mountPoint);
String result = command.execute();
result = command.execute();
if (result != null) {
logger.warn("Unable to umount " + mountPoint + " due to " + result);
}
@ -882,9 +873,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
for (String mountPoint : _storageMounts.values()) {
logger.info("umount NFS mount: " + mountPoint);
String result = null;
Script command = new Script(true, "umount", _timeout, logger);
command.add(mountPoint);
String result = command.execute();
result = command.execute();
if (result != null) {
logger.warn("Unable to umount " + mountPoint + " due to " + result);
}
@ -902,8 +894,8 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return null;
}
Script script;
String result;
Script script = null;
String result = null;
Script command = new Script(true, "mount", _timeout, logger);
command.add("-t", "nfs");
if (nfsVersion != null){
@ -990,9 +982,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
public void processConnect(Host host, StartupCommand cmd, boolean forRebalance) {
if (cmd != null) {
if (cmd instanceof StartupCommand) {
if (host.getHypervisorType() == HypervisorType.VMware) {
updateClusterNativeHAState(host, cmd);
} else {
return;
}
}
}
@ -1062,16 +1056,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
public Pair<Integer, Integer> getAddiionalVncPortRange() {
return new Pair<>(_additionalPortRangeStart, _additionalPortRangeSize);
return new Pair<Integer, Integer>(_additionalPortRangeStart, _additionalPortRangeSize);
}
@Override
public Map<String, String> getNexusVSMCredentialsByClusterId(Long clusterId) {
CiscoNexusVSMDeviceVO nexusVSM;
ClusterVSMMapVO vsmMapVO;
CiscoNexusVSMDeviceVO nexusVSM = null;
ClusterVSMMapVO vsmMapVO = null;
vsmMapVO = _vsmMapDao.findByClusterId(clusterId);
long vsmId;
long vsmId = 0;
if (vsmMapVO != null) {
vsmId = vsmMapVO.getVsmId();
logger.info("vsmId is " + vsmId);
@ -1082,7 +1076,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
return null;
}
Map<String, String> nexusVSMCredentials = new HashMap<>();
Map<String, String> nexusVSMCredentials = new HashMap<String, String>();
if (nexusVSM != null) {
nexusVSMCredentials.put("vsmip", nexusVSM.getipaddr());
nexusVSMCredentials.put("vsmusername", nexusVSM.getUserName());
@ -1109,7 +1103,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmdList = new ArrayList<>();
List<Class<?>> cmdList = new ArrayList<Class<?>>();
cmdList.add(AddVmwareDcCmd.class);
cmdList.add(UpdateVmwareDcCmd.class);
cmdList.add(RemoveVmwareDcCmd.class);
@ -1118,14 +1112,13 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
cmdList.add(ListVsphereStoragePoliciesCmd.class);
cmdList.add(ListVsphereStoragePolicyCompatiblePoolsCmd.class);
cmdList.add(ListVmwareDcVmsCmd.class);
cmdList.add(ListVmwareDcHostsCmd.class);
return cmdList;
}
@Override
@DB
public VmwareDatacenterVO addVmwareDatacenter(AddVmwareDcCmd cmd) throws ResourceInUseException {
VmwareDatacenterVO vmwareDc;
VmwareDatacenterVO vmwareDc = null;
Long zoneId = cmd.getZoneId();
String userName = cmd.getUsername();
String password = cmd.getPassword();
@ -1181,10 +1174,10 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
checkIfDcIsUsed(vCenterHost, vmwareDcName, zoneId);
VmwareContext context = null;
DatacenterMO dcMo;
DatacenterMO dcMo = null;
String dcCustomFieldValue;
boolean addDcCustomFieldDef = false;
boolean dcInUse;
boolean dcInUse = false;
String guid;
ManagedObjectReference dcMor;
try {
@ -1217,7 +1210,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
// Map zone with vmware datacenter
vmwareDcZoneMap = new VmwareDatacenterZoneMapVO(zoneId, vmwareDc.getId());
vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap);
vmwareDcZoneMap = vmwareDatacenterZoneMapDao.persist(vmwareDcZoneMap);
// Set custom field for this DC
if (addDcCustomFieldDef) {
@ -1237,6 +1230,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (context != null) {
context.close();
}
context = null;
}
importVsphereStoragePoliciesInternal(zoneId, vmwareDc.getId());
return vmwareDc;
@ -1261,9 +1255,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
* Check if DC is already part of zone
* In that case vmware_data_center table should have the DC and a dc zone mapping should exist
*
* @param vCenterHost the vcenter appliance hostname
* @param vmwareDcName the name of the vmware DC
* @param zoneId zone that the DC should be connected to
* @param vCenterHost
* @param vmwareDcName
* @param zoneId
* @throws ResourceInUseException if the DC can not be used.
*/
private void checkIfDcIsUsed(String vCenterHost, String vmwareDcName, Long zoneId) throws ResourceInUseException {
@ -1271,7 +1265,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
vmwareDc = vmwareDcDao.getVmwareDatacenterByGuid(vmwareDcName + "@" + vCenterHost);
if (vmwareDc != null) {
VmwareDatacenterZoneMapVO mapping = vmwareDatacenterZoneMapDao.findByVmwareDcId(vmwareDc.getId());
if (mapping != null && zoneId == mapping.getZoneId()) {
if (mapping != null && Long.compare(zoneId, mapping.getZoneId()) == 0) {
throw new ResourceInUseException(String.format("This DC (%s) is already part of other CloudStack zone (%d). Cannot add this DC to more zones.", vmwareDc.getUuid(), zoneId));
}
}
@ -1280,7 +1274,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
@Override
@ActionEvent(eventType = EventTypes.EVENT_ZONE_EDIT, eventDescription = "updating VMware datacenter")
public VmwareDatacenter updateVmwareDatacenter(UpdateVmwareDcCmd cmd) {
final long zoneId = cmd.getZoneId();
final Long zoneId = cmd.getZoneId();
final String userName = cmd.getUsername();
final String password = cmd.getPassword();
final String vCenterHost = cmd.getVcenter();
@ -1308,7 +1302,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
}
vmwareDc.setGuid(String.format("%s@%s", vmwareDc.getVmwareDatacenterName(), vmwareDc.getVcenterHost()));
return Transaction.execute(new TransactionCallback<>() {
return Transaction.execute(new TransactionCallback<VmwareDatacenter>() {
@Override
public VmwareDatacenter doInTransaction(TransactionStatus status) {
if (vmwareDcDao.update(vmwareDc.getId(), vmwareDc)) {
@ -1357,7 +1351,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String vCenterHost;
String userName;
String password;
DatacenterMO dcMo;
DatacenterMO dcMo = null;
final VmwareDatacenterZoneMapVO vmwareDcZoneMap = vmwareDatacenterZoneMapDao.findByZoneId(zoneId);
// Check if zone is associated with VMware DC
if (vmwareDcZoneMap == null) {
@ -1394,9 +1388,11 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
throw new DiscoveryException(msg);
}
assert (dcMo != null);
// Reset custom field property cloud.zone over this DC
dcMo.setCustomFieldValue(CustomFieldConstants.CLOUD_ZONE, "false");
logger.info("Sucessfully reset custom field property cloud.zone over DC {}", vmwareDcName);
logger.info("Successfully reset custom field property cloud.zone over DC {}", vmwareDcName);
} catch (Exception e) {
String msg = "Unable to reset custom field property cloud.zone over DC " + vmwareDcName + " due to : " + VmwareHelper.getExceptionMessage(e);
logger.error(msg);
@ -1405,6 +1401,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
if (context != null) {
context.close();
}
context = null;
}
return true;
}
@ -1425,7 +1422,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
private void validateZoneWithResources(Long zoneId, String errStr) throws ResourceInUseException {
// Check if zone has resources? - For now look for clusters
List<ClusterVO> clusters = clusterDao.listByZoneId(zoneId);
if (!CollectionUtils.isNullOrEmpty(clusters)) {
if (clusters != null && clusters.size() > 0) {
// Look for VMware hypervisor.
for (ClusterVO cluster : clusters) {
if (cluster.getHypervisorType().equals(HypervisorType.VMware)) {
@ -1446,9 +1443,9 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
}
@Override
public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException {
public List<? extends VmwareDatacenter> listVmwareDatacenters(ListVmwareDcsCmd cmd) throws CloudRuntimeException, InvalidParameterValueException {
Long zoneId = cmd.getZoneId();
List<VmwareDatacenterVO> vmwareDcList = new ArrayList<>();
List<VmwareDatacenterVO> vmwareDcList = new ArrayList<VmwareDatacenterVO>();
VmwareDatacenterZoneMapVO vmwareDcZoneMap;
VmwareDatacenterVO vmwareDatacenter;
long vmwareDcId;
@ -1506,7 +1503,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
String vCenterHost = vmwareDatacenter.getVcenterHost();
String userName = vmwareDatacenter.getUser();
String password = vmwareDatacenter.getPassword();
List<PbmProfile> storageProfiles;
List<PbmProfile> storageProfiles = null;
try {
logger.debug(String.format("Importing vSphere Storage Policies for the vmware DC %d in zone %d", vmwareDcId, zoneId));
VmwareContext context = VmwareContextFactory.getContext(vCenterHost, userName, password);
@ -1534,15 +1531,16 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
List<VsphereStoragePolicyVO> allStoragePolicies = vsphereStoragePolicyDao.listAll();
List<PbmProfile> finalStorageProfiles = storageProfiles;
List<VsphereStoragePolicyVO> needToMarkRemoved = allStoragePolicies.stream()
.filter(existingPolicy -> finalStorageProfiles.stream()
.noneMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId())))
.filter(existingPolicy -> !finalStorageProfiles.stream()
.anyMatch(storageProfile -> storageProfile.getProfileId().getUniqueId().equals(existingPolicy.getPolicyId())))
.collect(Collectors.toList());
for (VsphereStoragePolicyVO storagePolicy : needToMarkRemoved) {
vsphereStoragePolicyDao.remove(storagePolicy.getId());
}
return vsphereStoragePolicyDao.listAll();
List<VsphereStoragePolicyVO> storagePolicies = vsphereStoragePolicyDao.listAll();
return storagePolicies;
}
@Override
@ -1588,87 +1586,13 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
}
@Override
public List<HostMO> listHostsInDatacenter(ListVmwareDcHostsCmd cmd) {
VcenterData vmwaredc = getVcenterData(cmd);
try {
VmwareContext context = getVmwareContext(vmwaredc);
DatacenterMO dcMo = getDatacenterMO(context, vmwaredc);
return dcMo.getAllHostsOnDatacenter();
} catch (RuntimeFaultFaultMsg | URISyntaxException | VmwareClientException | InvalidLocaleFaultMsg |
InvalidLoginFaultMsg | InvalidPropertyFaultMsg e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vmwaredc.vcenter, vmwaredc.datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
}
}
@Override
public Pair<String, List<UnmanagedInstanceTO>> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
Integer maxObjects = cmd.getBatchSize();
String token = cmd.getToken();
String host = cmd.getHost();
VcenterData vmwaredc = getVcenterData(cmd);
try {
VmwareContext context = getVmwareContext(vmwaredc);
DatacenterMO dcMo = getDatacenterMO(context, vmwaredc);
if (com.cloud.utils.StringUtils.isNotBlank(host)) {
ManagedObjectReference hostMor = dcMo.findHost(host);
if (hostMor == null) {
throw new VmwareClientException(String.format("No host '%s' found on DC: %s.", host, dcMo.getName()));
}
HostMO hostMo = new HostMO(context, hostMor);
return hostMo.getVms(maxObjects, token);
} else {
return dcMo.getVms(maxObjects, token);
}
} catch (InvalidParameterValueException | VmwareClientException | InvalidLocaleFaultMsg | InvalidLoginFaultMsg |
RuntimeFaultFaultMsg | URISyntaxException | InvalidPropertyFaultMsg | InvocationTargetException |
NoSuchMethodException | IllegalAccessException e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vmwaredc.vcenter, vmwaredc.datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
}
}
@NotNull
private DatacenterMO getDatacenterMO(VmwareContext context, VcenterData vmwaredc) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg {
DatacenterMO dcMo = new DatacenterMO(context, vmwaredc.datacenterName);
ManagedObjectReference dcMor = dcMo.getMor();
if (dcMor == null) {
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s",
vmwaredc.datacenterName, vmwaredc.vcenter);
logger.error(msg);
throw new InvalidParameterValueException(msg);
}
return dcMo;
}
@NotNull
private VmwareContext getVmwareContext(VcenterData vmwaredc) throws RuntimeFaultFaultMsg, URISyntaxException, VmwareClientException, InvalidLocaleFaultMsg, InvalidLoginFaultMsg {
logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs",
vmwaredc.datacenterName, vmwaredc.vcenter));
String serviceUrl = String.format("https://%s/sdk/vimService", vmwaredc.vcenter);
VmwareClient vimClient = new VmwareClient(vmwaredc.vcenter);
vimClient.connect(serviceUrl, vmwaredc.username, vmwaredc.password);
VmwareContext context = new VmwareContext(vimClient, vmwaredc.vcenter);
return context;
}
@NotNull
private VcenterData getVcenterData(ListVmwareDcItems cmd) {
public List<UnmanagedInstanceTO> listVMsInDatacenter(ListVmwareDcVmsCmd cmd) {
String vcenter = cmd.getVcenter();
String datacenterName = cmd.getDatacenterName();
String username = cmd.getUsername();
String password = cmd.getPassword();
Long existingVcenterId = cmd.getExistingVcenterId();
String keyword = cmd.getKeyword();
if ((existingVcenterId == null && StringUtils.isBlank(vcenter)) ||
(existingVcenterId != null && StringUtils.isNotBlank(vcenter))) {
@ -1689,27 +1613,37 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
username = vmwareDc.getUser();
password = vmwareDc.getPassword();
}
VcenterData vmwaredc = new VcenterData(vcenter, datacenterName, username, password);
return vmwaredc;
try {
logger.debug(String.format("Connecting to the VMware datacenter %s at vCenter %s to retrieve VMs",
datacenterName, vcenter));
String serviceUrl = String.format("https://%s/sdk/vimService", vcenter);
VmwareClient vimClient = new VmwareClient(vcenter);
vimClient.connect(serviceUrl, username, password);
VmwareContext context = new VmwareContext(vimClient, vcenter);
DatacenterMO dcMo = new DatacenterMO(context, datacenterName);
ManagedObjectReference dcMor = dcMo.getMor();
if (dcMor == null) {
String msg = String.format("Unable to find VMware datacenter %s in vCenter %s",
datacenterName, vcenter);
logger.error(msg);
throw new InvalidParameterValueException(msg);
}
private static class VcenterData {
public final String vcenter;
public final String datacenterName;
public final String username;
public final String password;
public VcenterData(String vcenter, String datacenterName, String username, String password) {
this.vcenter = vcenter;
this.datacenterName = datacenterName;
this.username = username;
this.password = password;
List<UnmanagedInstanceTO> instances = dcMo.getAllVmsOnDatacenter();
return StringUtils.isBlank(keyword) ? instances :
instances.stream().filter(x -> x.getName().toLowerCase().contains(keyword.toLowerCase())).collect(Collectors.toList());
} catch (Exception e) {
String errorMsg = String.format("Error retrieving stopped VMs from the VMware VC %s datacenter %s: %s",
vcenter, datacenterName, e.getMessage());
logger.error(errorMsg, e);
throw new CloudRuntimeException(errorMsg);
}
}
@Override
public boolean hasNexusVSM(Long clusterId) {
ClusterVSMMapVO vsmMapVo;
ClusterVSMMapVO vsmMapVo = null;
vsmMapVo = _vsmMapDao.findByClusterId(clusterId);
if (vsmMapVo == null) {
@ -1759,7 +1693,7 @@ public class VmwareManagerImpl extends ManagerBase implements VmwareManager, Vmw
}
/**
* This task is to clean-up templates from primary storage that are otherwise not cleaned by the {@see com.cloud.storage.StorageManagerImpl.StorageGarbageCollector}.
* This task is to cleanup templates from primary storage that are otherwise not cleaned by the {@link com.cloud.storage.StorageManagerImpl.StorageGarbageCollector}.
* it is called at regular intervals when storage.template.cleanup.enabled == true
* It collect all templates that
* - are deleted from cloudstack

View File

@ -51,6 +51,7 @@ import javax.xml.datatype.XMLGregorianCalendar;
import com.cloud.capacity.CapacityManager;
import com.cloud.hypervisor.vmware.mo.HostDatastoreBrowserMO;
import com.vmware.vim25.Description;
import com.vmware.vim25.FileInfo;
import com.vmware.vim25.FileQueryFlags;
import com.vmware.vim25.FolderFileInfo;
@ -58,6 +59,7 @@ import com.vmware.vim25.HostDatastoreBrowserSearchResults;
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
import com.vmware.vim25.VirtualCdromIsoBackingInfo;
import com.vmware.vim25.VirtualMachineConfigSummary;
import com.vmware.vim25.VirtualTPM;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.backup.PrepareForBackupRestorationCommand;
import org.apache.cloudstack.storage.command.CopyCommand;
@ -2597,12 +2599,16 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
setBootOptions(vmSpec, bootMode, vmConfigSpec);
// Config vTPM
configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
if (StringUtils.isNotEmpty(vmStoragePolicyId)) {
vmConfigSpec.getVmProfile().add(vmProfileSpec);
if (logger.isTraceEnabled()) {
logger.trace(String.format("Configuring the VM %s with storage policy: %s", vmInternalCSName, vmStoragePolicyId));
}
}
//
// Configure VM
//
@ -3203,6 +3209,57 @@ public class VmwareResource extends ServerResourceBase implements StoragePoolRes
vmConfigSpec.getDeviceChange().add(arrayVideoCardConfigSpecs);
}
/**
* Add or Remove virtual TPM module
*
* @param vmMo virtual machine mo
* @param vmSpec virtual machine specs
* @param vmConfigSpec virtual machine config spec
* @throws Exception exception
*/
protected void configureVirtualTPM(VirtualMachineMO vmMo, VirtualMachineTO vmSpec, VirtualMachineConfigSpec vmConfigSpec) throws Exception {
String virtualTPMEnabled = vmSpec.getDetails().getOrDefault(VmDetailConstants.VIRTUAL_TPM_ENABLED, null);
if (Boolean.parseBoolean(virtualTPMEnabled)) {
for (VirtualDevice device : vmMo.getAllDeviceList()) {
if (device instanceof VirtualTPM) {
logger.debug(String.format("Virtual TPM device has already been added to VM %s, returning", vmMo.getVmName()));
return;
}
}
logger.debug(String.format("Adding Virtual TPM device to the VM %s", vmMo.getVmName()));
addVirtualTPMDevice(vmConfigSpec);
} else if (virtualTPMEnabled == null) {
logger.debug(String.format("Virtual TPM device is neither enabled nor disabled for VM %s, skipping", vmMo.getVmName()));
} else {
logger.debug(String.format("Virtual TPM device is disabled for VM %s", vmMo.getVmName()));
for (VirtualDevice device : vmMo.getAllDeviceList()) {
if (device instanceof VirtualTPM) {
logger.debug(String.format("Removing Virtual TPM device from VM %s as it is disabled", vmMo.getVmName()));
removeVirtualTPMDevice(vmConfigSpec, (VirtualTPM) device);
}
}
}
}
protected void addVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec) {
Description description = new Description();
description.setSummary("Trusted Platform Module");
description.setLabel("Trusted Platform Module");
VirtualTPM virtualTPM = new VirtualTPM();
virtualTPM.setDeviceInfo(description);
VirtualDeviceConfigSpec deviceConfigSpec = new VirtualDeviceConfigSpec();
deviceConfigSpec.setDevice(virtualTPM);
deviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.ADD);
vmConfigSpec.getDeviceChange().add(deviceConfigSpec);
}
protected void removeVirtualTPMDevice(VirtualMachineConfigSpec vmConfigSpec, VirtualTPM virtualTPM) {
VirtualDeviceConfigSpec virtualDeviceConfigSpec = new VirtualDeviceConfigSpec();
virtualDeviceConfigSpec.setDevice(virtualTPM);
virtualDeviceConfigSpec.setOperation(VirtualDeviceConfigSpecOperation.REMOVE);
vmConfigSpec.getDeviceChange().add(virtualDeviceConfigSpec);
}
private void tearDownVm(VirtualMachineMO vmMo) throws Exception {
if (vmMo == null)

View File

@ -36,8 +36,8 @@ import com.cloud.dc.VmwareDatacenterVO;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
@APICommand(name = "addVmwareDc", description = "Adds a Vmware datacenter to specified zone",
responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false)
@APICommand(name = "addVmwareDc", description = "Adds a VMware datacenter to specified zone", responseObject = VmwareDatacenterResponse.class,
requestHasSensitiveInfo = true, responseHasSensitiveInfo = false)
public class AddVmwareDcCmd extends BaseCmd {
@Inject
@ -45,7 +45,7 @@ public class AddVmwareDcCmd extends BaseCmd {
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of Vmware datacenter to be added to specified zone.")
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "Name of VMware datacenter to be added to specified zone.")
private String name;
@Parameter(name = ApiConstants.VCENTER,
@ -54,10 +54,10 @@ public class AddVmwareDcCmd extends BaseCmd {
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vCenter;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, required = false, description = "The Username required to connect to resource.")
private String username;
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, required = false, description = "The password for specified username.")
private String password;
@Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "The Zone ID.")
@ -99,7 +99,7 @@ public class AddVmwareDcCmd extends BaseCmd {
response.setResponseName(getCommandName());
response.setObjectName("vmwaredc");
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add Vmware Datacenter to zone.");
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to add VMware Datacenter to zone.");
}
this.setResponseObject(response);
} catch (DiscoveryException ex) {

View File

@ -72,13 +72,6 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.importVsphereStoragePolicies(this);
final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>();
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = getVsphereStoragePoliciesResponses(storagePolicies, dataCenter);
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
private static List<VsphereStoragePoliciesResponse> getVsphereStoragePoliciesResponses(List<? extends VsphereStoragePolicy> storagePolicies, DataCenter dataCenter) {
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>();
for (VsphereStoragePolicy storagePolicy : storagePolicies) {
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
@ -91,7 +84,9 @@ public class ImportVsphereStoragePoliciesCmd extends BaseCmd {
storagePoliciesResponseList.add(storagePoliciesResponse);
}
return storagePoliciesResponseList;
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
@Override

View File

@ -1,144 +0,0 @@
// 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 org.apache.cloudstack.api.command.admin.zone;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.hypervisor.vmware.mo.HostMO;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
import com.vmware.vim25.InvalidPropertyFaultMsg;
import com.vmware.vim25.RuntimeFaultFaultMsg;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.HostResponse;
import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import javax.inject.Inject;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
@APICommand(name = "listVmwareDcHosts", responseObject = VmwareRequestResponse.class,
description = "Lists the VMs in a Vmware Datacenter",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcHostsCmd extends BaseCmd implements ListVmwareDcItems {
@Inject
public VmwareDatacenterService _vmwareDatacenterService;
@Parameter(name = ApiConstants.EXISTING_VCENTER_ID,
type = CommandType.UUID,
entityType = VmwareDatacenterResponse.class,
description = "UUID of a linked existing vCenter")
private Long existingVcenterId;
@Parameter(name = ApiConstants.VCENTER,
type = CommandType.STRING,
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vcenter;
@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of Vmware datacenter.")
private String datacenterName;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
private String username;
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
private String password;
public String getVcenter() {
return vcenter;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getDatacenterName() {
return datacenterName;
}
public Long getExistingVcenterId() {
return existingVcenterId;
}
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
checkParameters();
try {
List<HostMO> hosts = _vmwareDatacenterService.listHostsInDatacenter(this);
List<BaseResponse> baseResponseList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(hosts)) {
for (HostMO vmwareHost : hosts) {
HostResponse resp = createHostResponse(vmwareHost);
baseResponseList.add(resp);
}
}
VmwareRequestResponse<BaseResponse> response = new VmwareRequestResponse<>();
response.setResponses(baseResponseList, baseResponseList.size());
response.setResponseName(getCommandName());
setResponseObject(response);
} catch (CloudRuntimeException | InvalidPropertyFaultMsg | RuntimeFaultFaultMsg | InvocationTargetException |
NoSuchMethodException | IllegalAccessException e) {
String errorMsg = String.format("Error retrieving VMs from Vmware VC: %s", e.getMessage());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
}
}
private HostResponse createHostResponse(HostMO hostInstance) throws InvalidPropertyFaultMsg, RuntimeFaultFaultMsg, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
HostResponse response = new HostResponse();
response.setHypervisor(Hypervisor.HypervisorType.VMware.toString());
response.setName(hostInstance.getHostName());
response.setObjectName("host");
return response;
}
private void checkParameters() {
if ((existingVcenterId == null && vcenter == null) || (existingVcenterId != null && vcenter != null)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
"Please provide an existing vCenter ID or a vCenter IP/Name, parameters are mutually exclusive");
}
if (existingVcenterId == null && StringUtils.isAnyBlank(vcenter, datacenterName, username, password)) {
throw new ServerApiException(ApiErrorCode.PARAM_ERROR,
"Please set all the information for a vCenter IP/Name, datacenter, username and password");
}
}
@Override
public long getEntityOwnerId() {
return Account.ACCOUNT_ID_SYSTEM;
}
}

View File

@ -1,29 +0,0 @@
// 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 org.apache.cloudstack.api.command.admin.zone;
public interface ListVmwareDcItems {
String getVcenter();
String getDatacenterName();
String getUsername();
String getPassword();
Long getExistingVcenterId();
}

View File

@ -23,15 +23,15 @@ import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseListCmd;
import org.apache.cloudstack.api.BaseResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.response.ListResponse;
import org.apache.cloudstack.api.response.UnmanagedInstanceResponse;
import org.apache.cloudstack.api.response.VmwareDatacenterResponse;
import org.apache.cloudstack.vm.UnmanagedInstanceTO;
@ -42,10 +42,10 @@ import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
@APICommand(name = "listVmwareDcVms", responseObject = VmwareRequestResponse.class,
description = "Lists the VMs in a Vmware Datacenter",
@APICommand(name = "listVmwareDcVms", responseObject = UnmanagedInstanceResponse.class,
description = "Lists the VMs in a VMware Datacenter",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
public class ListVmwareDcVmsCmd extends BaseListCmd {
@Inject
public VmwareDatacenterService _vmwareDatacenterService;
@ -61,7 +61,7 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
description = "The name/ip of vCenter. Make sure it is IP address or full qualified domain name for host running vCenter server.")
private String vcenter;
@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of Vmware datacenter.")
@Parameter(name = ApiConstants.DATACENTER_NAME, type = CommandType.STRING, description = "Name of VMware datacenter.")
private String datacenterName;
@Parameter(name = ApiConstants.USERNAME, type = CommandType.STRING, description = "The Username required to connect to resource.")
@ -70,18 +70,6 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
@Parameter(name = ApiConstants.PASSWORD, type = CommandType.STRING, description = "The password for specified username.")
private String password;
@Parameter(name = ApiConstants.HOST, type = CommandType.STRING, description = "get only the VMs from the specified host.")
private String host;
@Parameter(name = ApiConstants.BATCH_SIZE, type = CommandType.INTEGER, description = "The maximum number of results to return.")
private Integer batchSize;
@Parameter(name = ApiConstants.TOKEN, type = CommandType.STRING,
description = "For listVmwareDcVms, if the maximum number of results (the `batchsize`) is exceeded, " +
" a token is returned. This token can be used in subsequent calls to retrieve more results." +
" As long as a token is returned, more results can be retrieved.")
private String token;
public String getVcenter() {
return vcenter;
}
@ -94,18 +82,6 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
return password;
}
public Integer getBatchSize() {
return batchSize;
}
public String getHost() {
return host;
}
public String getToken() {
return token;
}
public String getDatacenterName() {
return datacenterName;
}
@ -118,8 +94,7 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
checkParameters();
try {
Pair<String, List<UnmanagedInstanceTO>> results = _vmwareDatacenterService.listVMsInDatacenter(this);
List<UnmanagedInstanceTO> vms = results.second();
List<UnmanagedInstanceTO> vms = _vmwareDatacenterService.listVMsInDatacenter(this);
List<BaseResponse> baseResponseList = new ArrayList<>();
if (CollectionUtils.isNotEmpty(vms)) {
for (UnmanagedInstanceTO vmwareVm : vms) {
@ -127,13 +102,16 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
baseResponseList.add(resp);
}
}
VmwareRequestResponse<BaseResponse> response = new VmwareRequestResponse<>();
response.setResponses(baseResponseList, baseResponseList.size());
List<BaseResponse> pagingList = com.cloud.utils.StringUtils.applyPagination(baseResponseList, this.getStartIndex(), this.getPageSizeVal());
if (CollectionUtils.isEmpty(pagingList)) {
pagingList = baseResponseList;
}
ListResponse<BaseResponse> response = new ListResponse<>();
response.setResponses(pagingList, baseResponseList.size());
response.setResponseName(getCommandName());
response.setToken(results.first());
setResponseObject(response);
} catch (CloudRuntimeException e) {
String errorMsg = String.format("Error retrieving VMs from Vmware VC: %s", e.getMessage());
String errorMsg = String.format("Error retrieving VMs from VMware VC: %s", e.getMessage());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMsg);
}
}
@ -156,6 +134,6 @@ public class ListVmwareDcVmsCmd extends BaseCmd implements ListVmwareDcItems {
@Override
public String getCommandName() {
return "listVmwareDcVmsResponse".toLowerCase();
return "listvmwaredcvmsresponse";
}
}

View File

@ -42,7 +42,7 @@ import com.cloud.dc.VmwareDatacenter;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account;
@APICommand(name = "listVmwareDcs", responseObject = VmwareDatacenterResponse.class, description = "Retrieves Vmware DC(s) associated with a zone.",
@APICommand(name = "listVmwareDcs", responseObject = VmwareDatacenterResponse.class, description = "Retrieves VMware DC(s) associated with a zone.",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class ListVmwareDcsCmd extends BaseListCmd {
@ -50,6 +50,7 @@ public class ListVmwareDcsCmd extends BaseListCmd {
public VmwareDatacenterService _vmwareDatacenterService;
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@ -72,27 +73,20 @@ public class ListVmwareDcsCmd extends BaseListCmd {
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
ResourceAllocationException {
List<? extends VmwareDatacenter> vmwareDcList;
List<? extends VmwareDatacenter> vmwareDcList = null;
try {
vmwareDcList = _vmwareDatacenterService.listVmwareDatacenters(this);
} catch (InvalidParameterValueException ie) {
throw new InvalidParameterValueException("Invalid zone id " + getZoneId());
} catch (Exception e) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find associated Vmware DCs associated with zone " + getZoneId());
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to find associated VMware DCs associated with zone " + getZoneId());
}
ListResponse<VmwareDatacenterResponse> response = new ListResponse<>();
List<VmwareDatacenterResponse> vmwareDcResponses = getVmwareDatacenterResponses(vmwareDcList);
response.setResponses(vmwareDcResponses);
response.setResponseName(getCommandName());
setResponseObject(response);
}
ListResponse<VmwareDatacenterResponse> response = new ListResponse<VmwareDatacenterResponse>();
List<VmwareDatacenterResponse> vmwareDcResponses = new ArrayList<VmwareDatacenterResponse>();
private List<VmwareDatacenterResponse> getVmwareDatacenterResponses(List<? extends VmwareDatacenter> vmwareDcList) {
List<VmwareDatacenterResponse> vmwareDcResponses = new ArrayList<>();
if (vmwareDcList != null && !vmwareDcList.isEmpty()) {
if (vmwareDcList != null && vmwareDcList.size() > 0) {
for (VmwareDatacenter vmwareDc : vmwareDcList) {
VmwareDatacenterResponse vmwareDcResponse = new VmwareDatacenterResponse();
@ -100,12 +94,14 @@ public class ListVmwareDcsCmd extends BaseListCmd {
vmwareDcResponse.setVcenter(vmwareDc.getVcenterHost());
vmwareDcResponse.setName(vmwareDc.getVmwareDatacenterName());
vmwareDcResponse.setZoneId(getZoneId());
vmwareDcResponse.setObjectName(ApiConstants.VMWARE_DC);
vmwareDcResponse.setObjectName("VMwareDC");
vmwareDcResponses.add(vmwareDcResponse);
}
}
return vmwareDcResponses;
response.setResponses(vmwareDcResponses);
response.setResponseName(getCommandName());
setResponseObject(response);
}
@Override

View File

@ -71,13 +71,6 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
List<? extends VsphereStoragePolicy> storagePolicies = _vmwareDatacenterService.listVsphereStoragePolicies(this);
final ListResponse<VsphereStoragePoliciesResponse> responseList = new ListResponse<>();
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = getVsphereStoragePoliciesResponses(storagePolicies, dataCenter);
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
private static List<VsphereStoragePoliciesResponse> getVsphereStoragePoliciesResponses(List<? extends VsphereStoragePolicy> storagePolicies, DataCenter dataCenter) {
final List<VsphereStoragePoliciesResponse> storagePoliciesResponseList = new ArrayList<>();
for (VsphereStoragePolicy storagePolicy : storagePolicies) {
final VsphereStoragePoliciesResponse storagePoliciesResponse = new VsphereStoragePoliciesResponse();
@ -86,11 +79,13 @@ public class ListVsphereStoragePoliciesCmd extends BaseCmd {
storagePoliciesResponse.setName(storagePolicy.getName());
storagePoliciesResponse.setPolicyId(storagePolicy.getPolicyId());
storagePoliciesResponse.setDescription(storagePolicy.getDescription());
storagePoliciesResponse.setObjectName(ApiConstants.STORAGE_POLICY);
storagePoliciesResponse.setObjectName("StoragePolicy");
storagePoliciesResponseList.add(storagePoliciesResponse);
}
return storagePoliciesResponseList;
responseList.setResponses(storagePoliciesResponseList);
responseList.setResponseName(getCommandName());
setResponseObject(responseList);
}
@Override

View File

@ -68,7 +68,7 @@ public class ListVsphereStoragePolicyCompatiblePoolsCmd extends BaseListCmd {
List<StoragePoolResponse> poolResponses = new ArrayList<>();
for (StoragePool pool : pools) {
StoragePoolResponse poolResponse = _responseGenerator.createStoragePoolForMigrationResponse(pool);
poolResponse.setObjectName(ApiConstants.STORAGE_POOL);
poolResponse.setObjectName("storagepool");
poolResponses.add(poolResponse);
}
response.setResponses(poolResponses);

View File

@ -34,7 +34,7 @@ import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account;
import com.cloud.utils.exception.CloudRuntimeException;
@APICommand(name = "removeVmwareDc", responseObject = SuccessResponse.class, description = "Remove a Vmware datacenter from a zone.",
@APICommand(name = "removeVmwareDc", responseObject = SuccessResponse.class, description = "Remove a VMware datacenter from a zone.",
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
public class RemoveVmwareDcCmd extends BaseCmd {
@ -47,7 +47,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
type = CommandType.UUID,
entityType = ZoneResponse.class,
required = true,
description = "The id of Zone from which Vmware datacenter has to be removed.")
description = "The id of Zone from which VMware datacenter has to be removed.")
private Long zoneId;
public Long getZoneId() {
@ -63,7 +63,7 @@ public class RemoveVmwareDcCmd extends BaseCmd {
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove Vmware datacenter from zone");
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to remove VMware datacenter from zone");
}
} catch (ResourceInUseException ex) {
logger.warn("The zone has one or more resources (like cluster), hence not able to remove VMware datacenter from zone."

View File

@ -33,7 +33,7 @@ import com.cloud.dc.VmwareDatacenter;
import com.cloud.hypervisor.vmware.VmwareDatacenterService;
import com.cloud.user.Account;
@APICommand(name = "updateVmwareDc", description = "Updates a Vmware datacenter details for a zone",
@APICommand(name = "updateVmwareDc", description = "Updates a VMware datacenter details for a zone",
responseObject = VmwareDatacenterResponse.class, responseHasSensitiveInfo = false,
since = "4.12.0", authorized = {RoleType.Admin})
public class UpdateVmwareDcCmd extends BaseCmd {
@ -50,7 +50,7 @@ public class UpdateVmwareDcCmd extends BaseCmd {
private Long zoneId;
@Parameter(name = ApiConstants.NAME, type = CommandType.STRING,
description = "Vmware datacenter name.")
description = "VMware datacenter name.")
private String name;
@Parameter(name = ApiConstants.VCENTER, type = CommandType.STRING,
@ -105,13 +105,13 @@ public class UpdateVmwareDcCmd extends BaseCmd {
public void execute() {
final VmwareDatacenter vmwareDatacenter = vmwareDatacenterService.updateVmwareDatacenter(this);
if (vmwareDatacenter == null) {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update Vmware datacenter");
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to update VMware datacenter");
}
final VmwareDatacenterResponse response = new VmwareDatacenterResponse();
response.setId(vmwareDatacenter.getUuid());
response.setName(vmwareDatacenter.getVmwareDatacenterName());
response.setResponseName(getCommandName());
response.setObjectName(ApiConstants.VMWARE_DC);
response.setObjectName("vmwaredc");
setResponseObject(response);
}

View File

@ -1,38 +0,0 @@
// 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 org.apache.cloudstack.api.command.admin.zone;
import com.cloud.serializer.Param;
import com.google.gson.annotations.SerializedName;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.response.ListResponse;
public class VmwareRequestResponse<T extends ResponseObject> extends ListResponse<T> {
@SerializedName(ApiConstants.TOKEN)
@Param(description = "The Vmware API token to use for retrieving further responses with")
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}

View File

@ -50,6 +50,8 @@ import com.cloud.hypervisor.vmware.util.VmwareHelper;
import com.vmware.vim25.FileInfo;
import com.vmware.vim25.HostDatastoreBrowserSearchResults;
import com.vmware.vim25.HostDatastoreBrowserSearchSpec;
import com.vmware.vim25.VirtualTPM;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.storage.command.CopyCommand;
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsAnswer;
import org.apache.cloudstack.storage.command.browser.ListDataStoreObjectsCommand;
@ -835,4 +837,41 @@ public class VmwareResourceTest {
assertEquals(Collections.singletonList(1L), answer.getSizes());
assertEquals(Collections.singletonList(date.getTime()), answer.getLastModified());
}
@Test
public void testAddVirtualTPMDevice() throws Exception {
VirtualMachineMO vmMo = Mockito.mock(VirtualMachineMO.class);
VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class);
VirtualMachineConfigSpec vmConfigSpec = Mockito.mock(VirtualMachineConfigSpec.class);
Map<String, String> details = new HashMap<>();
details.put(ApiConstants.BootType.UEFI.toString(), "SECURE");
details.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, "true");
when(vmSpec.getDetails()).thenReturn(details);
when(vmMo.getAllDeviceList()).thenReturn(new ArrayList<>());
List<VirtualDeviceConfigSpec> deviceChanges = Mockito.mock(List.class);
when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges);
vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
Mockito.verify(vmwareResource, Mockito.times(1)).addVirtualTPMDevice(vmConfigSpec);
Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class));
}
@Test
public void testRemoveVirtualTPMDevice() throws Exception {
VirtualMachineMO vmMo = Mockito.mock(VirtualMachineMO.class);
VirtualMachineTO vmSpec = Mockito.mock(VirtualMachineTO.class);
VirtualMachineConfigSpec vmConfigSpec = Mockito.mock(VirtualMachineConfigSpec.class);
Map<String, String> details = new HashMap<>();
details.put(ApiConstants.BootType.UEFI.toString(), "SECURE");
details.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, "false");
when(vmSpec.getDetails()).thenReturn(details);
VirtualTPM tpm = new VirtualTPM();
when(vmMo.getAllDeviceList()).thenReturn(List.of(tpm));
List<VirtualDeviceConfigSpec> deviceChanges = Mockito.mock(List.class);
when(vmConfigSpec.getDeviceChange()).thenReturn(deviceChanges);
vmwareResource.configureVirtualTPM(vmMo, vmSpec, vmConfigSpec);
Mockito.verify(vmwareResource, Mockito.times(1)).removeVirtualTPMDevice(vmConfigSpec, tpm);
Mockito.verify(deviceChanges, Mockito.times(1)).add(any(VirtualDeviceConfigSpec.class));
}
}

View File

@ -22,7 +22,6 @@ import java.util.List;
import javax.inject.Inject;
import com.cloud.cpu.CPU;
import org.apache.cloudstack.api.ApiCommandResourceType;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd;
@ -38,6 +37,7 @@ import org.apache.commons.lang3.StringUtils;
import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.cpu.CPU;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
@ -58,6 +58,7 @@ import com.cloud.utils.Pair;
import com.cloud.utils.component.ComponentContext;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.Filter;
import com.cloud.utils.db.JoinBuilder;
import com.cloud.utils.db.SearchBuilder;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
@ -94,6 +95,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
if (template.getState() != null) {
response.setIsoState(template.getState().toString());
}
response.setIsoArch(template.getArch().getType());
response.setDirectDownload(template.isDirectDownload());
}
@ -267,6 +269,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
final Long zoneId = cmd.getZoneId();
String minimumSemanticVersion = cmd.getMinimumSemanticVersion();
final Long minimumKubernetesVersionId = cmd.getMinimumKubernetesVersionId();
final String arch = cmd.getArch();
if (StringUtils.isNotEmpty(minimumSemanticVersion) && minimumKubernetesVersionId != null) {
throw new CloudRuntimeException(String.format("Both parameters %s and %s can not be passed together", ApiConstants.MIN_SEMANTIC_VERSION, ApiConstants.MIN_KUBERNETES_VERSION_ID));
}
@ -281,6 +284,13 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
SearchBuilder<KubernetesSupportedVersionVO> sb = kubernetesSupportedVersionDao.createSearchBuilder();
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
sb.and("keyword", sb.entity().getName(), SearchCriteria.Op.LIKE);
if (StringUtils.isNotBlank(arch)) {
SearchBuilder<VMTemplateVO> isoSearch = templateDao.createSearchBuilder();
isoSearch.and("arch", isoSearch.entity().getArch(), SearchCriteria.Op.EQ);
sb.join("isoSearch", isoSearch, isoSearch.entity().getId(), sb.entity().getIsoId(), JoinBuilder.JoinType.INNER);
isoSearch.done();
}
sb.done();
SearchCriteria<KubernetesSupportedVersionVO> sc = sb.create();
String keyword = cmd.getKeyword();
if (versionId != null) {
@ -295,6 +305,9 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
if(keyword != null){
sc.setParameters("keyword", "%" + keyword + "%");
}
if (StringUtils.isNotBlank(arch)) {
sc.setJoinParameters("isoSearch", "arch", arch);
}
Pair<List<KubernetesSupportedVersionVO>, Integer> versionsAndCount =
kubernetesSupportedVersionDao.searchAndCount(sc, searchFilter);
List<KubernetesSupportedVersionVO> versions =

View File

@ -66,6 +66,11 @@ public class ListKubernetesSupportedVersionsCmd extends BaseListCmd {
description = "the ID of the minimum Kubernetes supported version")
private Long minimumKubernetesVersionId;
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
description = "the CPU arch of the binaries ISO. Valid options are: x86_64, aarch64",
since = "4.20")
private String arch;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -85,6 +90,10 @@ public class ListKubernetesSupportedVersionsCmd extends BaseListCmd {
return minimumSemanticVersion;
}
public String getArch() {
return arch;
}
public Long getMinimumKubernetesVersionId() {
return minimumKubernetesVersionId;
}

View File

@ -54,6 +54,10 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
@Param(description = "the state of the binaries ISO for Kubernetes supported version")
private String isoState;
@SerializedName(ApiConstants.ARCH)
@Param(description = "the arch of the binaries ISO for Kubernetes supported version", since = "4.20.1")
private String isoArch;
@SerializedName(ApiConstants.ZONE_ID)
@Param(description = "the id of the zone in which Kubernetes supported version is available")
private String zoneId;
@ -138,6 +142,14 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
this.isoState = isoState;
}
public String getIsoArch() {
return isoArch;
}
public void setIsoArch(String isoArch) {
this.isoArch = isoArch;
}
public String getZoneId() {
return zoneId;
}

View File

@ -31,6 +31,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import com.cloud.api.query.dao.TemplateJoinDao;
import com.cloud.api.query.vo.TemplateJoinVO;
import com.cloud.cpu.CPU;
@RunWith(MockitoJUnitRunner.class)
public class KubernetesVersionManagerImplTest {
@ -57,6 +58,7 @@ public class KubernetesVersionManagerImplTest {
Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L);
KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse();
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
String uuid = UUID.randomUUID().toString();
Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid);
Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO);

View File

@ -125,6 +125,7 @@ public class KubernetesVersionServiceTest {
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready);
when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
when(templateJoinDao.findById(Mockito.anyLong())).thenReturn(templateJoinVO);
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);

View File

@ -16,6 +16,12 @@
// under the License.
package org.apache.cloudstack.network.lb;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Hyperv;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.KVM;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.LXC;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.VMware;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.XenServer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
@ -31,6 +37,7 @@ import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationSe
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.commons.collections.CollectionUtils;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@ -118,12 +125,6 @@ import com.cloud.vm.VirtualMachineProfile.Param;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.Hyperv;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.KVM;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.LXC;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.VMware;
import static com.cloud.hypervisor.Hypervisor.HypervisorType.XenServer;
public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements InternalLoadBalancerVMManager, InternalLoadBalancerVMService, VirtualMachineGuru {
static final private String InternalLbVmNamePrefix = "b";
@ -732,6 +733,70 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
return internalLbVms;
}
protected String getRouterTemplateForHypervisor(HypervisorType hypervisorType, long dataCenterId) {
String templateName = null;
if (XenServer.equals(hypervisorType)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateXen.valueIn(dataCenterId);
} else if (KVM.equals(hypervisorType)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateKvm.valueIn(dataCenterId);
} else if (VMware.equals(hypervisorType)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateVmware.valueIn(dataCenterId);
} else if (Hyperv.equals(hypervisorType)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateHyperV.valueIn(dataCenterId);
} else if (LXC.equals(hypervisorType)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateLxc.valueIn(dataCenterId);
}
return templateName;
}
protected DomainRouterVO createOrUpdateInternalLb(DomainRouterVO internalLbVm, final long id,
final long internalLbProviderId, final Account owner, final long userId, final Long vpcId,
final ServiceOffering routerOffering, final VMTemplateVO template) {
if (internalLbVm == null) {
internalLbVm = new DomainRouterVO(id, routerOffering.getId(), internalLbProviderId,
VirtualMachineName.getSystemVmName(id, _instance, InternalLbVmNamePrefix),
template.getId(), template.getHypervisorType(), template.getGuestOSId(),
owner.getDomainId(), owner.getId(), userId, false,
RedundantState.UNKNOWN, false, false,
VirtualMachine.Type.InternalLoadBalancerVm, vpcId);
internalLbVm.setRole(Role.INTERNAL_LB_VM);
internalLbVm.setLimitCpuUse(routerOffering.getLimitCpuUse());
internalLbVm.setDynamicallyScalable(template.isDynamicallyScalable());
return _internalLbVmDao.persist(internalLbVm);
}
internalLbVm.setTemplateId(template.getId());
internalLbVm.setDynamicallyScalable(template.isDynamicallyScalable());
_internalLbVmDao.update(internalLbVm.getId(), internalLbVm);
return internalLbVm;
}
protected DomainRouterVO deployInternalLbVmWithTemplates(DomainRouterVO internalLbVm, final long id,
final DeploymentPlan plan, final long internalLbProviderId, final Account owner, final long userId,
final Long vpcId, final ServiceOffering routerOffering,
final LinkedHashMap<Network, List<? extends NicProfile>> networks, final List<VMTemplateVO> templates)
throws InsufficientCapacityException {
for (final Iterator<VMTemplateVO> templatesIterator = templates.iterator(); templatesIterator.hasNext();) {
final VMTemplateVO template = templatesIterator.next();
try {
internalLbVm = createOrUpdateInternalLb(internalLbVm, id, internalLbProviderId, owner, userId, vpcId,
routerOffering, template);
_itMgr.allocate(internalLbVm.getInstanceName(), template, routerOffering, networks, plan, null);
internalLbVm = _internalLbVmDao.findById(internalLbVm.getId());
if (templatesIterator.hasNext()) {
_itMgr.checkDeploymentPlan(internalLbVm, template, routerOffering, owner, plan);
}
return internalLbVm;
} catch (InsufficientCapacityException ex) {
if (templatesIterator.hasNext()) {
logger.debug("Failed to allocate the VR with hypervisor {} and {}, retrying with another template", template.getHypervisorType(), template);
} else {
throw ex;
}
}
}
return null;
}
protected DomainRouterVO deployInternalLbVm(final Account owner, final DeployDestination dest, final DeploymentPlan plan, final Map<Param, Object> params, final long internalLbProviderId,
final long svcOffId, final Long vpcId, final LinkedHashMap<Network, List<? extends NicProfile>> networks, final boolean startVm) throws ConcurrentOperationException,
InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException,
@ -743,35 +808,6 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
// Try to allocate the internal lb twice using diff hypervisors, and when failed both times, throw the exception up
final List<HypervisorType> hypervisors = getHypervisors(dest, plan, null);
int allocateRetry = 0;
int startRetry = 0;
DomainRouterVO internalLbVm = null;
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
final HypervisorType hType = iter.next();
try {
final long id = _internalLbVmDao.getNextInSequence(Long.class, "id");
if (logger.isDebugEnabled()) {
logger.debug("Creating the internal lb vm " + id + " in datacenter " + dest.getDataCenter() + " with hypervisor type " + hType);
}
String templateName = null;
if (hType.equals(XenServer)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateXen.valueIn(dest.getDataCenter().getId());
} else if (hType.equals(KVM)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateKvm.valueIn(dest.getDataCenter().getId());
} else if (hType.equals(VMware)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateVmware.valueIn(dest.getDataCenter().getId());
} else if (hType.equals(Hyperv)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateHyperV.valueIn(dest.getDataCenter().getId());
} else if (hType.equals(LXC)) {
templateName = VirtualNetworkApplianceManager.RouterTemplateLxc.valueIn(dest.getDataCenter().getId());
}
final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
if (template == null) {
logger.debug(hType + " won't support system vm, skip it");
continue;
}
long userId = CallContext.current().getCallingUserId();
if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
@ -780,16 +816,31 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
}
}
internalLbVm =
new DomainRouterVO(id, routerOffering.getId(), internalLbProviderId, VirtualMachineName.getSystemVmName(id, _instance, InternalLbVmNamePrefix),
template.getId(), template.getHypervisorType(), template.getGuestOSId(), owner.getDomainId(), owner.getId(), userId, false, RedundantState.UNKNOWN, false, false, VirtualMachine.Type.InternalLoadBalancerVm, vpcId);
internalLbVm.setRole(Role.INTERNAL_LB_VM);
internalLbVm = _internalLbVmDao.persist(internalLbVm);
_itMgr.allocate(internalLbVm.getInstanceName(), template, routerOffering, networks, plan, null);
internalLbVm = _internalLbVmDao.findById(internalLbVm.getId());
int allocateRetry = 0;
int startRetry = 0;
DomainRouterVO internalLbVm = null;
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
final HypervisorType hType = iter.next();
try {
final long id = _internalLbVmDao.getNextInSequence(Long.class, "id");
if (logger.isDebugEnabled()) {
logger.debug("Creating the internal lb vm {} in datacenter {} with hypervisor type {}",
id, dest.getDataCenter(), hType);
}
final long zoneId = dest.getDataCenter().getId();
final String templateName = getRouterTemplateForHypervisor(hType, zoneId);
final String preferredArch = ResourceManager.SystemVmPreferredArchitecture.valueIn(zoneId);
final List<VMTemplateVO> templates = _templateDao.findRoutingTemplates(hType, templateName,
preferredArch);
if (CollectionUtils.isEmpty(templates)) {
logger.debug("{} won't support system vm, skip it", hType);
continue;
}
internalLbVm = deployInternalLbVmWithTemplates(internalLbVm, id, plan, internalLbProviderId, owner,
userId, vpcId, routerOffering, networks, templates);
} catch (final InsufficientCapacityException ex) {
if (allocateRetry < 2 && iter.hasNext()) {
logger.debug("Failed to allocate the Internal lb vm with hypervisor type " + hType + ", retrying one more time");
logger.debug("Failed to allocate the Internal lb vm with hypervisor type {}, retrying one more time", hType);
continue;
} else {
throw ex;
@ -804,8 +855,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
break;
} catch (final InsufficientCapacityException ex) {
if (startRetry < 2 && iter.hasNext()) {
logger.debug("Failed to start the Internal lb vm " + internalLbVm + " with hypervisor type " + hType + ", " +
"destroying it and recreating one more time");
logger.debug("Failed to start the Internal lb vm {} with hypervisor type {}, destroying it and recreating one more time", internalLbVm, hType);
// destroy the internal lb vm
destroyInternalLbVm(internalLbVm.getId(), _accountMgr.getSystemAccount(), User.UID_SYSTEM);
continue;

View File

@ -0,0 +1,172 @@
// 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 org.apache.cloudstack.network.lb;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.network.Network;
import com.cloud.network.router.VirtualRouter;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicProfile;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.DomainRouterDao;
@RunWith(MockitoJUnitRunner.class)
public class InternalLoadBalancerVMManagerImplTest {
@Mock
private DomainRouterDao internalLbVmDao;
@Mock
private VirtualMachineManager virtualMachineManager;
@InjectMocks
private InternalLoadBalancerVMManagerImpl service;
// Dummy objects for testing.
private Account account;
private ServiceOffering serviceOffering;
private VMTemplateVO template1;
private VMTemplateVO template2;
private DeploymentPlan plan;
@Before
public void setUp() {
account = mock(Account.class);
serviceOffering = mock(ServiceOffering.class);
template1 = mock(VMTemplateVO.class);
template2 = mock(VMTemplateVO.class);
plan = new DataCenterDeployment(1L);
}
@Test
public void testCreateOrUpdateInternalLb_New() {
long id = 1L;
long internalLbProviderId = 2L;
long userId = 100L;
Long vpcId = 200L;
when(template1.isDynamicallyScalable()).thenReturn(true);
when(serviceOffering.getLimitCpuUse()).thenReturn(true);
when(internalLbVmDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
DomainRouterVO result = service.createOrUpdateInternalLb(null, id, internalLbProviderId, account,
userId, vpcId, serviceOffering, template1);
verify(internalLbVmDao).persist(any(DomainRouterVO.class));
assertEquals(template1.getId(), result.getTemplateId());
assertTrue(result.isDynamicallyScalable());
assertEquals(VirtualRouter.Role.INTERNAL_LB_VM, result.getRole());
assertTrue(result.limitCpuUse());
}
@Test
public void testCreateOrUpdateInternalLb_Update() {
long id = 1L;
long internalLbProviderId = 2L;
long userId = 100L;
Long vpcId = 200L;
DomainRouterVO existing = mock(DomainRouterVO.class);
when(existing.getId()).thenReturn(id);
when(template1.isDynamicallyScalable()).thenReturn(true);
final boolean[] dsResult = {false};
doAnswer((Answer<Void>) invocation -> {
dsResult[0] = invocation.getArgument(0);
return null;
}).when(existing).setDynamicallyScalable(anyBoolean());
DomainRouterVO result = service.createOrUpdateInternalLb(existing, id, internalLbProviderId, account, userId, vpcId, serviceOffering, template1);
verify(internalLbVmDao).update(existing.getId(), existing);
assertEquals(template1.getId(), result.getTemplateId());
assertTrue(dsResult[0]);
}
@Test
public void testDeployInternalLbVmWithTemplates_SuccessfulFirstTemplate() throws Exception {
long id = 1L;
long internalLbProviderId = 2L;
long userId = 100L;
Long vpcId = 200L;
List<VMTemplateVO> templates = Arrays.asList(template1);
LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<>();
when(internalLbVmDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
when(internalLbVmDao.findById(anyLong())).thenReturn(mock(DomainRouterVO.class));
DomainRouterVO result = service.deployInternalLbVmWithTemplates(null, id, plan, internalLbProviderId, account, userId, vpcId, serviceOffering, networks, templates);
assertNotNull(result);
verify(virtualMachineManager).allocate(anyString(), eq(template1), eq(serviceOffering), eq(networks), eq(plan), isNull());
}
@Test
public void testDeployInternalLbVmWithTemplates_RetryOnInsufficientCapacity() throws Exception {
long id = 1L;
long internalLbProviderId = 2L;
long userId = 100L;
Long vpcId = 200L;
List<VMTemplateVO> templates = Arrays.asList(template1, template2);
LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<>();
when(internalLbVmDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
when(internalLbVmDao.findById(anyLong())).thenReturn(mock(DomainRouterVO.class));
doThrow(new InsufficientServerCapacityException("Not enough capacity", id))
.when(virtualMachineManager).allocate(anyString(), eq(template1), eq(serviceOffering), eq(networks), eq(plan), isNull());
DomainRouterVO result = service.deployInternalLbVmWithTemplates(null, id, plan, internalLbProviderId, account, userId, vpcId, serviceOffering, networks, templates);
assertNotNull(result);
verify(virtualMachineManager).allocate(anyString(), eq(template1), eq(serviceOffering), eq(networks), eq(plan), isNull());
verify(virtualMachineManager).allocate(anyString(), eq(template2), eq(serviceOffering), eq(networks), eq(plan), isNull());
}
@Test(expected = InsufficientCapacityException.class)
public void testDeployInternalLbVmWithTemplates_AllTemplatesFail() throws Exception {
long id = 1L;
long internalLbProviderId = 2L;
long userId = 100L;
Long vpcId = 200L;
List<VMTemplateVO> templates = Arrays.asList(template1, template2);
LinkedHashMap<Network, List<? extends NicProfile>> networks = new LinkedHashMap<>();
when(internalLbVmDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
doThrow(new InsufficientServerCapacityException("Insufficient capacity", id))
.when(virtualMachineManager).allocate(anyString(), any(VMTemplateVO.class), eq(serviceOffering), eq(networks), eq(plan), isNull());
service.deployInternalLbVmWithTemplates(null, id, plan, internalLbProviderId, account, userId, vpcId, serviceOffering, networks, templates);
}
}

View File

@ -1718,6 +1718,7 @@ public class ApiResponseHelper implements ResponseGenerator {
if (template != null) {
vmResponse.setTemplateId(template.getUuid());
vmResponse.setTemplateName(template.getName());
vmResponse.setArch(template.getArch().getType());
}
vmResponse.setCreated(vm.getCreated());
vmResponse.setHypervisor(vm.getHypervisorType().getHypervisorDisplayName());

View File

@ -1308,6 +1308,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long userId = cmd.getUserId();
Long userdataId = cmd.getUserdataId();
Map<String, String> tags = cmd.getTags();
final CPU.CPUArch arch = cmd.getArch();
boolean isAdmin = false;
boolean isRootAdmin = false;
@ -1535,8 +1536,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
}
Boolean isVnf = cmd.getVnf();
if (isVnf != null) {
boolean templateJoinNeeded = isVnf != null || arch != null;
if (templateJoinNeeded) {
SearchBuilder<VMTemplateVO> templateSearch = _templateDao.createSearchBuilder();
templateSearch.and("templateArch", templateSearch.entity().getArch(), Op.EQ);
templateSearch.and("templateTypeEQ", templateSearch.entity().getTemplateType(), Op.EQ);
templateSearch.and("templateTypeNEQ", templateSearch.entity().getTemplateType(), Op.NEQ);
@ -1665,6 +1668,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
userVmSearchCriteria.setJoinParameters("vmTemplate", "templateTypeNEQ", TemplateType.VNF);
}
}
if (arch != null) {
userVmSearchCriteria.setJoinParameters("vmTemplate", "templateArch", arch);
}
if (isRootAdmin) {
if (podId != null) {
@ -2366,6 +2372,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long pageSize = cmd.getPageSizeVal();
Hypervisor.HypervisorType hypervisorType = cmd.getHypervisor();
Long msId = cmd.getManagementServerId();
final CPU.CPUArch arch = cmd.getArch();
Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
@ -2382,6 +2389,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
hostSearchBuilder.and("resourceState", hostSearchBuilder.entity().getResourceState(), SearchCriteria.Op.EQ);
hostSearchBuilder.and("hypervisor_type", hostSearchBuilder.entity().getHypervisorType(), SearchCriteria.Op.EQ);
hostSearchBuilder.and("mgmt_server_id", hostSearchBuilder.entity().getManagementServerId(), SearchCriteria.Op.EQ);
hostSearchBuilder.and("arch", hostSearchBuilder.entity().getArch(), SearchCriteria.Op.EQ);
if (keyword != null) {
hostSearchBuilder.and().op("keywordName", hostSearchBuilder.entity().getName(), SearchCriteria.Op.LIKE);
@ -2469,6 +2477,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
}
}
if (arch != null) {
sc.setParameters("arch", arch);
}
Pair<List<HostVO>, Integer> uniqueHostPair = hostDao.searchAndCount(sc, searchFilter);
Integer count = uniqueHostPair.second();
List<Long> hostIds = uniqueHostPair.first().stream().map(HostVO::getId).collect(Collectors.toList());
@ -5053,6 +5065,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
.map(item -> (item).trim())
.collect(Collectors.toList());
userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings);
for (final String detail : userDenyListedSettings) {
if (options.containsKey(detail)) {
options.remove(detail);
@ -5103,6 +5116,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
options.put(VmDetailConstants.IOTHREADS, Arrays.asList("enabled"));
options.put(VmDetailConstants.NIC_MULTIQUEUE_NUMBER, Collections.emptyList());
options.put(VmDetailConstants.NIC_PACKED_VIRTQUEUES_ENABLED, Arrays.asList("true", "false"));
options.put(VmDetailConstants.VIRTUAL_TPM_MODEL, Arrays.asList("tpm-tis", "tpm-crb"));
options.put(VmDetailConstants.VIRTUAL_TPM_VERSION, Arrays.asList("1.2", "2.0"));
options.put(VmDetailConstants.GUEST_CPU_MODE, Arrays.asList("custom", "host-model", "host-passthrough"));
options.put(VmDetailConstants.GUEST_CPU_MODEL, Collections.emptyList());
}
if (HypervisorType.VMware.equals(hypervisorType)) {
@ -5112,6 +5129,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
options.put(VmDetailConstants.NESTED_VIRTUALIZATION_FLAG, Arrays.asList("true", "false"));
options.put(VmDetailConstants.SVGA_VRAM_SIZE, Collections.emptyList());
options.put(VmDetailConstants.RAM_RESERVATION, Collections.emptyList());
options.put(VmDetailConstants.VIRTUAL_TPM_ENABLED, Arrays.asList("true", "false"));
}
}

View File

@ -88,6 +88,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
routerResponse.setZoneId(router.getDataCenterUuid());
routerResponse.setName(router.getName());
routerResponse.setTemplateId(router.getTemplateUuid());
routerResponse.setArch(router.getArch().getType());
VMTemplateVO template = ApiDBUtils.findTemplateById(router.getTemplateId());
if (template != null) {
routerResponse.setTemplateName(template.getName());

View File

@ -188,6 +188,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
userVmResponse.setInstanceName(userVm.getInstanceName());
userVmResponse.setHostId(userVm.getHostUuid());
userVmResponse.setHostName(userVm.getHostName());
userVmResponse.setArch(userVm.getArch());
}
if (userVm.getHostStatus() != null) {
userVmResponse.setHostControlState(ControlState.getControlState(userVm.getHostStatus(), userVm.getHostResourceState()).toString());

View File

@ -27,6 +27,7 @@ import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import com.cloud.cpu.CPU;
import com.cloud.host.Status;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.Network.GuestType;
@ -38,6 +39,8 @@ import com.cloud.user.Account;
import com.cloud.utils.db.GenericDao;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import org.apache.cloudstack.util.CPUArchConverter;
import org.apache.cloudstack.util.HypervisorTypeConverter;
@Entity
@ -143,6 +146,10 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
@Convert(converter = HypervisorTypeConverter.class)
private Hypervisor.HypervisorType hypervisorType;
@Column(name="arch")
@Convert(converter = CPUArchConverter.class)
private CPU.CPUArch arch;
@Column(name = "template_id", updatable = true, nullable = true, length = 17)
private long templateId;
@ -376,6 +383,10 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
return hypervisorType;
}
public CPU.CPUArch getArch() {
return arch;
}
public Long getClusterId() {
return clusterId;
}

View File

@ -439,6 +439,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
@Column(name = "delete_protection")
protected Boolean deleteProtection;
@Column(name = "arch")
protected String arch;
public UserVmJoinVO() {
// Empty constructor
@ -977,4 +980,8 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
public String getUserDataDetails() {
return userDataDetails;
}
public String getArch() {
return arch;
}
}

View File

@ -48,7 +48,6 @@ import org.apache.cloudstack.framework.security.keystore.KeystoreVO;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
@ -82,9 +81,9 @@ import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.host.Host.Type;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.info.ConsoleProxyConnectionInfo;
@ -111,10 +110,8 @@ import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DataStoreRole;
import com.cloud.storage.Storage;
import com.cloud.storage.StoragePoolStatus;
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
@ -281,9 +278,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
}
@Override
public void onAgentDisconnect(long agentId, com.cloud.host.Status state) {
public void onAgentDisconnect(long agentId, Status state) {
if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
if (state == Status.Alert || state == Status.Disconnected) {
HostVO host = _hostDao.findById(agentId);
if (host.getType() == Type.ConsoleProxy) {
String name = host.getName();
@ -465,7 +462,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
public ConsoleProxyVO startProxy(long proxyVmId, boolean ignoreRestartSetting) {
try {
ConsoleProxyVO proxy = consoleProxyDao.findById(proxyVmId);
if (proxy.getState() == VirtualMachine.State.Running) {
if (proxy.getState() == State.Running) {
return proxy;
}
@ -474,7 +471,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
return null;
}
if (proxy.getState() == VirtualMachine.State.Stopped) {
if (proxy.getState() == State.Stopped) {
virtualMachineManager.advanceStart(proxy.getUuid(), null, null);
proxy = consoleProxyDao.findById(proxy.getId());
return proxy;
@ -575,12 +572,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
}
HypervisorType availableHypervisor = resourceManager.getAvailableHypervisor(dataCenterId);
VMTemplateVO template = vmTemplateDao.findSystemVMReadyTemplate(dataCenterId, availableHypervisor);
if (template == null) {
List<VMTemplateVO> templates = vmTemplateDao.findSystemVMReadyTemplates(dataCenterId, availableHypervisor,
ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenterId));
if (CollectionUtils.isEmpty(templates)) {
throw new CloudRuntimeException("Not able to find the System templates or not downloaded in zone " + dataCenterId);
}
Map<String, Object> context = createProxyInstance(dataCenterId, template);
Map<String, Object> context = createProxyInstance(dataCenterId, templates);
long proxyVmId = (Long)context.get("proxyVmId");
if (proxyVmId == 0) {
@ -673,7 +671,26 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
return defaultNetworks.get(0);
}
protected Map<String, Object> createProxyInstance(long dataCenterId, VMTemplateVO template) throws ConcurrentOperationException {
protected ConsoleProxyVO createOrUpdateConsoleProxy(ConsoleProxyVO proxy, long dataCenterId, long id, String name,
ServiceOffering serviceOffering, VMTemplateVO template, Account systemAccount) {
if (proxy == null) {
proxy = new ConsoleProxyVO(id, serviceOffering.getId(), name, template.getId(),
template.getHypervisorType(), template.getGuestOSId(), dataCenterId, systemAccount.getDomainId(),
systemAccount.getId(), accountManager.getSystemUser().getId(), 0,
serviceOffering.isOfferHA());
proxy.setDynamicallyScalable(template.isDynamicallyScalable());
proxy.setLimitCpuUse(serviceOffering.getLimitCpuUse());
return consoleProxyDao.persist(proxy);
}
proxy.setTemplateId(template.getId());
proxy.setHypervisorType(template.getHypervisorType());
proxy.setGuestOSId(template.getGuestOSId());
proxy.setDynamicallyScalable(template.isDynamicallyScalable());
consoleProxyDao.update(proxy.getId(), proxy);
return proxy;
}
protected Map<String, Object> createProxyInstance(long dataCenterId, List<VMTemplateVO> templates) throws ConcurrentOperationException {
long id = consoleProxyDao.getNextInSequence(Long.class, "id");
String name = VirtualMachineName.getConsoleProxyName(id, instance);
@ -702,18 +719,23 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
if (serviceOffering == null) {
serviceOffering = serviceOfferingDao.findDefaultSystemOffering(ServiceOffering.consoleProxyDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
}
ConsoleProxyVO proxy =
new ConsoleProxyVO(id, serviceOffering.getId(), name, template.getId(), template.getHypervisorType(), template.getGuestOSId(), dataCenterId,
systemAcct.getDomainId(), systemAcct.getId(), accountManager.getSystemUser().getId(), 0, serviceOffering.isOfferHA());
proxy.setDynamicallyScalable(template.isDynamicallyScalable());
proxy.setLimitCpuUse(serviceOffering.getLimitCpuUse());
proxy = consoleProxyDao.persist(proxy);
ConsoleProxyVO proxy = null;
for (final Iterator<VMTemplateVO> templateIterator = templates.iterator(); templateIterator.hasNext();) {
VMTemplateVO template = templateIterator.next();
proxy = createOrUpdateConsoleProxy(proxy, dataCenterId, id, name, serviceOffering, template, systemAcct);
try {
virtualMachineManager.allocate(name, template, serviceOffering, networks, plan, null);
virtualMachineManager.allocate(name, template, serviceOffering, networks, plan,
template.getHypervisorType());
proxy = consoleProxyDao.findById(proxy.getId());
virtualMachineManager.checkDeploymentPlan(proxy, template, serviceOffering, systemAcct, plan);
break;
} catch (InsufficientCapacityException e) {
String message = String.format("Unable to allocate proxy [%s] on zone [%s] due to [%s].", proxy.toString(), dataCenterId, e.getMessage());
logger.warn(message, e);
throw new CloudRuntimeException(message, e);
if (templateIterator.hasNext()) {
logger.debug("Unable to allocate proxy {} with {} in {} due to [{}]. Retrying with another template", proxy, template, dc, e.getMessage(), e);
continue;
}
throw new CloudRuntimeException("Failed to allocate proxy [%s] in zone [%s] with available templates", e);
}
}
Map<String, Object> context = new HashMap<>();
@ -737,8 +759,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
updateConsoleProxyStatus(answer.getDetails(), answer.getProxyVmId());
}
public void handleAgentDisconnect(long agentId, com.cloud.host.Status state) {
if (state == com.cloud.host.Status.Alert || state == com.cloud.host.Status.Disconnected) {
public void handleAgentDisconnect(long agentId, Status state) {
if (state == Status.Alert || state == Status.Disconnected) {
HostVO host = hostDao.findById(agentId);
if (host.getType() == Type.ConsoleProxy) {
String name = host.getName();
@ -789,8 +811,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
return false;
}
List<ConsoleProxyVO> l =
consoleProxyDao.getProxyListInStates(dcId, VirtualMachine.State.Starting, VirtualMachine.State.Running, VirtualMachine.State.Stopping,
VirtualMachine.State.Stopped, VirtualMachine.State.Migrating, VirtualMachine.State.Shutdown, VirtualMachine.State.Unknown);
consoleProxyDao.getProxyListInStates(dcId, State.Starting, State.Running, State.Stopping,
State.Stopped, State.Migrating, State.Shutdown, State.Unknown);
String value = configurationDao.getValue(Config.ConsoleProxyLaunchMax.key());
int launchLimit = NumbersUtil.parseInt(value, 10);
@ -876,22 +898,15 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
}
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenter.getId());
if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
VMTemplateVO template = vmTemplateDao.findSystemVMReadyTemplate(dataCenter.getId(), HypervisorType.Any);
if (template == null) {
List<VMTemplateVO> templates = vmTemplateDao.findSystemVMReadyTemplates(dataCenter.getId(),
HypervisorType.Any, null);
if (CollectionUtils.isEmpty(templates)) {
if (logger.isDebugEnabled()) {
logger.debug("System vm template is not ready at data center {}, wait until it is ready to launch console proxy vm", dataCenter);
}
return false;
}
TemplateDataStoreVO templateHostRef;
if (template.isDirectDownload()) {
templateHostRef = templateDataStoreDao.findByTemplate(template.getId(), DataStoreRole.Image);
} else {
templateHostRef = templateDataStoreDao.findByTemplateZoneDownloadStatus(template.getId(), dataCenter.getId(), Status.DOWNLOADED);
}
if (templateHostRef != null) {
Boolean useLocalStorage = BooleanUtils.toBoolean(ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenter.getId()));
boolean useLocalStorage = BooleanUtils.toBoolean(ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenter.getId()));
boolean hasDatacenterStoragePoolHostInfo = consoleProxyDao.hasDatacenterStoragePoolHostInfo(dataCenter.getId(), !useLocalStorage);
if (hasDatacenterStoragePoolHostInfo) {
return true;
@ -900,11 +915,6 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
logger.debug("Primary storage is not ready, wait until it is ready to launch console proxy");
}
}
} else {
if (logger.isDebugEnabled()) {
logger.debug("Zone [{}] is ready, but console proxy template [{}] is not ready on secondary storage.", dataCenter, template);
}
}
}
return false;
}
@ -912,9 +922,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
int expectedFlags;
if (useStorageVm) {
expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK;
expectedFlags = ZoneHostInfo.ROUTING_HOST_MASK;
} else {
expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK;
expectedFlags = ZoneHostInfo.ALL_HOST_MASK;
}
return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
@ -1093,7 +1103,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
proxy.setPrivateIpAddress(null);
consoleProxyDao.update(proxy.getId(), proxy);
consoleProxyDao.remove(vmId);
HostVO host = hostDao.findByTypeNameAndZoneId(proxy.getDataCenterId(), proxy.getHostName(), Host.Type.ConsoleProxy);
HostVO host = hostDao.findByTypeNameAndZoneId(proxy.getDataCenterId(), proxy.getHostName(), Type.ConsoleProxy);
if (host != null) {
logger.debug("Removing host [{}] entry for proxy [{}].", host, proxy);
return hostDao.remove(host.getId());
@ -1511,7 +1521,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
return false;
}
List<ConsoleProxyVO> l = consoleProxyDao.getProxyListInStates(VirtualMachine.State.Starting, VirtualMachine.State.Stopping);
List<ConsoleProxyVO> l = consoleProxyDao.getProxyListInStates(State.Starting, State.Stopping);
if (l.size() > 0) {
if (logger.isDebugEnabled()) {
logger.debug("Zone {} has {} console proxy VM(s) in transition state", zone, l.size());
@ -1568,7 +1578,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
return null;
}
host.setType(com.cloud.host.Host.Type.ConsoleProxy);
host.setType(Type.ConsoleProxy);
return host;
}
@ -1584,7 +1594,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
protected HostVO findConsoleProxyHostByName(String name) {
QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
sc.and(sc.entity().getType(), Op.EQ, Host.Type.ConsoleProxy);
sc.and(sc.entity().getType(), Op.EQ, Type.ConsoleProxy);
sc.and(sc.entity().getName(), Op.EQ, name);
return sc.find();
}

View File

@ -1788,8 +1788,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (ipv4 && Objects.isNull(startIP)) {
throw new CloudRuntimeException("IPv4 address range needs to be provided");
}
if (ipv6 && Objects.isNull(startIPv6)) {
throw new CloudRuntimeException("IPv6 address range needs to be provided");
if (ipv6) {
logger.info(String.format("ip range for network '%s' is specified as %s - %s", name, startIPv6, endIPv6));
}
}
Pair<Integer, Integer> interfaceMTUs = validateMtuConfig(publicMtu, privateMtu, zone.getId());
@ -2186,12 +2186,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (implementedNetwork == null || implementedNetwork.first() == null) {
logger.warn("Failed to provision the network " + network);
}
Network implemented = implementedNetwork.second();
if (implemented != null) {
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_CREATE, implemented.getAccountId(), implemented.getDataCenterId(), implemented.getId(),
implemented.getName(), implemented.getNetworkOfferingId(), null, null, null, Network.class.getName(), implemented.getUuid());
}
return implemented;
return implementedNetwork.second();
} catch (ResourceUnavailableException ex) {
logger.warn("Failed to implement persistent guest network " + network + "due to ", ex);
CloudRuntimeException e = new CloudRuntimeException("Failed to implement persistent guest network");
@ -3592,8 +3587,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
}
Network updatedNetwork = getNetwork(network.getId());
UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_UPDATE, updatedNetwork.getAccountId(), updatedNetwork.getDataCenterId(), updatedNetwork.getId(),
updatedNetwork.getName(), updatedNetwork.getNetworkOfferingId(), null, updatedNetwork.getState().name(), Network.class.getName(), updatedNetwork.getUuid(), true);
UsageEventUtils.publishNetworkUpdate(updatedNetwork);
return updatedNetwork;
}

View File

@ -28,8 +28,6 @@ import java.util.Map;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.utils.validation.ChecksumUtil;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
@ -38,8 +36,8 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
import org.apache.cloudstack.utils.CloudStackVersion;
import org.apache.commons.collections.CollectionUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
@ -86,6 +84,7 @@ import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.router.VirtualRouter.RedundantState;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.network.rules.LbStickinessMethod;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.resource.ResourceManager;
@ -104,6 +103,7 @@ import com.cloud.user.dao.UserDao;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import com.cloud.utils.validation.ChecksumUtil;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.Nic;
import com.cloud.vm.NicProfile;
@ -498,18 +498,77 @@ public class NetworkHelperImpl implements NetworkHelper {
return templateName;
}
protected DomainRouterVO createOrUpdateDomainRouter(DomainRouterVO router, final long id,
final RouterDeploymentDefinition routerDeploymentDefinition, final Account owner, final long userId,
final ServiceOfferingVO routerOffering, final boolean offerHA, final Long vpcId,
final VMTemplateVO template) {
if (router == null) {
router = new DomainRouterVO(id, routerOffering.getId(),
routerDeploymentDefinition.getVirtualProvider().getId(),
VirtualMachineName.getRouterName(id, s_vmInstanceName), template.getId(),
template.getHypervisorType(), template.getGuestOSId(), owner.getDomainId(), owner.getId(),
userId, routerDeploymentDefinition.isRedundant(), RedundantState.UNKNOWN, offerHA, false,
vpcId);
router.setDynamicallyScalable(template.isDynamicallyScalable());
router.setRole(Role.VIRTUAL_ROUTER);
router.setLimitCpuUse(routerOffering.getLimitCpuUse());
return _routerDao.persist(router);
}
router.setTemplateId(template.getId());
router.setDynamicallyScalable(template.isDynamicallyScalable());
_routerDao.update(router.getId(), router);
return router;
}
protected DomainRouterVO deployRouterWithTemplates(DomainRouterVO router, final long id,
final RouterDeploymentDefinition routerDeploymentDefinition, final Account owner, final long userId,
final ServiceOfferingVO routerOffering, final boolean offerHA, final Long vpcId,
final List<VMTemplateVO> templates) throws InsufficientCapacityException {
for (final Iterator<VMTemplateVO> templatesIterator = templates.iterator(); templatesIterator.hasNext();) {
final VMTemplateVO template = templatesIterator.next();
try {
router = createOrUpdateDomainRouter(router, id, routerDeploymentDefinition, owner, userId,
routerOffering, offerHA, vpcId, template);
reallocateRouterNetworks(routerDeploymentDefinition, router, template, null);
router = _routerDao.findById(router.getId());
if (templatesIterator.hasNext()) {
_itMgr.checkDeploymentPlan(router, template, routerOffering, owner,
routerDeploymentDefinition.getPlan());
}
return router;
} catch (InsufficientCapacityException ex) {
if (templatesIterator.hasNext()) {
logger.debug("Failed to allocate the VR with hypervisor {} and {}, retrying with another template", template.getHypervisorType(), template);
} else {
throw ex;
}
}
}
return null;
}
@Override
public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, final boolean startRouter)
throws InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException {
final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getServiceOfferingId());
final boolean offerHA = routerOffering.isOfferHA();
final Account owner = routerDeploymentDefinition.getOwner();
final Long vpcId = routerDeploymentDefinition.getVpc() != null ? routerDeploymentDefinition.getVpc().getId() : null;
// Router is the network element, we don't know the hypervisor type yet.
// Try to allocate the domR twice using diff hypervisors, and when
// failed both times, throw the exception up
final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition);
long userId = CallContext.current().getCallingUserId();
if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
final List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
if (!userVOs.isEmpty()) {
userId = userVOs.get(0).getId();
}
}
DomainRouterVO router = null;
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
final HypervisorType hType = iter.next();
@ -521,43 +580,20 @@ public class NetworkHelperImpl implements NetworkHelper {
logger.debug(String.format("Allocating the VR with id=%s in datacenter %s with the hypervisor type %s", id, routerDeploymentDefinition.getDest()
.getDataCenter(), hType));
}
final String templateName = retrieveTemplateName(hType, routerDeploymentDefinition.getDest().getDataCenter().getId());
final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
if (template == null) {
logger.debug(hType + " won't support system vm, skip it");
final long zoneId = routerDeploymentDefinition.getDest().getDataCenter().getId();
final String templateName = retrieveTemplateName(hType, zoneId);
final String preferredArch = ResourceManager.SystemVmPreferredArchitecture.valueIn(zoneId);
final List<VMTemplateVO> templates = _templateDao.findRoutingTemplates(hType, templateName,
preferredArch);
if (CollectionUtils.isEmpty(templates)) {
logger.debug("{} won't support system vm, skip it", hType);
continue;
}
final boolean offerHA = routerOffering.isOfferHA();
// routerDeploymentDefinition.getVpc().getId() ==> do not use
// VPC because it is not a VPC offering.
final Long vpcId = routerDeploymentDefinition.getVpc() != null ? routerDeploymentDefinition.getVpc().getId() : null;
long userId = CallContext.current().getCallingUserId();
if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
final List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
if (!userVOs.isEmpty()) {
userId = userVOs.get(0).getId();
}
}
router = new DomainRouterVO(id, routerOffering.getId(), routerDeploymentDefinition.getVirtualProvider().getId(), VirtualMachineName.getRouterName(id,
s_vmInstanceName), template.getId(), template.getHypervisorType(), template.getGuestOSId(), owner.getDomainId(), owner.getId(),
userId, routerDeploymentDefinition.isRedundant(), RedundantState.UNKNOWN, offerHA, false, vpcId);
router.setDynamicallyScalable(template.isDynamicallyScalable());
router.setRole(Role.VIRTUAL_ROUTER);
router.setLimitCpuUse(routerOffering.getLimitCpuUse());
router = _routerDao.persist(router);
reallocateRouterNetworks(routerDeploymentDefinition, router, template, null);
router = _routerDao.findById(router.getId());
router = deployRouterWithTemplates(router, id, routerDeploymentDefinition, owner, userId,
routerOffering, offerHA, vpcId, templates);
} catch (final InsufficientCapacityException ex) {
if (iter.hasNext()) {
logger.debug("Failed to allocate the VR with hypervisor type " + hType + ", retrying one more time");
logger.debug("Failed to allocate the VR with {}, retrying with another hypervisor", hType);
continue;
} else {
throw ex;

View File

@ -32,7 +32,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
@ -60,10 +59,8 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
@ -175,6 +172,7 @@ import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.utils.StringUtils;
import com.cloud.utils.Ternary;
import com.cloud.utils.UriUtils;
import com.cloud.utils.component.Manager;
@ -201,7 +199,6 @@ import com.cloud.utils.net.NetUtils;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.utils.ssh.SshException;
import com.cloud.vm.UserVmManager;
import com.cloud.utils.StringUtils;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@ -1204,6 +1201,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
}
if (arch != null) {
List<CPU.CPUArch> architectureTypes = _hostDao.listDistinctArchTypes(cluster.getId());
if (architectureTypes.stream().anyMatch(a -> !a.equals(arch))) {
throw new InvalidParameterValueException(String.format(
"Cluster has host(s) present with arch type(s): %s",
StringUtils.join(architectureTypes.stream().map(CPU.CPUArch::getType).toArray())));
}
cluster.setArch(arch.getType());
doUpdate = true;
}
@ -3276,12 +3279,16 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
@Override
public List<HypervisorType> listAvailHypervisorInZone(final Long zoneId) {
List<VMTemplateVO> systemVMTemplates = _templateDao.listAllReadySystemVMTemplates(zoneId);
final Set<HypervisorType> hypervisors = new HashSet<>();
for (final VMTemplateVO systemVMTemplate : systemVMTemplates) {
hypervisors.add(systemVMTemplate.getHypervisorType());
final SearchCriteria<String> sc = _hypervisorsInDC.create();
if (zoneId != null) {
sc.setParameters("dataCenter", zoneId);
}
return new ArrayList<>(hypervisors);
sc.setParameters("type", Host.Type.Routing);
return _hostDao.customSearch(sc, null).stream()
// The search is not able to return list of enums, so getting
// list of hypervisors as strings and then converting them to enum
.map(HypervisorType::getType).collect(Collectors.toList());
}
@Override
@ -3546,6 +3553,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey<?>[] {KvmSshToAgentEnabled, HOST_MAINTENANCE_LOCAL_STRATEGY};
return new ConfigKey<?>[] {
KvmSshToAgentEnabled,
HOST_MAINTENANCE_LOCAL_STRATEGY,
SystemVmPreferredArchitecture
};
}
}

View File

@ -44,7 +44,6 @@ import javax.crypto.spec.SecretKeySpec;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.cpu.CPU;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
@ -674,6 +673,7 @@ import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManagerImpl;
import com.cloud.consoleproxy.ConsoleProxyManagementState;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.cpu.CPU;
import com.cloud.dc.AccountVlanMapVO;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
@ -1274,6 +1274,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
final Object clusterType = cmd.getClusterType();
final Object allocationState = cmd.getAllocationState();
final String keyword = cmd.getKeyword();
final CPU.CPUArch arch = cmd.getArch();
zoneId = _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), zoneId);
final Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
@ -1286,6 +1287,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
sb.and("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ);
sb.and("clusterType", sb.entity().getClusterType(), SearchCriteria.Op.EQ);
sb.and("allocationState", sb.entity().getAllocationState(), SearchCriteria.Op.EQ);
sb.and("arch", sb.entity().getArch(), SearchCriteria.Op.EQ);
final SearchCriteria<ClusterVO> sc = sb.create();
if (id != null) {
@ -1325,6 +1327,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
}
if (arch != null) {
sc.setParameters("arch", arch);
}
final Pair<List<ClusterVO>, Integer> result = _clusterDao.searchAndCount(sc, searchFilter);
return new Pair<>(result.first(), result.second());
}
@ -4182,6 +4188,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
final Long podId = cmd.getPodId();
final Long hostId = cmd.getHostId();
final Long storageId = cmd.getStorageId();
final CPU.CPUArch arch = cmd.getArch();
final Filter searchFilter = new Filter(VMInstanceVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
final SearchBuilder<VMInstanceVO> sb = _vmInstanceDao.createSearchBuilder();
@ -4208,6 +4215,13 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
}
boolean templateJoinNeeded = arch != null;
if (templateJoinNeeded) {
SearchBuilder<VMTemplateVO> templateSearch = templateDao.createSearchBuilder();
templateSearch.and("templateArch", templateSearch.entity().getArch(), SearchCriteria.Op.EQ);
sb.join("vmTemplate", templateSearch, templateSearch.entity().getId(), sb.entity().getTemplateId(), JoinBuilder.JoinType.INNER);
}
final SearchCriteria<VMInstanceVO> sc = sb.create();
if (keyword != null) {
@ -4255,6 +4269,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
}
}
if (arch != null) {
sc.setJoinParameters("vmTemplate", "templateArch", arch);
}
final Pair<List<VMInstanceVO>, Integer> result = _vmInstanceDao.searchAndCount(sc, searchFilter);
return new Pair<>(result.first(), result.second());
}

View File

@ -178,6 +178,7 @@ import com.cloud.configuration.Config;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.configuration.ConfigurationManagerImpl;
import com.cloud.configuration.Resource.ResourceType;
import com.cloud.cpu.CPU;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VsphereStoragePolicyVO;
@ -3585,17 +3586,49 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
return (ImageStore)_dataStoreMgr.getDataStore(store.getId(), DataStoreRole.Image);
}
protected void registerSystemVmTemplateForHypervisorArch(final HypervisorType hypervisorType,
final CPU.CPUArch arch, final Long zoneId, final String url, final DataStore store,
final SystemVmTemplateRegistration systemVmTemplateRegistration, final String filePath,
final Pair<String, Long> storeUrlAndId, final String nfsVersion) {
if (HypervisorType.Simulator.equals(hypervisorType)) {
return;
}
String templateName = getValidTemplateName(zoneId, hypervisorType);
VMTemplateVO registeredTemplate = systemVmTemplateRegistration.getRegisteredTemplate(templateName, arch);
TemplateDataStoreVO templateDataStoreVO = null;
if (registeredTemplate != null) {
templateDataStoreVO = _templateStoreDao.findByStoreTemplate(store.getId(), registeredTemplate.getId());
if (templateDataStoreVO != null) {
try {
if (systemVmTemplateRegistration.validateIfSeeded(templateDataStoreVO, url,
templateDataStoreVO.getInstallPath(), nfsVersion)) {
return;
}
} catch (Exception e) {
logger.error("Failed to validated if template is seeded", e);
}
}
}
SystemVmTemplateRegistration.mountStore(storeUrlAndId.first(), filePath, nfsVersion);
if (templateDataStoreVO != null) {
systemVmTemplateRegistration.validateAndRegisterTemplate(hypervisorType, templateName,
storeUrlAndId.second(), registeredTemplate, templateDataStoreVO, filePath);
} else {
systemVmTemplateRegistration.validateAndRegisterTemplateForNonExistingEntries(hypervisorType, arch,
templateName, storeUrlAndId, filePath);
}
}
private void registerSystemVmTemplateOnFirstNfsStore(Long zoneId, String providerName, String url, DataStore store) {
if (DataStoreProvider.NFS_IMAGE.equals(providerName) && zoneId != null) {
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(final TransactionStatus status) {
List<ImageStoreVO> stores = _imageStoreDao.listAllStoresInZone(zoneId, providerName, DataStoreRole.Image);
stores = stores.stream().filter(str -> str.getId() != store.getId()).collect(Collectors.toList());
// Check if it's the only/first store in the zone
if (stores.size() == 0) {
List<HypervisorType> hypervisorTypes = _clusterDao.getAvailableHypervisorInZone(zoneId);
Set<HypervisorType> hypSet = new HashSet<>(hypervisorTypes);
List<ImageStoreVO> stores = _imageStoreDao.listAllStoresInZoneExceptId(zoneId, providerName,
DataStoreRole.Image, store.getId());
if (CollectionUtils.isEmpty(stores)) {
List<Pair<HypervisorType, CPU.CPUArch>> hypervisorTypes =
_clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId);
TransactionLegacy txn = TransactionLegacy.open("AutomaticTemplateRegister");
SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration();
String filePath = null;
@ -3606,40 +3639,15 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
}
Pair<String, Long> storeUrlAndId = new Pair<>(url, store.getId());
String nfsVersion = imageStoreDetailsUtil.getNfsVersion(store.getId());
for (HypervisorType hypervisorType : hypSet) {
for (Pair<HypervisorType, CPU.CPUArch> hypervisorArchType : hypervisorTypes) {
try {
if (HypervisorType.Simulator == hypervisorType) {
continue;
}
String templateName = getValidTemplateName(zoneId, hypervisorType);
Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName =
new Pair<>(hypervisorType, templateName);
Long templateId = systemVmTemplateRegistration.getRegisteredTemplateId(hypervisorAndTemplateName);
VMTemplateVO vmTemplateVO = null;
TemplateDataStoreVO templateVO = null;
if (templateId != null) {
vmTemplateVO = _templateDao.findById(templateId);
templateVO = _templateStoreDao.findByStoreTemplate(store.getId(), templateId);
if (templateVO != null) {
try {
if (systemVmTemplateRegistration.validateIfSeeded(
templateVO, url, templateVO.getInstallPath(), nfsVersion)) {
continue;
}
} catch (Exception e) {
logger.error("Failed to validated if template is seeded", e);
}
}
}
SystemVmTemplateRegistration.mountStore(storeUrlAndId.first(), filePath, nfsVersion);
if (templateVO != null && vmTemplateVO != null) {
systemVmTemplateRegistration.registerTemplate(hypervisorAndTemplateName, storeUrlAndId, vmTemplateVO, templateVO, filePath);
} else {
systemVmTemplateRegistration.registerTemplate(hypervisorAndTemplateName, storeUrlAndId, filePath);
}
registerSystemVmTemplateForHypervisorArch(hypervisorArchType.first(),
hypervisorArchType.second(), zoneId, url, store,
systemVmTemplateRegistration, filePath, storeUrlAndId, nfsVersion);
} catch (CloudRuntimeException e) {
SystemVmTemplateRegistration.unmountStore(filePath);
logger.error(String.format("Failed to register systemVM template for hypervisor: %s", hypervisorType.name()), e);
logger.error("Failed to register system VM template for hypervisor: {} {}",
hypervisorArchType.first().name(), hypervisorArchType.second().name(), e);
}
}
} catch (Exception e) {

View File

@ -21,6 +21,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.inject.Inject;
@ -243,7 +244,11 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
List<VMTemplateVO> systemvmTmplts = _tmpltDao.listAllSystemVMTemplates();
for (VMTemplateVO template : systemvmTmplts) {
if (template.getName().equalsIgnoreCase(name) || template.getDisplayText().equalsIgnoreCase(displayText)) {
if ((template.getName().equalsIgnoreCase(name) ||
template.getDisplayText().equalsIgnoreCase(displayText)) &&
Objects.equals(template.getArch(), arch)) {
logger.error("{} for same arch {} is having same name or description", template,
template.getArch());
throw new IllegalArgumentException("Cannot use reserved names for templates");
}
}

View File

@ -2839,6 +2839,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
final List<String> userDenyListedSettings = Stream.of(QueryService.UserVMDeniedDetails.value().split(","))
.map(item -> (item).trim())
.collect(Collectors.toList());
userDenyListedSettings.addAll(QueryService.RootAdminOnlyVmSettings);
final List<String> userReadOnlySettings = Stream.of(QueryService.UserVMReadOnlyDetails.value().split(","))
.map(item -> (item).trim())
.collect(Collectors.toList());

View File

@ -0,0 +1,107 @@
// 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.consoleproxy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.vm.ConsoleProxyVO;
import com.cloud.vm.dao.ConsoleProxyDao;
@RunWith(MockitoJUnitRunner.class)
public class ConsoleProxyManagerImplTest {
@InjectMocks
private ConsoleProxyManagerImpl consoleProxyManager;
@Mock
private ConsoleProxyDao consoleProxyDao;
@Mock
private AccountManager accountManager;
@Mock
private ServiceOffering serviceOffering;
@Mock
private VMTemplateVO template;
@Mock
private Account systemAccount;
@Mock
private User systemUser;
@Before
public void setUp() {
when(accountManager.getSystemUser()).thenReturn(systemUser);
}
@Test
public void testCreateConsoleProxy_New() {
long dataCenterId = 1L;
long id = 10L;
String name = "console1";
// When creating a new proxy, persist should be called.
when(consoleProxyDao.persist(any(ConsoleProxyVO.class)))
.thenAnswer(invocation -> invocation.getArgument(0));
ConsoleProxyVO result = consoleProxyManager.createOrUpdateConsoleProxy(null, dataCenterId, id, name, serviceOffering, template, systemAccount);
assertNotNull(result);
assertEquals(id, result.getId());
assertEquals(serviceOffering.getId(), result.getServiceOfferingId());
assertEquals(name, result.getName());
assertEquals(template.getId(), result.getTemplateId());
assertEquals(template.getHypervisorType(), result.getHypervisorType());
assertEquals(template.getGuestOSId(), result.getGuestOSId());
assertEquals(dataCenterId, result.getDataCenterId());
assertEquals(systemAccount.getDomainId(), result.getDomainId());
assertEquals(systemAccount.getId(), result.getAccountId());
assertEquals(serviceOffering.isOfferHA(), result.isHaEnabled());
assertEquals(template.isDynamicallyScalable(), result.isDynamicallyScalable());
assertEquals(serviceOffering.getLimitCpuUse(), result.limitCpuUse());
verify(consoleProxyDao).persist(any(ConsoleProxyVO.class));
}
@Test
public void testUpdateConsoleProxy() {
long dataCenterId = 1L;
long id = 10L;
String name = "console1";
ConsoleProxyVO existing = new ConsoleProxyVO(id, serviceOffering.getId(), name, 999L, Hypervisor.HypervisorType.KVM, 111L,
dataCenterId, systemAccount.getDomainId(), systemAccount.getId(),
systemUser.getId(), 0, serviceOffering.isOfferHA());
existing.setDynamicallyScalable(false);
ConsoleProxyVO result = consoleProxyManager.createOrUpdateConsoleProxy(existing, dataCenterId, id, name, serviceOffering, template, systemAccount);
verify(consoleProxyDao).update(existing.getId(), existing);
assertEquals(template.getId(), result.getTemplateId());
assertEquals(template.getHypervisorType(), result.getHypervisorType());
assertEquals(template.getGuestOSId(), result.getGuestOSId());
assertEquals(template.isDynamicallyScalable(), result.isDynamicallyScalable());
}
}

View File

@ -16,27 +16,11 @@
// under the License.
package com.cloud.network.router;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.manager.Commands;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkDao;
import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
@ -45,6 +29,34 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.Command;
import com.cloud.agent.manager.Commands;
import com.cloud.exception.AgentUnavailableException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.NetworkModel;
import com.cloud.network.VirtualRouterProvider;
import com.cloud.network.dao.NetworkDao;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.VirtualMachineName;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
@RunWith(MockitoJUnitRunner.class)
public class NetworkHelperImplTest {
@ -54,6 +66,9 @@ public class NetworkHelperImplTest {
@Mock
protected AgentManager agentManager;
@Mock
DomainRouterDao routerDao;
@InjectMocks
protected NetworkHelperImpl nwHelper = new NetworkHelperImpl();
@Mock
@ -65,10 +80,27 @@ public class NetworkHelperImplTest {
@Mock
NicDao nicDao;
@Mock
private RouterDeploymentDefinition routerDeploymentDefinition;
@Mock
private VirtualRouterProvider virtualProvider;
@Mock
private Account owner;
@Mock
private ServiceOfferingVO routerOffering;
@Mock
private VMTemplateVO template;
@Before
public void setUp() {
nwHelper._networkDao = networkDao;
nwHelper._networkModel = networkModel;
when(template.getId()).thenReturn(1L);
when(template.isDynamicallyScalable()).thenReturn(true);
when(virtualProvider.getId()).thenReturn(1L);
when(routerDeploymentDefinition.getVirtualProvider()).thenReturn(virtualProvider);
when(routerDeploymentDefinition.isRedundant()).thenReturn(true);
when(routerOffering.getLimitCpuUse()).thenReturn(true);
}
@Test(expected=ResourceUnavailableException.class)
@ -83,7 +115,7 @@ public class NetworkHelperImplTest {
nwHelperUT.sendCommandsToRouter(vr, null);
// Assert
verify(this.agentManager, times(0)).send((Long) ArgumentMatchers.any(), (Command) ArgumentMatchers.any());
verify(this.agentManager, times(0)).send((Long) any(), (Command) any());
}
@Test
@ -187,4 +219,53 @@ public class NetworkHelperImplTest {
verify(answer1, times(0)).getResult();
assertFalse(result);
}
@Test
public void testCreateDomainRouter_New() {
long id = 1L;
long userId = 800L;
boolean offerHA = false;
Long vpcId = 900L;
when(routerDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
DomainRouterVO result = nwHelper.createOrUpdateDomainRouter(
null, id, routerDeploymentDefinition, owner, userId, routerOffering, offerHA, vpcId, template);
assertNotNull(result);
assertEquals(id, result.getId());
assertEquals(routerOffering.getId(), result.getServiceOfferingId());
assertEquals(1L, result.getElementId());
assertEquals(VirtualMachineName.getRouterName(id, NetworkHelperImpl.s_vmInstanceName), result.getInstanceName());
assertEquals(template.getId(), result.getTemplateId());
assertEquals(template.getHypervisorType(), result.getHypervisorType());
assertEquals(template.getGuestOSId(), result.getGuestOSId());
assertEquals(owner.getDomainId(), result.getDomainId());
assertEquals(owner.getId(), result.getAccountId());
assertEquals(userId, result.getUserId());
assertTrue(result.getIsRedundantRouter());
assertEquals(VirtualRouter.RedundantState.UNKNOWN, result.getRedundantState());
assertEquals(offerHA, result.isHaEnabled());
assertEquals(vpcId, result.getVpcId());
assertTrue(result.isDynamicallyScalable());
assertEquals(VirtualRouter.Role.VIRTUAL_ROUTER, result.getRole());
assertTrue(result.limitCpuUse());
verify(routerDao).persist(any(DomainRouterVO.class));
}
@Test
public void testUpdateDomainRouter() {
long id = 1L;
long userId = 800L;
boolean offerHA = false;
Long vpcId = 900L;
DomainRouterVO existing = new DomainRouterVO(id, routerOffering.getId(), virtualProvider.getId(),
VirtualMachineName.getRouterName(id, NetworkHelperImpl.s_vmInstanceName), 999L, Hypervisor.HypervisorType.KVM, 888L,
owner.getDomainId(), owner.getId(), userId, routerDeploymentDefinition.isRedundant(), VirtualRouter.RedundantState.UNKNOWN,
offerHA, false, vpcId);
existing.setDynamicallyScalable(false);
DomainRouterVO result = nwHelper.createOrUpdateDomainRouter(
existing, id, routerDeploymentDefinition, owner, userId, routerOffering, offerHA, vpcId, template);
verify(routerDao).update(existing.getId(), existing);
assertEquals(template.getId(), result.getTemplateId());
assertEquals(Hypervisor.HypervisorType.KVM, result.getHypervisorType());
assertTrue(result.isDynamicallyScalable());
}
}

View File

@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -618,6 +619,25 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
return defaultNetworks.get(0);
}
protected SecondaryStorageVmVO createOrUpdateSecondaryStorageVm(SecondaryStorageVmVO ssvm, long dataCenterId,
long id, String name, ServiceOffering serviceOffering, VMTemplateVO template, Account systemAccount,
SecondaryStorageVm.Role role) {
if (ssvm == null) {
ssvm = new SecondaryStorageVmVO(id, serviceOffering.getId(), name, template.getId(),
template.getHypervisorType(), template.getGuestOSId(), dataCenterId, systemAccount.getDomainId(),
systemAccount.getId(), _accountMgr.getSystemUser().getId(), role, serviceOffering.isOfferHA());
ssvm.setDynamicallyScalable(template.isDynamicallyScalable());
ssvm.setLimitCpuUse(serviceOffering.getLimitCpuUse());
return _secStorageVmDao.persist(ssvm);
}
ssvm.setTemplateId(template.getId());
ssvm.setHypervisorType(template.getHypervisorType());
ssvm.setGuestOSId(template.getGuestOSId());
ssvm.setDynamicallyScalable(template.isDynamicallyScalable());
_secStorageVmDao.update(ssvm.getId(), ssvm);
return ssvm;
}
protected Map<String, Object> createSecStorageVmInstance(long dataCenterId, SecondaryStorageVm.Role role) {
DataStore secStore = _dataStoreMgr.getImageStoreWithFreeCapacity(dataCenterId);
if (secStore == null) {
@ -657,28 +677,33 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
}
HypervisorType availableHypervisor = _resourceMgr.getAvailableHypervisor(dataCenterId);
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, availableHypervisor);
if (template == null) {
throw new CloudRuntimeException(String.format("Unable to find the system templates or it was not downloaded in %s.", dc.toString()));
List<VMTemplateVO> templates = _templateDao.findSystemVMReadyTemplates(dataCenterId, availableHypervisor,
ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenterId));
if (CollectionUtils.isEmpty(templates)) {
throw new CloudRuntimeException(String.format("Unable to find the system templates or it was not downloaded in %s.", dc));
}
ServiceOfferingVO serviceOffering = _serviceOffering;
if (serviceOffering == null) {
serviceOffering = _offeringDao.findDefaultSystemOffering(ServiceOffering.ssvmDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
}
SecondaryStorageVmVO secStorageVm =
new SecondaryStorageVmVO(id, serviceOffering.getId(), name, template.getId(), template.getHypervisorType(), template.getGuestOSId(), dataCenterId,
systemAcct.getDomainId(), systemAcct.getId(), _accountMgr.getSystemUser().getId(), role, serviceOffering.isOfferHA());
secStorageVm.setDynamicallyScalable(template.isDynamicallyScalable());
secStorageVm.setLimitCpuUse(serviceOffering.getLimitCpuUse());
secStorageVm = _secStorageVmDao.persist(secStorageVm);
SecondaryStorageVmVO secStorageVm = null;
for (final Iterator<VMTemplateVO> templateIterator = templates.iterator(); templateIterator.hasNext();) {
VMTemplateVO template = templateIterator.next();
secStorageVm = createOrUpdateSecondaryStorageVm(secStorageVm, dataCenterId, id, name, serviceOffering,
template, systemAcct, role);
try {
_itMgr.allocate(name, template, serviceOffering, networks, plan, null);
_itMgr.allocate(name, template, serviceOffering, networks, plan, template.getHypervisorType());
secStorageVm = _secStorageVmDao.findById(secStorageVm.getId());
_itMgr.checkDeploymentPlan(secStorageVm, template, serviceOffering, systemAcct, plan);
break;
} catch (InsufficientCapacityException e) {
String errorMessage = String.format("Unable to allocate secondary storage VM [%s] due to [%s].", name, e.getMessage());
logger.warn(errorMessage, e);
throw new CloudRuntimeException(errorMessage, e);
if (templateIterator.hasNext()) {
logger.debug("Unable to allocate secondary storage {} with {} due to [{}]. Retrying with another template", secStorageVm, template, e.getMessage(), e);
continue;
}
throw new CloudRuntimeException("Failed to allocate secondary storage VM [%s] in zone [%s] with available templates", e);
}
}
Map<String, Object> context = new HashMap<>();
@ -820,8 +845,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
}
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) {
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);
if (template == null) {
List<VMTemplateVO> templates = _templateDao.findSystemVMReadyTemplates(dataCenterId,
HypervisorType.Any, null);
if (CollectionUtils.isEmpty(templates)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("System VM template is not ready at zone [%s], wait until it is ready to launch secondary storage VM.", dataCenterId));
}
@ -834,13 +860,6 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
return false;
}
if (!template.isDirectDownload() && templateMgr.getImageStore(dataCenterId, template.getId()) == null) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("No secondary storage available in zone [%s], wait until it is ready to launch secondary storage VM.", dataCenterId));
}
return false;
}
boolean useLocalStorage = BooleanUtils.toBoolean(ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
boolean hasStoragePoolHostInfo = _storagePoolHostDao.hasDatacenterStoragePoolHostInfo(dataCenterId, !useLocalStorage);
if (hasStoragePoolHostInfo) {

View File

@ -16,39 +16,69 @@
// under the License.
package org.apache.cloudstack.secondarystorage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import com.cloud.agent.api.to.DataStoreTO;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.VMTemplateVO;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.User;
import com.cloud.utils.net.NetUtils;
import com.cloud.vm.SecondaryStorageVm;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.google.common.net.InetAddresses;
@RunWith(MockitoJUnitRunner.class)
public class SecondaryStorageManagerImplTest {
private final SecureRandom secureRandom = new SecureRandom();
@Mock
private SecondaryStorageVmDao secStorageVmDao;
@Mock
private AccountManager accountManager;
@Spy
@InjectMocks
private SecondaryStorageManagerImpl secondaryStorageManager;
@Mock
private ServiceOffering serviceOffering;
@Mock
private VMTemplateVO template;
@Mock
private Account systemAccount;
@Mock
private User systemUser;
private List<DataStore> mockDataStoresForTestAddSecondaryStorageServerAddressToBuffer(List<String> addresses) {
List<DataStore> dataStores = new ArrayList<>();
for (String address: addresses) {
DataStore dataStore = Mockito.mock(DataStore.class);
DataStoreTO dataStoreTO = Mockito.mock(DataStoreTO.class);
Mockito.when(dataStoreTO.getUrl()).thenReturn(NetUtils.isValidIp4(address) ? String.format("http://%s", address) : address);
Mockito.when(dataStore.getTO()).thenReturn(dataStoreTO);
when(dataStoreTO.getUrl()).thenReturn(NetUtils.isValidIp4(address) ? String.format("http://%s", address) : address);
when(dataStore.getTO()).thenReturn(dataStoreTO);
dataStores.add(dataStore);
}
return dataStores;
@ -60,7 +90,7 @@ public class SecondaryStorageManagerImplTest {
secondaryStorageManager.addSecondaryStorageServerAddressToBuffer(builder, dataStores, "VM");
String result = builder.toString();
result = result.contains("=") ? result.split("=")[1] : null;
Assert.assertEquals(expected, result);
assertEquals(expected, result);
}
@Test
@ -86,4 +116,55 @@ public class SecondaryStorageManagerImplTest {
List<String> addresses = List.of(randomIp1, "garbage", randomIp2);
runAddSecondaryStorageServerAddressToBufferTest(addresses, StringUtils.join(List.of(randomIp1, randomIp2), ","));
}
@Test
public void testCreateSecondaryStorageVm_New() {
long dataCenterId = 1L;
long id = 100L;
String name = "ssvm1";
SecondaryStorageVm.Role role = SecondaryStorageVm.Role.templateProcessor;
when(systemUser.getId()).thenReturn(1L);
when(accountManager.getSystemUser()).thenReturn(systemUser);
when(secStorageVmDao.persist(any(SecondaryStorageVmVO.class)))
.thenAnswer(invocation -> invocation.getArgument(0));
SecondaryStorageVmVO result = secondaryStorageManager.createOrUpdateSecondaryStorageVm(
null, dataCenterId, id, name, serviceOffering, template, systemAccount, role);
assertNotNull(result);
assertEquals(id, result.getId());
assertEquals(serviceOffering.getId(), result.getServiceOfferingId());
assertEquals(name, result.getName());
assertEquals(template.getId(), result.getTemplateId());
assertEquals(template.getHypervisorType(), result.getHypervisorType());
assertEquals(template.getGuestOSId(), result.getGuestOSId());
assertEquals(dataCenterId, result.getDataCenterId());
assertEquals(systemAccount.getDomainId(), result.getDomainId());
assertEquals(systemAccount.getId(), result.getAccountId());
assertEquals(role, result.getRole());
assertEquals(template.isDynamicallyScalable(), result.isDynamicallyScalable());
assertEquals(serviceOffering.getLimitCpuUse(), result.limitCpuUse());
verify(secStorageVmDao).persist(any(SecondaryStorageVmVO.class));
}
@Test
public void testUpdateSecondaryStorageVm() {
long dataCenterId = 1L;
long id = 100L;
String name = "ssvm1";
SecondaryStorageVm.Role role = SecondaryStorageVm.Role.commandExecutor;
SecondaryStorageVmVO existing = new SecondaryStorageVmVO(id, serviceOffering.getId(), name,
999L, Hypervisor.HypervisorType.KVM, 888L, dataCenterId, systemAccount.getDomainId(), systemAccount.getId(),
systemUser.getId(), role, serviceOffering.isOfferHA());
existing.setDynamicallyScalable(false);
SecondaryStorageVmVO result = secondaryStorageManager.createOrUpdateSecondaryStorageVm(
existing, dataCenterId, id, name, serviceOffering, template, systemAccount, role);
assertNotNull(result);
assertEquals(template.getId(), result.getTemplateId());
assertEquals(template.getHypervisorType(), result.getHypervisorType());
assertEquals(template.getGuestOSId(), result.getGuestOSId());
assertEquals(template.isDynamicallyScalable(), result.isDynamicallyScalable());
verify(secStorageVmDao).update(existing.getId(), existing);
}
}

View File

@ -43,6 +43,7 @@ CREATE TABLE `simulator`.`mockhost` (
`cpus` int(10) unsigned,
`speed` int(10) unsigned,
`ram` bigint unsigned,
`arch` varchar(8) DEFAULT "x86_64" COMMENT "the CPU architecture of the host",
`capabilities` varchar(255) COMMENT 'host capabilities in comma separated list',
`vm_id` bigint unsigned,
`resource` varchar(255) DEFAULT NULL COMMENT 'If it is a local resource, this is the class name',

View File

@ -24,13 +24,7 @@ from marvin.lib.common import list_hosts
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from OpenSSL.crypto import FILETYPE_PEM, verify, X509
PUBKEY_VERIFY=True
try:
from OpenSSL.crypto import load_publickey
except ImportError:
PUBKEY_VERIFY=False
from cryptography.hazmat.primitives.asymmetric import padding
class TestCARootProvider(cloudstackTestCase):
@ -52,6 +46,20 @@ class TestCARootProvider(cloudstackTestCase):
raise Exception("Warning: Exception during cleanup : %s" % e)
def verifySignature(self, caCert, cert):
print("Verifying Certificate")
caPublicKey = caCert.public_key()
try:
caPublicKey.verify(
cert.signature,
cert.tbs_certificate_bytes,
padding.PKCS1v15(),
cert.signature_hash_algorithm,
)
print("Certificate is valid!")
except Exception as e:
print(f"Certificate verification failed: {e}")
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
@ -136,13 +144,8 @@ class TestCARootProvider(cloudstackTestCase):
self.assertTrue(address in [str(x) for x in altNames.value.get_values_for_type(x509.IPAddress)])
# Validate certificate against CA public key
global PUBKEY_VERIFY
if not PUBKEY_VERIFY:
return
caCert = x509.load_pem_x509_certificate(self.getCaCertificate().encode(), default_backend())
x = X509()
x.set_pubkey(load_publickey(FILETYPE_PEM, caCert.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo)))
verify(x, cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm.name)
self.verifySignature(caCert, cert)
@attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)
@ -165,13 +168,8 @@ class TestCARootProvider(cloudstackTestCase):
self.assertEqual(cert.subject.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value, 'v-1-VM')
# Validate certificate against CA public key
global PUBKEY_VERIFY
if not PUBKEY_VERIFY:
return
caCert = x509.load_pem_x509_certificate(self.getCaCertificate().encode(), default_backend())
x = X509()
x.set_pubkey(load_publickey(FILETYPE_PEM, caCert.public_key().public_bytes(serialization.Encoding.PEM, serialization.PublicFormat.SubjectPublicKeyInfo)))
verify(x, cert.signature, cert.tbs_certificate_bytes, cert.signature_hash_algorithm.name)
self.verifySignature(caCert, cert)
@attr(tags=['advanced', 'simulator', 'basic', 'sg'], required_hardware=False)

View File

@ -23,11 +23,12 @@ import logging
import time
from collections.abc import Iterable
from marvin.codes import FAILED
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.cloudstackAPI import (migrateSystemVm, listRouters, listSystemVms)
from marvin.lib.base import (Cluster, Configurations, Host, Network, NetworkOffering, ServiceOffering, VirtualMachine,
Zone)
from marvin.lib.common import (get_domain, get_zone, get_template)
from marvin.lib.common import (get_domain, get_zone, get_test_template)
from marvin.lib.utils import wait_until
from marvin import jsonHelper
from nose.plugins.attrib import attr
@ -43,7 +44,15 @@ class TestClusterDRS(cloudstackTestCase):
zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests())
cls.zone = Zone(zone.__dict__)
cls.template = get_template(cls.apiclient, cls.zone.id)
cls.hypervisor = cls.testClient.getHypervisorInfo()
cls.template = get_test_template(
cls.apiclient,
cls.zone.id,
cls.hypervisor
)
if cls.template == FAILED:
assert False, "get_test_template() failed to return template\
with hypervisor %s" % cls.hypervisor
cls._cleanup = []
cls.logger = logging.getLogger("TestClusterDRS")

View File

@ -74,7 +74,6 @@ class TestData(object):
"listApis": "allow",
"listAccounts": "allow",
"listClusters": "deny",
"*VmwareDc*": "allow",
"*VM*": "allow",
"*Host*": "deny"
}

Some files were not shown because too many files have changed in this diff Show More