mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
api,ui: multi arch improvements (#10289)
This commit is contained in:
parent
1adfaf90ad
commit
12c077d704
@ -16,52 +16,55 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.cpu;
|
package com.cloud.cpu;
|
||||||
|
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class CPU {
|
public class CPU {
|
||||||
|
public enum CPUArch {
|
||||||
|
x86("i686", 32),
|
||||||
|
amd64("x86_64", 64),
|
||||||
|
arm64("aarch64", 64);
|
||||||
|
|
||||||
public static final String archX86Identifier = "i686";
|
private final String type;
|
||||||
public static final String archX86_64Identifier = "x86_64";
|
private final int bits;
|
||||||
public static final String archARM64Identifier = "aarch64";
|
|
||||||
|
|
||||||
public static class CPUArch {
|
CPUArch(String type, int bits) {
|
||||||
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) {
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.bits = bits;
|
this.bits = bits;
|
||||||
cpuArchMap.put(type, this);
|
}
|
||||||
|
|
||||||
|
public static CPUArch getDefault() {
|
||||||
|
return amd64;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return this.type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBits() {
|
public int getBits() {
|
||||||
return this.bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CPUArch fromType(String type) {
|
public static CPUArch fromType(String type) {
|
||||||
if (StringUtils.isBlank(type)) {
|
if (StringUtils.isBlank(type)) {
|
||||||
return amd64;
|
return getDefault();
|
||||||
}
|
}
|
||||||
switch (type) {
|
for (CPUArch arch : values()) {
|
||||||
case archX86Identifier: return archX86;
|
if (arch.type.equals(type)) {
|
||||||
case archX86_64Identifier: return amd64;
|
return arch;
|
||||||
case archARM64Identifier: return arm64;
|
|
||||||
default: throw new CloudRuntimeException(String.format("Unsupported arch type: %s", type));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.cluster;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.cloudstack.api.APICommand;
|
import org.apache.cloudstack.api.APICommand;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
import org.apache.cloudstack.api.BaseListCmd;
|
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.ListResponse;
|
||||||
import org.apache.cloudstack.api.response.PodResponse;
|
import org.apache.cloudstack.api.response.PodResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
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.org.Cluster;
|
||||||
import com.cloud.utils.Pair;
|
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")
|
@Parameter(name = ApiConstants.SHOW_CAPACITIES, type = CommandType.BOOLEAN, description = "flag to display the capacity of the clusters")
|
||||||
private Boolean showCapacities;
|
private Boolean showCapacities;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
|
||||||
|
description = "CPU arch of the clusters",
|
||||||
|
since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -112,6 +118,10 @@ public class ListClustersCmd extends BaseListCmd {
|
|||||||
return showCapacities;
|
return showCapacities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -21,7 +21,6 @@ import java.util.EnumSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.cloudstack.api.APICommand;
|
import org.apache.cloudstack.api.APICommand;
|
||||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
@ -34,7 +33,9 @@ import org.apache.cloudstack.api.response.ListResponse;
|
|||||||
import org.apache.cloudstack.api.response.PodResponse;
|
import org.apache.cloudstack.api.response.PodResponse;
|
||||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
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.exception.InvalidParameterValueException;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
@ -105,6 +106,9 @@ public class ListHostsCmd extends BaseListCmd {
|
|||||||
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "hypervisor type of host: XenServer,KVM,VMware,Hyperv,BareMetal,Simulator")
|
@Parameter(name = ApiConstants.HYPERVISOR, type = CommandType.STRING, description = "hypervisor type of host: XenServer,KVM,VMware,Hyperv,BareMetal,Simulator")
|
||||||
private String hypervisor;
|
private String hypervisor;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING, description = "CPU Arch of the host", since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -189,6 +193,10 @@ public class ListHostsCmd extends BaseListCmd {
|
|||||||
return outOfBandManagementPowerState;
|
return outOfBandManagementPowerState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -16,8 +16,6 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.api.command.admin.router;
|
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.APICommand;
|
||||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
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.UserVmResponse;
|
||||||
import org.apache.cloudstack.api.response.VpcResponse;
|
import org.apache.cloudstack.api.response.VpcResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
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.network.router.VirtualRouter.Role;
|
||||||
import com.cloud.vm.VirtualMachine;
|
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")
|
description = "if true is passed for this parameter, also fetch last executed health check results for the router. Default is false")
|
||||||
private Boolean fetchHealthCheckResults;
|
private Boolean fetchHealthCheckResults;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
|
||||||
|
description = "CPU arch of the router",
|
||||||
|
since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -146,6 +152,10 @@ public class ListRoutersCmd extends BaseListProjectAndAccountResourcesCmd {
|
|||||||
return BooleanUtils.isTrue(fetchHealthCheckResults);
|
return BooleanUtils.isTrue(fetchHealthCheckResults);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
|
|||||||
@ -19,7 +19,6 @@ package org.apache.cloudstack.api.command.admin.systemvm;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.cloudstack.api.APICommand;
|
import org.apache.cloudstack.api.APICommand;
|
||||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
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.StoragePoolResponse;
|
||||||
import org.apache.cloudstack.api.response.SystemVmResponse;
|
import org.apache.cloudstack.api.response.SystemVmResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
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.utils.Pair;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
|
|
||||||
@ -74,6 +75,11 @@ public class ListSystemVMsCmd extends BaseListCmd {
|
|||||||
since = "3.0.1")
|
since = "3.0.1")
|
||||||
private Long storageId;
|
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 ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -110,6 +116,10 @@ public class ListSystemVMsCmd extends BaseListCmd {
|
|||||||
return storageId;
|
return storageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -46,9 +46,11 @@ import org.apache.cloudstack.api.response.UserResponse;
|
|||||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
import org.apache.cloudstack.api.response.UserVmResponse;
|
||||||
import org.apache.cloudstack.api.response.VpcResponse;
|
import org.apache.cloudstack.api.response.VpcResponse;
|
||||||
import org.apache.cloudstack.api.response.ZoneResponse;
|
import org.apache.cloudstack.api.response.ZoneResponse;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
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.exception.InvalidParameterValueException;
|
||||||
import com.cloud.server.ResourceIcon;
|
import com.cloud.server.ResourceIcon;
|
||||||
import com.cloud.server.ResourceTag;
|
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")
|
@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;
|
private Long userdataId;
|
||||||
|
|
||||||
|
@Parameter(name = ApiConstants.ARCH, type = CommandType.STRING,
|
||||||
|
description = "CPU arch of the VM",
|
||||||
|
since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -292,6 +299,10 @@ public class ListVMsCmd extends BaseListRetrieveOnlyResourceCountCmd implements
|
|||||||
return isVnf;
|
return isVnf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return StringUtils.isBlank(arch) ? null : CPU.CPUArch.fromType(arch);
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|||||||
@ -245,6 +245,10 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
|
|||||||
@Param(description = "the version of the code / software in the router")
|
@Param(description = "the version of the code / software in the router")
|
||||||
private String softwareVersion;
|
private String softwareVersion;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ARCH)
|
||||||
|
@Param(description = "CPU arch of the router", since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
public DomainRouterResponse() {
|
public DomainRouterResponse() {
|
||||||
nics = new LinkedHashSet<NicResponse>();
|
nics = new LinkedHashSet<NicResponse>();
|
||||||
}
|
}
|
||||||
@ -518,4 +522,8 @@ public class DomainRouterResponse extends BaseResponseWithAnnotations implements
|
|||||||
public void setSoftwareVersion(String softwareVersion) {
|
public void setSoftwareVersion(String softwareVersion) {
|
||||||
this.softwareVersion = softwareVersion;
|
this.softwareVersion = softwareVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setArch(String arch) {
|
||||||
|
this.arch = arch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -186,6 +186,10 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
|
|||||||
@Param(description = "the name of the service offering of the system virtual machine.")
|
@Param(description = "the name of the service offering of the system virtual machine.")
|
||||||
private String serviceOfferingName;
|
private String serviceOfferingName;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ARCH)
|
||||||
|
@Param(description = "CPU arch of the system VM", since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getObjectId() {
|
public String getObjectId() {
|
||||||
return this.getId();
|
return this.getId();
|
||||||
@ -490,4 +494,8 @@ public class SystemVmResponse extends BaseResponseWithAnnotations {
|
|||||||
public void setServiceOfferingName(String serviceOfferingName) {
|
public void setServiceOfferingName(String serviceOfferingName) {
|
||||||
this.serviceOfferingName = serviceOfferingName;
|
this.serviceOfferingName = serviceOfferingName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setArch(String arch) {
|
||||||
|
this.arch = arch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,13 +31,13 @@ import org.apache.cloudstack.affinity.AffinityGroupResponse;
|
|||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
|
import org.apache.cloudstack.api.BaseResponseWithTagInformation;
|
||||||
import org.apache.cloudstack.api.EntityReference;
|
import org.apache.cloudstack.api.EntityReference;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
import com.cloud.network.router.VirtualRouter;
|
import com.cloud.network.router.VirtualRouter;
|
||||||
import com.cloud.serializer.Param;
|
import com.cloud.serializer.Param;
|
||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@EntityReference(value = {VirtualMachine.class, UserVm.class, VirtualRouter.class})
|
@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")
|
@Param(description = "User VM type", since = "4.20.0")
|
||||||
private String vmType;
|
private String vmType;
|
||||||
|
|
||||||
|
@SerializedName(ApiConstants.ARCH)
|
||||||
|
@Param(description = "CPU arch of the VM", since = "4.20.1")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
public UserVmResponse() {
|
public UserVmResponse() {
|
||||||
securityGroupList = new LinkedHashSet<>();
|
securityGroupList = new LinkedHashSet<>();
|
||||||
nics = new TreeSet<>(Comparator.comparingInt(x -> Integer.parseInt(x.getDeviceId())));
|
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) {
|
public void setIpAddress(String ipAddress) {
|
||||||
this.ipAddress = ipAddress;
|
this.ipAddress = ipAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArch(String arch) {
|
||||||
|
this.arch = arch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
67
api/src/test/java/com/cloud/cpu/CPUTest.java
Normal file
67
api/src/test/java/com/cloud/cpu/CPUTest.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
2
debian/cloudstack-management.postinst
vendored
2
debian/cloudstack-management.postinst
vendored
@ -56,6 +56,8 @@ if [ "$1" = configure ]; then
|
|||||||
chmod 0640 ${CONFDIR}/${DBPROPS}
|
chmod 0640 ${CONFDIR}/${DBPROPS}
|
||||||
chgrp cloud ${CONFDIR}/${DBPROPS}
|
chgrp cloud ${CONFDIR}/${DBPROPS}
|
||||||
chown -R cloud:cloud /var/log/cloudstack/management
|
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
|
ln -sf ${CONFDIR}/log4j-cloud.xml ${CONFDIR}/log4j2.xml
|
||||||
|
|
||||||
|
|||||||
@ -309,4 +309,8 @@ public interface VirtualMachineManager extends Manager {
|
|||||||
|
|
||||||
Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds);
|
Map<Long, Boolean> getDiskOfferingSuitabilityForVm(long vmId, List<Long> diskOfferingIds);
|
||||||
|
|
||||||
|
void checkDeploymentPlan(VirtualMachine virtualMachine, VirtualMachineTemplate template,
|
||||||
|
ServiceOffering serviceOffering, Account systemAccount, DeploymentPlan plan)
|
||||||
|
throws InsufficientServerCapacityException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import com.cloud.agent.api.StartupCommand;
|
|||||||
import com.cloud.agent.api.StartupRoutingCommand;
|
import com.cloud.agent.api.StartupRoutingCommand;
|
||||||
import com.cloud.agent.api.VgpuTypesInfo;
|
import com.cloud.agent.api.VgpuTypesInfo;
|
||||||
import com.cloud.agent.api.to.GPUDeviceTO;
|
import com.cloud.agent.api.to.GPUDeviceTO;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.HostPodVO;
|
import com.cloud.dc.HostPodVO;
|
||||||
import com.cloud.dc.PodCluster;
|
import com.cloud.dc.PodCluster;
|
||||||
@ -61,6 +62,17 @@ public interface ResourceManager extends ResourceService, Configurable {
|
|||||||
+ "To force-stop VMs, choose 'ForceStop' strategy",
|
+ "To force-stop VMs, choose 'ForceStop' strategy",
|
||||||
true, ConfigKey.Scope.Global, null, null, null, null, null, ConfigKey.Kind.Select, "Error,Migration,ForceStop");
|
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.
|
* Register a listener for different types of resource life cycle events.
|
||||||
* There can only be one type of listener per type of host.
|
* There can only be one type of listener per type of host.
|
||||||
|
|||||||
@ -6083,4 +6083,18 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||||||
}
|
}
|
||||||
return result;
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -165,6 +165,15 @@
|
|||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<test.mode>true</test.mode>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
<profiles>
|
<profiles>
|
||||||
|
|||||||
@ -18,11 +18,11 @@ package com.cloud.dc.dao;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import com.cloud.cpu.CPU;
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.ClusterVO;
|
import com.cloud.dc.ClusterVO;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.db.GenericDao;
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
public interface ClusterDao extends GenericDao<ClusterVO, Long> {
|
public interface ClusterDao extends GenericDao<ClusterVO, Long> {
|
||||||
@ -30,13 +30,11 @@ public interface ClusterDao extends GenericDao<ClusterVO, Long> {
|
|||||||
|
|
||||||
ClusterVO findBy(String name, long podId);
|
ClusterVO findBy(String name, long podId);
|
||||||
|
|
||||||
List<ClusterVO> listByHyTypeWithoutGuid(String hyType);
|
|
||||||
|
|
||||||
List<ClusterVO> listByZoneId(long zoneId);
|
List<ClusterVO> listByZoneId(long zoneId);
|
||||||
|
|
||||||
List<HypervisorType> getAvailableHypervisorInZone(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);
|
List<ClusterVO> listByDcHyType(long dcId, String hyType);
|
||||||
|
|
||||||
|
|||||||
@ -21,10 +21,8 @@ import java.sql.ResultSet;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@ -39,6 +37,7 @@ import com.cloud.dc.HostPodVO;
|
|||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.org.Grouping;
|
import com.cloud.org.Grouping;
|
||||||
import com.cloud.org.Managed;
|
import com.cloud.org.Managed;
|
||||||
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.db.GenericDaoBase;
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
import com.cloud.utils.db.GenericSearchBuilder;
|
import com.cloud.utils.db.GenericSearchBuilder;
|
||||||
import com.cloud.utils.db.JoinBuilder;
|
import com.cloud.utils.db.JoinBuilder;
|
||||||
@ -148,14 +147,6 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
|
|||||||
return findOneBy(sc);
|
return findOneBy(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ClusterVO> listByHyTypeWithoutGuid(String hyType) {
|
|
||||||
SearchCriteria<ClusterVO> sc = HyTypeWithoutGuidSearch.create();
|
|
||||||
sc.setParameters("hypervisorType", hyType);
|
|
||||||
|
|
||||||
return listBy(sc);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ClusterVO> listByDcHyType(long dcId, String hyType) {
|
public List<ClusterVO> listByDcHyType(long dcId, String hyType) {
|
||||||
SearchCriteria<ClusterVO> sc = ZoneHyTypeSearch.create();
|
SearchCriteria<ClusterVO> sc = ZoneHyTypeSearch.create();
|
||||||
@ -178,8 +169,19 @@ public class ClusterDaoImpl extends GenericDaoBase<ClusterVO, Long> implements C
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<HypervisorType> getDistinctAvailableHypervisorsAcrossClusters() {
|
public List<Pair<HypervisorType, CPU.CPUArch>> listDistinctHypervisorsArchAcrossClusters(Long zoneId) {
|
||||||
return new HashSet<>(getAvailableHypervisorInZone(null));
|
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
|
@Override
|
||||||
|
|||||||
@ -19,6 +19,7 @@ package com.cloud.host.dao;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.host.Host.Type;
|
import com.cloud.host.Host.Type;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
@ -194,5 +195,9 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
|
|||||||
|
|
||||||
List<HypervisorType> listDistinctHypervisorTypes(final Long zoneId);
|
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);
|
List<HostVO> listByIds(final List<Long> ids);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ import com.cloud.agent.api.VgpuTypesInfo;
|
|||||||
import com.cloud.cluster.agentlb.HostTransferMapVO;
|
import com.cloud.cluster.agentlb.HostTransferMapVO;
|
||||||
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
|
import com.cloud.cluster.agentlb.dao.HostTransferMapDao;
|
||||||
import com.cloud.configuration.ManagementServiceConfiguration;
|
import com.cloud.configuration.ManagementServiceConfiguration;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.ClusterVO;
|
import com.cloud.dc.ClusterVO;
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
import com.cloud.gpu.dao.HostGpuGroupsDao;
|
||||||
@ -1743,17 +1744,52 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HypervisorType> listDistinctHypervisorTypes(final Long zoneId) {
|
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("zoneId", sb.entity().getDataCenterId(), SearchCriteria.Op.EQ);
|
||||||
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
|
sb.and("type", sb.entity().getType(), SearchCriteria.Op.EQ);
|
||||||
sb.select(null, Func.DISTINCT, sb.entity().getHypervisorType());
|
sb.select(null, Func.DISTINCT, sb.entity().getHypervisorType());
|
||||||
sb.done();
|
sb.done();
|
||||||
SearchCriteria<HypervisorType> sc = sb.create();
|
SearchCriteria<String> sc = sb.create();
|
||||||
if (zoneId != null) {
|
if (zoneId != null) {
|
||||||
sc.setParameters("zoneId", zoneId);
|
sc.setParameters("zoneId", zoneId);
|
||||||
}
|
}
|
||||||
sc.setParameters("type", Type.Routing);
|
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
|
@Override
|
||||||
|
|||||||
@ -19,6 +19,7 @@ package com.cloud.storage.dao;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
@ -73,9 +74,13 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
|
|||||||
|
|
||||||
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType);
|
VMTemplateVO findSystemVMReadyTemplate(long zoneId, HypervisorType hypervisorType);
|
||||||
|
|
||||||
|
List<VMTemplateVO> findSystemVMReadyTemplates(long zoneId, HypervisorType hypervisorType, String preferredArch);
|
||||||
|
|
||||||
VMTemplateVO findRoutingTemplate(HypervisorType type, String templateName);
|
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);
|
public Long countTemplatesForAccount(long accountId);
|
||||||
|
|
||||||
@ -87,7 +92,7 @@ public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<
|
|||||||
|
|
||||||
List<VMTemplateVO> listByParentTemplatetId(long parentTemplatetId);
|
List<VMTemplateVO> listByParentTemplatetId(long parentTemplatetId);
|
||||||
|
|
||||||
VMTemplateVO findLatestTemplateByName(String name);
|
VMTemplateVO findLatestTemplateByName(String name, CPU.CPUArch arch);
|
||||||
|
|
||||||
List<VMTemplateVO> findTemplatesLinkedToUserdata(long userdataId);
|
List<VMTemplateVO> findTemplatesLinkedToUserdata(long userdataId);
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,9 @@ package com.cloud.storage.dao;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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.TemplateDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
import com.cloud.dc.dao.DataCenterDao;
|
||||||
import com.cloud.domain.dao.DomainDao;
|
import com.cloud.domain.dao.DomainDao;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
@ -47,6 +51,7 @@ import com.cloud.storage.VMTemplateZoneVO;
|
|||||||
import com.cloud.tags.ResourceTagVO;
|
import com.cloud.tags.ResourceTagVO;
|
||||||
import com.cloud.tags.dao.ResourceTagDao;
|
import com.cloud.tags.dao.ResourceTagDao;
|
||||||
import com.cloud.template.VirtualMachineTemplate;
|
import com.cloud.template.VirtualMachineTemplate;
|
||||||
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
import com.cloud.utils.db.Filter;
|
import com.cloud.utils.db.Filter;
|
||||||
import com.cloud.utils.db.GenericDaoBase;
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
@ -111,6 +116,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||||||
LatestTemplateByHypervisorTypeSearch = createSearchBuilder();
|
LatestTemplateByHypervisorTypeSearch = createSearchBuilder();
|
||||||
LatestTemplateByHypervisorTypeSearch.and("hypervisorType", LatestTemplateByHypervisorTypeSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
LatestTemplateByHypervisorTypeSearch.and("hypervisorType", LatestTemplateByHypervisorTypeSearch.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
||||||
LatestTemplateByHypervisorTypeSearch.and("templateType", LatestTemplateByHypervisorTypeSearch.entity().getTemplateType(), 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);
|
LatestTemplateByHypervisorTypeSearch.and("removed", LatestTemplateByHypervisorTypeSearch.entity().getRemoved(), SearchCriteria.Op.NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,10 +244,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VMTemplateVO findLatestTemplateByName(String name) {
|
public VMTemplateVO findLatestTemplateByName(String name, CPU.CPUArch arch) {
|
||||||
SearchCriteria<VMTemplateVO> sc = createSearchCriteria();
|
SearchBuilder<VMTemplateVO> sb = createSearchBuilder();
|
||||||
sc.addAnd("name", SearchCriteria.Op.EQ, name);
|
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
|
||||||
sc.addAnd("removed", SearchCriteria.Op.NULL);
|
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);
|
Filter filter = new Filter(VMTemplateVO.class, "id", false, null, 1L);
|
||||||
List<VMTemplateVO> templates = listBy(sc, filter);
|
List<VMTemplateVO> templates = listBy(sc, filter);
|
||||||
if ((templates != null) && !templates.isEmpty()) {
|
if ((templates != null) && !templates.isEmpty()) {
|
||||||
@ -580,6 +592,59 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||||||
.orElse(null);
|
.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
|
@Override
|
||||||
public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) {
|
public VMTemplateVO findRoutingTemplate(HypervisorType hType, String templateName) {
|
||||||
SearchCriteria<VMTemplateVO> sc = tmpltTypeHyperSearch2.create();
|
SearchCriteria<VMTemplateVO> sc = tmpltTypeHyperSearch2.create();
|
||||||
@ -618,10 +683,43 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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();
|
SearchCriteria<VMTemplateVO> sc = LatestTemplateByHypervisorTypeSearch.create();
|
||||||
sc.setParameters("hypervisorType", hypervisorType);
|
sc.setParameters("hypervisorType", hypervisorType);
|
||||||
sc.setParameters("templateType", type);
|
sc.setParameters("templateType", type);
|
||||||
|
if (arch != null) {
|
||||||
|
sc.setParameters("arch", arch);
|
||||||
|
}
|
||||||
Filter filter = new Filter(VMTemplateVO.class, "id", false, null, 1L);
|
Filter filter = new Filter(VMTemplateVO.class, "id", false, null, 1L);
|
||||||
List<VMTemplateVO> templates = listBy(sc, filter);
|
List<VMTemplateVO> templates = listBy(sc, filter);
|
||||||
if (templates != null && !templates.isEmpty()) {
|
if (templates != null && !templates.isEmpty()) {
|
||||||
|
|||||||
@ -16,6 +16,47 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.upgrade;
|
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.DataCenterVO;
|
||||||
import com.cloud.dc.dao.ClusterDao;
|
import com.cloud.dc.dao.ClusterDao;
|
||||||
import com.cloud.dc.dao.ClusterDaoImpl;
|
import com.cloud.dc.dao.ClusterDaoImpl;
|
||||||
@ -36,6 +77,7 @@ import com.cloud.template.VirtualMachineTemplate;
|
|||||||
import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl;
|
import com.cloud.upgrade.dao.BasicTemplateDataStoreDaoImpl;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
import com.cloud.utils.DateUtil;
|
import com.cloud.utils.DateUtil;
|
||||||
|
import com.cloud.utils.HttpUtils;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.UriUtils;
|
import com.cloud.utils.UriUtils;
|
||||||
import com.cloud.utils.db.GlobalLock;
|
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.utils.script.Script;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDaoImpl;
|
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 {
|
public class SystemVmTemplateRegistration {
|
||||||
protected static Logger LOGGER = LogManager.getLogger(SystemVmTemplateRegistration.class);
|
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 UMOUNT_COMMAND = "sudo umount %s";
|
||||||
private static final String RELATIVE_TEMPLATE_PATH = "./engine/schema/dist/systemvm-templates/";
|
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/";
|
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 LINUX_7_ID = 183;
|
||||||
private static final Integer SCRIPT_TIMEOUT = 1800000;
|
private static final Integer SCRIPT_TIMEOUT = 1800000;
|
||||||
private static final Integer LOCK_WAIT_TIMEOUT = 1200;
|
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;
|
public static String CS_MAJOR_VERSION = null;
|
||||||
@ -128,6 +135,8 @@ public class SystemVmTemplateRegistration {
|
|||||||
|
|
||||||
private String systemVmTemplateVersion;
|
private String systemVmTemplateVersion;
|
||||||
|
|
||||||
|
private final File tempDownloadDir;
|
||||||
|
|
||||||
public SystemVmTemplateRegistration() {
|
public SystemVmTemplateRegistration() {
|
||||||
dataCenterDao = new DataCenterDaoImpl();
|
dataCenterDao = new DataCenterDaoImpl();
|
||||||
vmTemplateDao = new VMTemplateDaoImpl();
|
vmTemplateDao = new VMTemplateDaoImpl();
|
||||||
@ -138,6 +147,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
imageStoreDetailsDao = new ImageStoreDetailsDaoImpl();
|
imageStoreDetailsDao = new ImageStoreDetailsDaoImpl();
|
||||||
clusterDao = new ClusterDaoImpl();
|
clusterDao = new ClusterDaoImpl();
|
||||||
configurationDao = new ConfigurationDaoImpl();
|
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) {
|
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)) {
|
if (StringUtils.isNotBlank(nfsVersion)) {
|
||||||
cmd = String.format("%s -o vers=%s", cmd, nfsVersion);
|
cmd = String.format("%s -o vers=%s", cmd, nfsVersion);
|
||||||
}
|
}
|
||||||
@ -163,6 +173,10 @@ public class SystemVmTemplateRegistration {
|
|||||||
return systemVmTemplateVersion;
|
return systemVmTemplateVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getTempDownloadDir() {
|
||||||
|
return tempDownloadDir;
|
||||||
|
}
|
||||||
|
|
||||||
private static class SystemVMTemplateDetails {
|
private static class SystemVMTemplateDetails {
|
||||||
Long id;
|
Long id;
|
||||||
String uuid;
|
String uuid;
|
||||||
@ -174,6 +188,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
ImageFormat format;
|
ImageFormat format;
|
||||||
Integer guestOsId;
|
Integer guestOsId;
|
||||||
Hypervisor.HypervisorType hypervisorType;
|
Hypervisor.HypervisorType hypervisorType;
|
||||||
|
CPU.CPUArch arch;
|
||||||
Long storeId;
|
Long storeId;
|
||||||
Long size;
|
Long size;
|
||||||
Long physicalSize;
|
Long physicalSize;
|
||||||
@ -183,7 +198,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
|
|
||||||
SystemVMTemplateDetails(String uuid, String name, Date created, String url, String checksum,
|
SystemVMTemplateDetails(String uuid, String name, Date created, String url, String checksum,
|
||||||
ImageFormat format, Integer guestOsId, Hypervisor.HypervisorType hypervisorType,
|
ImageFormat format, Integer guestOsId, Hypervisor.HypervisorType hypervisorType,
|
||||||
Long storeId) {
|
CPU.CPUArch arch, Long storeId) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.created = created;
|
this.created = created;
|
||||||
@ -192,6 +207,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
this.format = format;
|
this.format = format;
|
||||||
this.guestOsId = guestOsId;
|
this.guestOsId = guestOsId;
|
||||||
this.hypervisorType = hypervisorType;
|
this.hypervisorType = hypervisorType;
|
||||||
|
this.arch = arch;
|
||||||
this.storeId = storeId;
|
this.storeId = storeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,6 +251,10 @@ public class SystemVmTemplateRegistration {
|
|||||||
return hypervisorType;
|
return hypervisorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getStoreId() {
|
public Long getStoreId() {
|
||||||
return storeId;
|
return storeId;
|
||||||
}
|
}
|
||||||
@ -288,18 +308,17 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final List<Hypervisor.HypervisorType> hypervisorList = Arrays.asList(Hypervisor.HypervisorType.KVM,
|
public static final List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorList = Arrays.asList(
|
||||||
Hypervisor.HypervisorType.VMware,
|
new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.amd64),
|
||||||
Hypervisor.HypervisorType.XenServer,
|
new Pair<>(Hypervisor.HypervisorType.KVM, CPU.CPUArch.arm64),
|
||||||
Hypervisor.HypervisorType.Hyperv,
|
new Pair<>(Hypervisor.HypervisorType.VMware, null),
|
||||||
Hypervisor.HypervisorType.LXC,
|
new Pair<>(Hypervisor.HypervisorType.XenServer, null),
|
||||||
Hypervisor.HypervisorType.Ovm3
|
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<String, MetadataTemplateDetails> NewTemplateMap = new HashMap<>();
|
||||||
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<Hypervisor.HypervisorType, String> RouterTemplateConfigurationNames = new HashMap<Hypervisor.HypervisorType, String>() {
|
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) {
|
private static String getHypervisorArchLog(Hypervisor.HypervisorType hypervisorType, CPU.CPUArch arch) {
|
||||||
VMTemplateVO vmTemplate = vmTemplateDao.findLatestTemplateByName(hypervisorAndTemplateName.second());
|
StringBuilder sb = new StringBuilder("hypervisor: ").append(hypervisorType.name());
|
||||||
Long templateId = null;
|
if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) {
|
||||||
if (vmTemplate != null) {
|
sb.append(", arch: ").append(arch == null ? CPU.CPUArch.amd64.getType() : arch.getType());
|
||||||
templateId = vmTemplate.getId();
|
|
||||||
}
|
}
|
||||||
return templateId;
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String fetchTemplatesPath() {
|
protected static String getHypervisorArchKey(Hypervisor.HypervisorType hypervisorType, CPU.CPUArch arch) {
|
||||||
String filePath = RELATIVE_TEMPLATE_PATH + METADATA_FILE_NAME;
|
if (Hypervisor.HypervisorType.KVM.equals(hypervisorType)) {
|
||||||
LOGGER.debug(String.format("Looking for file [ %s ] in the classpath.", filePath));
|
return String.format("%s-%s", hypervisorType.name().toLowerCase(),
|
||||||
File metaFile = new File(filePath);
|
arch == null ? CPU.CPUArch.amd64.getType() : arch.getType());
|
||||||
String templatePath = null;
|
|
||||||
if (metaFile.exists()) {
|
|
||||||
templatePath = RELATIVE_TEMPLATE_PATH;
|
|
||||||
}
|
}
|
||||||
if (templatePath == null) {
|
return hypervisorType.name().toLowerCase();
|
||||||
filePath = ABSOLUTE_TEMPLATE_PATH + METADATA_FILE_NAME;
|
}
|
||||||
metaFile = new File(filePath);
|
|
||||||
templatePath = ABSOLUTE_TEMPLATE_PATH;
|
protected static MetadataTemplateDetails getMetadataTemplateDetails(Hypervisor.HypervisorType hypervisorType,
|
||||||
LOGGER.debug(String.format("Looking for file [ %s ] in the classpath.", filePath));
|
CPU.CPUArch arch) {
|
||||||
if (!metaFile.exists()) {
|
return NewTemplateMap.get(getHypervisorArchKey(hypervisorType, arch));
|
||||||
String errMsg = String.format("Unable to locate metadata file in your setup at %s", filePath.toString());
|
}
|
||||||
|
|
||||||
|
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);
|
LOGGER.error(errMsg);
|
||||||
throw new CloudRuntimeException(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() {
|
private List<Long> getEligibleZoneIds() {
|
||||||
List<Long> zoneIds = new ArrayList<>();
|
List<Long> zoneIds = new ArrayList<>();
|
||||||
@ -430,28 +467,28 @@ public class SystemVmTemplateRegistration {
|
|||||||
return zoneIds;
|
return zoneIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Pair<String, Long> getNfsStoreInZone(Long zoneId) {
|
protected Pair<String, Long> getNfsStoreInZone(Long zoneId) {
|
||||||
String url = null;
|
|
||||||
Long storeId = null;
|
|
||||||
ImageStoreVO storeVO = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs");
|
ImageStoreVO storeVO = imageStoreDao.findOneByZoneAndProtocol(zoneId, "nfs");
|
||||||
if (storeVO == null) {
|
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);
|
LOGGER.error(errMsg);
|
||||||
throw new CloudRuntimeException(errMsg);
|
throw new CloudRuntimeException(errMsg);
|
||||||
}
|
}
|
||||||
url = storeVO.getUrl();
|
String url = storeVO.getUrl();
|
||||||
storeId = storeVO.getId();
|
Long storeId = storeVO.getId();
|
||||||
return new Pair<>(url, storeId);
|
return new Pair<>(url, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void mountStore(String storeUrl, String path, String nfsVersion) {
|
public static void mountStore(String storeUrl, String path, String nfsVersion) {
|
||||||
try {
|
try {
|
||||||
if (storeUrl != null) {
|
if (storeUrl == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
URI uri = new URI(UriUtils.encodeURIComponent(storeUrl));
|
URI uri = new URI(UriUtils.encodeURIComponent(storeUrl));
|
||||||
String host = uri.getHost();
|
String host = uri.getHost();
|
||||||
String mountPath = uri.getPath();
|
String mountPath = uri.getPath();
|
||||||
Script.runSimpleBashScript(getMountCommand(nfsVersion, host + ":" + mountPath, path));
|
Script.runSimpleBashScript(getMountCommand(nfsVersion, host + ":" + mountPath, path));
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String msg = "NFS Store URL is not in the correct format";
|
String msg = "NFS Store URL is not in the correct format";
|
||||||
LOGGER.error(msg, e);
|
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) {
|
private VMTemplateVO createTemplateObjectInDB(SystemVMTemplateDetails details) {
|
||||||
Long templateId = vmTemplateDao.getNextInSequence(Long.class, "id");
|
Long templateId = vmTemplateDao.getNextInSequence(Long.class, "id");
|
||||||
VMTemplateVO template = new VMTemplateVO();
|
VMTemplateVO template = new VMTemplateVO();
|
||||||
@ -486,6 +516,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
template.setGuestOSId(details.getGuestOsId());
|
template.setGuestOSId(details.getGuestOsId());
|
||||||
template.setCrossZones(true);
|
template.setCrossZones(true);
|
||||||
template.setHypervisorType(details.getHypervisorType());
|
template.setHypervisorType(details.getHypervisorType());
|
||||||
|
template.setArch(details.getArch());
|
||||||
template.setState(VirtualMachineTemplate.State.Inactive);
|
template.setState(VirtualMachineTemplate.State.Inactive);
|
||||||
template.setDeployAsIs(false);
|
template.setDeployAsIs(false);
|
||||||
template = vmTemplateDao.persist(template);
|
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 destTempFolder) throws CloudRuntimeException {
|
||||||
String setupTmpltScript = Script.findScript(storageScriptsDir, "setup-sysvm-tmplt");
|
String setupTmpltScript = Script.findScript(storageScriptsDir, "setup-sysvm-tmplt");
|
||||||
if (setupTmpltScript == null) {
|
if (setupTmpltScript == null) {
|
||||||
@ -635,8 +666,12 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
Script scr = new Script(setupTmpltScript, SCRIPT_TIMEOUT, LOGGER);
|
Script scr = new Script(setupTmpltScript, SCRIPT_TIMEOUT, LOGGER);
|
||||||
scr.add("-u", templateName);
|
scr.add("-u", templateName);
|
||||||
scr.add("-f", TEMPLATES_PATH + FileNames.get(hypervisorAndTemplateName.first()));
|
MetadataTemplateDetails templateDetails = NewTemplateMap.get(getHypervisorArchKey(hypervisor, arch));
|
||||||
scr.add("-h", hypervisorAndTemplateName.first().name().toLowerCase(Locale.ROOT));
|
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);
|
scr.add("-d", destTempFolder);
|
||||||
String result = scr.execute();
|
String result = scr.execute();
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
@ -644,17 +679,15 @@ public class SystemVmTemplateRegistration {
|
|||||||
LOGGER.error(errMsg);
|
LOGGER.error(errMsg);
|
||||||
throw new CloudRuntimeException(errMsg);
|
throw new CloudRuntimeException(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long performTemplateRegistrationOperations(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName,
|
private Long performTemplateRegistrationOperations(Hypervisor.HypervisorType hypervisor,
|
||||||
String url, String checksum, ImageFormat format, long guestOsId,
|
String name, CPU.CPUArch arch, String url, String checksum, ImageFormat format, long guestOsId,
|
||||||
Long storeId, Long templateId, String filePath, TemplateDataStoreVO templateDataStoreVO) {
|
Long storeId, Long templateId, String filePath, TemplateDataStoreVO templateDataStoreVO) {
|
||||||
Hypervisor.HypervisorType hypervisor = hypervisorAndTemplateName.first();
|
|
||||||
String templateName = UUID.randomUUID().toString();
|
String templateName = UUID.randomUUID().toString();
|
||||||
Date created = new Date(DateUtil.currentGMTTime().getTime());
|
Date created = new Date(DateUtil.currentGMTTime().getTime());
|
||||||
SystemVMTemplateDetails details = new SystemVMTemplateDetails(templateName, hypervisorAndTemplateName.second(), created,
|
SystemVMTemplateDetails details = new SystemVMTemplateDetails(templateName, name, created,
|
||||||
url, checksum, format, (int) guestOsId, hypervisor, storeId);
|
url, checksum, format, (int) guestOsId, hypervisor, arch, storeId);
|
||||||
if (templateId == null) {
|
if (templateId == null) {
|
||||||
VMTemplateVO template = createTemplateObjectInDB(details);
|
VMTemplateVO template = createTemplateObjectInDB(details);
|
||||||
if (template == null) {
|
if (template == null) {
|
||||||
@ -671,23 +704,44 @@ public class SystemVmTemplateRegistration {
|
|||||||
if (templateDataStoreVO == null) {
|
if (templateDataStoreVO == null) {
|
||||||
createTemplateStoreRefEntry(details);
|
createTemplateStoreRefEntry(details);
|
||||||
}
|
}
|
||||||
setupTemplate(templateName, hypervisorAndTemplateName, destTempFolder);
|
setupTemplate(templateName, hypervisor, arch, destTempFolder);
|
||||||
readTemplateProperties(destTempFolder + "/template.properties", details);
|
readTemplateProperties(destTempFolder + "/template.properties", details);
|
||||||
details.setUpdated(new Date(DateUtil.currentGMTTime().getTime()));
|
details.setUpdated(new Date(DateUtil.currentGMTTime().getTime()));
|
||||||
updateTemplateDetails(details);
|
updateTemplateDetails(details);
|
||||||
return templateId;
|
return templateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerTemplate(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName,
|
public void registerTemplate(Hypervisor.HypervisorType hypervisor, String name, Long storeId,
|
||||||
Pair<String, Long> storeUrlAndId, VMTemplateVO templateVO,
|
VMTemplateVO templateVO, TemplateDataStoreVO templateDataStoreVO, String filePath) {
|
||||||
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;
|
Long templateId = null;
|
||||||
try {
|
try {
|
||||||
templateId = templateVO.getId();
|
MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisor, arch);
|
||||||
performTemplateRegistrationOperations(hypervisorAndTemplateName, templateVO.getUrl(), templateVO.getChecksum(),
|
templateId = performTemplateRegistrationOperations(hypervisor, name,
|
||||||
templateVO.getFormat(), templateVO.getGuestOSId(), storeUrlAndId.second(), templateId, filePath, templateDataStoreVO);
|
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) {
|
} 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);
|
LOGGER.error(errMsg, e);
|
||||||
if (templateId != null) {
|
if (templateId != null) {
|
||||||
updateTemplateTablesOnFailure(templateId);
|
updateTemplateTablesOnFailure(templateId);
|
||||||
@ -697,28 +751,33 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerTemplate(Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName, Pair<String, Long> storeUrlAndId, String filePath) {
|
protected void validateTemplateFileForHypervisorAndArch(Hypervisor.HypervisorType hypervisor, CPU.CPUArch arch) {
|
||||||
Long templateId = null;
|
MetadataTemplateDetails templateDetails = getMetadataTemplateDetails(hypervisor, arch);
|
||||||
try {
|
File templateFile = getTemplateFile(templateDetails);
|
||||||
Hypervisor.HypervisorType hypervisor = hypervisorAndTemplateName.first();
|
if (templateFile == null) {
|
||||||
templateId = performTemplateRegistrationOperations(hypervisorAndTemplateName, NewTemplateUrl.get(hypervisor), NewTemplateChecksum.get(hypervisor),
|
throw new CloudRuntimeException("Failed to find local template file");
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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
|
* 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
|
* @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.
|
* exist a template corresponding to the current code version.
|
||||||
*/
|
*/
|
||||||
public static String parseMetadataFile() {
|
public static String parseMetadataFile() {
|
||||||
try {
|
String metadataFilePath = getMetadataFilePath();
|
||||||
Ini ini = new Ini();
|
String errMsg = String.format("Failed to parse systemVM template metadata file: %s", metadataFilePath);
|
||||||
ini.load(new FileReader(METADATA_FILE));
|
final Ini ini = new Ini();
|
||||||
for (Hypervisor.HypervisorType hypervisorType : hypervisorList) {
|
try (FileReader reader = new FileReader(metadataFilePath)) {
|
||||||
String hypervisor = hypervisorType.name().toLowerCase(Locale.ROOT);
|
ini.load(reader);
|
||||||
Ini.Section section = ini.get(hypervisor);
|
} catch (IOException e) {
|
||||||
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);
|
|
||||||
LOGGER.error(errMsg, e);
|
LOGGER.error(errMsg, e);
|
||||||
throw new CloudRuntimeException(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) {
|
private static void cleanupStore(Long templateId, String filePath) {
|
||||||
String destTempFolder = filePath + PARTIAL_TEMPLATE_FOLDER + String.valueOf(templateId);
|
String destTempFolder = filePath + PARTIAL_TEMPLATE_FOLDER + String.valueOf(templateId);
|
||||||
@ -755,31 +829,60 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateTemplates(Set<Hypervisor.HypervisorType> hypervisorsInUse) {
|
protected File getTemplateFile(MetadataTemplateDetails templateDetails) {
|
||||||
Set<String> hypervisors = hypervisorsInUse.stream().
|
File templateFile = new File(templateDetails.getDefaultFilePath());
|
||||||
map(Hypervisor.HypervisorType::name).map(name -> name.toLowerCase(Locale.ROOT)).map(this::getHypervisorName).collect(Collectors.toSet());
|
if (templateFile.exists()) {
|
||||||
List<String> templates = new ArrayList<>();
|
return templateFile;
|
||||||
for (Hypervisor.HypervisorType hypervisorType : hypervisorsInUse) {
|
}
|
||||||
templates.add(FileNames.get(hypervisorType));
|
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;
|
boolean templatesFound = true;
|
||||||
for (String hypervisor : hypervisors) {
|
for (Pair<Hypervisor.HypervisorType, CPU.CPUArch> hypervisorArch : hypervisorsArchInUse) {
|
||||||
String matchedTemplate = templates.stream().filter(x -> x.contains(hypervisor)).findAny().orElse(null);
|
MetadataTemplateDetails matchedTemplate = getMetadataTemplateDetails(hypervisorArch.first(),
|
||||||
|
hypervisorArch.second());
|
||||||
if (matchedTemplate == null) {
|
if (matchedTemplate == null) {
|
||||||
templatesFound = false;
|
templatesFound = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
File tempFile = getTemplateFile(matchedTemplate);
|
||||||
File tempFile = new File(TEMPLATES_PATH + matchedTemplate);
|
if (tempFile == null) {
|
||||||
String templateChecksum = DigestHelper.calculateChecksum(tempFile);
|
LOGGER.warn("Failed to download template for {}, moving ahead",
|
||||||
if (!templateChecksum.equals(NewTemplateChecksum.get(getHypervisorType(hypervisor)))) {
|
matchedTemplate.getHypervisorArchLog());
|
||||||
LOGGER.error(String.format("Checksum mismatch: %s != %s ", templateChecksum, NewTemplateChecksum.get(getHypervisorType(hypervisor))));
|
continue;
|
||||||
|
}
|
||||||
|
if (isTemplateFileChecksumDifferent(matchedTemplate, tempFile)) {
|
||||||
templatesFound = false;
|
templatesFound = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!templatesFound) {
|
if (!templatesFound) {
|
||||||
String errMsg = "SystemVm template not found. Cannot upgrade system Vms";
|
String errMsg = "SystemVm template not found. Cannot upgrade system Vms";
|
||||||
LOGGER.error(errMsg);
|
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");
|
GlobalLock lock = GlobalLock.getInternLock("UpgradeDatabase-Lock");
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Grabbing lock to register templates.");
|
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.");
|
throw new CloudRuntimeException("Unable to acquire lock to register SystemVM template.");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
validateTemplates(hypervisorsInUse);
|
validateTemplates(hypervisorsArchInUse);
|
||||||
// Perform Registration if templates not already registered
|
// Perform Registration if templates not already registered
|
||||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||||
@Override
|
@Override
|
||||||
@ -808,32 +944,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
if (filePath == null) {
|
if (filePath == null) {
|
||||||
throw new CloudRuntimeException("Failed to create temporary file path to mount the store");
|
throw new CloudRuntimeException("Failed to create temporary file path to mount the store");
|
||||||
}
|
}
|
||||||
Pair<String, Long> storeUrlAndId = getNfsStoreInZone(zoneId);
|
registerTemplatesForZone(zoneId, filePath);
|
||||||
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);
|
|
||||||
}
|
|
||||||
unmountStore(filePath);
|
unmountStore(filePath);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
unmountStore(filePath);
|
unmountStore(filePath);
|
||||||
@ -851,12 +962,7 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRegisteredTemplateDetails(Long templateId, Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
|
private void updateRegisteredTemplateDetails(Long templateId, MetadataTemplateDetails templateDetails) {
|
||||||
Pair<Hypervisor.HypervisorType, String> entry = new Pair<>(hypervisorAndTemplateName.getKey(), hypervisorAndTemplateName.getValue());
|
|
||||||
updateRegisteredTemplateDetails(templateId, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateRegisteredTemplateDetails(Long templateId, Pair<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
|
|
||||||
VMTemplateVO templateVO = vmTemplateDao.findById(templateId);
|
VMTemplateVO templateVO = vmTemplateDao.findById(templateId);
|
||||||
templateVO.setTemplateType(Storage.TemplateType.SYSTEM);
|
templateVO.setTemplateType(Storage.TemplateType.SYSTEM);
|
||||||
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
||||||
@ -865,68 +971,81 @@ public class SystemVmTemplateRegistration {
|
|||||||
LOGGER.error(errMsg);
|
LOGGER.error(errMsg);
|
||||||
throw new CloudRuntimeException(errMsg);
|
throw new CloudRuntimeException(errMsg);
|
||||||
}
|
}
|
||||||
|
Hypervisor.HypervisorType hypervisorType = templateDetails.getHypervisorType();
|
||||||
updateSystemVMEntries(templateId, hypervisorAndTemplateName.first());
|
updateSystemVMEntries(templateId, hypervisorType);
|
||||||
|
|
||||||
// Change value of global configuration parameter router.template.* for the corresponding hypervisor and minreq.sysvmtemplate.version for the ACS version
|
// 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<>();
|
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());
|
configParams.put("minreq.sysvmtemplate.version", getSystemVmTemplateVersion());
|
||||||
updateConfigurationParams(configParams);
|
updateConfigurationParams(configParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTemplateUrlAndChecksum(VMTemplateVO templateVO, Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName) {
|
private void updateTemplateUrlAndChecksum(VMTemplateVO templateVO, MetadataTemplateDetails templateDetails) {
|
||||||
templateVO.setUrl(NewTemplateUrl.get(hypervisorAndTemplateName.getKey()));
|
templateVO.setUrl(templateDetails.getUrl());
|
||||||
templateVO.setChecksum(NewTemplateChecksum.get(hypervisorAndTemplateName.getKey()));
|
templateVO.setChecksum(templateDetails.getChecksum());
|
||||||
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
boolean updated = vmTemplateDao.update(templateVO.getId(), templateVO);
|
||||||
if (!updated) {
|
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);
|
LOGGER.error(errMsg);
|
||||||
throw new CloudRuntimeException(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) {
|
public void updateSystemVmTemplates(final Connection conn) {
|
||||||
LOGGER.debug("Updating System Vm template IDs");
|
LOGGER.debug("Updating System Vm template IDs");
|
||||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||||
@Override
|
@Override
|
||||||
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||||
Set<Hypervisor.HypervisorType> hypervisorsListInUse = new HashSet<Hypervisor.HypervisorType>();
|
List<Pair<Hypervisor.HypervisorType, CPU.CPUArch>> hypervisorsInUse;
|
||||||
try {
|
try {
|
||||||
hypervisorsListInUse = clusterDao.getDistinctAvailableHypervisorsAcrossClusters();
|
hypervisorsInUse = clusterDao.listDistinctHypervisorsArchAcrossClusters(null);
|
||||||
|
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
LOGGER.error("updateSystemVmTemplates: Exception caught while getting hypervisor types from clusters: " + e.getMessage());
|
throw new CloudRuntimeException("Exception while getting hypervisor types from clusters", e);
|
||||||
throw new CloudRuntimeException("updateSystemVmTemplates:Exception while getting hypervisor types from clusters", e);
|
|
||||||
}
|
}
|
||||||
|
Collection<MetadataTemplateDetails> templateEntries = NewTemplateMap.values();
|
||||||
for (final Map.Entry<Hypervisor.HypervisorType, String> hypervisorAndTemplateName : NewTemplateNameList.entrySet()) {
|
for (MetadataTemplateDetails templateDetails : templateEntries) {
|
||||||
LOGGER.debug("Updating " + hypervisorAndTemplateName.getKey() + " System Vms");
|
|
||||||
Long templateId = getRegisteredTemplateId(new Pair<>(hypervisorAndTemplateName.getKey(), hypervisorAndTemplateName.getValue()));
|
|
||||||
try {
|
try {
|
||||||
// change template type to SYSTEM
|
if (registerOrUpdateSystemVmTemplate(templateDetails, hypervisorsInUse)) {
|
||||||
if (templateId != null) {
|
|
||||||
updateRegisteredTemplateDetails(templateId, hypervisorAndTemplateName);
|
|
||||||
} else {
|
|
||||||
if (hypervisorsListInUse.contains(hypervisorAndTemplateName.getKey())) {
|
|
||||||
try {
|
|
||||||
registerTemplates(hypervisorsListInUse);
|
|
||||||
break;
|
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) {
|
} 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);
|
LOGGER.error(errMsg, e);
|
||||||
throw new CloudRuntimeException(errMsg, e);
|
throw new CloudRuntimeException(errMsg, e);
|
||||||
}
|
}
|
||||||
@ -948,4 +1067,64 @@ public class SystemVmTemplateRegistration {
|
|||||||
}
|
}
|
||||||
return null;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,7 @@ public class Upgrade42000to42010 extends DbUpgradeAbstractImpl implements DbUpgr
|
|||||||
try {
|
try {
|
||||||
systemVmTemplateRegistration.updateSystemVmTemplates(conn);
|
systemVmTemplateRegistration.updateSystemVmTemplates(conn);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)");
|
throw new CloudRuntimeException("Failed to find / register SystemVM template(s)", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ public interface ImageStoreDao extends GenericDao<ImageStoreVO, Long> {
|
|||||||
|
|
||||||
List<ImageStoreVO> listStoresByZoneId(long zoneId);
|
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);
|
List<ImageStoreVO> findByProtocol(String protocol);
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
|
|||||||
private SearchBuilder<ImageStoreVO> nameSearch;
|
private SearchBuilder<ImageStoreVO> nameSearch;
|
||||||
private SearchBuilder<ImageStoreVO> providerSearch;
|
private SearchBuilder<ImageStoreVO> providerSearch;
|
||||||
private SearchBuilder<ImageStoreVO> regionSearch;
|
private SearchBuilder<ImageStoreVO> regionSearch;
|
||||||
private SearchBuilder<ImageStoreVO> storeSearch;
|
private SearchBuilder<ImageStoreVO> storesExceptIdSearch;
|
||||||
private SearchBuilder<ImageStoreVO> protocolSearch;
|
private SearchBuilder<ImageStoreVO> protocolSearch;
|
||||||
private SearchBuilder<ImageStoreVO> zoneProtocolSearch;
|
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.and("role", regionSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||||
regionSearch.done();
|
regionSearch.done();
|
||||||
|
|
||||||
storeSearch = createSearchBuilder();
|
storesExceptIdSearch = createSearchBuilder();
|
||||||
storeSearch.and("providerName", storeSearch.entity().getProviderName(), SearchCriteria.Op.EQ);
|
storesExceptIdSearch.and("providerName", storesExceptIdSearch.entity().getProviderName(), SearchCriteria.Op.EQ);
|
||||||
storeSearch.and("role", storeSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
storesExceptIdSearch.and("role", storesExceptIdSearch.entity().getRole(), SearchCriteria.Op.EQ);
|
||||||
storeSearch.and("dataCenterId", storeSearch.entity().getDcId(), SearchCriteria.Op.EQ);
|
storesExceptIdSearch.and("dataCenterId", storesExceptIdSearch.entity().getDcId(), SearchCriteria.Op.EQ);
|
||||||
storeSearch.done();
|
storesExceptIdSearch.and("id", storesExceptIdSearch.entity().getId(), SearchCriteria.Op.NEQ);
|
||||||
|
storesExceptIdSearch.done();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -113,11 +114,12 @@ public class ImageStoreDaoImpl extends GenericDaoBase<ImageStoreVO, Long> implem
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ImageStoreVO> listAllStoresInZone(Long zoneId, String provider, DataStoreRole role) {
|
public List<ImageStoreVO> listAllStoresInZoneExceptId(Long zoneId, String provider, DataStoreRole role, long id) {
|
||||||
SearchCriteria<ImageStoreVO> sc = storeSearch.create();
|
SearchCriteria<ImageStoreVO> sc = storesExceptIdSearch.create();
|
||||||
sc.setParameters("providerName", provider);
|
sc.setParameters("providerName", provider);
|
||||||
sc.setParameters("role", role);
|
sc.setParameters("role", role);
|
||||||
sc.setParameters("dataCenterId", zoneId);
|
sc.setParameters("dataCenterId", zoneId);
|
||||||
|
sc.setParameters("id", id);
|
||||||
return listBy(sc);
|
return listBy(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,7 +21,7 @@ import com.cloud.cpu.CPU;
|
|||||||
import javax.persistence.AttributeConverter;
|
import javax.persistence.AttributeConverter;
|
||||||
import javax.persistence.Converter;
|
import javax.persistence.Converter;
|
||||||
|
|
||||||
@Converter
|
@Converter(autoApply = true)
|
||||||
public class CPUArchConverter implements AttributeConverter<CPU.CPUArch, String> {
|
public class CPUArchConverter implements AttributeConverter<CPU.CPUArch, String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -58,6 +58,7 @@ select
|
|||||||
host.resource_state host_resource_state,
|
host.resource_state host_resource_state,
|
||||||
vm_template.id template_id,
|
vm_template.id template_id,
|
||||||
vm_template.uuid template_uuid,
|
vm_template.uuid template_uuid,
|
||||||
|
vm_template.arch arch,
|
||||||
service_offering.id service_offering_id,
|
service_offering.id service_offering_id,
|
||||||
service_offering.uuid service_offering_uuid,
|
service_offering.uuid service_offering_uuid,
|
||||||
service_offering.name service_offering_name,
|
service_offering.name service_offering_name,
|
||||||
|
|||||||
@ -83,6 +83,7 @@ SELECT
|
|||||||
`iso`.`uuid` AS `iso_uuid`,
|
`iso`.`uuid` AS `iso_uuid`,
|
||||||
`iso`.`name` AS `iso_name`,
|
`iso`.`name` AS `iso_name`,
|
||||||
`iso`.`display_text` AS `iso_display_text`,
|
`iso`.`display_text` AS `iso_display_text`,
|
||||||
|
`vm_template`.`arch` AS `arch`,
|
||||||
`service_offering`.`id` AS `service_offering_id`,
|
`service_offering`.`id` AS `service_offering_id`,
|
||||||
`service_offering`.`uuid` AS `service_offering_uuid`,
|
`service_offering`.`uuid` AS `service_offering_uuid`,
|
||||||
`disk_offering`.`uuid` AS `disk_offering_uuid`,
|
`disk_offering`.`uuid` AS `disk_offering_uuid`,
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
package com.cloud.dc.dao;
|
package com.cloud.dc.dao;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@ -36,9 +37,13 @@ import org.mockito.InjectMocks;
|
|||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.ClusterVO;
|
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.GenericSearchBuilder;
|
||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class ClusterDaoImplTest {
|
public class ClusterDaoImplTest {
|
||||||
@ -75,4 +80,39 @@ public class ClusterDaoImplTest {
|
|||||||
verify(clusterDao).customSearch(genericSearchBuilder.create(), null);
|
verify(clusterDao).customSearch(genericSearchBuilder.create(), null);
|
||||||
assertTrue(result.isEmpty());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,18 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.host.dao;
|
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.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -26,6 +37,7 @@ import org.mockito.Mockito;
|
|||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.Status;
|
import com.cloud.host.Status;
|
||||||
@ -52,10 +64,10 @@ public class HostDaoImplTest {
|
|||||||
public void testCountUpAndEnabledHostsInZone() {
|
public void testCountUpAndEnabledHostsInZone() {
|
||||||
long testZoneId = 100L;
|
long testZoneId = 100L;
|
||||||
hostDao.HostTypeCountSearch = mockSearchBuilder;
|
hostDao.HostTypeCountSearch = mockSearchBuilder;
|
||||||
Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
|
when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
|
||||||
Mockito.doNothing().when(mockSearchCriteria).setParameters(Mockito.anyString(), Mockito.any());
|
Mockito.doNothing().when(mockSearchCriteria).setParameters(Mockito.anyString(), any());
|
||||||
int expected = 5;
|
int expected = 5;
|
||||||
Mockito.doReturn(expected).when(hostDao).getCount(mockSearchCriteria);
|
doReturn(expected).when(hostDao).getCount(mockSearchCriteria);
|
||||||
Integer count = hostDao.countUpAndEnabledHostsInZone(testZoneId);
|
Integer count = hostDao.countUpAndEnabledHostsInZone(testZoneId);
|
||||||
Assert.assertSame(expected, count);
|
Assert.assertSame(expected, count);
|
||||||
Mockito.verify(mockSearchCriteria).setParameters("type", Host.Type.Routing);
|
Mockito.verify(mockSearchCriteria).setParameters("type", Host.Type.Routing);
|
||||||
@ -70,16 +82,16 @@ public class HostDaoImplTest {
|
|||||||
GenericDaoBase.SumCount mockSumCount = new GenericDaoBase.SumCount();
|
GenericDaoBase.SumCount mockSumCount = new GenericDaoBase.SumCount();
|
||||||
mockSumCount.count = 10;
|
mockSumCount.count = 10;
|
||||||
mockSumCount.sum = 20;
|
mockSumCount.sum = 20;
|
||||||
HostVO host = Mockito.mock(HostVO.class);
|
HostVO host = mock(HostVO.class);
|
||||||
GenericSearchBuilder<HostVO, GenericDaoBase.SumCount> sb = Mockito.mock(GenericSearchBuilder.class);
|
GenericSearchBuilder<HostVO, GenericDaoBase.SumCount> sb = mock(GenericSearchBuilder.class);
|
||||||
Mockito.when(sb.entity()).thenReturn(host);
|
when(sb.entity()).thenReturn(host);
|
||||||
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(GenericDaoBase.SumCount.class);
|
doReturn(sb).when(hostDao).createSearchBuilder(GenericDaoBase.SumCount.class);
|
||||||
SearchCriteria<GenericDaoBase.SumCount> sc = Mockito.mock(SearchCriteria.class);
|
SearchCriteria<GenericDaoBase.SumCount> sc = mock(SearchCriteria.class);
|
||||||
Mockito.when(sb.create()).thenReturn(sc);
|
when(sb.create()).thenReturn(sc);
|
||||||
Mockito.doReturn(List.of(mockSumCount)).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(List.of(mockSumCount)).when(hostDao).customSearch(any(SearchCriteria.class), any());
|
||||||
Pair<Integer, Integer> result = hostDao.countAllHostsAndCPUSocketsByType(type);
|
Pair<Integer, Integer> result = hostDao.countAllHostsAndCPUSocketsByType(type);
|
||||||
Assert.assertEquals(10, result.first().intValue());
|
assertEquals(10, result.first().intValue());
|
||||||
Assert.assertEquals(20, result.second().intValue());
|
assertEquals(20, result.second().intValue());
|
||||||
Mockito.verify(sc).setParameters("type", type);
|
Mockito.verify(sc).setParameters("type", type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,13 +99,13 @@ public class HostDaoImplTest {
|
|||||||
public void testIsHostUp() {
|
public void testIsHostUp() {
|
||||||
long testHostId = 101L;
|
long testHostId = 101L;
|
||||||
List<Status> statuses = List.of(Status.Up);
|
List<Status> statuses = List.of(Status.Up);
|
||||||
HostVO host = Mockito.mock(HostVO.class);
|
HostVO host = mock(HostVO.class);
|
||||||
GenericSearchBuilder<HostVO, Status> sb = Mockito.mock(GenericSearchBuilder.class);
|
GenericSearchBuilder<HostVO, Status> sb = mock(GenericSearchBuilder.class);
|
||||||
Mockito.when(sb.entity()).thenReturn(host);
|
when(sb.entity()).thenReturn(host);
|
||||||
SearchCriteria<Status> sc = Mockito.mock(SearchCriteria.class);
|
SearchCriteria<Status> sc = mock(SearchCriteria.class);
|
||||||
Mockito.when(sb.create()).thenReturn(sc);
|
when(sb.create()).thenReturn(sc);
|
||||||
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Status.class);
|
doReturn(sb).when(hostDao).createSearchBuilder(Status.class);
|
||||||
Mockito.doReturn(statuses).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(statuses).when(hostDao).customSearch(any(SearchCriteria.class), any());
|
||||||
boolean result = hostDao.isHostUp(testHostId);
|
boolean result = hostDao.isHostUp(testHostId);
|
||||||
Assert.assertTrue("Host should be up", result);
|
Assert.assertTrue("Host should be up", result);
|
||||||
Mockito.verify(sc).setParameters("id", testHostId);
|
Mockito.verify(sc).setParameters("id", testHostId);
|
||||||
@ -108,17 +120,17 @@ public class HostDaoImplTest {
|
|||||||
List<Host.Type> types = List.of(Host.Type.Routing);
|
List<Host.Type> types = List.of(Host.Type.Routing);
|
||||||
List<Hypervisor.HypervisorType> hypervisorTypes = List.of(Hypervisor.HypervisorType.KVM);
|
List<Hypervisor.HypervisorType> hypervisorTypes = List.of(Hypervisor.HypervisorType.KVM);
|
||||||
List<Long> mockResults = List.of(1001L, 1002L); // Mocked result
|
List<Long> mockResults = List.of(1001L, 1002L); // Mocked result
|
||||||
HostVO host = Mockito.mock(HostVO.class);
|
HostVO host = mock(HostVO.class);
|
||||||
GenericSearchBuilder<HostVO, Long> sb = Mockito.mock(GenericSearchBuilder.class);
|
GenericSearchBuilder<HostVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||||
Mockito.when(sb.entity()).thenReturn(host);
|
when(sb.entity()).thenReturn(host);
|
||||||
SearchCriteria<Long> sc = Mockito.mock(SearchCriteria.class);
|
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||||
Mockito.when(sb.create()).thenReturn(sc);
|
when(sb.create()).thenReturn(sc);
|
||||||
Mockito.when(sb.and()).thenReturn(sb);
|
when(sb.and()).thenReturn(sb);
|
||||||
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
|
doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
|
||||||
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(mockResults).when(hostDao).customSearch(any(SearchCriteria.class), any());
|
||||||
List<Long> hostIds = hostDao.findHostIdsByZoneClusterResourceStateTypeAndHypervisorType(
|
List<Long> hostIds = hostDao.findHostIdsByZoneClusterResourceStateTypeAndHypervisorType(
|
||||||
zoneId, clusterId, resourceStates, types, hypervisorTypes);
|
zoneId, clusterId, resourceStates, types, hypervisorTypes);
|
||||||
Assert.assertEquals(mockResults, hostIds);
|
assertEquals(mockResults, hostIds);
|
||||||
Mockito.verify(sc).setParameters("zoneId", zoneId);
|
Mockito.verify(sc).setParameters("zoneId", zoneId);
|
||||||
Mockito.verify(sc).setParameters("clusterId", clusterId);
|
Mockito.verify(sc).setParameters("clusterId", clusterId);
|
||||||
Mockito.verify(sc).setParameters("resourceState", resourceStates.toArray());
|
Mockito.verify(sc).setParameters("resourceState", resourceStates.toArray());
|
||||||
@ -130,15 +142,16 @@ public class HostDaoImplTest {
|
|||||||
public void testListDistinctHypervisorTypes() {
|
public void testListDistinctHypervisorTypes() {
|
||||||
Long zoneId = 1L;
|
Long zoneId = 1L;
|
||||||
List<Hypervisor.HypervisorType> mockResults = List.of(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.XenServer);
|
List<Hypervisor.HypervisorType> mockResults = List.of(Hypervisor.HypervisorType.KVM, Hypervisor.HypervisorType.XenServer);
|
||||||
HostVO host = Mockito.mock(HostVO.class);
|
HostVO host = mock(HostVO.class);
|
||||||
GenericSearchBuilder<HostVO, Hypervisor.HypervisorType> sb = Mockito.mock(GenericSearchBuilder.class);
|
GenericSearchBuilder<HostVO, String> sb = mock(GenericSearchBuilder.class);
|
||||||
Mockito.when(sb.entity()).thenReturn(host);
|
when(sb.entity()).thenReturn(host);
|
||||||
SearchCriteria<Hypervisor.HypervisorType> sc = Mockito.mock(SearchCriteria.class);
|
SearchCriteria<String> sc = mock(SearchCriteria.class);
|
||||||
Mockito.when(sb.create()).thenReturn(sc);
|
when(sb.create()).thenReturn(sc);
|
||||||
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Hypervisor.HypervisorType.class);
|
doReturn(sb).when(hostDao).createSearchBuilder(String.class);
|
||||||
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(mockResults.stream().map(h -> h.name()).collect(Collectors.toList())).when(hostDao)
|
||||||
|
.customSearch(any(SearchCriteria.class), any());
|
||||||
List<Hypervisor.HypervisorType> hypervisorTypes = hostDao.listDistinctHypervisorTypes(zoneId);
|
List<Hypervisor.HypervisorType> hypervisorTypes = hostDao.listDistinctHypervisorTypes(zoneId);
|
||||||
Assert.assertEquals(mockResults, hypervisorTypes);
|
assertEquals(mockResults, hypervisorTypes);
|
||||||
Mockito.verify(sc).setParameters("zoneId", zoneId);
|
Mockito.verify(sc).setParameters("zoneId", zoneId);
|
||||||
Mockito.verify(sc).setParameters("type", Host.Type.Routing);
|
Mockito.verify(sc).setParameters("type", Host.Type.Routing);
|
||||||
}
|
}
|
||||||
@ -146,12 +159,12 @@ public class HostDaoImplTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testListByIds() {
|
public void testListByIds() {
|
||||||
List<Long> ids = List.of(101L, 102L);
|
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;
|
hostDao.IdsSearch = mockSearchBuilder;
|
||||||
Mockito.when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
|
when(mockSearchBuilder.create()).thenReturn(mockSearchCriteria);
|
||||||
Mockito.doReturn(mockResults).when(hostDao).search(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(mockResults).when(hostDao).search(any(SearchCriteria.class), any());
|
||||||
List<HostVO> hosts = hostDao.listByIds(ids);
|
List<HostVO> hosts = hostDao.listByIds(ids);
|
||||||
Assert.assertEquals(mockResults, hosts);
|
assertEquals(mockResults, hosts);
|
||||||
Mockito.verify(mockSearchCriteria).setParameters("id", ids.toArray());
|
Mockito.verify(mockSearchCriteria).setParameters("id", ids.toArray());
|
||||||
Mockito.verify(hostDao).search(mockSearchCriteria, null);
|
Mockito.verify(hostDao).search(mockSearchCriteria, null);
|
||||||
}
|
}
|
||||||
@ -164,15 +177,15 @@ public class HostDaoImplTest {
|
|||||||
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
|
Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
|
||||||
Long zoneId = 1L, podId = 2L, clusterId = 3L;
|
Long zoneId = 1L, podId = 2L, clusterId = 3L;
|
||||||
List<Long> mockResults = List.of(1001L, 1002L);
|
List<Long> mockResults = List.of(1001L, 1002L);
|
||||||
HostVO host = Mockito.mock(HostVO.class);
|
HostVO host = mock(HostVO.class);
|
||||||
GenericSearchBuilder<HostVO, Long> sb = Mockito.mock(GenericSearchBuilder.class);
|
GenericSearchBuilder<HostVO, Long> sb = mock(GenericSearchBuilder.class);
|
||||||
Mockito.when(sb.entity()).thenReturn(host);
|
when(sb.entity()).thenReturn(host);
|
||||||
SearchCriteria<Long> sc = Mockito.mock(SearchCriteria.class);
|
SearchCriteria<Long> sc = mock(SearchCriteria.class);
|
||||||
Mockito.when(sb.create()).thenReturn(sc);
|
when(sb.create()).thenReturn(sc);
|
||||||
Mockito.doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
|
doReturn(sb).when(hostDao).createSearchBuilder(Long.class);
|
||||||
Mockito.doReturn(mockResults).when(hostDao).customSearch(Mockito.any(SearchCriteria.class), Mockito.any());
|
doReturn(mockResults).when(hostDao).customSearch(any(SearchCriteria.class), any());
|
||||||
List<Long> hostIds = hostDao.listIdsBy(type, status, resourceState, hypervisorType, zoneId, podId, clusterId);
|
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("type", type);
|
||||||
Mockito.verify(sc).setParameters("status", status);
|
Mockito.verify(sc).setParameters("status", status);
|
||||||
Mockito.verify(sc).setParameters("resourceState", resourceState);
|
Mockito.verify(sc).setParameters("resourceState", resourceState);
|
||||||
@ -181,4 +194,57 @@ public class HostDaoImplTest {
|
|||||||
Mockito.verify(sc).setParameters("podId", podId);
|
Mockito.verify(sc).setParameters("podId", podId);
|
||||||
Mockito.verify(sc).setParameters("clusterId", clusterId);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -58,11 +58,12 @@ function createMetadataFile() {
|
|||||||
for template in "${templates[@]}"
|
for template in "${templates[@]}"
|
||||||
do
|
do
|
||||||
section="${template%%:*}"
|
section="${template%%:*}"
|
||||||
hvName=$(getGenericName $section)
|
sectionHv="${section%%-*}"
|
||||||
|
hvName=$(getGenericName $sectionHv)
|
||||||
|
|
||||||
downloadurl="${template#*:}"
|
downloadurl="${template#*:}"
|
||||||
arch=$(echo ${downloadurl#*"/systemvmtemplate-$VERSION-"} | cut -d'-' -f 1)
|
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")
|
checksum=$(getChecksum "$fileData" "$VERSION-${arch}-$hvName")
|
||||||
filename=$(echo ${downloadurl##*'/'})
|
filename=$(echo ${downloadurl##*'/'})
|
||||||
echo -e "["$section"]\ntemplatename = $templatename\nchecksum = $checksum\ndownloadurl = $downloadurl\nfilename = $filename\narch = $arch\n" >> $METADATAFILE
|
echo -e "["$section"]\ntemplatename = $templatename\nchecksum = $checksum\ndownloadurl = $downloadurl\nfilename = $filename\narch = $arch\n" >> $METADATAFILE
|
||||||
@ -71,7 +72,8 @@ function createMetadataFile() {
|
|||||||
|
|
||||||
declare -a templates
|
declare -a templates
|
||||||
getTemplateVersion $1
|
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"
|
"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"
|
"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"
|
"hyperv:https://download.cloudstack.org/systemvm/$CS_VERSION/systemvmtemplate-$VERSION-x86_64-hyperv.vhd.zip"
|
||||||
|
|||||||
@ -573,6 +573,9 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
|||||||
} else {
|
} else {
|
||||||
field.set(entity, rs.getLong(index));
|
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()) {
|
} else if (type.isEnum()) {
|
||||||
final Enumerated enumerated = field.getAnnotation(Enumerated.class);
|
final Enumerated enumerated = field.getAnnotation(Enumerated.class);
|
||||||
final EnumType enumType = (enumerated == null) ? EnumType.STRING : enumerated.value();
|
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) {
|
} else if (type == byte[].class) {
|
||||||
field.set(entity, rs.getBytes(index));
|
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 {
|
} else {
|
||||||
field.set(entity, rs.getObject(index));
|
field.set(entity, rs.getObject(index));
|
||||||
}
|
}
|
||||||
@ -949,7 +949,7 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DB()
|
@DB()
|
||||||
protected List<T> listBy(SearchCriteria<T> sc, final Filter filter) {
|
public List<T> listBy(SearchCriteria<T> sc, final Filter filter) {
|
||||||
sc = checkAndSetRemovedIsNull(sc);
|
sc = checkAndSetRemovedIsNull(sc);
|
||||||
return listIncludingRemovedBy(sc, filter);
|
return listIncludingRemovedBy(sc, filter);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,6 +36,8 @@ import com.cloud.utils.exception.CloudRuntimeException;
|
|||||||
import net.sf.cglib.proxy.Factory;
|
import net.sf.cglib.proxy.Factory;
|
||||||
import net.sf.cglib.proxy.MethodInterceptor;
|
import net.sf.cglib.proxy.MethodInterceptor;
|
||||||
import net.sf.cglib.proxy.MethodProxy;
|
import net.sf.cglib.proxy.MethodProxy;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,7 +124,7 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
|
|||||||
if (_entity == null) {
|
if (_entity == null) {
|
||||||
throw new RuntimeException("SearchBuilder cannot be modified once it has been setup");
|
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");
|
throw new RuntimeException("You can't specify more than one field to search on");
|
||||||
}
|
}
|
||||||
if (func.getCount() != -1 && (func.getCount() != (params.length + 1))) {
|
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);
|
_selects.add(select);
|
||||||
|
|
||||||
_specifiedAttrs.clear();
|
_specifiedAttrs.clear();
|
||||||
@ -185,7 +187,7 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
|
|||||||
} catch (final SecurityException e) {
|
} catch (final SecurityException e) {
|
||||||
} catch (final NoSuchFieldException 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();
|
_specifiedAttrs.clear();
|
||||||
@ -528,16 +530,18 @@ public abstract class SearchBase<J extends SearchBase<?, T, K>, T, K> {
|
|||||||
|
|
||||||
protected static class Select {
|
protected static class Select {
|
||||||
public Func func;
|
public Func func;
|
||||||
public Attribute attr;
|
public List<Attribute> attributes = new ArrayList<>();
|
||||||
public Object[] params;
|
public Object[] params;
|
||||||
public Field field;
|
public Field field;
|
||||||
|
|
||||||
protected Select() {
|
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.func = func;
|
||||||
this.attr = attr;
|
if (CollectionUtils.isNotEmpty(attributes)) {
|
||||||
|
this.attributes.addAll(attributes);
|
||||||
|
}
|
||||||
this.params = params;
|
this.params = params;
|
||||||
this.field = field;
|
this.field = field;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import java.util.HashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
@ -59,7 +60,7 @@ public class SearchCriteria<K> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum Func {
|
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 String func;
|
||||||
private int count;
|
private int count;
|
||||||
@ -135,10 +136,12 @@ public class SearchCriteria<K> {
|
|||||||
|
|
||||||
for (Select select : _selects) {
|
for (Select select : _selects) {
|
||||||
String func = select.func.toString() + ",";
|
String func = select.func.toString() + ",";
|
||||||
if (select.attr == null) {
|
if (CollectionUtils.isEmpty(select.attributes)) {
|
||||||
func = func.replace("@", "*");
|
func = func.replace("@", "*");
|
||||||
} else {
|
} 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);
|
str.insert(insertAt, func);
|
||||||
insertAt += func.length();
|
insertAt += func.length();
|
||||||
|
|||||||
@ -470,6 +470,8 @@ if [ -f %{_sysconfdir}/sysconfig/%{name}-management ] ; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
chown -R cloud:cloud /var/log/cloudstack/management
|
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
|
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/*.sh
|
||||||
%{_datadir}/%{name}-management/setup/server-setup.xml
|
%{_datadir}/%{name}-management/setup/server-setup.xml
|
||||||
%{_datadir}/%{name}-management/webapp/*
|
%{_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) %{_bindir}/%{name}-external-ipallocator.py
|
||||||
%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
|
%attr(0755,root,root) %{_initrddir}/%{name}-ipallocator
|
||||||
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
|
%dir %attr(0770,root,root) %{_localstatedir}/log/%{name}/ipallocator
|
||||||
|
|||||||
@ -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 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_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 int DEFAULT_HOST_SPEED_MHZ = 8000; // 1 GHz CPUs
|
||||||
|
public static final String DEFAULT_HOST_ARCH = "x86_64";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean configure(String name, Map<String, Object> params) throws ConfigurationException;
|
boolean configure(String name, Map<String, Object> params) throws ConfigurationException;
|
||||||
|
|||||||
@ -153,6 +153,7 @@ public class MockAgentManagerImpl extends ManagerBase implements MockAgentManage
|
|||||||
long cpuSpeed = Long.parseLong((String)params.get("cpuspeed"));
|
long cpuSpeed = Long.parseLong((String)params.get("cpuspeed"));
|
||||||
long memory = Long.parseLong((String)params.get("memory"));
|
long memory = Long.parseLong((String)params.get("memory"));
|
||||||
long localStorageSize = Long.parseLong((String)params.get("localstorage"));
|
long localStorageSize = Long.parseLong((String)params.get("localstorage"));
|
||||||
|
String arch = (String)params.get("arch");
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
long dataCenterId = Long.parseLong((String)params.get("zone"));
|
long dataCenterId = Long.parseLong((String)params.get("zone"));
|
||||||
long podId = Long.parseLong((String)params.get("pod"));
|
long podId = Long.parseLong((String)params.get("pod"));
|
||||||
@ -170,6 +171,7 @@ public class MockAgentManagerImpl extends ManagerBase implements MockAgentManage
|
|||||||
mockHost.setCpuCount(cpuCore);
|
mockHost.setCpuCount(cpuCore);
|
||||||
mockHost.setCpuSpeed(cpuSpeed);
|
mockHost.setCpuSpeed(cpuSpeed);
|
||||||
mockHost.setMemorySize(memory);
|
mockHost.setMemorySize(memory);
|
||||||
|
mockHost.setArch(arch);
|
||||||
String guid = UUID.randomUUID().toString();
|
String guid = UUID.randomUUID().toString();
|
||||||
mockHost.setGuid(guid);
|
mockHost.setGuid(guid);
|
||||||
mockHost.setName("SimulatedAgent." + guid);
|
mockHost.setName("SimulatedAgent." + guid);
|
||||||
|
|||||||
@ -177,6 +177,7 @@ public class AgentRoutingResource extends AgentStorageResource {
|
|||||||
StartupRoutingCommand cmd =
|
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,
|
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);
|
RouterPrivateIpStrategy.HostLocal);
|
||||||
|
cmd.setCpuArch((String)info.get(5));
|
||||||
|
|
||||||
Map<String, String> hostDetails = new HashMap<String, String>();
|
Map<String, String> hostDetails = new HashMap<String, String>();
|
||||||
hostDetails.put(RouterPrivateIpStrategy.class.getCanonicalName(), RouterPrivateIpStrategy.DcGlobal.toString());
|
hostDetails.put(RouterPrivateIpStrategy.class.getCanonicalName(), RouterPrivateIpStrategy.DcGlobal.toString());
|
||||||
@ -274,12 +275,14 @@ public class AgentRoutingResource extends AgentStorageResource {
|
|||||||
long cpus = agentHost.getCpuCount();
|
long cpus = agentHost.getCpuCount();
|
||||||
long ram = agentHost.getMemorySize();
|
long ram = agentHost.getMemorySize();
|
||||||
long dom0Ram = agentHost.getMemorySize() / 10;
|
long dom0Ram = agentHost.getMemorySize() / 10;
|
||||||
|
String arch = agentHost.getArch();
|
||||||
|
|
||||||
info.add((int)cpus);
|
info.add((int)cpus);
|
||||||
info.add(speed);
|
info.add(speed);
|
||||||
info.add(ram);
|
info.add(ram);
|
||||||
info.add(agentHost.getCapabilities());
|
info.add(agentHost.getCapabilities());
|
||||||
info.add(dom0Ram);
|
info.add(dom0Ram);
|
||||||
|
info.add(arch);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,7 @@ public class SimulatorDiscoverer extends DiscovererBase implements Discoverer, L
|
|||||||
long cpuCores = MockAgentManager.DEFAULT_HOST_CPU_CORES;
|
long cpuCores = MockAgentManager.DEFAULT_HOST_CPU_CORES;
|
||||||
long memory = MockAgentManager.DEFAULT_HOST_MEM_SIZE;
|
long memory = MockAgentManager.DEFAULT_HOST_MEM_SIZE;
|
||||||
long localstorageSize = MockStorageManager.DEFAULT_HOST_STORAGE_SIZE;
|
long localstorageSize = MockStorageManager.DEFAULT_HOST_STORAGE_SIZE;
|
||||||
|
String arch = MockAgentManager.DEFAULT_HOST_ARCH;
|
||||||
if (scheme.equals("http")) {
|
if (scheme.equals("http")) {
|
||||||
if (host == null || !host.startsWith("sim")) {
|
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;
|
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]);
|
memory = Long.parseLong(parameter[1]);
|
||||||
} else if (parameter[0].equalsIgnoreCase("localstorage") && parameter[1] != null) {
|
} else if (parameter[0].equalsIgnoreCase("localstorage") && parameter[1] != null) {
|
||||||
localstorageSize = Long.parseLong(parameter[1]);
|
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("cpucore", Long.toString(cpuCores));
|
||||||
params.put("memory", Long.toString(memory));
|
params.put("memory", Long.toString(memory));
|
||||||
params.put("localstorage", Long.toString(localstorageSize));
|
params.put("localstorage", Long.toString(localstorageSize));
|
||||||
|
params.put("arch", arch);
|
||||||
|
|
||||||
resources = createAgentResources(params);
|
resources = createAgentResources(params);
|
||||||
return resources;
|
return resources;
|
||||||
|
|||||||
@ -23,6 +23,8 @@ public interface MockHost {
|
|||||||
|
|
||||||
public long getMemorySize();
|
public long getMemorySize();
|
||||||
|
|
||||||
|
String getArch();
|
||||||
|
|
||||||
public String getCapabilities();
|
public String getCapabilities();
|
||||||
|
|
||||||
public long getId();
|
public long getId();
|
||||||
|
|||||||
@ -87,6 +87,9 @@ public class MockHostVO implements MockHost, InternalIdentity {
|
|||||||
@Column(name = "ram")
|
@Column(name = "ram")
|
||||||
private long memorySize;
|
private long memorySize;
|
||||||
|
|
||||||
|
@Column(name = "arch")
|
||||||
|
private String arch;
|
||||||
|
|
||||||
@Column(name = "capabilities")
|
@Column(name = "capabilities")
|
||||||
private String capabilities;
|
private String capabilities;
|
||||||
|
|
||||||
@ -143,6 +146,14 @@ public class MockHostVO implements MockHost, InternalIdentity {
|
|||||||
this.memorySize = memorySize;
|
this.memorySize = memorySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArch(String arch) {
|
||||||
|
this.arch = arch;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCapabilities() {
|
public String getCapabilities() {
|
||||||
return this.capabilities;
|
return this.capabilities;
|
||||||
|
|||||||
@ -22,7 +22,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import com.cloud.cpu.CPU;
|
|
||||||
import org.apache.cloudstack.api.ApiCommandResourceType;
|
import org.apache.cloudstack.api.ApiCommandResourceType;
|
||||||
import org.apache.cloudstack.api.ApiConstants;
|
import org.apache.cloudstack.api.ApiConstants;
|
||||||
import org.apache.cloudstack.api.command.admin.kubernetes.version.AddKubernetesSupportedVersionCmd;
|
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.dao.TemplateJoinDao;
|
||||||
import com.cloud.api.query.vo.TemplateJoinVO;
|
import com.cloud.api.query.vo.TemplateJoinVO;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.DataCenter;
|
import com.cloud.dc.DataCenter;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.dao.DataCenterDao;
|
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.ComponentContext;
|
||||||
import com.cloud.utils.component.ManagerBase;
|
import com.cloud.utils.component.ManagerBase;
|
||||||
import com.cloud.utils.db.Filter;
|
import com.cloud.utils.db.Filter;
|
||||||
|
import com.cloud.utils.db.JoinBuilder;
|
||||||
import com.cloud.utils.db.SearchBuilder;
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
import com.cloud.utils.db.SearchCriteria;
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
@ -94,6 +95,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
if (template.getState() != null) {
|
if (template.getState() != null) {
|
||||||
response.setIsoState(template.getState().toString());
|
response.setIsoState(template.getState().toString());
|
||||||
}
|
}
|
||||||
|
response.setIsoArch(template.getArch().getType());
|
||||||
response.setDirectDownload(template.isDirectDownload());
|
response.setDirectDownload(template.isDirectDownload());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,6 +269,7 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
final Long zoneId = cmd.getZoneId();
|
final Long zoneId = cmd.getZoneId();
|
||||||
String minimumSemanticVersion = cmd.getMinimumSemanticVersion();
|
String minimumSemanticVersion = cmd.getMinimumSemanticVersion();
|
||||||
final Long minimumKubernetesVersionId = cmd.getMinimumKubernetesVersionId();
|
final Long minimumKubernetesVersionId = cmd.getMinimumKubernetesVersionId();
|
||||||
|
final String arch = cmd.getArch();
|
||||||
if (StringUtils.isNotEmpty(minimumSemanticVersion) && minimumKubernetesVersionId != null) {
|
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));
|
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();
|
SearchBuilder<KubernetesSupportedVersionVO> sb = kubernetesSupportedVersionDao.createSearchBuilder();
|
||||||
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
sb.and("id", sb.entity().getId(), SearchCriteria.Op.EQ);
|
||||||
sb.and("keyword", sb.entity().getName(), SearchCriteria.Op.LIKE);
|
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();
|
SearchCriteria<KubernetesSupportedVersionVO> sc = sb.create();
|
||||||
String keyword = cmd.getKeyword();
|
String keyword = cmd.getKeyword();
|
||||||
if (versionId != null) {
|
if (versionId != null) {
|
||||||
@ -295,6 +305,9 @@ public class KubernetesVersionManagerImpl extends ManagerBase implements Kuberne
|
|||||||
if(keyword != null){
|
if(keyword != null){
|
||||||
sc.setParameters("keyword", "%" + keyword + "%");
|
sc.setParameters("keyword", "%" + keyword + "%");
|
||||||
}
|
}
|
||||||
|
if (StringUtils.isNotBlank(arch)) {
|
||||||
|
sc.setJoinParameters("isoSearch", "arch", arch);
|
||||||
|
}
|
||||||
Pair<List<KubernetesSupportedVersionVO>, Integer> versionsAndCount =
|
Pair<List<KubernetesSupportedVersionVO>, Integer> versionsAndCount =
|
||||||
kubernetesSupportedVersionDao.searchAndCount(sc, searchFilter);
|
kubernetesSupportedVersionDao.searchAndCount(sc, searchFilter);
|
||||||
List<KubernetesSupportedVersionVO> versions =
|
List<KubernetesSupportedVersionVO> versions =
|
||||||
|
|||||||
@ -66,6 +66,11 @@ public class ListKubernetesSupportedVersionsCmd extends BaseListCmd {
|
|||||||
description = "the ID of the minimum Kubernetes supported version")
|
description = "the ID of the minimum Kubernetes supported version")
|
||||||
private Long minimumKubernetesVersionId;
|
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 ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -85,6 +90,10 @@ public class ListKubernetesSupportedVersionsCmd extends BaseListCmd {
|
|||||||
return minimumSemanticVersion;
|
return minimumSemanticVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getMinimumKubernetesVersionId() {
|
public Long getMinimumKubernetesVersionId() {
|
||||||
return minimumKubernetesVersionId;
|
return minimumKubernetesVersionId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,6 +54,10 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||||||
@Param(description = "the state of the binaries ISO for Kubernetes supported version")
|
@Param(description = "the state of the binaries ISO for Kubernetes supported version")
|
||||||
private String isoState;
|
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)
|
@SerializedName(ApiConstants.ZONE_ID)
|
||||||
@Param(description = "the id of the zone in which Kubernetes supported version is available")
|
@Param(description = "the id of the zone in which Kubernetes supported version is available")
|
||||||
private String zoneId;
|
private String zoneId;
|
||||||
@ -138,6 +142,14 @@ public class KubernetesSupportedVersionResponse extends BaseResponse {
|
|||||||
this.isoState = isoState;
|
this.isoState = isoState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getIsoArch() {
|
||||||
|
return isoArch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsoArch(String isoArch) {
|
||||||
|
this.isoArch = isoArch;
|
||||||
|
}
|
||||||
|
|
||||||
public String getZoneId() {
|
public String getZoneId() {
|
||||||
return zoneId;
|
return zoneId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ import org.springframework.test.util.ReflectionTestUtils;
|
|||||||
|
|
||||||
import com.cloud.api.query.dao.TemplateJoinDao;
|
import com.cloud.api.query.dao.TemplateJoinDao;
|
||||||
import com.cloud.api.query.vo.TemplateJoinVO;
|
import com.cloud.api.query.vo.TemplateJoinVO;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class KubernetesVersionManagerImplTest {
|
public class KubernetesVersionManagerImplTest {
|
||||||
@ -57,6 +58,7 @@ public class KubernetesVersionManagerImplTest {
|
|||||||
Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L);
|
Mockito.when(kubernetesSupportedVersion.getIsoId()).thenReturn(1L);
|
||||||
KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse();
|
KubernetesSupportedVersionResponse response = new KubernetesSupportedVersionResponse();
|
||||||
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
|
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
|
||||||
|
Mockito.when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid);
|
Mockito.when(templateJoinVO.getUuid()).thenReturn(uuid);
|
||||||
Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO);
|
Mockito.when(templateJoinDao.findById(1L)).thenReturn(templateJoinVO);
|
||||||
|
|||||||
@ -125,6 +125,7 @@ public class KubernetesVersionServiceTest {
|
|||||||
|
|
||||||
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
|
TemplateJoinVO templateJoinVO = Mockito.mock(TemplateJoinVO.class);
|
||||||
when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready);
|
when(templateJoinVO.getState()).thenReturn(ObjectInDataStoreStateMachine.State.Ready);
|
||||||
|
when(templateJoinVO.getArch()).thenReturn(CPU.CPUArch.getDefault());
|
||||||
when(templateJoinDao.findById(Mockito.anyLong())).thenReturn(templateJoinVO);
|
when(templateJoinDao.findById(Mockito.anyLong())).thenReturn(templateJoinVO);
|
||||||
|
|
||||||
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
KubernetesSupportedVersionVO versionVO = Mockito.mock(KubernetesSupportedVersionVO.class);
|
||||||
|
|||||||
@ -16,6 +16,12 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.network.lb;
|
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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Iterator;
|
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.framework.config.dao.ConfigurationDao;
|
||||||
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
|
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
|
||||||
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
|
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import com.cloud.agent.AgentManager;
|
||||||
import com.cloud.agent.api.Answer;
|
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.DomainRouterDao;
|
||||||
import com.cloud.vm.dao.NicDao;
|
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 {
|
public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements InternalLoadBalancerVMManager, InternalLoadBalancerVMService, VirtualMachineGuru {
|
||||||
static final private String InternalLbVmNamePrefix = "b";
|
static final private String InternalLbVmNamePrefix = "b";
|
||||||
|
|
||||||
@ -732,6 +733,70 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
|
|||||||
return internalLbVms;
|
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,
|
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,
|
final long svcOffId, final Long vpcId, final LinkedHashMap<Network, List<? extends NicProfile>> networks, final boolean startVm) throws ConcurrentOperationException,
|
||||||
InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException,
|
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
|
// 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);
|
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();
|
long userId = CallContext.current().getCallingUserId();
|
||||||
if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
|
if (CallContext.current().getCallingAccount().getId() != owner.getId()) {
|
||||||
List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
|
List<UserVO> userVOs = _userDao.listByAccount(owner.getAccountId());
|
||||||
@ -780,16 +816,31 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internalLbVm =
|
int allocateRetry = 0;
|
||||||
new DomainRouterVO(id, routerOffering.getId(), internalLbProviderId, VirtualMachineName.getSystemVmName(id, _instance, InternalLbVmNamePrefix),
|
int startRetry = 0;
|
||||||
template.getId(), template.getHypervisorType(), template.getGuestOSId(), owner.getDomainId(), owner.getId(), userId, false, RedundantState.UNKNOWN, false, false, VirtualMachine.Type.InternalLoadBalancerVm, vpcId);
|
DomainRouterVO internalLbVm = null;
|
||||||
internalLbVm.setRole(Role.INTERNAL_LB_VM);
|
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
|
||||||
internalLbVm = _internalLbVmDao.persist(internalLbVm);
|
final HypervisorType hType = iter.next();
|
||||||
_itMgr.allocate(internalLbVm.getInstanceName(), template, routerOffering, networks, plan, null);
|
try {
|
||||||
internalLbVm = _internalLbVmDao.findById(internalLbVm.getId());
|
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) {
|
} catch (final InsufficientCapacityException ex) {
|
||||||
if (allocateRetry < 2 && iter.hasNext()) {
|
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;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
throw ex;
|
throw ex;
|
||||||
@ -804,8 +855,7 @@ public class InternalLoadBalancerVMManagerImpl extends ManagerBase implements In
|
|||||||
break;
|
break;
|
||||||
} catch (final InsufficientCapacityException ex) {
|
} catch (final InsufficientCapacityException ex) {
|
||||||
if (startRetry < 2 && iter.hasNext()) {
|
if (startRetry < 2 && iter.hasNext()) {
|
||||||
logger.debug("Failed to start the Internal lb vm " + internalLbVm + " with hypervisor type " + hType + ", " +
|
logger.debug("Failed to start the Internal lb vm {} with hypervisor type {}, destroying it and recreating one more time", internalLbVm, hType);
|
||||||
"destroying it and recreating one more time");
|
|
||||||
// destroy the internal lb vm
|
// destroy the internal lb vm
|
||||||
destroyInternalLbVm(internalLbVm.getId(), _accountMgr.getSystemAccount(), User.UID_SYSTEM);
|
destroyInternalLbVm(internalLbVm.getId(), _accountMgr.getSystemAccount(), User.UID_SYSTEM);
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1718,6 +1718,7 @@ public class ApiResponseHelper implements ResponseGenerator {
|
|||||||
if (template != null) {
|
if (template != null) {
|
||||||
vmResponse.setTemplateId(template.getUuid());
|
vmResponse.setTemplateId(template.getUuid());
|
||||||
vmResponse.setTemplateName(template.getName());
|
vmResponse.setTemplateName(template.getName());
|
||||||
|
vmResponse.setArch(template.getArch().getType());
|
||||||
}
|
}
|
||||||
vmResponse.setCreated(vm.getCreated());
|
vmResponse.setCreated(vm.getCreated());
|
||||||
vmResponse.setHypervisor(vm.getHypervisorType().getHypervisorDisplayName());
|
vmResponse.setHypervisor(vm.getHypervisorType().getHypervisorDisplayName());
|
||||||
|
|||||||
@ -1298,6 +1298,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
Long userId = cmd.getUserId();
|
Long userId = cmd.getUserId();
|
||||||
Long userdataId = cmd.getUserdataId();
|
Long userdataId = cmd.getUserdataId();
|
||||||
Map<String, String> tags = cmd.getTags();
|
Map<String, String> tags = cmd.getTags();
|
||||||
|
final CPU.CPUArch arch = cmd.getArch();
|
||||||
|
|
||||||
boolean isAdmin = false;
|
boolean isAdmin = false;
|
||||||
boolean isRootAdmin = false;
|
boolean isRootAdmin = false;
|
||||||
@ -1525,8 +1526,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
}
|
}
|
||||||
|
|
||||||
Boolean isVnf = cmd.getVnf();
|
Boolean isVnf = cmd.getVnf();
|
||||||
if (isVnf != null) {
|
boolean templateJoinNeeded = isVnf != null || arch != null;
|
||||||
|
if (templateJoinNeeded) {
|
||||||
SearchBuilder<VMTemplateVO> templateSearch = _templateDao.createSearchBuilder();
|
SearchBuilder<VMTemplateVO> templateSearch = _templateDao.createSearchBuilder();
|
||||||
|
templateSearch.and("templateArch", templateSearch.entity().getArch(), Op.EQ);
|
||||||
templateSearch.and("templateTypeEQ", templateSearch.entity().getTemplateType(), Op.EQ);
|
templateSearch.and("templateTypeEQ", templateSearch.entity().getTemplateType(), Op.EQ);
|
||||||
templateSearch.and("templateTypeNEQ", templateSearch.entity().getTemplateType(), Op.NEQ);
|
templateSearch.and("templateTypeNEQ", templateSearch.entity().getTemplateType(), Op.NEQ);
|
||||||
|
|
||||||
@ -1655,6 +1658,9 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
userVmSearchCriteria.setJoinParameters("vmTemplate", "templateTypeNEQ", TemplateType.VNF);
|
userVmSearchCriteria.setJoinParameters("vmTemplate", "templateTypeNEQ", TemplateType.VNF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (arch != null) {
|
||||||
|
userVmSearchCriteria.setJoinParameters("vmTemplate", "templateArch", arch);
|
||||||
|
}
|
||||||
|
|
||||||
if (isRootAdmin) {
|
if (isRootAdmin) {
|
||||||
if (podId != null) {
|
if (podId != null) {
|
||||||
@ -2355,6 +2361,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
Long startIndex = cmd.getStartIndex();
|
Long startIndex = cmd.getStartIndex();
|
||||||
Long pageSize = cmd.getPageSizeVal();
|
Long pageSize = cmd.getPageSizeVal();
|
||||||
Hypervisor.HypervisorType hypervisorType = cmd.getHypervisor();
|
Hypervisor.HypervisorType hypervisorType = cmd.getHypervisor();
|
||||||
|
final CPU.CPUArch arch = cmd.getArch();
|
||||||
|
|
||||||
Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
|
Filter searchFilter = new Filter(HostVO.class, "id", Boolean.TRUE, startIndex, pageSize);
|
||||||
|
|
||||||
@ -2370,6 +2377,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
hostSearchBuilder.and("clusterId", hostSearchBuilder.entity().getClusterId(), SearchCriteria.Op.EQ);
|
hostSearchBuilder.and("clusterId", hostSearchBuilder.entity().getClusterId(), SearchCriteria.Op.EQ);
|
||||||
hostSearchBuilder.and("resourceState", hostSearchBuilder.entity().getResourceState(), SearchCriteria.Op.EQ);
|
hostSearchBuilder.and("resourceState", hostSearchBuilder.entity().getResourceState(), SearchCriteria.Op.EQ);
|
||||||
hostSearchBuilder.and("hypervisor_type", hostSearchBuilder.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
hostSearchBuilder.and("hypervisor_type", hostSearchBuilder.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
||||||
|
hostSearchBuilder.and("arch", hostSearchBuilder.entity().getArch(), SearchCriteria.Op.EQ);
|
||||||
|
|
||||||
if (keyword != null) {
|
if (keyword != null) {
|
||||||
hostSearchBuilder.and().op("keywordName", hostSearchBuilder.entity().getName(), SearchCriteria.Op.LIKE);
|
hostSearchBuilder.and().op("keywordName", hostSearchBuilder.entity().getName(), SearchCriteria.Op.LIKE);
|
||||||
@ -2450,6 +2458,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
|
|||||||
sc.setParameters("hypervisor_type", hypervisorType);
|
sc.setParameters("hypervisor_type", hypervisorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arch != null) {
|
||||||
|
sc.setParameters("arch", arch);
|
||||||
|
}
|
||||||
|
|
||||||
Pair<List<HostVO>, Integer> uniqueHostPair = hostDao.searchAndCount(sc, searchFilter);
|
Pair<List<HostVO>, Integer> uniqueHostPair = hostDao.searchAndCount(sc, searchFilter);
|
||||||
Integer count = uniqueHostPair.second();
|
Integer count = uniqueHostPair.second();
|
||||||
List<Long> hostIds = uniqueHostPair.first().stream().map(HostVO::getId).collect(Collectors.toList());
|
List<Long> hostIds = uniqueHostPair.first().stream().map(HostVO::getId).collect(Collectors.toList());
|
||||||
|
|||||||
@ -88,6 +88,7 @@ public class DomainRouterJoinDaoImpl extends GenericDaoBase<DomainRouterJoinVO,
|
|||||||
routerResponse.setZoneId(router.getDataCenterUuid());
|
routerResponse.setZoneId(router.getDataCenterUuid());
|
||||||
routerResponse.setName(router.getName());
|
routerResponse.setName(router.getName());
|
||||||
routerResponse.setTemplateId(router.getTemplateUuid());
|
routerResponse.setTemplateId(router.getTemplateUuid());
|
||||||
|
routerResponse.setArch(router.getArch().getType());
|
||||||
VMTemplateVO template = ApiDBUtils.findTemplateById(router.getTemplateId());
|
VMTemplateVO template = ApiDBUtils.findTemplateById(router.getTemplateId());
|
||||||
if (template != null) {
|
if (template != null) {
|
||||||
routerResponse.setTemplateName(template.getName());
|
routerResponse.setTemplateName(template.getName());
|
||||||
|
|||||||
@ -188,6 +188,7 @@ public class UserVmJoinDaoImpl extends GenericDaoBaseWithTagInformation<UserVmJo
|
|||||||
userVmResponse.setInstanceName(userVm.getInstanceName());
|
userVmResponse.setInstanceName(userVm.getInstanceName());
|
||||||
userVmResponse.setHostId(userVm.getHostUuid());
|
userVmResponse.setHostId(userVm.getHostUuid());
|
||||||
userVmResponse.setHostName(userVm.getHostName());
|
userVmResponse.setHostName(userVm.getHostName());
|
||||||
|
userVmResponse.setArch(userVm.getArch());
|
||||||
}
|
}
|
||||||
if (userVm.getHostStatus() != null) {
|
if (userVm.getHostStatus() != null) {
|
||||||
userVmResponse.setHostControlState(ControlState.getControlState(userVm.getHostStatus(), userVm.getHostResourceState()).toString());
|
userVmResponse.setHostControlState(ControlState.getControlState(userVm.getHostStatus(), userVm.getHostResourceState()).toString());
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import javax.persistence.Enumerated;
|
|||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.host.Status;
|
import com.cloud.host.Status;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
import com.cloud.network.Network.GuestType;
|
import com.cloud.network.Network.GuestType;
|
||||||
@ -38,6 +39,8 @@ import com.cloud.user.Account;
|
|||||||
import com.cloud.utils.db.GenericDao;
|
import com.cloud.utils.db.GenericDao;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.VirtualMachine.State;
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
|
||||||
|
import org.apache.cloudstack.util.CPUArchConverter;
|
||||||
import org.apache.cloudstack.util.HypervisorTypeConverter;
|
import org.apache.cloudstack.util.HypervisorTypeConverter;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@ -143,6 +146,10 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||||||
@Convert(converter = HypervisorTypeConverter.class)
|
@Convert(converter = HypervisorTypeConverter.class)
|
||||||
private Hypervisor.HypervisorType hypervisorType;
|
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)
|
@Column(name = "template_id", updatable = true, nullable = true, length = 17)
|
||||||
private long templateId;
|
private long templateId;
|
||||||
|
|
||||||
@ -376,6 +383,10 @@ public class DomainRouterJoinVO extends BaseViewVO implements ControlledViewEnti
|
|||||||
return hypervisorType;
|
return hypervisorType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CPU.CPUArch getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getClusterId() {
|
public Long getClusterId() {
|
||||||
return clusterId;
|
return clusterId;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -439,6 +439,9 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||||||
@Column(name = "delete_protection")
|
@Column(name = "delete_protection")
|
||||||
protected Boolean deleteProtection;
|
protected Boolean deleteProtection;
|
||||||
|
|
||||||
|
@Column(name = "arch")
|
||||||
|
protected String arch;
|
||||||
|
|
||||||
|
|
||||||
public UserVmJoinVO() {
|
public UserVmJoinVO() {
|
||||||
// Empty constructor
|
// Empty constructor
|
||||||
@ -977,4 +980,8 @@ public class UserVmJoinVO extends BaseViewWithTagInformationVO implements Contro
|
|||||||
public String getUserDataDetails() {
|
public String getUserDataDetails() {
|
||||||
return userDataDetails;
|
return userDataDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getArch() {
|
||||||
|
return arch;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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.PrimaryDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||||
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
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.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
|
|
||||||
@ -82,9 +81,9 @@ import com.cloud.exception.InsufficientAddressCapacityException;
|
|||||||
import com.cloud.exception.InsufficientCapacityException;
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
import com.cloud.exception.OperationTimedoutException;
|
import com.cloud.exception.OperationTimedoutException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.host.Host;
|
|
||||||
import com.cloud.host.Host.Type;
|
import com.cloud.host.Host.Type;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
|
import com.cloud.host.Status;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.info.ConsoleProxyConnectionInfo;
|
import com.cloud.info.ConsoleProxyConnectionInfo;
|
||||||
@ -111,10 +110,8 @@ import com.cloud.resource.ServerResource;
|
|||||||
import com.cloud.resource.UnableDeleteHostException;
|
import com.cloud.resource.UnableDeleteHostException;
|
||||||
import com.cloud.service.ServiceOfferingVO;
|
import com.cloud.service.ServiceOfferingVO;
|
||||||
import com.cloud.service.dao.ServiceOfferingDao;
|
import com.cloud.service.dao.ServiceOfferingDao;
|
||||||
import com.cloud.storage.DataStoreRole;
|
|
||||||
import com.cloud.storage.Storage;
|
import com.cloud.storage.Storage;
|
||||||
import com.cloud.storage.StoragePoolStatus;
|
import com.cloud.storage.StoragePoolStatus;
|
||||||
import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
|
|
||||||
import com.cloud.storage.VMTemplateVO;
|
import com.cloud.storage.VMTemplateVO;
|
||||||
import com.cloud.storage.dao.VMTemplateDao;
|
import com.cloud.storage.dao.VMTemplateDao;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
@ -281,9 +278,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
HostVO host = _hostDao.findById(agentId);
|
||||||
if (host.getType() == Type.ConsoleProxy) {
|
if (host.getType() == Type.ConsoleProxy) {
|
||||||
String name = host.getName();
|
String name = host.getName();
|
||||||
@ -465,7 +462,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
public ConsoleProxyVO startProxy(long proxyVmId, boolean ignoreRestartSetting) {
|
public ConsoleProxyVO startProxy(long proxyVmId, boolean ignoreRestartSetting) {
|
||||||
try {
|
try {
|
||||||
ConsoleProxyVO proxy = consoleProxyDao.findById(proxyVmId);
|
ConsoleProxyVO proxy = consoleProxyDao.findById(proxyVmId);
|
||||||
if (proxy.getState() == VirtualMachine.State.Running) {
|
if (proxy.getState() == State.Running) {
|
||||||
return proxy;
|
return proxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +471,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy.getState() == VirtualMachine.State.Stopped) {
|
if (proxy.getState() == State.Stopped) {
|
||||||
virtualMachineManager.advanceStart(proxy.getUuid(), null, null);
|
virtualMachineManager.advanceStart(proxy.getUuid(), null, null);
|
||||||
proxy = consoleProxyDao.findById(proxy.getId());
|
proxy = consoleProxyDao.findById(proxy.getId());
|
||||||
return proxy;
|
return proxy;
|
||||||
@ -575,12 +572,13 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
HypervisorType availableHypervisor = resourceManager.getAvailableHypervisor(dataCenterId);
|
HypervisorType availableHypervisor = resourceManager.getAvailableHypervisor(dataCenterId);
|
||||||
VMTemplateVO template = vmTemplateDao.findSystemVMReadyTemplate(dataCenterId, availableHypervisor);
|
List<VMTemplateVO> templates = vmTemplateDao.findSystemVMReadyTemplates(dataCenterId, availableHypervisor,
|
||||||
if (template == null) {
|
ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenterId));
|
||||||
|
if (CollectionUtils.isEmpty(templates)) {
|
||||||
throw new CloudRuntimeException("Not able to find the System templates or not downloaded in zone " + dataCenterId);
|
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");
|
long proxyVmId = (Long)context.get("proxyVmId");
|
||||||
if (proxyVmId == 0) {
|
if (proxyVmId == 0) {
|
||||||
@ -673,7 +671,26 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
return defaultNetworks.get(0);
|
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");
|
long id = consoleProxyDao.getNextInSequence(Long.class, "id");
|
||||||
String name = VirtualMachineName.getConsoleProxyName(id, instance);
|
String name = VirtualMachineName.getConsoleProxyName(id, instance);
|
||||||
@ -702,18 +719,23 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
if (serviceOffering == null) {
|
if (serviceOffering == null) {
|
||||||
serviceOffering = serviceOfferingDao.findDefaultSystemOffering(ServiceOffering.consoleProxyDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
|
serviceOffering = serviceOfferingDao.findDefaultSystemOffering(ServiceOffering.consoleProxyDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
|
||||||
}
|
}
|
||||||
ConsoleProxyVO proxy =
|
ConsoleProxyVO proxy = null;
|
||||||
new ConsoleProxyVO(id, serviceOffering.getId(), name, template.getId(), template.getHypervisorType(), template.getGuestOSId(), dataCenterId,
|
for (final Iterator<VMTemplateVO> templateIterator = templates.iterator(); templateIterator.hasNext();) {
|
||||||
systemAcct.getDomainId(), systemAcct.getId(), accountManager.getSystemUser().getId(), 0, serviceOffering.isOfferHA());
|
VMTemplateVO template = templateIterator.next();
|
||||||
proxy.setDynamicallyScalable(template.isDynamicallyScalable());
|
proxy = createOrUpdateConsoleProxy(proxy, dataCenterId, id, name, serviceOffering, template, systemAcct);
|
||||||
proxy.setLimitCpuUse(serviceOffering.getLimitCpuUse());
|
|
||||||
proxy = consoleProxyDao.persist(proxy);
|
|
||||||
try {
|
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) {
|
} catch (InsufficientCapacityException e) {
|
||||||
String message = String.format("Unable to allocate proxy [%s] on zone [%s] due to [%s].", proxy.toString(), dataCenterId, e.getMessage());
|
if (templateIterator.hasNext()) {
|
||||||
logger.warn(message, e);
|
logger.debug("Unable to allocate proxy {} with {} in {} due to [{}]. Retrying with another template", proxy, template, dc, e.getMessage(), e);
|
||||||
throw new CloudRuntimeException(message, e);
|
continue;
|
||||||
|
}
|
||||||
|
throw new CloudRuntimeException("Failed to allocate proxy [%s] in zone [%s] with available templates", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> context = new HashMap<>();
|
Map<String, Object> context = new HashMap<>();
|
||||||
@ -737,8 +759,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
updateConsoleProxyStatus(answer.getDetails(), answer.getProxyVmId());
|
updateConsoleProxyStatus(answer.getDetails(), answer.getProxyVmId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleAgentDisconnect(long agentId, com.cloud.host.Status state) {
|
public void handleAgentDisconnect(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);
|
HostVO host = hostDao.findById(agentId);
|
||||||
if (host.getType() == Type.ConsoleProxy) {
|
if (host.getType() == Type.ConsoleProxy) {
|
||||||
String name = host.getName();
|
String name = host.getName();
|
||||||
@ -789,8 +811,8 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
List<ConsoleProxyVO> l =
|
List<ConsoleProxyVO> l =
|
||||||
consoleProxyDao.getProxyListInStates(dcId, VirtualMachine.State.Starting, VirtualMachine.State.Running, VirtualMachine.State.Stopping,
|
consoleProxyDao.getProxyListInStates(dcId, State.Starting, State.Running, State.Stopping,
|
||||||
VirtualMachine.State.Stopped, VirtualMachine.State.Migrating, VirtualMachine.State.Shutdown, VirtualMachine.State.Unknown);
|
State.Stopped, State.Migrating, State.Shutdown, State.Unknown);
|
||||||
|
|
||||||
String value = configurationDao.getValue(Config.ConsoleProxyLaunchMax.key());
|
String value = configurationDao.getValue(Config.ConsoleProxyLaunchMax.key());
|
||||||
int launchLimit = NumbersUtil.parseInt(value, 10);
|
int launchLimit = NumbersUtil.parseInt(value, 10);
|
||||||
@ -876,22 +898,15 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
}
|
}
|
||||||
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenter.getId());
|
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenter.getId());
|
||||||
if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
|
if (zoneHostInfo != null && isZoneHostReady(zoneHostInfo)) {
|
||||||
VMTemplateVO template = vmTemplateDao.findSystemVMReadyTemplate(dataCenter.getId(), HypervisorType.Any);
|
List<VMTemplateVO> templates = vmTemplateDao.findSystemVMReadyTemplates(dataCenter.getId(),
|
||||||
if (template == null) {
|
HypervisorType.Any, null);
|
||||||
|
if (CollectionUtils.isEmpty(templates)) {
|
||||||
if (logger.isDebugEnabled()) {
|
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);
|
logger.debug("System vm template is not ready at data center {}, wait until it is ready to launch console proxy vm", dataCenter);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TemplateDataStoreVO templateHostRef;
|
boolean useLocalStorage = BooleanUtils.toBoolean(ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenter.getId()));
|
||||||
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 hasDatacenterStoragePoolHostInfo = consoleProxyDao.hasDatacenterStoragePoolHostInfo(dataCenter.getId(), !useLocalStorage);
|
boolean hasDatacenterStoragePoolHostInfo = consoleProxyDao.hasDatacenterStoragePoolHostInfo(dataCenter.getId(), !useLocalStorage);
|
||||||
if (hasDatacenterStoragePoolHostInfo) {
|
if (hasDatacenterStoragePoolHostInfo) {
|
||||||
return true;
|
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");
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
@ -912,9 +922,9 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
|
private boolean isZoneHostReady(ZoneHostInfo zoneHostInfo) {
|
||||||
int expectedFlags;
|
int expectedFlags;
|
||||||
if (useStorageVm) {
|
if (useStorageVm) {
|
||||||
expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK;
|
expectedFlags = ZoneHostInfo.ROUTING_HOST_MASK;
|
||||||
} else {
|
} else {
|
||||||
expectedFlags = RunningHostInfoAgregator.ZoneHostInfo.ALL_HOST_MASK;
|
expectedFlags = ZoneHostInfo.ALL_HOST_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
|
return (zoneHostInfo.getFlags() & expectedFlags) == expectedFlags;
|
||||||
@ -1093,7 +1103,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
proxy.setPrivateIpAddress(null);
|
proxy.setPrivateIpAddress(null);
|
||||||
consoleProxyDao.update(proxy.getId(), proxy);
|
consoleProxyDao.update(proxy.getId(), proxy);
|
||||||
consoleProxyDao.remove(vmId);
|
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) {
|
if (host != null) {
|
||||||
logger.debug("Removing host [{}] entry for proxy [{}].", host, proxy);
|
logger.debug("Removing host [{}] entry for proxy [{}].", host, proxy);
|
||||||
return hostDao.remove(host.getId());
|
return hostDao.remove(host.getId());
|
||||||
@ -1511,7 +1521,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
return false;
|
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 (l.size() > 0) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Zone {} has {} console proxy VM(s) in transition state", zone, l.size());
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
host.setType(com.cloud.host.Host.Type.ConsoleProxy);
|
host.setType(Type.ConsoleProxy);
|
||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1584,7 +1594,7 @@ public class ConsoleProxyManagerImpl extends ManagerBase implements ConsoleProxy
|
|||||||
|
|
||||||
protected HostVO findConsoleProxyHostByName(String name) {
|
protected HostVO findConsoleProxyHostByName(String name) {
|
||||||
QueryBuilder<HostVO> sc = QueryBuilder.create(HostVO.class);
|
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);
|
sc.and(sc.entity().getName(), Op.EQ, name);
|
||||||
return sc.find();
|
return sc.find();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,6 @@ import java.util.Map;
|
|||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
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.api.ApiConstants;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
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.network.router.deployment.RouterDeploymentDefinition;
|
||||||
import org.apache.cloudstack.utils.CloudStackVersion;
|
import org.apache.cloudstack.utils.CloudStackVersion;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.logging.log4j.Logger;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import com.cloud.agent.AgentManager;
|
||||||
import com.cloud.agent.api.Answer;
|
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.RedundantState;
|
||||||
import com.cloud.network.router.VirtualRouter.Role;
|
import com.cloud.network.router.VirtualRouter.Role;
|
||||||
import com.cloud.network.rules.LbStickinessMethod;
|
import com.cloud.network.rules.LbStickinessMethod;
|
||||||
|
import com.cloud.network.vpc.dao.VpcDao;
|
||||||
import com.cloud.network.vpn.Site2SiteVpnManager;
|
import com.cloud.network.vpn.Site2SiteVpnManager;
|
||||||
import com.cloud.offering.NetworkOffering;
|
import com.cloud.offering.NetworkOffering;
|
||||||
import com.cloud.resource.ResourceManager;
|
import com.cloud.resource.ResourceManager;
|
||||||
@ -104,6 +103,7 @@ import com.cloud.user.dao.UserDao;
|
|||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.utils.net.NetUtils;
|
import com.cloud.utils.net.NetUtils;
|
||||||
|
import com.cloud.utils.validation.ChecksumUtil;
|
||||||
import com.cloud.vm.DomainRouterVO;
|
import com.cloud.vm.DomainRouterVO;
|
||||||
import com.cloud.vm.Nic;
|
import com.cloud.vm.Nic;
|
||||||
import com.cloud.vm.NicProfile;
|
import com.cloud.vm.NicProfile;
|
||||||
@ -498,18 +498,77 @@ public class NetworkHelperImpl implements NetworkHelper {
|
|||||||
return templateName;
|
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
|
@Override
|
||||||
public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, final boolean startRouter)
|
public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, final boolean startRouter)
|
||||||
throws InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException {
|
throws InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException {
|
||||||
|
|
||||||
final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getServiceOfferingId());
|
final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getServiceOfferingId());
|
||||||
|
final boolean offerHA = routerOffering.isOfferHA();
|
||||||
final Account owner = routerDeploymentDefinition.getOwner();
|
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.
|
// Router is the network element, we don't know the hypervisor type yet.
|
||||||
// Try to allocate the domR twice using diff hypervisors, and when
|
// Try to allocate the domR twice using diff hypervisors, and when
|
||||||
// failed both times, throw the exception up
|
// failed both times, throw the exception up
|
||||||
final List<HypervisorType> hypervisors = getHypervisors(routerDeploymentDefinition);
|
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;
|
DomainRouterVO router = null;
|
||||||
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
|
for (final Iterator<HypervisorType> iter = hypervisors.iterator(); iter.hasNext();) {
|
||||||
final HypervisorType hType = iter.next();
|
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()
|
logger.debug(String.format("Allocating the VR with id=%s in datacenter %s with the hypervisor type %s", id, routerDeploymentDefinition.getDest()
|
||||||
.getDataCenter(), hType));
|
.getDataCenter(), hType));
|
||||||
}
|
}
|
||||||
|
final long zoneId = routerDeploymentDefinition.getDest().getDataCenter().getId();
|
||||||
final String templateName = retrieveTemplateName(hType, routerDeploymentDefinition.getDest().getDataCenter().getId());
|
final String templateName = retrieveTemplateName(hType, zoneId);
|
||||||
final VMTemplateVO template = _templateDao.findRoutingTemplate(hType, templateName);
|
final String preferredArch = ResourceManager.SystemVmPreferredArchitecture.valueIn(zoneId);
|
||||||
|
final List<VMTemplateVO> templates = _templateDao.findRoutingTemplates(hType, templateName,
|
||||||
if (template == null) {
|
preferredArch);
|
||||||
logger.debug(hType + " won't support system vm, skip it");
|
if (CollectionUtils.isEmpty(templates)) {
|
||||||
|
logger.debug("{} won't support system vm, skip it", hType);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
router = deployRouterWithTemplates(router, id, routerDeploymentDefinition, owner, userId,
|
||||||
final boolean offerHA = routerOffering.isOfferHA();
|
routerOffering, offerHA, vpcId, templates);
|
||||||
|
|
||||||
// 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());
|
|
||||||
} catch (final InsufficientCapacityException ex) {
|
} catch (final InsufficientCapacityException ex) {
|
||||||
if (iter.hasNext()) {
|
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;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
throw ex;
|
throw ex;
|
||||||
|
|||||||
@ -1201,6 +1201,12 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arch != null) {
|
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());
|
cluster.setArch(arch.getType());
|
||||||
doUpdate = true;
|
doUpdate = true;
|
||||||
}
|
}
|
||||||
@ -3537,6 +3543,10 @@ public class ResourceManagerImpl extends ManagerBase implements ResourceManager,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConfigKey<?>[] getConfigKeys() {
|
public ConfigKey<?>[] getConfigKeys() {
|
||||||
return new ConfigKey<?>[] {KvmSshToAgentEnabled, HOST_MAINTENANCE_LOCAL_STRATEGY};
|
return new ConfigKey<?>[] {
|
||||||
|
KvmSshToAgentEnabled,
|
||||||
|
HOST_MAINTENANCE_LOCAL_STRATEGY,
|
||||||
|
SystemVmPreferredArchitecture
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,7 +44,6 @@ import javax.crypto.spec.SecretKeySpec;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
import com.cloud.cpu.CPU;
|
|
||||||
import org.apache.cloudstack.acl.ControlledEntity;
|
import org.apache.cloudstack.acl.ControlledEntity;
|
||||||
import org.apache.cloudstack.acl.SecurityChecker;
|
import org.apache.cloudstack.acl.SecurityChecker;
|
||||||
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
|
import org.apache.cloudstack.affinity.AffinityGroupProcessor;
|
||||||
@ -674,6 +673,7 @@ import com.cloud.configuration.Config;
|
|||||||
import com.cloud.configuration.ConfigurationManagerImpl;
|
import com.cloud.configuration.ConfigurationManagerImpl;
|
||||||
import com.cloud.consoleproxy.ConsoleProxyManagementState;
|
import com.cloud.consoleproxy.ConsoleProxyManagementState;
|
||||||
import com.cloud.consoleproxy.ConsoleProxyManager;
|
import com.cloud.consoleproxy.ConsoleProxyManager;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.AccountVlanMapVO;
|
import com.cloud.dc.AccountVlanMapVO;
|
||||||
import com.cloud.dc.ClusterVO;
|
import com.cloud.dc.ClusterVO;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
@ -1274,6 +1274,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
final Object clusterType = cmd.getClusterType();
|
final Object clusterType = cmd.getClusterType();
|
||||||
final Object allocationState = cmd.getAllocationState();
|
final Object allocationState = cmd.getAllocationState();
|
||||||
final String keyword = cmd.getKeyword();
|
final String keyword = cmd.getKeyword();
|
||||||
|
final CPU.CPUArch arch = cmd.getArch();
|
||||||
zoneId = _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), zoneId);
|
zoneId = _accountMgr.checkAccessAndSpecifyAuthority(CallContext.current().getCallingAccount(), zoneId);
|
||||||
|
|
||||||
final Filter searchFilter = new Filter(ClusterVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
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("hypervisorType", sb.entity().getHypervisorType(), SearchCriteria.Op.EQ);
|
||||||
sb.and("clusterType", sb.entity().getClusterType(), SearchCriteria.Op.EQ);
|
sb.and("clusterType", sb.entity().getClusterType(), SearchCriteria.Op.EQ);
|
||||||
sb.and("allocationState", sb.entity().getAllocationState(), 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();
|
final SearchCriteria<ClusterVO> sc = sb.create();
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
@ -1325,6 +1327,10 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
|
sc.addAnd("name", SearchCriteria.Op.SC, ssc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arch != null) {
|
||||||
|
sc.setParameters("arch", arch);
|
||||||
|
}
|
||||||
|
|
||||||
final Pair<List<ClusterVO>, Integer> result = _clusterDao.searchAndCount(sc, searchFilter);
|
final Pair<List<ClusterVO>, Integer> result = _clusterDao.searchAndCount(sc, searchFilter);
|
||||||
return new Pair<>(result.first(), result.second());
|
return new Pair<>(result.first(), result.second());
|
||||||
}
|
}
|
||||||
@ -4187,6 +4193,7 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
|
|||||||
final Long podId = cmd.getPodId();
|
final Long podId = cmd.getPodId();
|
||||||
final Long hostId = cmd.getHostId();
|
final Long hostId = cmd.getHostId();
|
||||||
final Long storageId = cmd.getStorageId();
|
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 Filter searchFilter = new Filter(VMInstanceVO.class, "id", true, cmd.getStartIndex(), cmd.getPageSizeVal());
|
||||||
final SearchBuilder<VMInstanceVO> sb = _vmInstanceDao.createSearchBuilder();
|
final SearchBuilder<VMInstanceVO> sb = _vmInstanceDao.createSearchBuilder();
|
||||||
@ -4213,6 +4220,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();
|
final SearchCriteria<VMInstanceVO> sc = sb.create();
|
||||||
|
|
||||||
if (keyword != null) {
|
if (keyword != null) {
|
||||||
@ -4260,6 +4274,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);
|
final Pair<List<VMInstanceVO>, Integer> result = _vmInstanceDao.searchAndCount(sc, searchFilter);
|
||||||
return new Pair<>(result.first(), result.second());
|
return new Pair<>(result.first(), result.second());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -178,6 +178,7 @@ import com.cloud.configuration.Config;
|
|||||||
import com.cloud.configuration.ConfigurationManager;
|
import com.cloud.configuration.ConfigurationManager;
|
||||||
import com.cloud.configuration.ConfigurationManagerImpl;
|
import com.cloud.configuration.ConfigurationManagerImpl;
|
||||||
import com.cloud.configuration.Resource.ResourceType;
|
import com.cloud.configuration.Resource.ResourceType;
|
||||||
|
import com.cloud.cpu.CPU;
|
||||||
import com.cloud.dc.ClusterVO;
|
import com.cloud.dc.ClusterVO;
|
||||||
import com.cloud.dc.DataCenterVO;
|
import com.cloud.dc.DataCenterVO;
|
||||||
import com.cloud.dc.VsphereStoragePolicyVO;
|
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);
|
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) {
|
private void registerSystemVmTemplateOnFirstNfsStore(Long zoneId, String providerName, String url, DataStore store) {
|
||||||
if (DataStoreProvider.NFS_IMAGE.equals(providerName) && zoneId != null) {
|
if (DataStoreProvider.NFS_IMAGE.equals(providerName) && zoneId != null) {
|
||||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
Transaction.execute(new TransactionCallbackNoReturn() {
|
||||||
@Override
|
@Override
|
||||||
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||||
List<ImageStoreVO> stores = _imageStoreDao.listAllStoresInZone(zoneId, providerName, DataStoreRole.Image);
|
List<ImageStoreVO> stores = _imageStoreDao.listAllStoresInZoneExceptId(zoneId, providerName,
|
||||||
stores = stores.stream().filter(str -> str.getId() != store.getId()).collect(Collectors.toList());
|
DataStoreRole.Image, store.getId());
|
||||||
// Check if it's the only/first store in the zone
|
if (CollectionUtils.isEmpty(stores)) {
|
||||||
if (stores.size() == 0) {
|
List<Pair<HypervisorType, CPU.CPUArch>> hypervisorTypes =
|
||||||
List<HypervisorType> hypervisorTypes = _clusterDao.getAvailableHypervisorInZone(zoneId);
|
_clusterDao.listDistinctHypervisorsArchAcrossClusters(zoneId);
|
||||||
Set<HypervisorType> hypSet = new HashSet<>(hypervisorTypes);
|
|
||||||
TransactionLegacy txn = TransactionLegacy.open("AutomaticTemplateRegister");
|
TransactionLegacy txn = TransactionLegacy.open("AutomaticTemplateRegister");
|
||||||
SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration();
|
SystemVmTemplateRegistration systemVmTemplateRegistration = new SystemVmTemplateRegistration();
|
||||||
String filePath = null;
|
String filePath = null;
|
||||||
@ -3606,40 +3639,15 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||||||
}
|
}
|
||||||
Pair<String, Long> storeUrlAndId = new Pair<>(url, store.getId());
|
Pair<String, Long> storeUrlAndId = new Pair<>(url, store.getId());
|
||||||
String nfsVersion = imageStoreDetailsUtil.getNfsVersion(store.getId());
|
String nfsVersion = imageStoreDetailsUtil.getNfsVersion(store.getId());
|
||||||
for (HypervisorType hypervisorType : hypSet) {
|
for (Pair<HypervisorType, CPU.CPUArch> hypervisorArchType : hypervisorTypes) {
|
||||||
try {
|
try {
|
||||||
if (HypervisorType.Simulator == hypervisorType) {
|
registerSystemVmTemplateForHypervisorArch(hypervisorArchType.first(),
|
||||||
continue;
|
hypervisorArchType.second(), zoneId, url, store,
|
||||||
}
|
systemVmTemplateRegistration, filePath, storeUrlAndId, nfsVersion);
|
||||||
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);
|
|
||||||
}
|
|
||||||
} catch (CloudRuntimeException e) {
|
} catch (CloudRuntimeException e) {
|
||||||
SystemVmTemplateRegistration.unmountStore(filePath);
|
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) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@ -243,7 +244,11 @@ public abstract class TemplateAdapterBase extends AdapterBase implements Templat
|
|||||||
|
|
||||||
List<VMTemplateVO> systemvmTmplts = _tmpltDao.listAllSystemVMTemplates();
|
List<VMTemplateVO> systemvmTmplts = _tmpltDao.listAllSystemVMTemplates();
|
||||||
for (VMTemplateVO template : systemvmTmplts) {
|
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");
|
throw new IllegalArgumentException("Cannot use reserved names for templates");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,27 +16,11 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.network.router;
|
package com.cloud.network.router;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import static org.junit.Assert.assertEquals;
|
||||||
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.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.lenient;
|
||||||
import static org.mockito.Mockito.mock;
|
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.verify;
|
||||||
import static org.mockito.Mockito.when;
|
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)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class NetworkHelperImplTest {
|
public class NetworkHelperImplTest {
|
||||||
@ -54,6 +66,9 @@ public class NetworkHelperImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
protected AgentManager agentManager;
|
protected AgentManager agentManager;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
DomainRouterDao routerDao;
|
||||||
|
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
protected NetworkHelperImpl nwHelper = new NetworkHelperImpl();
|
protected NetworkHelperImpl nwHelper = new NetworkHelperImpl();
|
||||||
@Mock
|
@Mock
|
||||||
@ -65,10 +80,27 @@ public class NetworkHelperImplTest {
|
|||||||
@Mock
|
@Mock
|
||||||
NicDao nicDao;
|
NicDao nicDao;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RouterDeploymentDefinition routerDeploymentDefinition;
|
||||||
|
@Mock
|
||||||
|
private VirtualRouterProvider virtualProvider;
|
||||||
|
@Mock
|
||||||
|
private Account owner;
|
||||||
|
@Mock
|
||||||
|
private ServiceOfferingVO routerOffering;
|
||||||
|
@Mock
|
||||||
|
private VMTemplateVO template;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
nwHelper._networkDao = networkDao;
|
nwHelper._networkDao = networkDao;
|
||||||
nwHelper._networkModel = networkModel;
|
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)
|
@Test(expected=ResourceUnavailableException.class)
|
||||||
@ -83,7 +115,7 @@ public class NetworkHelperImplTest {
|
|||||||
nwHelperUT.sendCommandsToRouter(vr, null);
|
nwHelperUT.sendCommandsToRouter(vr, null);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
verify(this.agentManager, times(0)).send((Long) ArgumentMatchers.any(), (Command) ArgumentMatchers.any());
|
verify(this.agentManager, times(0)).send((Long) any(), (Command) any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -187,4 +219,53 @@ public class NetworkHelperImplTest {
|
|||||||
verify(answer1, times(0)).getResult();
|
verify(answer1, times(0)).getResult();
|
||||||
assertFalse(result);
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -618,6 +619,25 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||||||
return defaultNetworks.get(0);
|
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) {
|
protected Map<String, Object> createSecStorageVmInstance(long dataCenterId, SecondaryStorageVm.Role role) {
|
||||||
DataStore secStore = _dataStoreMgr.getImageStoreWithFreeCapacity(dataCenterId);
|
DataStore secStore = _dataStoreMgr.getImageStoreWithFreeCapacity(dataCenterId);
|
||||||
if (secStore == null) {
|
if (secStore == null) {
|
||||||
@ -657,28 +677,33 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||||||
}
|
}
|
||||||
|
|
||||||
HypervisorType availableHypervisor = _resourceMgr.getAvailableHypervisor(dataCenterId);
|
HypervisorType availableHypervisor = _resourceMgr.getAvailableHypervisor(dataCenterId);
|
||||||
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, availableHypervisor);
|
List<VMTemplateVO> templates = _templateDao.findSystemVMReadyTemplates(dataCenterId, availableHypervisor,
|
||||||
if (template == null) {
|
ResourceManager.SystemVmPreferredArchitecture.valueIn(dataCenterId));
|
||||||
throw new CloudRuntimeException(String.format("Unable to find the system templates or it was not downloaded in %s.", dc.toString()));
|
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;
|
ServiceOfferingVO serviceOffering = _serviceOffering;
|
||||||
if (serviceOffering == null) {
|
if (serviceOffering == null) {
|
||||||
serviceOffering = _offeringDao.findDefaultSystemOffering(ServiceOffering.ssvmDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
|
serviceOffering = _offeringDao.findDefaultSystemOffering(ServiceOffering.ssvmDefaultOffUniqueName, ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
|
||||||
}
|
}
|
||||||
SecondaryStorageVmVO secStorageVm =
|
SecondaryStorageVmVO secStorageVm = null;
|
||||||
new SecondaryStorageVmVO(id, serviceOffering.getId(), name, template.getId(), template.getHypervisorType(), template.getGuestOSId(), dataCenterId,
|
for (final Iterator<VMTemplateVO> templateIterator = templates.iterator(); templateIterator.hasNext();) {
|
||||||
systemAcct.getDomainId(), systemAcct.getId(), _accountMgr.getSystemUser().getId(), role, serviceOffering.isOfferHA());
|
VMTemplateVO template = templateIterator.next();
|
||||||
secStorageVm.setDynamicallyScalable(template.isDynamicallyScalable());
|
secStorageVm = createOrUpdateSecondaryStorageVm(secStorageVm, dataCenterId, id, name, serviceOffering,
|
||||||
secStorageVm.setLimitCpuUse(serviceOffering.getLimitCpuUse());
|
template, systemAcct, role);
|
||||||
secStorageVm = _secStorageVmDao.persist(secStorageVm);
|
|
||||||
try {
|
try {
|
||||||
_itMgr.allocate(name, template, serviceOffering, networks, plan, null);
|
_itMgr.allocate(name, template, serviceOffering, networks, plan, template.getHypervisorType());
|
||||||
secStorageVm = _secStorageVmDao.findById(secStorageVm.getId());
|
secStorageVm = _secStorageVmDao.findById(secStorageVm.getId());
|
||||||
|
_itMgr.checkDeploymentPlan(secStorageVm, template, serviceOffering, systemAcct, plan);
|
||||||
|
break;
|
||||||
} catch (InsufficientCapacityException e) {
|
} catch (InsufficientCapacityException e) {
|
||||||
String errorMessage = String.format("Unable to allocate secondary storage VM [%s] due to [%s].", name, e.getMessage());
|
if (templateIterator.hasNext()) {
|
||||||
logger.warn(errorMessage, e);
|
logger.debug("Unable to allocate secondary storage {} with {} due to [{}]. Retrying with another template", secStorageVm, template, e.getMessage(), e);
|
||||||
throw new CloudRuntimeException(errorMessage, 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<>();
|
Map<String, Object> context = new HashMap<>();
|
||||||
@ -820,8 +845,9 @@ public class SecondaryStorageManagerImpl extends ManagerBase implements Secondar
|
|||||||
}
|
}
|
||||||
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
|
ZoneHostInfo zoneHostInfo = zoneHostInfoMap.get(dataCenterId);
|
||||||
if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) {
|
if (zoneHostInfo != null && (zoneHostInfo.getFlags() & RunningHostInfoAgregator.ZoneHostInfo.ROUTING_HOST_MASK) != 0) {
|
||||||
VMTemplateVO template = _templateDao.findSystemVMReadyTemplate(dataCenterId, HypervisorType.Any);
|
List<VMTemplateVO> templates = _templateDao.findSystemVMReadyTemplates(dataCenterId,
|
||||||
if (template == null) {
|
HypervisorType.Any, null);
|
||||||
|
if (CollectionUtils.isEmpty(templates)) {
|
||||||
if (logger.isDebugEnabled()) {
|
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));
|
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;
|
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 useLocalStorage = BooleanUtils.toBoolean(ConfigurationManagerImpl.SystemVMUseLocalStorage.valueIn(dataCenterId));
|
||||||
boolean hasStoragePoolHostInfo = _storagePoolHostDao.hasDatacenterStoragePoolHostInfo(dataCenterId, !useLocalStorage);
|
boolean hasStoragePoolHostInfo = _storagePoolHostDao.hasDatacenterStoragePoolHostInfo(dataCenterId, !useLocalStorage);
|
||||||
if (hasStoragePoolHostInfo) {
|
if (hasStoragePoolHostInfo) {
|
||||||
|
|||||||
@ -16,39 +16,69 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package org.apache.cloudstack.secondarystorage;
|
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.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.Spy;
|
import org.mockito.Spy;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
import com.cloud.agent.api.to.DataStoreTO;
|
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.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;
|
import com.google.common.net.InetAddresses;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class SecondaryStorageManagerImplTest {
|
public class SecondaryStorageManagerImplTest {
|
||||||
private final SecureRandom secureRandom = new SecureRandom();
|
private final SecureRandom secureRandom = new SecureRandom();
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SecondaryStorageVmDao secStorageVmDao;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AccountManager accountManager;
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
@InjectMocks
|
@InjectMocks
|
||||||
private SecondaryStorageManagerImpl secondaryStorageManager;
|
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) {
|
private List<DataStore> mockDataStoresForTestAddSecondaryStorageServerAddressToBuffer(List<String> addresses) {
|
||||||
List<DataStore> dataStores = new ArrayList<>();
|
List<DataStore> dataStores = new ArrayList<>();
|
||||||
for (String address: addresses) {
|
for (String address: addresses) {
|
||||||
DataStore dataStore = Mockito.mock(DataStore.class);
|
DataStore dataStore = Mockito.mock(DataStore.class);
|
||||||
DataStoreTO dataStoreTO = Mockito.mock(DataStoreTO.class);
|
DataStoreTO dataStoreTO = Mockito.mock(DataStoreTO.class);
|
||||||
Mockito.when(dataStoreTO.getUrl()).thenReturn(NetUtils.isValidIp4(address) ? String.format("http://%s", address) : address);
|
when(dataStoreTO.getUrl()).thenReturn(NetUtils.isValidIp4(address) ? String.format("http://%s", address) : address);
|
||||||
Mockito.when(dataStore.getTO()).thenReturn(dataStoreTO);
|
when(dataStore.getTO()).thenReturn(dataStoreTO);
|
||||||
dataStores.add(dataStore);
|
dataStores.add(dataStore);
|
||||||
}
|
}
|
||||||
return dataStores;
|
return dataStores;
|
||||||
@ -60,7 +90,7 @@ public class SecondaryStorageManagerImplTest {
|
|||||||
secondaryStorageManager.addSecondaryStorageServerAddressToBuffer(builder, dataStores, "VM");
|
secondaryStorageManager.addSecondaryStorageServerAddressToBuffer(builder, dataStores, "VM");
|
||||||
String result = builder.toString();
|
String result = builder.toString();
|
||||||
result = result.contains("=") ? result.split("=")[1] : null;
|
result = result.contains("=") ? result.split("=")[1] : null;
|
||||||
Assert.assertEquals(expected, result);
|
assertEquals(expected, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -86,4 +116,55 @@ public class SecondaryStorageManagerImplTest {
|
|||||||
List<String> addresses = List.of(randomIp1, "garbage", randomIp2);
|
List<String> addresses = List.of(randomIp1, "garbage", randomIp2);
|
||||||
runAddSecondaryStorageServerAddressToBufferTest(addresses, StringUtils.join(List.of(randomIp1, 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,6 +43,7 @@ CREATE TABLE `simulator`.`mockhost` (
|
|||||||
`cpus` int(10) unsigned,
|
`cpus` int(10) unsigned,
|
||||||
`speed` int(10) unsigned,
|
`speed` int(10) unsigned,
|
||||||
`ram` bigint 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',
|
`capabilities` varchar(255) COMMENT 'host capabilities in comma separated list',
|
||||||
`vm_id` bigint unsigned,
|
`vm_id` bigint unsigned,
|
||||||
`resource` varchar(255) DEFAULT NULL COMMENT 'If it is a local resource, this is the class name',
|
`resource` varchar(255) DEFAULT NULL COMMENT 'If it is a local resource, this is the class name',
|
||||||
|
|||||||
@ -27,7 +27,7 @@ except ImportError:
|
|||||||
raise RuntimeError("python setuptools is required to build Marvin")
|
raise RuntimeError("python setuptools is required to build Marvin")
|
||||||
|
|
||||||
|
|
||||||
VERSION = "4.20.1.0-SNAPSHOT"
|
VERSION = "4.20.1.0"
|
||||||
|
|
||||||
setup(name="Marvin",
|
setup(name="Marvin",
|
||||||
version=VERSION,
|
version=VERSION,
|
||||||
|
|||||||
@ -72,6 +72,9 @@
|
|||||||
<a-tag v-if="resource.broadcasturi">
|
<a-tag v-if="resource.broadcasturi">
|
||||||
{{ resource.broadcasturi }}
|
{{ resource.broadcasturi }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
|
<a-tag v-if="resource.arch">
|
||||||
|
{{ resource.arch }}
|
||||||
|
</a-tag>
|
||||||
<a-tag v-if="resource.hypervisor">
|
<a-tag v-if="resource.hypervisor">
|
||||||
{{ resource.hypervisor }}
|
{{ resource.hypervisor }}
|
||||||
</a-tag>
|
</a-tag>
|
||||||
|
|||||||
@ -310,7 +310,9 @@ export default {
|
|||||||
}
|
}
|
||||||
if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'account', 'hypervisor', 'level',
|
if (['zoneid', 'domainid', 'imagestoreid', 'storageid', 'state', 'account', 'hypervisor', 'level',
|
||||||
'clusterid', 'podid', 'groupid', 'entitytype', 'accounttype', 'systemvmtype', 'scope', 'provider',
|
'clusterid', 'podid', 'groupid', 'entitytype', 'accounttype', 'systemvmtype', 'scope', 'provider',
|
||||||
'type', 'scope', 'managementserverid', 'serviceofferingid', 'diskofferingid', 'networkid', 'usagetype', 'restartrequired', 'displaynetwork'].includes(item)
|
'type', 'scope', 'managementserverid', 'serviceofferingid',
|
||||||
|
'diskofferingid', 'networkid', 'usagetype', 'restartrequired',
|
||||||
|
'displaynetwork', 'arch'].includes(item)
|
||||||
) {
|
) {
|
||||||
type = 'list'
|
type = 'list'
|
||||||
} else if (item === 'tags') {
|
} else if (item === 'tags') {
|
||||||
@ -445,6 +447,13 @@ export default {
|
|||||||
]
|
]
|
||||||
this.fields[apiKeyAccessIndex].loading = false
|
this.fields[apiKeyAccessIndex].loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arrayField.includes('arch')) {
|
||||||
|
const typeIndex = this.fields.findIndex(item => item.name === 'arch')
|
||||||
|
this.fields[typeIndex].loading = true
|
||||||
|
this.fields[typeIndex].opts = this.$fetchCpuArchitectureTypes()
|
||||||
|
this.fields[typeIndex].loading = false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async fetchDynamicFieldData (arrayField, searchKeyword) {
|
async fetchDynamicFieldData (arrayField, searchKeyword) {
|
||||||
const promises = []
|
const promises = []
|
||||||
|
|||||||
@ -63,6 +63,7 @@ export default {
|
|||||||
if (store.getters.metrics) {
|
if (store.getters.metrics) {
|
||||||
fields.push(...metricsFields)
|
fields.push(...metricsFields)
|
||||||
}
|
}
|
||||||
|
fields.push('arch')
|
||||||
if (store.getters.userInfo.roletype === 'Admin') {
|
if (store.getters.userInfo.roletype === 'Admin') {
|
||||||
fields.splice(2, 0, 'instancename')
|
fields.splice(2, 0, 'instancename')
|
||||||
fields.push('hostname')
|
fields.push('hostname')
|
||||||
@ -78,10 +79,10 @@ export default {
|
|||||||
fields.push('zonename')
|
fields.push('zonename')
|
||||||
return fields
|
return fields
|
||||||
},
|
},
|
||||||
searchFilters: ['name', 'zoneid', 'domainid', 'account', 'groupid', 'tags'],
|
searchFilters: ['name', 'zoneid', 'domainid', 'account', 'groupid', 'arch', 'tags'],
|
||||||
details: () => {
|
details: () => {
|
||||||
var fields = ['name', 'displayname', 'id', 'state', 'ipaddress', 'ip6address', 'templatename', 'ostypename',
|
var fields = ['name', 'displayname', 'id', 'state', 'ipaddress', 'ip6address', 'templatename', 'ostypename',
|
||||||
'serviceofferingname', 'isdynamicallyscalable', 'haenable', 'hypervisor', 'boottype', 'bootmode', 'account',
|
'serviceofferingname', 'isdynamicallyscalable', 'haenable', 'hypervisor', 'arch', 'boottype', 'bootmode', 'account',
|
||||||
'domain', 'zonename', 'userdataid', 'userdataname', 'userdataparams', 'userdatadetails', 'userdatapolicy',
|
'domain', 'zonename', 'userdataid', 'userdataname', 'userdataparams', 'userdatadetails', 'userdatapolicy',
|
||||||
'hostcontrolstate', 'deleteprotection']
|
'hostcontrolstate', 'deleteprotection']
|
||||||
const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true)
|
const listZoneHaveSGEnabled = store.getters.zones.filter(zone => zone.securitygroupsenabled === true)
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return 'Not Ready'
|
return 'Not Ready'
|
||||||
}
|
}
|
||||||
}, 'ostypename', 'hypervisor']
|
}, 'ostypename', 'arch', 'hypervisor']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
fields.push('size')
|
fields.push('size')
|
||||||
fields.push('account')
|
fields.push('account')
|
||||||
@ -67,7 +67,7 @@ export default {
|
|||||||
return fields
|
return fields
|
||||||
},
|
},
|
||||||
searchFilters: () => {
|
searchFilters: () => {
|
||||||
var filters = ['name', 'zoneid', 'tags']
|
var filters = ['name', 'zoneid', 'tags', 'arch']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
filters.push('storageid')
|
filters.push('storageid')
|
||||||
filters.push('imagestoreid')
|
filters.push('imagestoreid')
|
||||||
@ -220,7 +220,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return 'Not Ready'
|
return 'Not Ready'
|
||||||
}
|
}
|
||||||
}, 'ostypename']
|
}, 'ostypename', 'arch']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
fields.push('size')
|
fields.push('size')
|
||||||
fields.push('account')
|
fields.push('account')
|
||||||
@ -235,7 +235,7 @@ export default {
|
|||||||
},
|
},
|
||||||
details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'arch', 'bootable', 'isready', 'passwordenabled', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'],
|
details: ['name', 'id', 'displaytext', 'checksum', 'ostypename', 'size', 'arch', 'bootable', 'isready', 'passwordenabled', 'directdownload', 'isextractable', 'ispublic', 'isfeatured', 'isdynamicallyscalable', 'crosszones', 'account', 'domain', 'created', 'userdatadetails', 'userdatapolicy', 'url'],
|
||||||
searchFilters: () => {
|
searchFilters: () => {
|
||||||
var filters = ['name', 'zoneid', 'tags']
|
var filters = ['name', 'zoneid', 'tags', 'arch']
|
||||||
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
if (['Admin', 'DomainAdmin'].includes(store.getters.userInfo.roletype)) {
|
||||||
filters.push('storageid')
|
filters.push('storageid')
|
||||||
filters.push('imagestoreid')
|
filters.push('imagestoreid')
|
||||||
@ -370,9 +370,9 @@ export default {
|
|||||||
icon: ['fa-solid', 'fa-dharmachakra'],
|
icon: ['fa-solid', 'fa-dharmachakra'],
|
||||||
docHelp: 'plugins/cloudstack-kubernetes-service.html#kubernetes-supported-versions',
|
docHelp: 'plugins/cloudstack-kubernetes-service.html#kubernetes-supported-versions',
|
||||||
permission: ['listKubernetesSupportedVersions'],
|
permission: ['listKubernetesSupportedVersions'],
|
||||||
searchFilters: ['zoneid', 'minimumsemanticversion'],
|
searchFilters: ['zoneid', 'minimumsemanticversion', 'arch'],
|
||||||
columns: ['name', 'state', 'semanticversion', 'isostate', 'mincpunumber', 'minmemory', 'zonename'],
|
columns: ['name', 'state', 'semanticversion', 'isostate', 'mincpunumber', 'minmemory', 'arch', 'zonename'],
|
||||||
details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created'],
|
details: ['name', 'semanticversion', 'supportsautoscaling', 'zoneid', 'zonename', 'isoid', 'isoname', 'isostate', 'arch', 'mincpunumber', 'minmemory', 'supportsha', 'state', 'created'],
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
name: 'details',
|
name: 'details',
|
||||||
|
|||||||
@ -24,9 +24,9 @@ export default {
|
|||||||
icon: 'cluster-outlined',
|
icon: 'cluster-outlined',
|
||||||
docHelp: 'conceptsandterminology/concepts.html#about-clusters',
|
docHelp: 'conceptsandterminology/concepts.html#about-clusters',
|
||||||
permission: ['listClustersMetrics'],
|
permission: ['listClustersMetrics'],
|
||||||
searchFilters: ['name', 'zoneid', 'podid', 'hypervisor'],
|
searchFilters: ['name', 'zoneid', 'podid', 'arch', 'hypervisor'],
|
||||||
columns: () => {
|
columns: () => {
|
||||||
const fields = ['name', 'state', 'allocationstate', 'clustertype', 'hypervisortype', 'hosts']
|
const fields = ['name', 'state', 'allocationstate', 'clustertype', 'arch', 'hypervisortype', 'hosts']
|
||||||
const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'drsimbalance']
|
const metricsFields = ['cpuused', 'cpumaxdeviation', 'cpuallocated', 'cputotal', 'memoryused', 'memorymaxdeviation', 'memoryallocated', 'memorytotal', 'drsimbalance']
|
||||||
if (store.getters.metrics) {
|
if (store.getters.metrics) {
|
||||||
fields.push(...metricsFields)
|
fields.push(...metricsFields)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export default {
|
|||||||
icon: 'database-outlined',
|
icon: 'database-outlined',
|
||||||
docHelp: 'conceptsandterminology/concepts.html#about-hosts',
|
docHelp: 'conceptsandterminology/concepts.html#about-hosts',
|
||||||
permission: ['listHostsMetrics'],
|
permission: ['listHostsMetrics'],
|
||||||
searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'hypervisor'],
|
searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'arch', 'hypervisor'],
|
||||||
resourceType: 'Host',
|
resourceType: 'Host',
|
||||||
filters: () => {
|
filters: () => {
|
||||||
const filters = ['enabled', 'disabled', 'maintenance', 'up', 'down', 'disconnected', 'alert']
|
const filters = ['enabled', 'disabled', 'maintenance', 'up', 'down', 'disconnected', 'alert']
|
||||||
@ -32,7 +32,7 @@ export default {
|
|||||||
},
|
},
|
||||||
params: { type: 'routing' },
|
params: { type: 'routing' },
|
||||||
columns: () => {
|
columns: () => {
|
||||||
const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'hypervisor', 'instances', 'powerstate', 'version']
|
const fields = ['name', 'state', 'resourcestate', 'ipaddress', 'arch', 'hypervisor', 'instances', 'powerstate', 'version']
|
||||||
const metricsFields = ['cpunumber', 'cputotalghz', 'cpuusedghz', 'cpuallocatedghz', 'memorytotalgb', 'memoryusedgb', 'memoryallocatedgb', 'networkread', 'networkwrite']
|
const metricsFields = ['cpunumber', 'cputotalghz', 'cpuusedghz', 'cpuallocatedghz', 'memorytotalgb', 'memoryusedgb', 'memoryallocatedgb', 'networkread', 'networkwrite']
|
||||||
if (store.getters.metrics) {
|
if (store.getters.metrics) {
|
||||||
fields.push(...metricsFields)
|
fields.push(...metricsFields)
|
||||||
|
|||||||
@ -26,12 +26,12 @@ export default {
|
|||||||
permission: ['listRouters'],
|
permission: ['listRouters'],
|
||||||
params: { projectid: '-1' },
|
params: { projectid: '-1' },
|
||||||
columns: () => {
|
columns: () => {
|
||||||
var columns = ['name', 'state', 'publicip', { field: 'guestnetworkname', customTitle: 'network' }, 'redundantstate', 'softwareversion', 'hostname', 'account', 'zonename', 'requiresupgrade']
|
var columns = ['name', 'state', 'publicip', { field: 'guestnetworkname', customTitle: 'network' }, 'redundantstate', 'softwareversion', 'hostname', 'arch', 'account', 'zonename', 'requiresupgrade']
|
||||||
columns.splice(6, 0, { field: 'version', customTitle: 'templateversion' })
|
columns.splice(6, 0, { field: 'version', customTitle: 'templateversion' })
|
||||||
return columns
|
return columns
|
||||||
},
|
},
|
||||||
searchFilters: ['name', 'zoneid', 'podid', 'clusterid'],
|
searchFilters: ['name', 'zoneid', 'podid', 'clusterid', 'arch'],
|
||||||
details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'account', 'zonename', 'created', 'hostcontrolstate'],
|
details: ['name', 'id', 'version', 'softwareversion', 'requiresupgrade', 'guestnetworkname', 'vpcname', 'publicip', 'guestipaddress', 'linklocalip', 'serviceofferingname', 'networkdomain', 'isredundantrouter', 'redundantstate', 'hostname', 'arch', 'account', 'zonename', 'created', 'hostcontrolstate'],
|
||||||
resourceType: 'VirtualRouter',
|
resourceType: 'VirtualRouter',
|
||||||
filters: () => {
|
filters: () => {
|
||||||
const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown']
|
const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown']
|
||||||
|
|||||||
@ -24,9 +24,9 @@ export default {
|
|||||||
icon: 'thunderbolt-outlined',
|
icon: 'thunderbolt-outlined',
|
||||||
docHelp: 'adminguide/systemvm.html',
|
docHelp: 'adminguide/systemvm.html',
|
||||||
permission: ['listSystemVms'],
|
permission: ['listSystemVms'],
|
||||||
searchFilters: ['name', 'zoneid', 'podid', 'hostid', 'systemvmtype', 'storageid'],
|
searchFilters: ['name', 'zoneid', 'podid', 'hostid', 'systemvmtype', 'storageid', 'arch'],
|
||||||
columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'version', 'hostname', 'zonename'],
|
columns: ['name', 'state', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'version', 'hostname', 'arch', 'zonename'],
|
||||||
details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'version', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'],
|
details: ['name', 'id', 'agentstate', 'systemvmtype', 'publicip', 'privateip', 'linklocalip', 'gateway', 'hostname', 'arch', 'version', 'zonename', 'created', 'activeviewersessions', 'isdynamicallyscalable', 'hostcontrolstate'],
|
||||||
resourceType: 'SystemVm',
|
resourceType: 'SystemVm',
|
||||||
filters: () => {
|
filters: () => {
|
||||||
const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown']
|
const filters = ['starting', 'running', 'stopping', 'stopped', 'destroyed', 'expunging', 'migrating', 'error', 'unknown', 'shutdown']
|
||||||
|
|||||||
@ -36,7 +36,8 @@ import {
|
|||||||
fileSizeUtilPlugin,
|
fileSizeUtilPlugin,
|
||||||
genericUtilPlugin,
|
genericUtilPlugin,
|
||||||
localesPlugin,
|
localesPlugin,
|
||||||
dialogUtilPlugin
|
dialogUtilPlugin,
|
||||||
|
cpuArchitectureUtilPlugin
|
||||||
} from './utils/plugins'
|
} from './utils/plugins'
|
||||||
import { VueAxios } from './utils/request'
|
import { VueAxios } from './utils/request'
|
||||||
import directives from './utils/directives'
|
import directives from './utils/directives'
|
||||||
@ -53,6 +54,7 @@ vueApp.use(fileSizeUtilPlugin)
|
|||||||
vueApp.use(localesPlugin)
|
vueApp.use(localesPlugin)
|
||||||
vueApp.use(genericUtilPlugin)
|
vueApp.use(genericUtilPlugin)
|
||||||
vueApp.use(dialogUtilPlugin)
|
vueApp.use(dialogUtilPlugin)
|
||||||
|
vueApp.use(cpuArchitectureUtilPlugin)
|
||||||
vueApp.use(extensions)
|
vueApp.use(extensions)
|
||||||
vueApp.use(directives)
|
vueApp.use(directives)
|
||||||
|
|
||||||
|
|||||||
@ -538,3 +538,15 @@ export const dialogUtilPlugin = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const cpuArchitectureUtilPlugin = {
|
||||||
|
install (app) {
|
||||||
|
app.config.globalProperties.$fetchCpuArchitectureTypes = function () {
|
||||||
|
const architectures = [
|
||||||
|
{ id: 'x86_64', name: 'AMD 64 bits (x86_64)' },
|
||||||
|
{ id: 'aarch64', name: 'ARM 64 bits (aarch64)' }
|
||||||
|
]
|
||||||
|
return architectures.map(item => ({ ...item, description: item.name }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -2569,14 +2569,28 @@ export default {
|
|||||||
if (this.clusterId === null) {
|
if (this.clusterId === null) {
|
||||||
this.form.clusterid = undefined
|
this.form.clusterid = undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetchOptions(this.params.hosts, 'hosts')
|
this.fetchOptions(this.params.hosts, 'hosts')
|
||||||
|
if (this.clusterId && Array.isArray(this.options.clusters)) {
|
||||||
|
const cluster = this.options.clusters.find(c => c.id === this.clusterId)
|
||||||
|
this.handleArchResourceSelected(cluster.arch)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onSelectHostId (value) {
|
onSelectHostId (value) {
|
||||||
this.hostId = value
|
this.hostId = value
|
||||||
if (this.hostId === null) {
|
if (this.hostId === null) {
|
||||||
this.form.hostid = undefined
|
this.form.hostid = undefined
|
||||||
}
|
}
|
||||||
|
if (this.hostId && Array.isArray(this.options.hosts)) {
|
||||||
|
const host = this.options.hosts.find(h => h.id === this.hostId)
|
||||||
|
this.handleArchResourceSelected(host.arch)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleArchResourceSelected (resourceArch) {
|
||||||
|
if (!resourceArch || !this.isZoneSelectedMultiArch || this.selectedArchitecture === resourceArch) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.selectedArchitecture = resourceArch
|
||||||
|
this.changeArchitecture(resourceArch, this.tabKey === 'templateid')
|
||||||
},
|
},
|
||||||
handleSearchFilter (name, options) {
|
handleSearchFilter (name, options) {
|
||||||
this.params[name].options = { ...this.params[name].options, ...options }
|
this.params[name].options = { ...this.params[name].options, ...options }
|
||||||
|
|||||||
@ -216,7 +216,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchData () {
|
fetchData () {
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
this.fetchZoneData()
|
this.fetchZoneData()
|
||||||
},
|
},
|
||||||
isValidValueForKey (obj, key) {
|
isValidValueForKey (obj, key) {
|
||||||
@ -225,19 +225,6 @@ export default {
|
|||||||
arrayHasItems (array) {
|
arrayHasItems (array) {
|
||||||
return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
|
return array !== null && array !== undefined && Array.isArray(array) && array.length > 0
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
},
|
|
||||||
fetchZoneData () {
|
fetchZoneData () {
|
||||||
const params = {}
|
const params = {}
|
||||||
params.showicon = true
|
params.showicon = true
|
||||||
|
|||||||
@ -384,7 +384,7 @@ export default {
|
|||||||
fetchData () {
|
fetchData () {
|
||||||
this.fetchZoneData()
|
this.fetchZoneData()
|
||||||
this.fetchOsType()
|
this.fetchOsType()
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
this.fetchUserData()
|
this.fetchUserData()
|
||||||
this.fetchUserdataPolicy()
|
this.fetchUserdataPolicy()
|
||||||
if ('listDomains' in this.$store.getters.apis) {
|
if ('listDomains' in this.$store.getters.apis) {
|
||||||
@ -410,19 +410,6 @@ export default {
|
|||||||
this.form.zoneid = (this.zones[0].id ? this.zones[0].id : '')
|
this.form.zoneid = (this.zones[0].id ? this.zones[0].id : '')
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
},
|
|
||||||
fetchOsType () {
|
fetchOsType () {
|
||||||
this.osTypeLoading = true
|
this.osTypeLoading = true
|
||||||
|
|
||||||
|
|||||||
@ -583,7 +583,7 @@ export default {
|
|||||||
this.fetchZone()
|
this.fetchZone()
|
||||||
this.fetchOsTypes()
|
this.fetchOsTypes()
|
||||||
this.fetchTemplateTypes()
|
this.fetchTemplateTypes()
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
this.fetchUserData()
|
this.fetchUserData()
|
||||||
this.fetchUserdataPolicy()
|
this.fetchUserdataPolicy()
|
||||||
if ('listDomains' in this.$store.getters.apis) {
|
if ('listDomains' in this.$store.getters.apis) {
|
||||||
@ -753,19 +753,6 @@ export default {
|
|||||||
}
|
}
|
||||||
this.templateTypes.opts = templatetypes
|
this.templateTypes.opts = templatetypes
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
},
|
|
||||||
fetchUserData () {
|
fetchUserData () {
|
||||||
const params = {}
|
const params = {}
|
||||||
params.listAll = true
|
params.listAll = true
|
||||||
|
|||||||
@ -216,7 +216,7 @@ export default {
|
|||||||
},
|
},
|
||||||
fetchData () {
|
fetchData () {
|
||||||
this.fetchOsTypes()
|
this.fetchOsTypes()
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
this.fetchUserdata()
|
this.fetchUserdata()
|
||||||
this.fetchUserdataPolicy()
|
this.fetchUserdataPolicy()
|
||||||
},
|
},
|
||||||
@ -235,19 +235,6 @@ export default {
|
|||||||
this.osTypes.loading = false
|
this.osTypes.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
},
|
|
||||||
fetchUserdataPolicy () {
|
fetchUserdataPolicy () {
|
||||||
const userdataPolicy = []
|
const userdataPolicy = []
|
||||||
userdataPolicy.push({
|
userdataPolicy.push({
|
||||||
|
|||||||
@ -310,7 +310,7 @@ export default {
|
|||||||
},
|
},
|
||||||
fetchData () {
|
fetchData () {
|
||||||
this.fetchOsTypes()
|
this.fetchOsTypes()
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
this.fetchRootDiskControllerTypes(this.resource.hypervisor)
|
this.fetchRootDiskControllerTypes(this.resource.hypervisor)
|
||||||
this.fetchNicAdapterTypes()
|
this.fetchNicAdapterTypes()
|
||||||
this.fetchKeyboardTypes()
|
this.fetchKeyboardTypes()
|
||||||
@ -335,19 +335,6 @@ export default {
|
|||||||
this.osTypes.loading = false
|
this.osTypes.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
},
|
|
||||||
fetchRootDiskControllerTypes (hyperVisor) {
|
fetchRootDiskControllerTypes (hyperVisor) {
|
||||||
const controller = []
|
const controller = []
|
||||||
this.rootDisk.opts = []
|
this.rootDisk.opts = []
|
||||||
|
|||||||
@ -213,7 +213,8 @@ export default {
|
|||||||
fetchData () {
|
fetchData () {
|
||||||
this.fetchZones()
|
this.fetchZones()
|
||||||
this.fetchHypervisors()
|
this.fetchHypervisors()
|
||||||
this.fetchArchitectureTypes()
|
this.architectureTypes.opts = this.$fetchCpuArchitectureTypes()
|
||||||
|
this.selectedArchitecture = this.architectureTypes?.opts?.[0]?.id || null
|
||||||
this.params = this.$store.getters.apis.addCluster.params
|
this.params = this.$store.getters.apis.addCluster.params
|
||||||
Object.keys(this.placeholder).forEach(item => { this.returnPlaceholder(item) })
|
Object.keys(this.placeholder).forEach(item => { this.returnPlaceholder(item) })
|
||||||
},
|
},
|
||||||
@ -240,20 +241,6 @@ export default {
|
|||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchArchitectureTypes () {
|
|
||||||
this.architectureTypes.opts = []
|
|
||||||
const typesList = []
|
|
||||||
typesList.push({
|
|
||||||
id: 'x86_64',
|
|
||||||
description: 'AMD 64 bits (x86_64)'
|
|
||||||
})
|
|
||||||
typesList.push({
|
|
||||||
id: 'aarch64',
|
|
||||||
description: 'ARM 64 bits (aarch64)'
|
|
||||||
})
|
|
||||||
this.architectureTypes.opts = typesList
|
|
||||||
this.selectedArchitecture = this.architectureTypes.opts[0].id
|
|
||||||
},
|
|
||||||
fetchPods () {
|
fetchPods () {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
api('listPods', {
|
api('listPods', {
|
||||||
|
|||||||
@ -96,6 +96,7 @@
|
|||||||
<a-input
|
<a-input
|
||||||
v-else
|
v-else
|
||||||
v-model:value="form[field.key]"
|
v-model:value="form[field.key]"
|
||||||
|
:defaultValue="field.defaultValue"
|
||||||
v-focus="index === 0"
|
v-focus="index === 0"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
|||||||
@ -151,15 +151,12 @@ export default {
|
|||||||
return this.prefillContent?.zoneSuperType === 'Edge' || false
|
return this.prefillContent?.zoneSuperType === 'Edge' || false
|
||||||
},
|
},
|
||||||
steps () {
|
steps () {
|
||||||
const steps = []
|
const steps = [{
|
||||||
const hypervisor = this.prefillContent.hypervisor ? this.prefillContent.hypervisor : null
|
|
||||||
if (!this.isEdgeZone) {
|
|
||||||
steps.push({
|
|
||||||
title: 'label.cluster',
|
title: 'label.cluster',
|
||||||
fromKey: 'clusterResource',
|
fromKey: 'clusterResource',
|
||||||
description: 'message.desc.cluster'
|
description: 'message.desc.cluster'
|
||||||
})
|
}]
|
||||||
}
|
const hypervisor = this.prefillContent.hypervisor ? this.prefillContent.hypervisor : null
|
||||||
if (hypervisor !== 'VMware') {
|
if (hypervisor !== 'VMware') {
|
||||||
steps.push({
|
steps.push({
|
||||||
title: 'label.host',
|
title: 'label.host',
|
||||||
@ -190,7 +187,8 @@ export default {
|
|||||||
title: 'label.cluster.name',
|
title: 'label.cluster.name',
|
||||||
key: 'clusterName',
|
key: 'clusterName',
|
||||||
placeHolder: 'message.error.cluster.name',
|
placeHolder: 'message.error.cluster.name',
|
||||||
required: true
|
required: true,
|
||||||
|
defaultValue: this.isEdgeZone ? 'Cluster-' + (this.prefillContent?.name || 'Edge') : undefined
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'label.arch',
|
title: 'label.arch',
|
||||||
|
|||||||
@ -1280,7 +1280,7 @@ export default {
|
|||||||
params.clustertype = clusterType
|
params.clustertype = clusterType
|
||||||
params.podId = this.stepData.podReturned.id
|
params.podId = this.stepData.podReturned.id
|
||||||
let clusterName = this.prefillContent?.clusterName || null
|
let clusterName = this.prefillContent?.clusterName || null
|
||||||
if (this.isEdgeZone) {
|
if (!clusterName && this.isEdgeZone) {
|
||||||
clusterName = 'Cluster-' + this.stepData.zoneReturned.name
|
clusterName = 'Cluster-' + this.stepData.zoneReturned.name
|
||||||
}
|
}
|
||||||
params.arch = this.prefillContent?.arch || null
|
params.arch = this.prefillContent?.arch || null
|
||||||
|
|||||||
@ -25,7 +25,12 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
import javax.servlet.http.Cookie;
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class HttpUtils {
|
public class HttpUtils {
|
||||||
@ -151,4 +156,50 @@ public class HttpUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean downloadFileWithProgress(final String fileURL, final String savePath, final Logger logger) {
|
||||||
|
HttpURLConnection httpConn = null;
|
||||||
|
try {
|
||||||
|
URL url = new URL(fileURL);
|
||||||
|
httpConn = (HttpURLConnection) url.openConnection();
|
||||||
|
int responseCode = httpConn.getResponseCode();
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
int contentLength = httpConn.getContentLength();
|
||||||
|
if (contentLength < 0) {
|
||||||
|
logger.warn("Content length not provided for {}, progress updates may not be accurate",
|
||||||
|
fileURL);
|
||||||
|
}
|
||||||
|
try (InputStream inputStream = httpConn.getInputStream();
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(savePath)) {
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int bytesRead;
|
||||||
|
int downloaded = 0;
|
||||||
|
int lastReportedPercent = 0;
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
downloaded += bytesRead;
|
||||||
|
if (contentLength > 0) {
|
||||||
|
int percentDownloaded = (int) ((downloaded / (double) contentLength) * 100);
|
||||||
|
// Update every 5 percent or on completion
|
||||||
|
if (percentDownloaded - lastReportedPercent >= 5 || percentDownloaded == 100) {
|
||||||
|
logger.debug("Downloaded {}% from {}", percentDownloaded, fileURL);
|
||||||
|
lastReportedPercent = percentDownloaded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("File {} downloaded successfully using {}.", fileURL, savePath);
|
||||||
|
} else {
|
||||||
|
logger.error("No file to download {}. Server replied with code: {}", fileURL, responseCode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
logger.error("Failed to download {} due to: {}", fileURL, ex.getMessage(), ex);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (httpConn != null) {
|
||||||
|
httpConn.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,21 +19,54 @@
|
|||||||
|
|
||||||
package com.cloud.utils;
|
package com.cloud.utils;
|
||||||
|
|
||||||
import org.junit.Test;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import org.springframework.mock.web.MockHttpSession;
|
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
import static org.mockito.ArgumentMatchers.contains;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.net.URLStreamHandler;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class HttpUtilsTest {
|
public class HttpUtilsTest {
|
||||||
|
|
||||||
|
// Use a custom protocol (e.g., "mockhttp") for testing.
|
||||||
|
private static FakeURLStreamHandler fakeHandler;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Logger logger;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private HttpURLConnection httpConn;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void findCookieTest() {
|
public void findCookieTest() {
|
||||||
Cookie[] cookies = null;
|
Cookie[] cookies = null;
|
||||||
@ -153,4 +186,97 @@ public class HttpUtilsTest {
|
|||||||
assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
|
assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.ParameterOnly));
|
||||||
assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
|
assertFalse(HttpUtils.validateSessionKey(session, params, cookies, sessionKeyString, HttpUtils.ApiSessionKeyCheckOption.CookieAndParameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FakeURLStreamHandler extends URLStreamHandler {
|
||||||
|
private HttpURLConnection connection;
|
||||||
|
|
||||||
|
public void setHttpURLConnection(HttpURLConnection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected URLConnection openConnection(URL u) {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register our custom URLStreamHandlerFactory once for the tests.
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUpOnce() {
|
||||||
|
fakeHandler = new FakeURLStreamHandler();
|
||||||
|
try {
|
||||||
|
URL.setURLStreamHandlerFactory(protocol -> {
|
||||||
|
if ("mockhttp".equals(protocol)) {
|
||||||
|
return fakeHandler;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
} catch (Error e) {
|
||||||
|
// The factory can only be set once. In case it is already set, ignore.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulDownload_withContentLength() throws Exception {
|
||||||
|
String fileURL = "mockhttp://example.com/file.txt";
|
||||||
|
File tempFile = File.createTempFile("downloadTest", ".tmp");
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
byte[] fileData = "Hello World".getBytes();
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
|
||||||
|
when(httpConn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(httpConn.getContentLength()).thenReturn(fileData.length);
|
||||||
|
when(httpConn.getInputStream()).thenReturn(inputStream);
|
||||||
|
fakeHandler.setHttpURLConnection(httpConn);
|
||||||
|
boolean result = HttpUtils.downloadFileWithProgress(fileURL, tempFile.getAbsolutePath(), logger);
|
||||||
|
assertTrue(result);
|
||||||
|
verify(logger, atLeastOnce()).debug(anyString(), anyInt(), eq(fileURL));
|
||||||
|
verify(logger).info("File {} downloaded successfully using {}.", fileURL, tempFile.getAbsolutePath());
|
||||||
|
byte[] actualData = Files.readAllBytes(tempFile.toPath());
|
||||||
|
assertArrayEquals(fileData, actualData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccessfulDownload_negativeContentLength() throws Exception {
|
||||||
|
String fileURL = "mockhttp://example.com/file.txt";
|
||||||
|
File tempFile = File.createTempFile("downloadTest", ".tmp");
|
||||||
|
tempFile.deleteOnExit();
|
||||||
|
byte[] fileData = "Hello World".getBytes();
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData);
|
||||||
|
when(httpConn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
// Simulate missing content length
|
||||||
|
when(httpConn.getContentLength()).thenReturn(-1);
|
||||||
|
when(httpConn.getInputStream()).thenReturn(inputStream);
|
||||||
|
fakeHandler.setHttpURLConnection(httpConn);
|
||||||
|
boolean result = HttpUtils.downloadFileWithProgress(fileURL, tempFile.getAbsolutePath(), logger);
|
||||||
|
assertTrue(result);
|
||||||
|
verify(logger).warn("Content length not provided for {}, progress updates may not be accurate", fileURL);
|
||||||
|
verify(logger).info("File {} downloaded successfully using {}.", fileURL, tempFile.getAbsolutePath());
|
||||||
|
byte[] actualData = Files.readAllBytes(tempFile.toPath());
|
||||||
|
assertArrayEquals(fileData, actualData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDownloadFile_nonOKResponse() throws Exception {
|
||||||
|
String fileURL = "mockhttp://example.com/file.txt";
|
||||||
|
String savePath = "dummyPath";
|
||||||
|
when(httpConn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_FOUND);
|
||||||
|
fakeHandler.setHttpURLConnection(httpConn);
|
||||||
|
boolean result = HttpUtils.downloadFileWithProgress(fileURL, savePath, logger);
|
||||||
|
assertFalse(result);
|
||||||
|
verify(logger).error("No file to download {}. Server replied with code: {}", fileURL, HttpURLConnection.HTTP_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDownloadFile_exceptionDuringDownload() throws Exception {
|
||||||
|
String fileURL = "mockhttp://example.com/file.txt";
|
||||||
|
String savePath = "dummyPath";
|
||||||
|
when(httpConn.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK);
|
||||||
|
when(httpConn.getContentLength()).thenReturn(100);
|
||||||
|
// Simulate an IOException when trying to get the InputStream
|
||||||
|
when(httpConn.getInputStream()).thenThrow(new IOException("Connection error"));
|
||||||
|
fakeHandler.setHttpURLConnection(httpConn);
|
||||||
|
boolean result = HttpUtils.downloadFileWithProgress(fileURL, savePath, logger);
|
||||||
|
assertFalse(result);
|
||||||
|
verify(logger).error(contains("Failed to download {} due to: {}"), eq(fileURL), eq("Connection error"), any(IOException.class));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user