mirror of https://github.com/apache/cloudstack.git
Merge remote-tracking branch 'apache/main' into integration-veeam-kvm
This commit is contained in:
commit
ebfe83d2ab
|
|
@ -22,19 +22,11 @@ import com.cloud.deploy.DeploymentPlan;
|
|||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.utils.component.Adapter;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
public interface HostAllocator extends Adapter {
|
||||
|
||||
/**
|
||||
* @param UserVm vm
|
||||
* @param ServiceOffering offering
|
||||
**/
|
||||
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);
|
||||
|
||||
/**
|
||||
* Determines which physical hosts are suitable to
|
||||
* allocate the guest virtual machines on
|
||||
|
|
@ -49,31 +41,6 @@ public interface HostAllocator extends Adapter {
|
|||
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo);
|
||||
|
||||
/**
|
||||
* Determines which physical hosts are suitable to allocate the guest
|
||||
* virtual machines on
|
||||
*
|
||||
* Allocators must set any other hosts not considered for allocation in the
|
||||
* ExcludeList avoid. Thus the avoid set and the list of hosts suitable,
|
||||
* together must cover the entire host set in the cluster.
|
||||
*
|
||||
* @param VirtualMachineProfile
|
||||
* vmProfile
|
||||
* @param DeploymentPlan
|
||||
* plan
|
||||
* @param GuestType
|
||||
* type
|
||||
* @param ExcludeList
|
||||
* avoid
|
||||
* @param int returnUpTo (use -1 to return all possible hosts)
|
||||
* @param boolean considerReservedCapacity (default should be true, set to
|
||||
* false if host capacity calculation should not look at reserved
|
||||
* capacity)
|
||||
* @return List<Host> List of hosts that are suitable for VM allocation
|
||||
**/
|
||||
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity);
|
||||
|
||||
/**
|
||||
* Determines which physical hosts are suitable to allocate the guest
|
||||
* virtual machines on
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public interface DeploymentPlanner extends Adapter {
|
|||
boolean canHandle(VirtualMachineProfile vm, DeploymentPlan plan, ExcludeList avoid);
|
||||
|
||||
public enum AllocationAlgorithm {
|
||||
random, firstfit, userdispersing;
|
||||
random, firstfit, userdispersing, firstfitleastconsumed;
|
||||
}
|
||||
|
||||
public enum PlannerResourceUsage {
|
||||
|
|
|
|||
|
|
@ -510,4 +510,6 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
|
|||
Integer getPrivateMtu();
|
||||
|
||||
Integer getNetworkCidrSize();
|
||||
|
||||
boolean getKeepMacAddressOnPublicNic();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -385,6 +385,11 @@ public class NetworkProfile implements Network {
|
|||
return networkCidrSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("NetworkProfile %s",
|
||||
|
|
|
|||
|
|
@ -107,4 +107,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
|
|||
String getIp6Dns2();
|
||||
|
||||
boolean useRouterIpAsResolver();
|
||||
|
||||
boolean getKeepMacAddressOnPublicNic();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public interface VpcService {
|
|||
*/
|
||||
Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain,
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Boolean displayVpc, Integer publicMtu, Integer cidrSize,
|
||||
Long asNumber, List<Long> bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException;
|
||||
Long asNumber, List<Long> bgpPeerIds, Boolean useVrIpResolver, boolean keepMacAddressOnPublicNic) throws ResourceAllocationException;
|
||||
|
||||
/**
|
||||
* Persists VPC record in the database
|
||||
|
|
@ -104,7 +104,7 @@ public interface VpcService {
|
|||
* @throws ResourceUnavailableException if during restart some resources may not be available
|
||||
* @throws InsufficientCapacityException if for instance no address space, compute or storage is sufficiently available
|
||||
*/
|
||||
Vpc updateVpc(long vpcId, String vpcName, String displayText, String customId, Boolean displayVpc, Integer mtu, String sourceNatIp) throws ResourceUnavailableException, InsufficientCapacityException;
|
||||
Vpc updateVpc(long vpcId, String vpcName, String displayText, String customId, Boolean displayVpc, Integer mtu, String sourceNatIp, Boolean keepMacAddressOnPublicNic) throws ResourceUnavailableException, InsufficientCapacityException;
|
||||
|
||||
/**
|
||||
* Lists VPC(s) based on the parameters passed to the API call
|
||||
|
|
|
|||
|
|
@ -1361,6 +1361,13 @@ public class ApiConstants {
|
|||
public static final String OBJECT_STORAGE_LIMIT = "objectstoragelimit";
|
||||
public static final String OBJECT_STORAGE_TOTAL = "objectstoragetotal";
|
||||
|
||||
public static final String KEEP_MAC_ADDRESS_ON_PUBLIC_NIC = "keepmacaddressonpublicnic";
|
||||
|
||||
public static final String PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC =
|
||||
"Indicates whether to use the same MAC address for the public NIC of VRs on the same network. If \"true\", when creating redundant routers or recreating" +
|
||||
" a VR, CloudStack will use the same MAC address for the public NIC of all VRs. Otherwise, if \"false\", new public NICs will always have " +
|
||||
" a new MAC address.";
|
||||
|
||||
public static final String PARAMETER_DESCRIPTION_ACTIVATION_RULE = "Quota tariff's activation rule. It can receive a JS script that results in either " +
|
||||
"a boolean or a numeric value: if it results in a boolean value, the tariff value will be applied according to the result; if it results in a numeric value, the " +
|
||||
"numeric value will be applied; if the result is neither a boolean nor a numeric value, the tariff will not be applied. If the rule is not informed, the tariff " +
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ public class FindHostsForMigrationCmd extends BaseListCmd {
|
|||
for (Host host : result.first()) {
|
||||
HostForMigrationResponse hostResponse = _responseGenerator.createHostForMigrationResponse(host);
|
||||
Boolean suitableForMigration = false;
|
||||
if (hostsWithCapacity.contains(host)) {
|
||||
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
|
||||
suitableForMigration = true;
|
||||
}
|
||||
hostResponse.setSuitableForMigration(suitableForMigration);
|
||||
|
|
|
|||
|
|
@ -252,7 +252,7 @@ public class ListHostsCmd extends BaseListCmd {
|
|||
for (Host host : result.first()) {
|
||||
HostResponse hostResponse = _responseGenerator.createHostResponse(host, getDetails());
|
||||
Boolean suitableForMigration = false;
|
||||
if (hostsWithCapacity.contains(host)) {
|
||||
if (hostsWithCapacity != null && hostsWithCapacity.contains(host)) {
|
||||
suitableForMigration = true;
|
||||
}
|
||||
hostResponse.setSuitableForMigration(suitableForMigration);
|
||||
|
|
|
|||
|
|
@ -199,6 +199,11 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
|
|||
@Parameter(name=ApiConstants.AS_NUMBER, type=CommandType.LONG, since = "4.20.0", description="the AS Number of the network")
|
||||
private Long asNumber;
|
||||
|
||||
@Parameter(name = ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
type = CommandType.BOOLEAN, since = "4.23.0", authorized = {RoleType.Admin})
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -286,6 +291,10 @@ public class CreateNetworkCmd extends BaseCmd implements UserCmd {
|
|||
return sourceNatIP;
|
||||
}
|
||||
|
||||
public Boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisplay() {
|
||||
if(displayNetwork == null)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,11 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd implements UserCmd {
|
|||
@Parameter(name = ApiConstants.SOURCE_NAT_IP, type = CommandType.STRING, description = "IPV4 address to be assigned to the public interface of the network router. This address must already be acquired for this network", since = "4.19")
|
||||
private String sourceNatIP;
|
||||
|
||||
@Parameter(name = ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
type = CommandType.BOOLEAN, since = "4.23.0", authorized = {RoleType.Admin})
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -186,6 +191,10 @@ public class UpdateNetworkCmd extends BaseAsyncCustomIdCmd implements UserCmd {
|
|||
return sourceNatIP;
|
||||
}
|
||||
|
||||
public Boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -130,6 +130,11 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd {
|
|||
description="(optional) for NSX based VPCs: when set to true, use the VR IP as nameserver, otherwise use DNS1 and DNS2")
|
||||
private Boolean useVrIpResolver;
|
||||
|
||||
@Parameter(name = ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
type = CommandType.BOOLEAN, since = "4.23.0", authorized = {RoleType.Admin})
|
||||
private boolean keepMacAddressOnPublicNic = true;
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// ///////////////// Accessors ///////////////////////
|
||||
// ///////////////////////////////////////////////////
|
||||
|
|
@ -214,6 +219,10 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd implements UserCmd {
|
|||
return BooleanUtils.toBoolean(useVrIpResolver);
|
||||
}
|
||||
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ public class UpdateVPCCmd extends BaseAsyncCustomIdCmd implements UserCmd {
|
|||
since = "4.19")
|
||||
private String sourceNatIP;
|
||||
|
||||
@Parameter(name = ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC,
|
||||
type = CommandType.BOOLEAN, since = "4.23.0", authorized = {RoleType.Admin})
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
@ -97,6 +102,10 @@ public class UpdateVPCCmd extends BaseAsyncCustomIdCmd implements UserCmd {
|
|||
return sourceNatIP;
|
||||
}
|
||||
|
||||
public Boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -331,6 +331,10 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
@Param(description = "The BGP peers for the network", since = "4.20.0")
|
||||
private Set<BgpPeerResponse> bgpPeers;
|
||||
|
||||
@SerializedName(ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC)
|
||||
@Param(description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC, since = "4.23.0")
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
public NetworkResponse() {}
|
||||
|
||||
public Boolean getDisplayNetwork() {
|
||||
|
|
@ -702,4 +706,8 @@ public class NetworkResponse extends BaseResponseWithAssociatedNetwork implement
|
|||
public void setIpv6Dns2(String ipv6Dns2) {
|
||||
this.ipv6Dns2 = ipv6Dns2;
|
||||
}
|
||||
|
||||
public void setKeepMacAddressOnPublicNic(Boolean keepMacAddressOnPublicNic) {
|
||||
this.keepMacAddressOnPublicNic = keepMacAddressOnPublicNic;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,6 +185,10 @@ public class VpcResponse extends BaseResponseWithAnnotations implements Controll
|
|||
@Param(description = "The BGP peers for the VPC", since = "4.20.0")
|
||||
private Set<BgpPeerResponse> bgpPeers;
|
||||
|
||||
@SerializedName(ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC)
|
||||
@Param(description = ApiConstants.PARAMETER_DESCRIPTION_KEEP_MAC_ADDRESS_ON_PUBLIC_NIC, since = "4.23.0")
|
||||
private Boolean keepMacAddressOnPublicNic;
|
||||
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
|
@ -366,4 +370,8 @@ public class VpcResponse extends BaseResponseWithAnnotations implements Controll
|
|||
}
|
||||
this.bgpPeers.add(bgpPeer);
|
||||
}
|
||||
|
||||
public void setKeepMacAddressOnPublicNic(Boolean keepMacAddressOnPublicNic) {
|
||||
this.keepMacAddressOnPublicNic = keepMacAddressOnPublicNic;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class UpdateVPCCmdTest extends TestCase {
|
|||
responseGenerator = Mockito.mock(ResponseGenerator.class);
|
||||
cmd._responseGenerator = responseGenerator;
|
||||
Mockito.verify(_vpcService, Mockito.times(0)).updateVpc(Mockito.anyLong(), Mockito.anyString(), Mockito.anyString(),
|
||||
Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt(), Mockito.anyString());
|
||||
Mockito.anyString(), Mockito.anyBoolean(), Mockito.anyInt(), Mockito.anyString(), Mockito.anyBoolean());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -377,11 +377,6 @@
|
|||
<artifactId>cloud-plugin-explicit-dedication</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-host-allocator-random</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloud-plugin-outofbandmanagement-driver-ipmitool</artifactId>
|
||||
|
|
|
|||
|
|
@ -181,15 +181,6 @@ public interface VirtualMachineManager extends Manager {
|
|||
void advanceReboot(String vmUuid, Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException,
|
||||
ConcurrentOperationException, OperationTimedoutException;
|
||||
|
||||
/**
|
||||
* Check to see if a virtual machine can be upgraded to the given service offering
|
||||
*
|
||||
* @param vm
|
||||
* @param offering
|
||||
* @return true if the host can handle the upgrade, false otherwise
|
||||
*/
|
||||
boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering);
|
||||
|
||||
VirtualMachine findById(long vmId);
|
||||
|
||||
void storageMigration(String vmUuid, Map<Long, Long> volumeToPool);
|
||||
|
|
|
|||
|
|
@ -220,6 +220,11 @@ public interface NetworkOrchestrationService {
|
|||
Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId, String routerIp, String routerIpv6,
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
|
||||
|
||||
Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain, Account owner,
|
||||
Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String ip6Gateway, String ip6Cidr,
|
||||
Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId, String routerIp, String routerIpv6,
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize, boolean keepMacAddressOnPublicNic) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException;
|
||||
|
||||
UserDataServiceProvider getPasswordResetProvider(Network network);
|
||||
|
||||
UserDataServiceProvider getSSHKeyResetProvider(Network network);
|
||||
|
|
|
|||
|
|
@ -4023,19 +4023,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualMachineUpgradable(final VirtualMachine vm, final ServiceOffering offering) {
|
||||
boolean isMachineUpgradable = true;
|
||||
for (final HostAllocator allocator : hostAllocators) {
|
||||
isMachineUpgradable = allocator.isVirtualMachineUpgradable(vm, offering);
|
||||
if (!isMachineUpgradable) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isMachineUpgradable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reboot(final String vmUuid, final Map<VirtualMachineProfile.Param, Object> params) throws InsufficientCapacityException, ResourceUnavailableException {
|
||||
try {
|
||||
|
|
@ -4475,11 +4462,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
|
|||
throw new InvalidParameterValueException("isSystem property is different for current service offering and new service offering");
|
||||
}
|
||||
|
||||
if (!isVirtualMachineUpgradable(vmInstance, newServiceOffering)) {
|
||||
throw new InvalidParameterValueException("Unable to upgrade virtual machine, not enough resources available " + "for an offering of " +
|
||||
newServiceOffering.getCpu() + " cpu(s) at " + newServiceOffering.getSpeed() + " Mhz, and " + newServiceOffering.getRamSize() + " MB of memory");
|
||||
}
|
||||
|
||||
final List<String> currentTags = StringUtils.csvTagsToList(currentDiskOffering.getTags());
|
||||
final List<String> newTags = StringUtils.csvTagsToList(newDiskOffering.getTags());
|
||||
if (VolumeApiServiceImpl.MatchStoragePoolTagsWithDiskOffering.valueIn(vmInstance.getDataCenterId())) {
|
||||
|
|
|
|||
|
|
@ -863,6 +863,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
vpcId, offering.isRedundantRouter(), predefined.getExternalId());
|
||||
vo.setDisplayNetwork(isDisplayNetworkEnabled == null || isDisplayNetworkEnabled);
|
||||
vo.setStrechedL2Network(offering.isSupportingStrechedL2());
|
||||
vo.setKeepMacAddressOnPublicNic(predefined.getKeepMacAddressOnPublicNic());
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
|
@ -2724,7 +2725,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
return createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId,
|
||||
bypassVlanOverlapCheck, null, owner, null, pNtwk, pNtwk.getDataCenterId(), ACLType.Account, null,
|
||||
vpcId, null, null, true, null, null, null, true, null, null,
|
||||
null, null, null, null, null, null);
|
||||
null, null, null, null, null, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -2735,10 +2736,25 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId,
|
||||
String routerIp, String routerIpv6, String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2,
|
||||
Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
|
||||
return createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck,
|
||||
networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr,
|
||||
isDisplayNetworkEnabled, isolatedPvlan, isolatedPvlanType, externalId, false, routerIp, routerIpv6,
|
||||
ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, vrIfaceMTUs, networkCidrSize, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
public Network createGuestNetwork(final long networkOfferingId, final String name, final String displayText, final String gateway, final String cidr, String vlanId,
|
||||
boolean bypassVlanOverlapCheck, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk,
|
||||
final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr,
|
||||
final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId,
|
||||
String routerIp, String routerIpv6, String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2,
|
||||
Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize, boolean keepMacAddressOnPublicNic) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
|
||||
// create Isolated/Shared/L2 network
|
||||
return createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck,
|
||||
networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr,
|
||||
isDisplayNetworkEnabled, isolatedPvlan, isolatedPvlanType, externalId, false, routerIp, routerIpv6, ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, vrIfaceMTUs, networkCidrSize);
|
||||
isDisplayNetworkEnabled, isolatedPvlan, isolatedPvlanType, externalId, false, routerIp, routerIpv6,
|
||||
ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, vrIfaceMTUs, networkCidrSize, keepMacAddressOnPublicNic);
|
||||
}
|
||||
|
||||
@DB
|
||||
|
|
@ -2747,7 +2763,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
final long zoneId, final ACLType aclType, Boolean subdomainAccess, final Long vpcId, final String ip6Gateway, final String ip6Cidr,
|
||||
final Boolean isDisplayNetworkEnabled, final String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId,
|
||||
final Boolean isPrivateNetwork, String routerIp, String routerIpv6, final String ip4Dns1, final String ip4Dns2,
|
||||
final String ip6Dns1, final String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
|
||||
final String ip6Dns1, final String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize,
|
||||
boolean keepMacAddressOnPublicNic) throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException {
|
||||
|
||||
final NetworkOfferingVO ntwkOff = _networkOfferingDao.findById(networkOfferingId);
|
||||
final DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
|
|
@ -3095,6 +3112,7 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra
|
|||
}
|
||||
}
|
||||
userNetwork.setNetworkCidrSize(networkCidrSize);
|
||||
userNetwork.setKeepMacAddressOnPublicNic(keepMacAddressOnPublicNic);
|
||||
final List<? extends Network> networks = setupNetwork(owner, ntwkOff, userNetwork, plan, name, displayText, true, domainId, aclType, subdomainAccessFinal, vpcId,
|
||||
isDisplayNetworkEnabled);
|
||||
Network network;
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ public interface HostDao extends GenericDao<HostVO, Long>, StateDao<Status, Stat
|
|||
*/
|
||||
List<String> listOrderedHostsHypervisorVersionsInDatacenter(long datacenterId, HypervisorType hypervisorType);
|
||||
|
||||
List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags);
|
||||
List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags);
|
||||
|
||||
List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags);
|
||||
|
||||
|
|
|
|||
|
|
@ -1520,7 +1520,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||
}
|
||||
}
|
||||
|
||||
public List<HostVO> findHostsWithTagRuleThatMatchComputeOferringTags(String computeOfferingTags) {
|
||||
public List<HostVO> findHostsWithTagRuleThatMatchComputeOfferingTags(String computeOfferingTags) {
|
||||
List<HostTagVO> hostTagVOList = _hostTagsDao.findHostRuleTags();
|
||||
List<HostVO> result = new ArrayList<>();
|
||||
for (HostTagVO rule: hostTagVOList) {
|
||||
|
|
@ -1534,7 +1534,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
|
|||
|
||||
public List<Long> findClustersThatMatchHostTagRule(String computeOfferingTags) {
|
||||
Set<Long> result = new HashSet<>();
|
||||
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOferringTags(computeOfferingTags);
|
||||
List<HostVO> hosts = findHostsWithTagRuleThatMatchComputeOfferingTags(computeOfferingTags);
|
||||
for (HostVO host: hosts) {
|
||||
result.add(host.getClusterId());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,9 +203,13 @@ public class NetworkVO implements Network {
|
|||
@Column(name = "private_mtu")
|
||||
Integer privateMtu;
|
||||
|
||||
@Column(name = "keep_mac_address_on_public_nic")
|
||||
private boolean keepMacAddressOnPublicNic = true;
|
||||
|
||||
@Transient
|
||||
Integer networkCidrSize;
|
||||
|
||||
|
||||
public NetworkVO() {
|
||||
uuid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
|
@ -773,4 +777,13 @@ public class NetworkVO implements Network {
|
|||
public void setNetworkCidrSize(Integer networkCidrSize) {
|
||||
this.networkCidrSize = networkCidrSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
public void setKeepMacAddressOnPublicNic(boolean keepMacAddressOnPublicNic) {
|
||||
this.keepMacAddressOnPublicNic = keepMacAddressOnPublicNic;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,6 +108,9 @@ public class VpcVO implements Vpc {
|
|||
@Column(name = "use_router_ip_resolver")
|
||||
boolean useRouterIpResolver = false;
|
||||
|
||||
@Column(name = "keep_mac_address_on_public_nic")
|
||||
private boolean keepMacAddressOnPublicNic = true;
|
||||
|
||||
@Transient
|
||||
boolean rollingRestart = false;
|
||||
|
||||
|
|
@ -321,4 +324,13 @@ public class VpcVO implements Vpc {
|
|||
public void setUseRouterIpResolver(boolean useRouterIpResolver) {
|
||||
this.useRouterIpResolver = useRouterIpResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
public void setKeepMacAddressOnPublicNic(boolean keepMacAddressOnPublicNic) {
|
||||
this.keepMacAddressOnPublicNic = keepMacAddressOnPublicNic;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -358,7 +358,8 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
|||
IdsPowerStateSelectSearch.entity().getPowerHostId(),
|
||||
IdsPowerStateSelectSearch.entity().getPowerState(),
|
||||
IdsPowerStateSelectSearch.entity().getPowerStateUpdateCount(),
|
||||
IdsPowerStateSelectSearch.entity().getPowerStateUpdateTime());
|
||||
IdsPowerStateSelectSearch.entity().getPowerStateUpdateTime(),
|
||||
IdsPowerStateSelectSearch.entity().getState());
|
||||
IdsPowerStateSelectSearch.done();
|
||||
|
||||
CountByOfferingId = createSearchBuilder(Integer.class);
|
||||
|
|
@ -1105,10 +1106,14 @@ public class VMInstanceDaoImpl extends GenericDaoBase<VMInstanceVO, Long> implem
|
|||
|
||||
private boolean isPowerStateInSyncWithInstanceState(final VirtualMachine.PowerState powerState, final long powerHostId, final VMInstanceVO instance) {
|
||||
State instanceState = instance.getState();
|
||||
if (instanceState == null) {
|
||||
logger.warn("VM {} has null instance state during power state sync check, treating as out of sync", instance);
|
||||
return false;
|
||||
}
|
||||
if ((powerState == VirtualMachine.PowerState.PowerOff && instanceState == State.Running)
|
||||
|| (powerState == VirtualMachine.PowerState.PowerOn && instanceState == State.Stopped)) {
|
||||
HostVO instanceHost = hostDao.findById(instance.getHostId());
|
||||
HostVO powerHost = powerHostId == instance.getHostId() ? instanceHost : hostDao.findById(powerHostId);
|
||||
HostVO powerHost = instance.getHostId() != null && powerHostId == instance.getHostId() ? instanceHost : hostDao.findById(powerHostId);
|
||||
logger.debug("VM: {} on host: {} and power host : {} is in {} state, but power state is {}",
|
||||
instance, instanceHost, powerHost, instanceState, powerState);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -18,3 +18,9 @@
|
|||
--;
|
||||
-- Schema upgrade cleanup from 4.22.0.0 to 4.22.1.0
|
||||
--;
|
||||
|
||||
-- Entries remaining on `cloud`.`resource_reservation` during the upgrade process are stale, so delete them.
|
||||
-- This script was added to normalize volume/primary storage reservations that got stuck due to a bug on VM deployment,
|
||||
-- but it is more interesting to introduce a smarter logic to clean these stale reservations in the future without the need
|
||||
-- for upgrades (for instance, by having a heartbeat_time column for the reservations and automatically cleaning old entries).
|
||||
DELETE FROM `cloud`.`resource_reservation`;
|
||||
|
|
|
|||
|
|
@ -128,6 +128,10 @@ CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_tariff_usage` (
|
|||
CONSTRAINT `fk_quota_tariff_usage__tariff_id` FOREIGN KEY (`tariff_id`) REFERENCES `cloud_usage`.`quota_tariff` (`id`),
|
||||
CONSTRAINT `fk_quota_tariff_usage__quota_usage_id` FOREIGN KEY (`quota_usage_id`) REFERENCES `cloud_usage`.`quota_usage` (`id`));
|
||||
|
||||
-- Add the 'keep_mac_address_on_public_nic' column to the 'cloud.networks' and 'cloud.vpc' tables
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.networks', 'keep_mac_address_on_public_nic', 'TINYINT(1) NOT NULL DEFAULT 1');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc', 'keep_mac_address_on_public_nic', 'TINYINT(1) NOT NULL DEFAULT 1');
|
||||
|
||||
-- Add management_server_details table to allow ManagementServer scope configs
|
||||
CREATE TABLE IF NOT EXISTS `management_server_details` (
|
||||
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import com.cloud.network.vpc.VpcVO;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import com.cloud.storage.StoragePoolTagVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.acl.RoleVO;
|
||||
import org.apache.cloudstack.acl.dao.RoleDao;
|
||||
import org.apache.cloudstack.backup.BackupOfferingVO;
|
||||
|
|
@ -783,10 +784,21 @@ public class PresetVariableHelper {
|
|||
value.setId(network.getUuid());
|
||||
value.setName(network.getName());
|
||||
value.setState(usageRecord.getState());
|
||||
|
||||
value.setResourceCounting(getPresetVariableValueNetworkResourceCounting(networkId));
|
||||
value.setNetworkOffering(getPresetVariableValueNetworkOffering(network.getNetworkOfferingId()));
|
||||
}
|
||||
|
||||
protected ResourceCounting getPresetVariableValueNetworkResourceCounting(Long networkId) {
|
||||
ResourceCounting resourceCounting = new ResourceCounting();
|
||||
List<VMInstanceVO> vmInstancesVO = vmInstanceDao.listNonRemovedVmsByTypeAndNetwork(networkId, VirtualMachine.Type.User);
|
||||
int runningVms = (int) vmInstancesVO.stream().filter(vm -> vm.getState().equals(VirtualMachine.State.Running)).count();
|
||||
int stoppedVms = (int) vmInstancesVO.stream().filter(vm -> vm.getState().equals(VirtualMachine.State.Stopped)).count();
|
||||
|
||||
resourceCounting.setRunningVms(runningVms);
|
||||
resourceCounting.setStoppedVms(stoppedVms);
|
||||
return resourceCounting;
|
||||
}
|
||||
|
||||
protected GenericPresetVariable getPresetVariableValueNetworkOffering(Long networkOfferingId) {
|
||||
NetworkOfferingVO networkOfferingVo = networkOfferingDao.findByIdIncludingRemoved(networkOfferingId);
|
||||
validateIfObjectIsNull(networkOfferingVo, networkOfferingId, "network offering");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
// 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.quota.activationrule.presetvariables;
|
||||
|
||||
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
public class ResourceCounting {
|
||||
|
||||
@PresetVariableDefinition(description = "The number of running user instances.", supportedTypes = {QuotaTypes.NETWORK})
|
||||
private int runningVms;
|
||||
@PresetVariableDefinition(description = "The number of stopped user instances.", supportedTypes = {QuotaTypes.NETWORK})
|
||||
private int stoppedVms;
|
||||
|
||||
public int getRunningVms() {
|
||||
return runningVms;
|
||||
}
|
||||
|
||||
public void setRunningVms(int runningVms) {
|
||||
this.runningVms = runningVms;
|
||||
}
|
||||
|
||||
public int getStoppedVms() {
|
||||
return stoppedVms;
|
||||
}
|
||||
|
||||
public void setStoppedVms(int stoppedVms) {
|
||||
this.stoppedVms = stoppedVms;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
|
||||
}
|
||||
}
|
||||
|
|
@ -84,6 +84,9 @@ public class Value extends GenericPresetVariable {
|
|||
@PresetVariableDefinition(description = "Backup offering of the backup.", supportedTypes = {QuotaTypes.BACKUP})
|
||||
private BackupOffering backupOffering;
|
||||
|
||||
@PresetVariableDefinition(description = "The amount of resources of the usage type.")
|
||||
private ResourceCounting resourceCounting;
|
||||
|
||||
@PresetVariableDefinition(description = "The hypervisor where the resource was deployed. Values can be: XenServer, KVM, VMware, Hyperv, BareMetal, Ovm, Ovm3 and LXC.",
|
||||
supportedTypes = {QuotaTypes.RUNNING_VM, QuotaTypes.ALLOCATED_VM, QuotaTypes.VM_SNAPSHOT, QuotaTypes.SNAPSHOT})
|
||||
private String hypervisorType;
|
||||
|
|
@ -262,6 +265,14 @@ public class Value extends GenericPresetVariable {
|
|||
this.state = state;
|
||||
}
|
||||
|
||||
public ResourceCounting getResourceCounting() {
|
||||
return resourceCounting;
|
||||
}
|
||||
|
||||
public void setResourceCounting(ResourceCounting resourceCounting) {
|
||||
this.resourceCounting = resourceCounting;
|
||||
}
|
||||
|
||||
public GenericPresetVariable getNetworkOffering() {
|
||||
return networkOffering;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,11 +31,13 @@ import com.cloud.dc.ClusterDetailsDao;
|
|||
import com.cloud.dc.ClusterDetailsVO;
|
||||
import com.cloud.host.HostTagVO;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.network.vpc.VpcOfferingVO;
|
||||
import com.cloud.network.vpc.VpcVO;
|
||||
import com.cloud.network.vpc.dao.VpcOfferingDao;
|
||||
import com.cloud.storage.StoragePoolTagVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import org.apache.cloudstack.acl.RoleType;
|
||||
import org.apache.cloudstack.acl.RoleVO;
|
||||
import org.apache.cloudstack.acl.dao.RoleDao;
|
||||
|
|
@ -238,6 +240,8 @@ public class PresetVariableHelperTest {
|
|||
value.setVmSnapshotType(VMSnapshot.Type.Disk.toString());
|
||||
value.setComputingResources(getComputingResourcesForTests());
|
||||
value.setVolumeType(Volume.Type.DATADISK.toString());
|
||||
value.setState(Network.State.Implemented.toString());
|
||||
value.setResourceCounting(getResourceCountingForTests());
|
||||
value.setNetworkOffering(getNetworkOfferingForTests());
|
||||
value.setVpcOffering(getVpcOfferingForTests());
|
||||
return value;
|
||||
|
|
@ -276,6 +280,13 @@ public class PresetVariableHelperTest {
|
|||
return configuration;
|
||||
}
|
||||
|
||||
private ResourceCounting getResourceCountingForTests() {
|
||||
ResourceCounting resourceCounting = new ResourceCounting();
|
||||
resourceCounting.setRunningVms(1);
|
||||
resourceCounting.setStoppedVms(1);
|
||||
return resourceCounting;
|
||||
}
|
||||
|
||||
private List<HostTagVO> getHostTagsForTests() {
|
||||
return Arrays.asList(new HostTagVO(1, "tag1", false), new HostTagVO(1, "tag2", false));
|
||||
}
|
||||
|
|
@ -1343,8 +1354,8 @@ public class PresetVariableHelperTest {
|
|||
Mockito.doReturn(expected.getId()).when(networkVoMock).getUuid();
|
||||
Mockito.doReturn(expected.getName()).when(networkVoMock).getName();
|
||||
Mockito.doReturn(expected.getState()).when(usageVoMock).getState();
|
||||
Mockito.doReturn(expected.getResourceCounting()).when(presetVariableHelperSpy).getPresetVariableValueNetworkResourceCounting(Mockito.anyLong());
|
||||
Mockito.doReturn(expected.getNetworkOffering()).when(presetVariableHelperSpy).getPresetVariableValueNetworkOffering(Mockito.anyLong());
|
||||
|
||||
Mockito.doReturn(UsageTypes.NETWORK).when(usageVoMock).getUsageType();
|
||||
|
||||
Value result = new Value();
|
||||
|
|
@ -1352,7 +1363,27 @@ public class PresetVariableHelperTest {
|
|||
|
||||
assertPresetVariableIdAndName(expected, result);
|
||||
Assert.assertEquals(expected.getState(), result.getState());
|
||||
Assert.assertEquals(expected.getNetworkOffering(), result.getNetworkOffering());
|
||||
Assert.assertEquals(expected.getResourceCounting(), result.getResourceCounting());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPresetVariableValueNetworkResourceCountingTestSetValueAndReturnObject() {
|
||||
VMInstanceVO vmInstanceVoMock1 = Mockito.spy(VMInstanceVO.class);
|
||||
vmInstanceVoMock1.setState(VirtualMachine.State.Stopped);
|
||||
|
||||
VMInstanceVO vmInstanceVoMock2 = Mockito.spy(VMInstanceVO.class);
|
||||
vmInstanceVoMock2.setState(VirtualMachine.State.Running);
|
||||
|
||||
Mockito.doReturn(List.of(vmInstanceVoMock1, vmInstanceVoMock2)).when(vmInstanceDaoMock).listNonRemovedVmsByTypeAndNetwork(Mockito.anyLong(), Mockito.any());
|
||||
|
||||
mockMethodValidateIfObjectIsNull();
|
||||
|
||||
ResourceCounting expected = getResourceCountingForTests();
|
||||
|
||||
ResourceCounting result = presetVariableHelperSpy.getPresetVariableValueNetworkResourceCounting(1L);
|
||||
|
||||
Assert.assertEquals(expected.getRunningVms(), result.getRunningVms());
|
||||
Assert.assertEquals(expected.getStoppedVms(), result.getStoppedVms());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1362,7 +1393,7 @@ public class PresetVariableHelperTest {
|
|||
presetVariableHelperSpy.loadPresetVariableValueForVpc(usageVoMock, null);
|
||||
});
|
||||
|
||||
Mockito.verifyNoInteractions(networkDaoMock);
|
||||
Mockito.verifyNoInteractions(vpcDaoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ import org.apache.cloudstack.quota.activationrule.presetvariables.ComputingResou
|
|||
import org.apache.cloudstack.quota.activationrule.presetvariables.GenericPresetVariable;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariableDefinition;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.PresetVariables;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.ResourceCounting;
|
||||
import org.apache.cloudstack.quota.activationrule.presetvariables.Value;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
|
|
@ -185,7 +186,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
|||
private VolumeDao volumeDao;
|
||||
|
||||
|
||||
private final Class<?>[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class};
|
||||
private final Class<?>[] assignableClasses = {GenericPresetVariable.class, ComputingResources.class, ResourceCounting.class};
|
||||
|
||||
private Set<Account.Type> accountTypesThatCanListAllQuotaSummaries = Sets.newHashSet(Account.Type.ADMIN, Account.Type.DOMAIN_ADMIN);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>cloud-plugin-host-allocator-random</artifactId>
|
||||
<name>Apache CloudStack Plugin - Host Allocator Random</name>
|
||||
<parent>
|
||||
<groupId>org.apache.cloudstack</groupId>
|
||||
<artifactId>cloudstack-plugins</artifactId>
|
||||
<version>4.23.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
</project>
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.agent.manager.allocator.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.ListUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.agent.manager.allocator.HostAllocator;
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Component
|
||||
public class RandomAllocator extends AdapterBase implements HostAllocator {
|
||||
@Inject
|
||||
private HostDao _hostDao;
|
||||
@Inject
|
||||
private ResourceManager _resourceMgr;
|
||||
@Inject
|
||||
private ClusterDao clusterDao;
|
||||
@Inject
|
||||
private ClusterDetailsDao clusterDetailsDao;
|
||||
@Inject
|
||||
private CapacityManager capacityManager;
|
||||
|
||||
protected List<HostVO> listHostsByTags(Host.Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
|
||||
List<HostVO> taggedHosts = new ArrayList<>();
|
||||
if (offeringHostTag != null) {
|
||||
taggedHosts.addAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag));
|
||||
}
|
||||
if (templateTag != null) {
|
||||
List<HostVO> templateTaggedHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
|
||||
if (taggedHosts.isEmpty()) {
|
||||
taggedHosts = templateTaggedHosts;
|
||||
} else {
|
||||
taggedHosts.retainAll(templateTaggedHosts);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Found %d hosts %s with type: %s, zone ID: %d, pod ID: %d, cluster ID: %s, offering host tag(s): %s, template tag: %s",
|
||||
taggedHosts.size(),
|
||||
(taggedHosts.isEmpty() ? "" : String.format("(%s)", StringUtils.join(taggedHosts.stream().map(HostVO::toString).toArray(), ","))),
|
||||
type.name(), dcId, podId, clusterId, offeringHostTag, templateTag));
|
||||
}
|
||||
return taggedHosts;
|
||||
}
|
||||
private List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
List<? extends Host> hostsCopy = null;
|
||||
List<Host> suitableHosts = new ArrayList<>();
|
||||
|
||||
if (type == Host.Type.Storage) {
|
||||
return suitableHosts;
|
||||
}
|
||||
String offeringHostTag = offering.getHostTag();
|
||||
|
||||
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
|
||||
String templateTag = template.getTemplateTag();
|
||||
String hostTag = null;
|
||||
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
|
||||
hostTag = ObjectUtils.allNotNull(offeringHostTag, templateTag) ?
|
||||
String.format("%s, %s", offeringHostTag, templateTag) :
|
||||
ObjectUtils.firstNonNull(offeringHostTag, templateTag);
|
||||
logger.debug("Looking for hosts in dc [{}], pod [{}], cluster [{}] and complying with host tag(s): [{}]", dcId, podId, clusterId, hostTag);
|
||||
} else {
|
||||
logger.debug("Looking for hosts in dc: {} pod: {} cluster: {}", dcId , podId, clusterId);
|
||||
}
|
||||
if (hosts != null) {
|
||||
// retain all computing hosts, regardless of whether they support routing...it's random after all
|
||||
hostsCopy = new ArrayList<>(hosts);
|
||||
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
|
||||
hostsCopy.retainAll(listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag));
|
||||
} else {
|
||||
hostsCopy.retainAll(_hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId));
|
||||
}
|
||||
} else {
|
||||
// list all computing hosts, regardless of whether they support routing...it's random after all
|
||||
if (offeringHostTag != null) {
|
||||
hostsCopy = listHostsByTags(type, dcId, podId, clusterId, offeringHostTag, templateTag);
|
||||
} else {
|
||||
hostsCopy = _hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
|
||||
}
|
||||
}
|
||||
hostsCopy = ListUtils.union(hostsCopy, _hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(offeringHostTag));
|
||||
|
||||
if (hostsCopy.isEmpty()) {
|
||||
logger.info("No suitable host found for VM [{}] in {}.", vmProfile, hostTag);
|
||||
return null;
|
||||
}
|
||||
|
||||
logger.debug("Random Allocator found {} hosts", hostsCopy.size());
|
||||
if (hostsCopy.isEmpty()) {
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
Collections.shuffle(hostsCopy);
|
||||
for (Host host : hostsCopy) {
|
||||
if (suitableHosts.size() == returnUpTo) {
|
||||
break;
|
||||
}
|
||||
if (avoid.shouldAvoid(host)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Host %s is in avoid set, skipping this and trying other available hosts", host));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
|
||||
if (!cpuCapabilityAndCapacity.first() || !cpuCapabilityAndCapacity.second()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Not using host %s; host has cpu capability? %s, host has capacity? %s", host, cpuCapabilityAndCapacity.first(), cpuCapabilityAndCapacity.second()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Found a suitable host, adding to list: %s", host));
|
||||
}
|
||||
suitableHosts.add(host);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Random Host Allocator returning " + suitableHosts.size() + " suitable hosts");
|
||||
}
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type,
|
||||
ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
if (CollectionUtils.isEmpty(hosts)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Random Allocator found 0 hosts as given host list is empty");
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return findSuitableHosts(vmProfile, plan, type, avoid, hosts, returnUpTo, considerReservedCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan,
|
||||
Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
return findSuitableHosts(vmProfile, plan, type, avoid, null, returnUpTo, considerReservedCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
|
||||
// currently we do no special checks to rule out a VM being upgradable to an offering, so
|
||||
// return true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
name=host-allocator-random
|
||||
parent=allocator
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
|
||||
http://www.springframework.org/schema/context
|
||||
http://www.springframework.org/schema/context/spring-context.xsd"
|
||||
>
|
||||
|
||||
<bean id="randomAllocator"
|
||||
class="com.cloud.agent.manager.allocator.impl.RandomAllocator" />
|
||||
|
||||
|
||||
</beans>
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package com.cloud.agent.manager.allocator.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RandomAllocatorTest {
|
||||
|
||||
@Mock
|
||||
HostDao hostDao;
|
||||
@InjectMocks
|
||||
RandomAllocator randomAllocator;
|
||||
|
||||
@Test
|
||||
public void testListHostsByTags() {
|
||||
Host.Type type = Host.Type.Routing;
|
||||
Long id = 1L;
|
||||
String templateTag = "tag1";
|
||||
String offeringTag = "tag2";
|
||||
HostVO host1 = Mockito.mock(HostVO.class);
|
||||
HostVO host2 = Mockito.mock(HostVO.class);
|
||||
Mockito.when(hostDao.listByHostTag(type, id, id, id, offeringTag)).thenReturn(List.of(host1, host2));
|
||||
|
||||
// No template tagged host
|
||||
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(new ArrayList<>());
|
||||
List<HostVO> result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
|
||||
Assert.assertTrue(CollectionUtils.isEmpty(result));
|
||||
|
||||
// Different template tagged host
|
||||
HostVO host3 = Mockito.mock(HostVO.class);
|
||||
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host3));
|
||||
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
|
||||
Assert.assertTrue(CollectionUtils.isEmpty(result));
|
||||
|
||||
// Matching template tagged host
|
||||
Mockito.when(hostDao.listByHostTag(type, id, id, id, templateTag)).thenReturn(List.of(host1));
|
||||
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, templateTag);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(result));
|
||||
Assert.assertEquals(1, result.size());
|
||||
|
||||
// No template tag
|
||||
result = randomAllocator.listHostsByTags(type, id, id, id, offeringTag, null);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(result));
|
||||
Assert.assertEquals(2, result.size());
|
||||
|
||||
// No offering tag
|
||||
result = randomAllocator.listHostsByTags(type, id, id, id, null, templateTag);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(result));
|
||||
Assert.assertEquals(1, result.size());
|
||||
}
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@ public class QemuImgTest {
|
|||
Connect conn = new Connect("qemu:///system", false);
|
||||
conn.getVersion();
|
||||
libVirtAvailable = true;
|
||||
} catch (LibvirtException ignored) {}
|
||||
} catch (LibvirtException | UnsatisfiedLinkError | ExceptionInInitializerError ignored) {}
|
||||
Assume.assumeTrue("libvirt not available", libVirtAvailable);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,8 +84,6 @@
|
|||
|
||||
<module>ha-planners/skip-heurestics</module>
|
||||
|
||||
<module>host-allocators/random</module>
|
||||
|
||||
<module>hypervisors/baremetal</module>
|
||||
<module>hypervisors/external</module>
|
||||
<module>hypervisors/hyperv</module>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
// 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.agent.manager.allocator.impl;
|
||||
|
||||
import com.cloud.agent.manager.allocator.HostAllocator;
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BaseAllocator extends AdapterBase implements HostAllocator {
|
||||
|
||||
@Inject
|
||||
protected HostDao hostDao;
|
||||
|
||||
@Inject
|
||||
protected CapacityManager capacityManager;
|
||||
|
||||
protected void retainHostsMatchingServiceOfferingAndTemplateTags(List<HostVO> availableHosts, Host.Type type, long dcId, Long podId, Long clusterId, String offeringHostTag, String templateTag) {
|
||||
logger.debug("Hosts {} will be checked for template and host tags compatibility.", availableHosts);
|
||||
|
||||
if (offeringHostTag != null) {
|
||||
logger.debug("Looking for hosts having the tag [{}] specified in the Service Offering.", offeringHostTag);
|
||||
List<HostVO> hostsWithHostTag = hostDao.listByHostTag(type, clusterId, podId, dcId, offeringHostTag);
|
||||
logger.debug("Retaining hosts {} because they match the offering host tag {}.", hostsWithHostTag, offeringHostTag);
|
||||
availableHosts.retainAll(hostsWithHostTag);
|
||||
}
|
||||
|
||||
if (templateTag != null) {
|
||||
logger.debug("Looking for hosts having the tag [{}] specified in the Template.", templateTag);
|
||||
List<HostVO> hostsWithTemplateTag = hostDao.listByHostTag(type, clusterId, podId, dcId, templateTag);
|
||||
logger.debug("Retaining hosts {} because they match the template tag {}.", hostsWithTemplateTag, templateTag);
|
||||
availableHosts.retainAll(hostsWithTemplateTag);
|
||||
}
|
||||
|
||||
logger.debug("Remaining hosts after template tag and host tags validations are {}.", availableHosts);
|
||||
}
|
||||
|
||||
protected void addHostsBasedOnTagRules(String hostTagOnOffering, List<HostVO> clusterHosts) {
|
||||
List<HostVO> hostsWithTagRules = hostDao.findHostsWithTagRuleThatMatchComputeOfferingTags(hostTagOnOffering);
|
||||
|
||||
if (CollectionUtils.isEmpty(hostsWithTagRules)) {
|
||||
logger.info("No hosts found with tag rules matching the compute offering tag [{}].", hostTagOnOffering);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Found hosts {} with tag rules matching the compute offering tag [{}].", hostsWithTagRules, hostTagOnOffering);
|
||||
clusterHosts.addAll(hostsWithTagRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds hosts with enough CPU capability and enough CPU capacity to the suitable hosts list.
|
||||
*/
|
||||
protected boolean hostHasCpuCapabilityAndCapacity(boolean considerReservedCapacity, ServiceOffering offering, Host host) {
|
||||
logger.debug("Looking for CPU frequency {} MHz and RAM {} MB.", () -> offering.getCpu() * offering.getSpeed(), offering::getRamSize);
|
||||
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = capacityManager.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
|
||||
Boolean hasCpuCapability = cpuCapabilityAndCapacity.first();
|
||||
Boolean hasCpuCapacity = cpuCapabilityAndCapacity.second();
|
||||
|
||||
if (hasCpuCapability && hasCpuCapacity) {
|
||||
logger.debug("Host {} is a suitable host as it has enough CPU capability and CPU capacity.", () -> host);
|
||||
return true;
|
||||
}
|
||||
|
||||
logger.debug("Cannot use host {}. Does the host have CPU capability? {}. Does the host have CPU capacity? {}..", () -> host, () -> hasCpuCapability, () -> hasCpuCapacity);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,6 +16,41 @@
|
|||
// under the License.
|
||||
package com.cloud.agent.manager.allocator.impl;
|
||||
|
||||
import static com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm.firstfitleastconsumed;
|
||||
import static com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm.random;
|
||||
import static com.cloud.deploy.DeploymentPlanner.AllocationAlgorithm.userdispersing;
|
||||
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.deploy.DeploymentClusterPlanner;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.deploy.FirstFitPlanner;
|
||||
import com.cloud.gpu.GPU;
|
||||
import com.cloud.host.DetailVO;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.GuestOSCategoryVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.StringUtils;
|
||||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
|
@ -29,59 +64,19 @@ import java.util.stream.Collectors;
|
|||
import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import com.cloud.gpu.dao.VgpuProfileDao;
|
||||
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.agent.manager.allocator.HostAllocator;
|
||||
import com.cloud.capacity.Capacity;
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.capacity.dao.CapacityDao;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.configuration.ConfigurationManager;
|
||||
import com.cloud.dc.ClusterDetailsDao;
|
||||
import com.cloud.dc.dao.ClusterDao;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentClusterPlanner;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.deploy.FirstFitPlanner;
|
||||
import com.cloud.gpu.GPU;
|
||||
import com.cloud.host.DetailVO;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.host.dao.HostDetailsDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.GuestOSCategoryVO;
|
||||
import com.cloud.storage.GuestOSVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.dao.GuestOSCategoryDao;
|
||||
import com.cloud.storage.dao.GuestOSDao;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* An allocator that tries to find a fit on a computing host. This allocator does not care whether or not the host supports routing.
|
||||
*/
|
||||
@Component
|
||||
public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
||||
@Inject
|
||||
protected HostDao _hostDao = null;
|
||||
public class FirstFitAllocator extends BaseAllocator {
|
||||
@Inject
|
||||
HostDetailsDao _hostDetailsDao = null;
|
||||
@Inject
|
||||
|
|
@ -95,289 +90,183 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
@Inject
|
||||
protected ResourceManager _resourceMgr;
|
||||
@Inject
|
||||
ClusterDao _clusterDao;
|
||||
@Inject
|
||||
ClusterDetailsDao _clusterDetailsDao;
|
||||
@Inject
|
||||
ServiceOfferingDetailsDao _serviceOfferingDetailsDao;
|
||||
@Inject
|
||||
CapacityManager _capacityMgr;
|
||||
@Inject
|
||||
CapacityDao _capacityDao;
|
||||
@Inject
|
||||
VMInstanceDetailsDao _vmInstanceDetailsDao;
|
||||
@Inject
|
||||
private VgpuProfileDao vgpuProfileDao;
|
||||
VMInstanceDetailsDao vmInstanceDetailsDao;
|
||||
|
||||
boolean _checkHvm = true;
|
||||
|
||||
static DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
|
||||
Account account = vmProfile.getOwner();
|
||||
|
||||
boolean isVMDeployedWithUefi = false;
|
||||
VMInstanceDetailVO vmInstanceDetailVO = _vmInstanceDetailsDao.findDetail(vmProfile.getId(), "UEFI");
|
||||
if(vmInstanceDetailVO != null){
|
||||
if ("secure".equalsIgnoreCase(vmInstanceDetailVO.getValue()) || "legacy".equalsIgnoreCase(vmInstanceDetailVO.getValue())) {
|
||||
isVMDeployedWithUefi = true;
|
||||
}
|
||||
}
|
||||
logger.info(" Guest VM is requested with Custom[UEFI] Boot Type "+ isVMDeployedWithUefi);
|
||||
|
||||
|
||||
if (type == Host.Type.Storage) {
|
||||
// FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of routing or not
|
||||
return new ArrayList<>();
|
||||
}
|
||||
String paramAsStringToLog = String.format("zone [%s], pod [%s], cluster [%s]", dcId, podId, clusterId);
|
||||
logger.debug("Looking for hosts in {}", paramAsStringToLog);
|
||||
|
||||
String hostTagOnOffering = offering.getHostTag();
|
||||
String hostTagOnTemplate = template.getTemplateTag();
|
||||
String hostTagUefi = "UEFI";
|
||||
|
||||
boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false;
|
||||
boolean hasTemplateTag = hostTagOnTemplate != null ? true : false;
|
||||
|
||||
List<HostVO> clusterHosts = new ArrayList<>();
|
||||
List<HostVO> hostsMatchingUefiTag = new ArrayList<>();
|
||||
if(isVMDeployedWithUefi){
|
||||
hostsMatchingUefiTag = _hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Hosts with tag '" + hostTagUefi + "' are:" + hostsMatchingUefiTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
if (haVmTag != null) {
|
||||
clusterHosts = _hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag);
|
||||
} else {
|
||||
if (hostTagOnOffering == null && hostTagOnTemplate == null) {
|
||||
clusterHosts = _resourceMgr.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId);
|
||||
} else {
|
||||
List<HostVO> hostsMatchingOfferingTag = new ArrayList<>();
|
||||
List<HostVO> hostsMatchingTemplateTag = new ArrayList<>();
|
||||
if (hasSvcOfferingTag) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for hosts having tag specified on SvcOffering:" + hostTagOnOffering);
|
||||
}
|
||||
hostsMatchingOfferingTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Hosts with tag '" + hostTagOnOffering + "' are:" + hostsMatchingOfferingTag);
|
||||
}
|
||||
}
|
||||
if (hasTemplateTag) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for hosts having tag specified on Template:" + hostTagOnTemplate);
|
||||
}
|
||||
hostsMatchingTemplateTag = _hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Hosts with tag '" + hostTagOnTemplate + "' are:" + hostsMatchingTemplateTag);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasSvcOfferingTag && hasTemplateTag) {
|
||||
hostsMatchingOfferingTag.retainAll(hostsMatchingTemplateTag);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found " + hostsMatchingOfferingTag.size() + " Hosts satisfying both tags, host ids are:" + hostsMatchingOfferingTag);
|
||||
}
|
||||
|
||||
clusterHosts = hostsMatchingOfferingTag;
|
||||
} else {
|
||||
if (hasSvcOfferingTag) {
|
||||
clusterHosts = hostsMatchingOfferingTag;
|
||||
} else {
|
||||
clusterHosts = hostsMatchingTemplateTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isVMDeployedWithUefi) {
|
||||
clusterHosts.retainAll(hostsMatchingUefiTag);
|
||||
}
|
||||
|
||||
clusterHosts.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering));
|
||||
|
||||
|
||||
if (clusterHosts.isEmpty()) {
|
||||
logger.warn("No suitable host found for VM [{}] with tags {} in {}.", vmProfile, hostTagOnOffering, paramAsStringToLog);
|
||||
return null;
|
||||
}
|
||||
// add all hosts that we are not considering to the avoid list
|
||||
List<HostVO> allhostsInCluster = _hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
|
||||
allhostsInCluster.removeAll(clusterHosts);
|
||||
|
||||
logger.debug(() -> String.format("Adding hosts [%s] to the avoid set because these hosts do not support HA.",
|
||||
ReflectionToStringBuilderUtils.reflectOnlySelectedFields(allhostsInCluster, "uuid", "name")));
|
||||
|
||||
for (HostVO host : allhostsInCluster) {
|
||||
avoid.addHost(host.getId());
|
||||
}
|
||||
|
||||
return allocateTo(vmProfile, plan, offering, template, avoid, clusterHosts, returnUpTo, considerReservedCapacity, account);
|
||||
return allocateTo(vmProfile, plan, type, avoid, null, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
boolean considerReservedCapacity) {
|
||||
if (type == Host.Type.Storage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
VMTemplateVO template = (VMTemplateVO)vmProfile.getTemplate();
|
||||
VMTemplateVO template = (VMTemplateVO) vmProfile.getTemplate();
|
||||
Account account = vmProfile.getOwner();
|
||||
List<Host> suitableHosts = new ArrayList<>();
|
||||
List<Host> hostsCopy = new ArrayList<>(hosts);
|
||||
|
||||
if (type == Host.Type.Storage) {
|
||||
// FirstFitAllocator should be used for user VMs only since it won't care whether the host is capable of
|
||||
// routing or not.
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
String hostTagOnOffering = offering.getHostTag();
|
||||
String hostTagOnTemplate = template.getTemplateTag();
|
||||
boolean hasSvcOfferingTag = hostTagOnOffering != null ? true : false;
|
||||
boolean hasTemplateTag = hostTagOnTemplate != null ? true : false;
|
||||
String paramAsStringToLog = String.format("zone [%s], pod [%s], cluster [%s]", dcId, podId, clusterId);
|
||||
|
||||
String haVmTag = (String)vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
if (haVmTag != null) {
|
||||
hostsCopy.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag));
|
||||
List<HostVO> suitableHosts = retrieveHosts(vmProfile, type, (List<HostVO>) hosts, clusterId, podId, dcId, hostTagOnOffering, hostTagOnTemplate);
|
||||
|
||||
if (suitableHosts.isEmpty()) {
|
||||
logger.info("No suitable host found for VM [{}] in {}.", vmProfile, paramAsStringToLog);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (CollectionUtils.isEmpty(hosts)) {
|
||||
addHostsToAvoidSet(type, avoid, clusterId, podId, dcId, suitableHosts);
|
||||
}
|
||||
|
||||
return allocateTo(vmProfile, plan, offering, template, avoid, suitableHosts, returnUpTo, considerReservedCapacity, account);
|
||||
}
|
||||
|
||||
protected List<HostVO> retrieveHosts(VirtualMachineProfile vmProfile, Type type, List<HostVO> hostsToFilter, Long clusterId, Long podId, long dcId, String hostTagOnOffering,
|
||||
String hostTagOnTemplate) {
|
||||
String haVmTag = (String) vmProfile.getParameter(VirtualMachineProfile.Param.HaTag);
|
||||
List<HostVO> clusterHosts;
|
||||
|
||||
if (CollectionUtils.isNotEmpty(hostsToFilter)) {
|
||||
clusterHosts = new ArrayList<>(hostsToFilter);
|
||||
} else {
|
||||
if (hostTagOnOffering == null && hostTagOnTemplate == null) {
|
||||
hostsCopy.retainAll(_resourceMgr.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId));
|
||||
} else {
|
||||
if (hasSvcOfferingTag) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for hosts having tag specified on SvcOffering:" + hostTagOnOffering);
|
||||
}
|
||||
hostsCopy.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Hosts with tag '" + hostTagOnOffering + "' are:" + hostsCopy);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasTemplateTag) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for hosts having tag specified on Template:" + hostTagOnTemplate);
|
||||
}
|
||||
|
||||
hostsCopy.retainAll(_hostDao.listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Hosts with tag '" + hostTagOnTemplate + "' are:" + hostsCopy);
|
||||
}
|
||||
}
|
||||
}
|
||||
clusterHosts = _resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId);
|
||||
}
|
||||
|
||||
hostsCopy.addAll(_hostDao.findHostsWithTagRuleThatMatchComputeOferringTags(hostTagOnOffering));
|
||||
|
||||
if (!hostsCopy.isEmpty()) {
|
||||
suitableHosts = allocateTo(vmProfile, plan, offering, template, avoid, hostsCopy, returnUpTo, considerReservedCapacity, account);
|
||||
if (haVmTag != null) {
|
||||
clusterHosts.retainAll(hostDao.listByHostTag(type, clusterId, podId, dcId, haVmTag));
|
||||
} else if (ObjectUtils.allNull(hostTagOnOffering, hostTagOnTemplate)) {
|
||||
clusterHosts.retainAll(_resourceMgr.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId));
|
||||
} else {
|
||||
retainHostsMatchingServiceOfferingAndTemplateTags(clusterHosts, type, dcId, podId, clusterId, hostTagOnOffering, hostTagOnTemplate);
|
||||
}
|
||||
|
||||
filterHostsWithUefiEnabled(type, vmProfile, clusterId, podId, dcId, clusterHosts);
|
||||
|
||||
addHostsBasedOnTagRules(hostTagOnOffering, clusterHosts);
|
||||
|
||||
return clusterHosts;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all hosts to the avoid set that were not considered during the allocation
|
||||
*/
|
||||
protected void addHostsToAvoidSet(Type type, ExcludeList avoid, Long clusterId, Long podId, long dcId, List<HostVO> suitableHosts) {
|
||||
List<HostVO> allHostsInCluster = hostDao.listAllUpAndEnabledNonHAHosts(type, clusterId, podId, dcId, null);
|
||||
|
||||
allHostsInCluster.removeAll(suitableHosts);
|
||||
|
||||
logger.debug("Adding hosts [{}] to the avoid set because these hosts were not considered for allocation.",
|
||||
() -> ReflectionToStringBuilderUtils.reflectOnlySelectedFields(allHostsInCluster, "uuid", "name"));
|
||||
|
||||
for (HostVO host : allHostsInCluster) {
|
||||
avoid.addHost(host.getId());
|
||||
}
|
||||
}
|
||||
|
||||
protected void filterHostsWithUefiEnabled(Type type, VirtualMachineProfile vmProfile, Long clusterId, Long podId, long dcId, List<HostVO> clusterHosts) {
|
||||
VMInstanceDetailVO vmInstanceDetailVO = vmInstanceDetailsDao.findDetail(vmProfile.getId(), "UEFI");
|
||||
|
||||
if (vmInstanceDetailVO == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!StringUtils.equalsAnyIgnoreCase(vmInstanceDetailVO.getValue(), ApiConstants.BootMode.SECURE.toString(), ApiConstants.BootMode.LEGACY.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Guest VM is requested with Custom[UEFI] Boot Type enabled.");
|
||||
|
||||
List<HostVO> hostsMatchingUefiTag = hostDao.listByHostCapability(type, clusterId, podId, dcId, Host.HOST_UEFI_ENABLE);
|
||||
|
||||
logger.debug("Hosts with UEFI enabled are {}.", hostsMatchingUefiTag);
|
||||
clusterHosts.retainAll(hostsMatchingUefiTag);
|
||||
}
|
||||
|
||||
protected List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity, Account account) {
|
||||
String vmAllocationAlgorithm = DeploymentClusterPlanner.VmAllocationAlgorithm.value();
|
||||
if (random.toString().equals(vmAllocationAlgorithm)) {
|
||||
Collections.shuffle(hosts);
|
||||
} else if (userdispersing.toString().equals(vmAllocationAlgorithm)) {
|
||||
hosts = reorderHostsByNumberOfVms(plan, hosts, account);
|
||||
} else if (firstfitleastconsumed.toString().equals(vmAllocationAlgorithm)) {
|
||||
hosts = reorderHostsByCapacity(plan, hosts);
|
||||
}
|
||||
|
||||
logger.debug("FirstFitAllocator has {} hosts to check for allocation {}.", hosts.size(), hosts);
|
||||
hosts = prioritizeHosts(template, offering, hosts);
|
||||
logger.debug("Found {} hosts for allocation after prioritization: {}.", hosts.size(), hosts);
|
||||
|
||||
List<Host> suitableHosts = checkHostsCompatibilities(offering, vmProfile, avoid, hosts, returnUpTo, considerReservedCapacity);
|
||||
logger.debug("Host Allocator returning {} suitable hosts.", suitableHosts.size());
|
||||
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
protected List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, ServiceOffering offering, VMTemplateVO template, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity, Account account) {
|
||||
String vmAllocationAlgorithm = DeploymentClusterPlanner.VmAllocationAlgorithm.value();
|
||||
if (vmAllocationAlgorithm.equals("random")) {
|
||||
// Shuffle this so that we don't check the hosts in the same order.
|
||||
Collections.shuffle(hosts);
|
||||
} else if (vmAllocationAlgorithm.equals("userdispersing")) {
|
||||
hosts = reorderHostsByNumberOfVms(plan, hosts, account);
|
||||
} else if(vmAllocationAlgorithm.equals("firstfitleastconsumed")){
|
||||
hosts = reorderHostsByCapacity(plan, hosts);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("FirstFitAllocator has " + hosts.size() + " hosts to check for allocation: " + hosts);
|
||||
}
|
||||
|
||||
// We will try to reorder the host lists such that we give priority to hosts that have
|
||||
// the minimums to support a VM's requirements
|
||||
hosts = prioritizeHosts(template, offering, hosts);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found " + hosts.size() + " hosts for allocation after prioritization: " + hosts);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Looking for speed=" + (offering.getCpu() * offering.getSpeed()) + "Mhz, Ram=" + offering.getRamSize() + " MB");
|
||||
}
|
||||
|
||||
long serviceOfferingId = offering.getId();
|
||||
protected List<Host> checkHostsCompatibilities(ServiceOffering offering, VirtualMachineProfile vmProfile, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo, boolean considerReservedCapacity) {
|
||||
List<Host> suitableHosts = new ArrayList<>();
|
||||
ServiceOfferingDetailsVO offeringDetails = null;
|
||||
logger.debug("Checking compatibility for the following hosts {}.", suitableHosts);
|
||||
|
||||
for (Host host : hosts) {
|
||||
if (suitableHosts.size() == returnUpTo) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avoid.shouldAvoid(host)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Host: {} is in avoid set, skipping this and trying other available hosts", host);
|
||||
}
|
||||
logger.debug("Host [{}] is in avoid set, skipping this and trying other available hosts", host);
|
||||
continue;
|
||||
}
|
||||
|
||||
//find number of guest VMs occupying capacity on this host.
|
||||
if (_capacityMgr.checkIfHostReachMaxGuestLimit(host)) {
|
||||
if (capacityManager.checkIfHostReachMaxGuestLimit(host)) {
|
||||
logger.debug("Adding host [{}] to the avoid set because this host already has the max number of running (user and/or system) VMs.", host);
|
||||
avoid.addHost(host.getId());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if GPU device is required by offering and host has the availability
|
||||
if (_resourceMgr.isGPUDeviceAvailable(offering, host, vmProfile.getId())) {
|
||||
logger.debug("Host [{}] has required GPU devices available.", host);
|
||||
} else {
|
||||
// If GPU is not available, skip this host
|
||||
logger.debug("Adding host [{}] to avoid set, because this host does not have required GPU devices available.", host);
|
||||
avoid.addHost(host.getId());
|
||||
if (offeringRequestedVGpuAndHostDoesNotHaveIt(offering, vmProfile, avoid, host)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Pair<Boolean, Boolean> cpuCapabilityAndCapacity = _capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host, offering, considerReservedCapacity);
|
||||
if (cpuCapabilityAndCapacity.first() && cpuCapabilityAndCapacity.second()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found a suitable host, adding to list: {}", host);
|
||||
}
|
||||
if (hostHasCpuCapabilityAndCapacity(considerReservedCapacity, offering, host)) {
|
||||
suitableHosts.add(host);
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Not using host {}; host has cpu capability? {}, host has capacity?{}",
|
||||
host, cpuCapabilityAndCapacity.first(), cpuCapabilityAndCapacity.second());
|
||||
}
|
||||
avoid.addHost(host.getId());
|
||||
continue;
|
||||
}
|
||||
avoid.addHost(host.getId());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Host Allocator returning " + suitableHosts.size() + " suitable hosts");
|
||||
}
|
||||
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
// Reorder hosts in the decreasing order of free capacity.
|
||||
protected boolean offeringRequestedVGpuAndHostDoesNotHaveIt(ServiceOffering offering, VirtualMachineProfile vmProfile, ExcludeList avoid, Host host) {
|
||||
if (_resourceMgr.isGPUDeviceAvailable(offering, host, vmProfile.getId())) {
|
||||
logger.debug("Host [{}] has required GPU devices available.", () -> host);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug("Adding host [{}] to avoid set, because this host does not have required GPU devices available.", () -> host);
|
||||
avoid.addHost(host.getId());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder hosts in the decreasing order of free capacity.
|
||||
*/
|
||||
private List<? extends Host> reorderHostsByCapacity(DeploymentPlan plan, List<? extends Host> hosts) {
|
||||
Long zoneId = plan.getDataCenterId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
|
|
@ -388,26 +277,10 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> decimalFormat.format(entry.getValue() * 100) + "%",
|
||||
(e1, e2) -> e1, LinkedHashMap::new));
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("List of hosts: [{}] in descending order of free capacity (percentage) in the cluster: {}",
|
||||
hostIdsByFreeCapacity, sortedHostByCapacity);
|
||||
}
|
||||
logger.debug("List of hosts: [{}] in descending order of free capacity (percentage) in the cluster: {}.",
|
||||
hostIdsByFreeCapacity, sortedHostByCapacity);
|
||||
|
||||
//now filter the given list of Hosts by this ordered list
|
||||
Map<Long, Host> hostMap = new HashMap<>();
|
||||
for (Host host : hosts) {
|
||||
hostMap.put(host.getId(), host);
|
||||
}
|
||||
List<Long> matchingHostIds = new ArrayList<>(hostMap.keySet());
|
||||
|
||||
hostIdsByFreeCapacity.retainAll(matchingHostIds);
|
||||
|
||||
List<Host> reorderedHosts = new ArrayList<>();
|
||||
for(Long id: hostIdsByFreeCapacity){
|
||||
reorderedHosts.add(hostMap.get(id));
|
||||
}
|
||||
|
||||
return reorderedHosts;
|
||||
return filterHosts(hosts, hostIdsByFreeCapacity);
|
||||
}
|
||||
|
||||
private Pair<List<Long>, Map<Long, Double>> getOrderedHostsByCapacity(Long zoneId, Long clusterId) {
|
||||
|
|
@ -450,116 +323,154 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
Long clusterId = plan.getClusterId();
|
||||
|
||||
List<Long> hostIdsByVmCount = _vmInstanceDao.listHostIdsByVmCount(dcId, podId, clusterId, account.getAccountId());
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("List of hosts in ascending order of number of VMs: " + hostIdsByVmCount);
|
||||
}
|
||||
logger.debug("List of hosts in ascending order of number of VMs: {}.", hostIdsByVmCount);
|
||||
|
||||
//now filter the given list of Hosts by this ordered list
|
||||
return filterHosts(hosts, hostIdsByVmCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the given list of Hosts considering the ordered list
|
||||
*/
|
||||
private List<? extends Host> filterHosts(List<? extends Host> hosts, List<Long> orderedHostIdsList) {
|
||||
Map<Long, Host> hostMap = new HashMap<>();
|
||||
|
||||
for (Host host : hosts) {
|
||||
hostMap.put(host.getId(), host);
|
||||
}
|
||||
List<Long> matchingHostIds = new ArrayList<>(hostMap.keySet());
|
||||
|
||||
hostIdsByVmCount.retainAll(matchingHostIds);
|
||||
orderedHostIdsList.retainAll(matchingHostIds);
|
||||
|
||||
List<Host> reorderedHosts = new ArrayList<>();
|
||||
for (Long id : hostIdsByVmCount) {
|
||||
for(Long id: orderedHostIdsList){
|
||||
reorderedHosts.add(hostMap.get(id));
|
||||
}
|
||||
|
||||
return reorderedHosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
|
||||
// currently we do no special checks to rule out a VM being upgradable to an offering, so
|
||||
// return true
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder the host list giving priority to hosts that have the minimum to support the VM's requirements.
|
||||
*/
|
||||
protected List<? extends Host> prioritizeHosts(VMTemplateVO template, ServiceOffering offering, List<? extends Host> hosts) {
|
||||
if (template == null) {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
// Determine the guest OS category of the template
|
||||
String templateGuestOSCategory = getTemplateGuestOSCategory(template);
|
||||
List<Host> hostsToCheck = filterHostWithNoHvmIfTemplateRequested(template, hosts);
|
||||
|
||||
List<Host> prioritizedHosts = new ArrayList<>();
|
||||
List<Host> noHvmHosts = new ArrayList<>();
|
||||
|
||||
// If a template requires HVM and a host doesn't support HVM, remove it from consideration
|
||||
List<Host> hostsToCheck = new ArrayList<>();
|
||||
if (template.isRequiresHvm()) {
|
||||
for (Host host : hosts) {
|
||||
if (hostSupportsHVM(host)) {
|
||||
hostsToCheck.add(host);
|
||||
} else {
|
||||
noHvmHosts.add(host);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hostsToCheck.addAll(hosts);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (noHvmHosts.size() > 0) {
|
||||
logger.debug("Not considering hosts: " + noHvmHosts + " to deploy template: " + template + " as they are not HVM enabled");
|
||||
}
|
||||
}
|
||||
// If a host is tagged with the same guest OS category as the template, move it to a high priority list
|
||||
// If a host is tagged with a different guest OS category than the template, move it to a low priority list
|
||||
List<Host> highPriorityHosts = new ArrayList<>();
|
||||
List<Host> lowPriorityHosts = new ArrayList<>();
|
||||
for (Host host : hostsToCheck) {
|
||||
String hostGuestOSCategory = getHostGuestOSCategory(host);
|
||||
if (hostGuestOSCategory == null) {
|
||||
continue;
|
||||
} else if (templateGuestOSCategory != null && templateGuestOSCategory.equals(hostGuestOSCategory)) {
|
||||
highPriorityHosts.add(host);
|
||||
} else {
|
||||
lowPriorityHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
prioritizeHostsWithMatchingGuestOs(template, hostsToCheck, highPriorityHosts, lowPriorityHosts);
|
||||
hostsToCheck.removeAll(highPriorityHosts);
|
||||
hostsToCheck.removeAll(lowPriorityHosts);
|
||||
|
||||
// Prioritize the remaining hosts by HVM capability
|
||||
for (Host host : hostsToCheck) {
|
||||
if (!template.isRequiresHvm() && !hostSupportsHVM(host)) {
|
||||
// Host and template both do not support hvm, put it as first consideration
|
||||
prioritizedHosts.add(0, host);
|
||||
} else {
|
||||
// Template doesn't require hvm, but the machine supports it, make it last for consideration
|
||||
prioritizedHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge the lists
|
||||
prioritizeHostsByHvmCapability(template, hostsToCheck, prioritizedHosts);
|
||||
prioritizedHosts.addAll(0, highPriorityHosts);
|
||||
prioritizedHosts.addAll(lowPriorityHosts);
|
||||
|
||||
// if service offering is not GPU enabled then move all the GPU enabled hosts to the end of priority list.
|
||||
if (_serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) == null && offering.getVgpuProfileId() == null) {
|
||||
prioritizeHostsByGpuEnabled(offering, prioritizedHosts);
|
||||
|
||||
List<Host> gpuEnabledHosts = new ArrayList<>();
|
||||
// Check for GPU enabled hosts.
|
||||
for (Host host : prioritizedHosts) {
|
||||
if (_resourceMgr.isHostGpuEnabled(host.getId())) {
|
||||
gpuEnabledHosts.add(host);
|
||||
}
|
||||
}
|
||||
// Move GPU enabled hosts to the end of list
|
||||
if(!gpuEnabledHosts.isEmpty()) {
|
||||
prioritizedHosts.removeAll(gpuEnabledHosts);
|
||||
prioritizedHosts.addAll(gpuEnabledHosts);
|
||||
}
|
||||
}
|
||||
return prioritizedHosts;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If a template requires HVM and a host doesn't support HVM, remove it from consideration.
|
||||
*/
|
||||
protected List<Host> filterHostWithNoHvmIfTemplateRequested(VMTemplateVO template, List<? extends Host> hosts) {
|
||||
List<Host> hostsToCheck = new ArrayList<>();
|
||||
|
||||
if (!template.isRequiresHvm()) {
|
||||
logger.debug("Template [{}] does not require HVM, therefore, the hosts {} will not be checked for HVM compatibility.", template, hostsToCheck);
|
||||
hostsToCheck.addAll(hosts);
|
||||
return hostsToCheck;
|
||||
}
|
||||
|
||||
List<Host> noHvmHosts = new ArrayList<>();
|
||||
logger.debug("Template [{}] requires HVM, therefore, the hosts %s will be checked for HVM compatibility.", template, hostsToCheck);
|
||||
|
||||
for (Host host : hosts) {
|
||||
if (hostSupportsHVM(host)) {
|
||||
hostsToCheck.add(host);
|
||||
} else {
|
||||
noHvmHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
if (!noHvmHosts.isEmpty()) {
|
||||
logger.debug("Not considering hosts {} to deploy VM using template {} as they are not HVM enabled.", noHvmHosts, template);
|
||||
}
|
||||
|
||||
return hostsToCheck;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If service offering did not request for vGPU, then move all host with GPU to the end of the host priority list.
|
||||
*/
|
||||
protected void prioritizeHostsByGpuEnabled(ServiceOffering offering, List<Host> prioritizedHosts) {
|
||||
boolean serviceOfferingRequestedVGpu = _serviceOfferingDetailsDao.findDetail(offering.getId(), GPU.Keys.vgpuType.toString()) != null || offering.getVgpuProfileId() != null;
|
||||
|
||||
if (serviceOfferingRequestedVGpu) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Host> gpuEnabledHosts = new ArrayList<>();
|
||||
|
||||
for (Host host : prioritizedHosts) {
|
||||
if (_resourceMgr.isHostGpuEnabled(host.getId())) {
|
||||
gpuEnabledHosts.add(host);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpuEnabledHosts.isEmpty()) {
|
||||
prioritizedHosts.removeAll(gpuEnabledHosts);
|
||||
prioritizedHosts.addAll(gpuEnabledHosts);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prioritize remaining host by HVM capability.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If host and template both do not support HVM, put it at the start of the list.</li>
|
||||
* <li>If the template doesn't require HVM, but the machine supports it, append it to the list.</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected void prioritizeHostsByHvmCapability(VMTemplateVO template, List<Host> hostsToCheck, List<Host> prioritizedHosts) {
|
||||
for (Host host : hostsToCheck) {
|
||||
if (!template.isRequiresHvm() && !hostSupportsHVM(host)) {
|
||||
prioritizedHosts.add(0, host);
|
||||
} else {
|
||||
prioritizedHosts.add(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <ul>
|
||||
* <li>If a host is tagged with the same guest OS category as the template, move it to a high priority list.</li>
|
||||
* <li>If a host is tagged with a different guest OS category than the template, move it to a low priority list.</li>
|
||||
* </ul>
|
||||
*/
|
||||
protected void prioritizeHostsWithMatchingGuestOs(VMTemplateVO template, List<Host> hostsToCheck, List<Host> highPriorityHosts, List<Host> lowPriorityHosts) {
|
||||
String templateGuestOSCategory = getTemplateGuestOSCategory(template);
|
||||
|
||||
for (Host host : hostsToCheck) {
|
||||
String hostGuestOSCategory = getHostGuestOSCategory(host);
|
||||
|
||||
if (StringUtils.equals(templateGuestOSCategory, hostGuestOSCategory)) {
|
||||
highPriorityHosts.add(host);
|
||||
} else if (hostGuestOSCategory != null) {
|
||||
lowPriorityHosts.add(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected boolean hostSupportsHVM(Host host) {
|
||||
if (!_checkHvm) {
|
||||
return true;
|
||||
|
|
@ -621,19 +532,8 @@ public class FirstFitAllocator extends AdapterBase implements HostAllocator {
|
|||
if (_configDao != null) {
|
||||
Map<String, String> configs = _configDao.getConfiguration(params);
|
||||
String value = configs.get("xenserver.check.hvm");
|
||||
_checkHvm = value == null ? true : Boolean.parseBoolean(value);
|
||||
_checkHvm = value == null || Boolean.parseBoolean(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
// 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.agent.manager.allocator.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Component
|
||||
public class RandomAllocator extends BaseAllocator {
|
||||
@Inject
|
||||
private ResourceManager _resourceMgr;
|
||||
|
||||
protected List<Host> findSuitableHosts(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
if (type == Host.Type.Storage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long dcId = plan.getDataCenterId();
|
||||
Long podId = plan.getPodId();
|
||||
Long clusterId = plan.getClusterId();
|
||||
ServiceOffering offering = vmProfile.getServiceOffering();
|
||||
|
||||
String offeringHostTag = offering.getHostTag();
|
||||
VMTemplateVO template = (VMTemplateVO) vmProfile.getTemplate();
|
||||
logger.debug("Looking for hosts in zone [{}], pod [{}], cluster [{}].", dcId, podId, clusterId);
|
||||
|
||||
List<? extends Host> availableHosts = retrieveHosts(type, (List<HostVO>) hosts, template, offeringHostTag, clusterId, podId, dcId);
|
||||
|
||||
if (availableHosts.isEmpty()) {
|
||||
logger.info("No suitable host found for VM [{}] in zone [{}], pod [{}], cluster [{}].", vmProfile, dcId, podId, clusterId);
|
||||
return null;
|
||||
}
|
||||
|
||||
return filterAvailableHosts(avoid, returnUpTo, considerReservedCapacity, availableHosts, offering);
|
||||
}
|
||||
|
||||
protected List<Host> filterAvailableHosts(ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity, List<? extends Host> availableHosts, ServiceOffering offering) {
|
||||
logger.debug("Random Allocator found [{}] available hosts. They will be checked if they are in the avoid set and for CPU capability and capacity.", availableHosts::size);
|
||||
List<Host> suitableHosts = new ArrayList<>();
|
||||
|
||||
Collections.shuffle(availableHosts);
|
||||
for (Host host : availableHosts) {
|
||||
if (suitableHosts.size() == returnUpTo) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (avoid.shouldAvoid(host)) {
|
||||
logger.debug("Host [{}] is in the avoid set, skipping it and trying other available hosts.", () -> host);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hostHasCpuCapabilityAndCapacity(considerReservedCapacity, offering, host)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.debug("Found the suitable host [{}], adding to list.", () -> host);
|
||||
suitableHosts.add(host);
|
||||
}
|
||||
|
||||
logger.debug("Random Host Allocator returning {} suitable hosts.", suitableHosts::size);
|
||||
return suitableHosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return all computing hosts, regardless of whether they support routing.
|
||||
*/
|
||||
protected List<HostVO> retrieveHosts(Type type, List<HostVO> hosts, VMTemplateVO template, String offeringHostTag, Long clusterId, Long podId, long dcId) {
|
||||
List<HostVO> availableHosts;
|
||||
String templateTag = template.getTemplateTag();
|
||||
|
||||
if (CollectionUtils.isNotEmpty(hosts)) {
|
||||
availableHosts = new ArrayList<>(hosts);
|
||||
} else {
|
||||
availableHosts = _resourceMgr.listAllUpAndEnabledHosts(type, clusterId, podId, dcId);
|
||||
}
|
||||
|
||||
if (ObjectUtils.anyNotNull(offeringHostTag, templateTag)) {
|
||||
retainHostsMatchingServiceOfferingAndTemplateTags(availableHosts, type, dcId, podId, clusterId, offeringHostTag, templateTag);
|
||||
} else {
|
||||
List<HostVO> hostsWithNoRuleTag = hostDao.listAllHostsThatHaveNoRuleTag(type, clusterId, podId, dcId);
|
||||
logger.debug("Retaining hosts {} because they do not have rule tags.", hostsWithNoRuleTag);
|
||||
availableHosts.retainAll(hostsWithNoRuleTag);
|
||||
}
|
||||
|
||||
addHostsBasedOnTagRules(offeringHostTag, availableHosts);
|
||||
|
||||
return availableHosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, null, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
return findSuitableHosts(vmProfile, plan, type, avoid, hosts, returnUpTo, considerReservedCapacity);
|
||||
}
|
||||
}
|
||||
|
|
@ -28,32 +28,24 @@ import com.cloud.deploy.DeploymentPlanner.ExcludeList;
|
|||
import com.cloud.host.Host;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.utils.component.AdapterBase;
|
||||
import com.cloud.vm.VirtualMachine;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
public class TestingAllocator extends AdapterBase implements HostAllocator {
|
||||
@Inject
|
||||
HostDao _hostDao;
|
||||
Long _computingHost;
|
||||
Long _storageHost;
|
||||
Long _routingHost;
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, true);
|
||||
return allocateTo(vmProfile, plan, type, avoid, null, returnUpTo, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, List<? extends Host> hosts, int returnUpTo,
|
||||
boolean considerReservedCapacity) {
|
||||
return allocateTo(vmProfile, plan, type, avoid, returnUpTo, considerReservedCapacity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Type type, ExcludeList avoid, int returnUpTo, boolean considerReservedCapacity) {
|
||||
List<Host> availableHosts = new ArrayList<Host>();
|
||||
boolean considerReservedCapacity) {
|
||||
List<Host> availableHosts = new ArrayList<>();
|
||||
Host host = null;
|
||||
if (type == Host.Type.Routing && _routingHost != null) {
|
||||
host = _hostDao.findById(_routingHost);
|
||||
|
|
@ -66,13 +58,6 @@ public class TestingAllocator extends AdapterBase implements HostAllocator {
|
|||
return availableHosts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualMachineUpgradable(VirtualMachine vm, ServiceOffering offering) {
|
||||
// currently we do no special checks to rule out a VM being upgradable to an offering, so
|
||||
// return true
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) {
|
||||
String value = (String)params.get(Host.Type.Routing.toString());
|
||||
|
|
|
|||
|
|
@ -2890,6 +2890,11 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
}
|
||||
}
|
||||
|
||||
if (CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN &&
|
||||
network.getVpcId() == null && network.getGuestType() == Network.GuestType.Isolated) {
|
||||
response.setKeepMacAddressOnPublicNic(network.getKeepMacAddressOnPublicNic());
|
||||
}
|
||||
|
||||
response.setObjectName("network");
|
||||
return response;
|
||||
}
|
||||
|
|
@ -3653,6 +3658,9 @@ public class ApiResponseHelper implements ResponseGenerator, ResourceIdSupport {
|
|||
}
|
||||
}
|
||||
|
||||
if (CallContext.current().getCallingAccount().getType() == Account.Type.ADMIN) {
|
||||
response.setKeepMacAddressOnPublicNic(vpc.getKeepMacAddressOnPublicNic());
|
||||
}
|
||||
response.setObjectName("vpc");
|
||||
return response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
|
@ -1714,20 +1713,19 @@ StateListener<State, VirtualMachine.Event, VirtualMachine>, Configurable {
|
|||
|
||||
@Override
|
||||
public void reorderHostsByPriority(Map<Long, Integer> priorities, List<Host> hosts) {
|
||||
logger.debug("Re-ordering hosts {} by priorities {}", hosts, priorities);
|
||||
if (CollectionUtils.isEmpty(hosts)){
|
||||
logger.debug("Hosts list is empty; therefore, there is nothing to reorder.");
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Re-ordering hosts [{}] by priorities [{}].", hosts, priorities);
|
||||
hosts.removeIf(host -> DataCenterDeployment.PROHIBITED_HOST_PRIORITY.equals(getHostPriority(priorities, host.getId())));
|
||||
hosts.sort((host1, host2) -> {
|
||||
int res = getHostPriority(priorities, host1.getId()).compareTo(getHostPriority(priorities, host2.getId()));
|
||||
return -res;
|
||||
});
|
||||
|
||||
Collections.sort(hosts, new Comparator<>() {
|
||||
@Override
|
||||
public int compare(Host host1, Host host2) {
|
||||
int res = getHostPriority(priorities, host1.getId()).compareTo(getHostPriority(priorities, host2.getId()));
|
||||
return -res;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
logger.debug("Hosts after re-ordering are: {}", hosts);
|
||||
logger.info("Hosts after re-ordering are: [{}].", hosts);
|
||||
}
|
||||
|
||||
private Integer getHostPriority(Map<Long, Integer> priorities, Long hostId) {
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ public class NetworkMigrationManagerImpl implements NetworkMigrationManager {
|
|||
|
||||
copyOfVpc = _vpcService.createVpc(vpc.getZoneId(), vpcOfferingId, vpc.getAccountId(), vpc.getName(),
|
||||
vpc.getDisplayText(), vpc.getCidr(), vpc.getNetworkDomain(), vpc.getIp4Dns1(), vpc.getIp4Dns2(),
|
||||
vpc.getIp6Dns1(), vpc.getIp6Dns2(), vpc.isDisplay(), vpc.getPublicMtu(), null, null, null, vpc.useRouterIpAsResolver());
|
||||
vpc.getIp6Dns1(), vpc.getIp6Dns2(), vpc.isDisplay(), vpc.getPublicMtu(), null, null, null, vpc.useRouterIpAsResolver(), vpc.getKeepMacAddressOnPublicNic());
|
||||
|
||||
copyOfVpcId = copyOfVpc.getId();
|
||||
//on resume of migration the uuid will be swapped already. So the copy will have the value of the original vpcid.
|
||||
|
|
|
|||
|
|
@ -1549,6 +1549,8 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
|
||||
DataCenter zone = getAndValidateZone(cmd, pNtwk);
|
||||
|
||||
boolean keepMacAddressOnPublicNic = getAndValidateSupportForKeepMacAddressOnPublicNicParameter(cmd.getKeepMacAddressOnPublicNic(), ntwkOff);
|
||||
|
||||
_accountMgr.checkAccess(owner, ntwkOff, zone);
|
||||
|
||||
validateZoneAvailability(caller, zone);
|
||||
|
|
@ -1834,7 +1836,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
|
||||
Network network = commitNetwork(networkOfferingId, gateway, startIP, endIP, netmask, networkDomain, vlanId, bypassVlanOverlapCheck, name, displayText, caller, physicalNetworkId, zone.getId(),
|
||||
domainId, isDomainSpecific, subdomainAccess, vpcId, startIPv6, endIPv6, ip6Gateway, ip6Cidr, displayNetwork, aclId, secondaryVlanId, privateVlanType, ntwkOff, pNtwk, aclType, owner, cidr, createVlan,
|
||||
externalId, routerIPv4, routerIPv6, associatedNetwork, ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, interfaceMTUs, networkCidrSize);
|
||||
externalId, routerIPv4, routerIPv6, associatedNetwork, ip4Dns1, ip4Dns2, ip6Dns1, ip6Dns2, interfaceMTUs, networkCidrSize, keepMacAddressOnPublicNic);
|
||||
|
||||
// retrieve, acquire and associate the correct IP addresses
|
||||
checkAndSetRouterSourceNatIp(owner, cmd, network);
|
||||
|
|
@ -1879,6 +1881,24 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
}
|
||||
}
|
||||
|
||||
protected boolean getAndValidateSupportForKeepMacAddressOnPublicNicParameter(Boolean keepMacAddressOnPublicNic, NetworkOffering networkOffering) {
|
||||
if (networkOffering.isForVpc() && keepMacAddressOnPublicNic != null) {
|
||||
throw new InvalidParameterValueException(
|
||||
String.format("The [%s] parameter cannot be specified on the creation of VPC tiers.", ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC)
|
||||
);
|
||||
}
|
||||
|
||||
GuestType guestType = networkOffering.getGuestType();
|
||||
if (guestType != GuestType.Isolated && keepMacAddressOnPublicNic != null) {
|
||||
throw new InvalidParameterValueException(String.format(
|
||||
"The [%s] parameter can only be specified on the creation of [%s] networks.",
|
||||
ApiConstants.KEEP_MAC_ADDRESS_ON_PUBLIC_NIC, GuestType.Isolated
|
||||
));
|
||||
}
|
||||
|
||||
return keepMacAddressOnPublicNic == null || keepMacAddressOnPublicNic;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DB
|
||||
@ActionEvent(eventType = EventTypes.EVENT_NETWORK_CREATE, eventDescription = "creating network")
|
||||
|
|
@ -2282,7 +2302,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
final Boolean displayNetwork, final Long aclId, final String isolatedPvlan, final PVlanType isolatedPvlanType, final NetworkOffering ntwkOff, final PhysicalNetwork pNtwk, final ACLType aclType, final Account ownerFinal,
|
||||
final String cidr, final boolean createVlan, final String externalId, String routerIp, String routerIpv6,
|
||||
final Network associatedNetwork, final String ip4Dns1, final String ip4Dns2, final String ip6Dns1, final String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs,
|
||||
final Integer networkCidrSize) throws InsufficientCapacityException, ResourceAllocationException {
|
||||
final Integer networkCidrSize, final boolean keepMacAddressOnPublicNic) throws InsufficientCapacityException, ResourceAllocationException {
|
||||
try {
|
||||
Network network = Transaction.execute(new TransactionCallbackWithException<Network, Exception>() {
|
||||
@Override
|
||||
|
|
@ -2348,7 +2368,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
}
|
||||
network = _networkMgr.createGuestNetwork(networkOfferingId, name, displayText, gateway, cidr, vlanId, bypassVlanOverlapCheck, networkDomain, owner, sharedDomainId, pNtwk,
|
||||
zoneId, aclType, subdomainAccess, vpcId, ip6Gateway, ip6Cidr, displayNetwork, isolatedPvlan, isolatedPvlanType, externalId, routerIp, routerIpv6, ip4Dns1, ip4Dns2,
|
||||
ip6Dns1, ip6Dns2, vrIfaceMTUs, networkCidrSize);
|
||||
ip6Dns1, ip6Dns2, vrIfaceMTUs, networkCidrSize, keepMacAddressOnPublicNic);
|
||||
}
|
||||
|
||||
if (createVlan && network != null) {
|
||||
|
|
@ -3156,6 +3176,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
String ip4Dns2 = cmd.getIp4Dns2();
|
||||
String ip6Dns1 = cmd.getIp6Dns1();
|
||||
String ip6Dns2 = cmd.getIp6Dns2();
|
||||
Boolean keepMacAddressOnPublicNic = cmd.getKeepMacAddressOnPublicNic();
|
||||
|
||||
boolean restartNetwork = false;
|
||||
|
||||
|
|
@ -3214,6 +3235,10 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
|
|||
network.setUuid(customId);
|
||||
}
|
||||
|
||||
if (keepMacAddressOnPublicNic != null) {
|
||||
network.setKeepMacAddressOnPublicNic(getAndValidateSupportForKeepMacAddressOnPublicNicParameter(keepMacAddressOnPublicNic, offering));
|
||||
}
|
||||
|
||||
// display flag is not null and has changed
|
||||
if (displayNetwork != null && displayNetwork != network.getDisplayNetwork()) {
|
||||
// Update resource count if it needs to be updated
|
||||
|
|
|
|||
|
|
@ -737,55 +737,91 @@ public class NetworkHelperImpl implements NetworkHelper {
|
|||
}
|
||||
|
||||
protected LinkedHashMap<Network, List<? extends NicProfile>> configurePublicNic(final RouterDeploymentDefinition routerDeploymentDefinition, final boolean hasGuestNic) throws InsufficientAddressCapacityException {
|
||||
final LinkedHashMap<Network, List<? extends NicProfile>> publicConfig = new LinkedHashMap<Network, List<? extends NicProfile>>(3);
|
||||
|
||||
if (routerDeploymentDefinition.isPublicNetwork()) {
|
||||
logger.debug("Adding NIC for Virtual Router in Public network ");
|
||||
// if source nat service is supported by the network, get the source
|
||||
// nat ip address
|
||||
final NicProfile defaultNic = new NicProfile();
|
||||
defaultNic.setDefaultNic(true);
|
||||
final PublicIp sourceNatIp = routerDeploymentDefinition.getSourceNatIP();
|
||||
defaultNic.setIPv4Address(sourceNatIp.getAddress().addr());
|
||||
defaultNic.setIPv4Gateway(sourceNatIp.getGateway());
|
||||
defaultNic.setIPv4Netmask(sourceNatIp.getNetmask());
|
||||
defaultNic.setMacAddress(sourceNatIp.getMacAddress());
|
||||
// get broadcast from public network
|
||||
final Network pubNet = _networkDao.findById(sourceNatIp.getNetworkId());
|
||||
if (pubNet.getBroadcastDomainType() == BroadcastDomainType.Vxlan) {
|
||||
defaultNic.setBroadcastType(BroadcastDomainType.Vxlan);
|
||||
defaultNic.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag()));
|
||||
defaultNic.setIsolationUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag()));
|
||||
} else {
|
||||
defaultNic.setBroadcastType(BroadcastDomainType.Vlan);
|
||||
defaultNic.setBroadcastUri(sourceNatIp.getVlanTag() != null ? BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag()) : null);
|
||||
defaultNic.setIsolationUri(sourceNatIp.getVlanTag() != null ? IsolationType.Vlan.toUri(sourceNatIp.getVlanTag()) : null);
|
||||
}
|
||||
|
||||
//If guest nic has already been added we will have 2 devices in the list.
|
||||
if (hasGuestNic) {
|
||||
defaultNic.setDeviceId(2);
|
||||
}
|
||||
|
||||
final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0);
|
||||
final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(s_systemAccount, publicOffering, routerDeploymentDefinition.getPlan(), null, null, false);
|
||||
final String publicIp = defaultNic.getIPv4Address();
|
||||
// We want to use the identical MAC address for RvR on public
|
||||
// interface if possible
|
||||
final NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetworks.get(0).getId());
|
||||
if (peerNic != null) {
|
||||
logger.info("Use same MAC as previous RvR, the MAC is " + peerNic.getMacAddress());
|
||||
defaultNic.setMacAddress(peerNic.getMacAddress());
|
||||
}
|
||||
if (routerDeploymentDefinition.getGuestNetwork() != null) {
|
||||
ipv6Service.updateNicIpv6(defaultNic, routerDeploymentDefinition.getDest().getDataCenter(), routerDeploymentDefinition.getGuestNetwork());
|
||||
}
|
||||
publicConfig.put(publicNetworks.get(0), new ArrayList<NicProfile>(Arrays.asList(defaultNic)));
|
||||
final LinkedHashMap<Network, List<? extends NicProfile>> publicConfig = new LinkedHashMap<>(3);
|
||||
if (!routerDeploymentDefinition.isPublicNetwork()) {
|
||||
return publicConfig;
|
||||
}
|
||||
|
||||
final PublicIp sourceNatIp = routerDeploymentDefinition.getSourceNatIP();
|
||||
final NicProfile defaultNic = new NicProfile();
|
||||
configurePublicVrNicBasedOnSourceNatIp(defaultNic, sourceNatIp);
|
||||
if (hasGuestNic) {
|
||||
logger.debug("Guest NIC has already been configured, therefore setting device ID of new VR (with source NAT [{}]) public NIC to [2].", sourceNatIp);
|
||||
defaultNic.setDeviceId(2);
|
||||
}
|
||||
|
||||
final NetworkOffering publicOffering = _networkModel.getSystemAccountNetworkOfferings(NetworkOffering.SystemPublicNetwork).get(0);
|
||||
final List<? extends Network> publicNetworks = _networkMgr.setupNetwork(s_systemAccount, publicOffering, routerDeploymentDefinition.getPlan(), null, null, false);
|
||||
|
||||
setPublicNicMacAddressSameAsPeerNic(defaultNic, publicNetworks.get(0), routerDeploymentDefinition);
|
||||
|
||||
if (routerDeploymentDefinition.getGuestNetwork() != null) {
|
||||
ipv6Service.updateNicIpv6(defaultNic, routerDeploymentDefinition.getDest().getDataCenter(), routerDeploymentDefinition.getGuestNetwork());
|
||||
}
|
||||
publicConfig.put(publicNetworks.get(0), List.of(defaultNic));
|
||||
return publicConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the public NIC of a Virtual Router based on the provided source NAT IP.
|
||||
* @param nic Virtual Router public NIC to be configured.
|
||||
* @param sourceNatIp Source NAT IP which should be used to configure the Virtual Router's public NIC.
|
||||
*/
|
||||
protected void configurePublicVrNicBasedOnSourceNatIp(NicProfile nic, PublicIp sourceNatIp) {
|
||||
logger.debug("Configuring public NIC of VR with source NAT IP equal to [{}]", sourceNatIp.getAddress().addr());
|
||||
nic.setDefaultNic(true);
|
||||
nic.setIPv4Address(sourceNatIp.getAddress().addr());
|
||||
nic.setIPv4Gateway(sourceNatIp.getGateway());
|
||||
nic.setIPv4Netmask(sourceNatIp.getNetmask());
|
||||
nic.setMacAddress(sourceNatIp.getMacAddress());
|
||||
|
||||
Network publicNetwork = _networkDao.findById(sourceNatIp.getNetworkId());
|
||||
if (publicNetwork.getBroadcastDomainType() == BroadcastDomainType.Vxlan) {
|
||||
nic.setBroadcastType(BroadcastDomainType.Vxlan);
|
||||
nic.setBroadcastUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag()));
|
||||
nic.setIsolationUri(BroadcastDomainType.Vxlan.toUri(sourceNatIp.getVlanTag()));
|
||||
} else {
|
||||
nic.setBroadcastType(BroadcastDomainType.Vlan);
|
||||
nic.setBroadcastUri(sourceNatIp.getVlanTag() != null ? BroadcastDomainType.Vlan.toUri(sourceNatIp.getVlanTag()) : null);
|
||||
nic.setIsolationUri(sourceNatIp.getVlanTag() != null ? IsolationType.Vlan.toUri(sourceNatIp.getVlanTag()) : null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MAC address of the new VR's public NIC the same as the previous VR's public NIC MAC address if
|
||||
* {@link RouterDeploymentDefinition#getKeepMacAddressOnPublicNic()} is set to {@code true} and a peer NIC is found; otherwise,
|
||||
* does nothing.
|
||||
*/
|
||||
protected void setPublicNicMacAddressSameAsPeerNic(NicProfile defaultNic, Network publicNetwork, RouterDeploymentDefinition routerDeploymentDefinition) throws InsufficientAddressCapacityException {
|
||||
String publicIp = defaultNic.getIPv4Address();
|
||||
logger.info("Verifying if we will use same MAC address for public NIC of new VR (with source NAT [{}]).", publicIp);
|
||||
|
||||
logger.debug("Searching for peer NIC for public IP [{}] and network [{}].", publicIp, publicNetwork.getUuid());
|
||||
NicVO peerNic = _nicDao.findByIp4AddressAndNetworkId(publicIp, publicNetwork.getId());
|
||||
if (peerNic == null) {
|
||||
logger.info("We will not use the same MAC address for public NIC of new VR as we have not found a peer NIC for public IP [{}] and network [{}].",
|
||||
publicIp, publicNetwork.getUuid());
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Found peer NIC [{}] for public IP [{}] and network [{}].", peerNic.getUuid(), publicIp, publicNetwork.getUuid());
|
||||
boolean keepMacAddressOnPublicNic = routerDeploymentDefinition.getKeepMacAddressOnPublicNic();
|
||||
String macAddressLog = String.format("same MAC address for public NIC of new VR (with source NAT [%s]) as the [keep_mac_address_on_public_nic] property is configured as [%s].", publicIp, keepMacAddressOnPublicNic);
|
||||
if (keepMacAddressOnPublicNic) {
|
||||
logger.info("Using {}", macAddressLog);
|
||||
defaultNic.setMacAddress(peerNic.getMacAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("Not using {}", macAddressLog);
|
||||
boolean fetchNewMacAddress = peerNic.getMacAddress().equals(defaultNic.getMacAddress());
|
||||
if (fetchNewMacAddress) {
|
||||
logger.debug("Fetching new MAC address for public NIC of new VR, since the MAC address of the peer NIC [UUID: {}, MAC address: {}] is equal to the predefined MAC address of the current NIC.", peerNic.getUuid(), peerNic.getMacAddress());
|
||||
routerDeploymentDefinition.findSourceNatIP();
|
||||
configurePublicVrNicBasedOnSourceNatIp(defaultNic, routerDeploymentDefinition.getSourceNatIP());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedHashMap<Network, List<? extends NicProfile>> configureDefaultNics(final RouterDeploymentDefinition routerDeploymentDefinition) throws ConcurrentOperationException, InsufficientAddressCapacityException {
|
||||
|
||||
|
|
|
|||
|
|
@ -1568,7 +1568,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
@ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", create = true)
|
||||
public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwnerId, final String vpcName, final String displayText, final String cidr, String networkDomain,
|
||||
final String ip4Dns1, final String ip4Dns2, final String ip6Dns1, final String ip6Dns2, final Boolean displayVpc, Integer publicMtu,
|
||||
final Integer cidrSize, final Long asNumber, final List<Long> bgpPeerIds, Boolean useVrIpResolver) throws ResourceAllocationException {
|
||||
final Integer cidrSize, final Long asNumber, final List<Long> bgpPeerIds, Boolean useVrIpResolver, boolean keepMacAddressOnPublicNic) throws ResourceAllocationException {
|
||||
final Account caller = CallContext.current().getCallingAccount();
|
||||
final Account owner = _accountMgr.getAccount(vpcOwnerId);
|
||||
|
||||
|
|
@ -1668,6 +1668,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
vpc.setPublicMtu(publicMtu);
|
||||
vpc.setDisplay(Boolean.TRUE.equals(displayVpc));
|
||||
vpc.setUseRouterIpResolver(Boolean.TRUE.equals(useVrIpResolver));
|
||||
vpc.setKeepMacAddressOnPublicNic(keepMacAddressOnPublicNic);
|
||||
|
||||
try (CheckedReservation vpcReservation = new CheckedReservation(owner, ResourceType.vpc, null, null, 1L, reservationDao, _resourceLimitMgr)) {
|
||||
if (vpc.getCidr() == null && cidrSize != null) {
|
||||
|
|
@ -1728,7 +1729,8 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
List<Long> bgpPeerIds = (cmd instanceof CreateVPCCmdByAdmin) ? ((CreateVPCCmdByAdmin)cmd).getBgpPeerIds() : null;
|
||||
Vpc vpc = createVpc(cmd.getZoneId(), cmd.getVpcOffering(), cmd.getEntityOwnerId(), cmd.getVpcName(), cmd.getDisplayText(),
|
||||
cmd.getCidr(), cmd.getNetworkDomain(), cmd.getIp4Dns1(), cmd.getIp4Dns2(), cmd.getIp6Dns1(),
|
||||
cmd.getIp6Dns2(), cmd.isDisplay(), cmd.getPublicMtu(), cmd.getCidrSize(), cmd.getAsNumber(), bgpPeerIds, cmd.getUseVrIpResolver());
|
||||
cmd.getIp6Dns2(), cmd.isDisplay(), cmd.getPublicMtu(), cmd.getCidrSize(), cmd.getAsNumber(), bgpPeerIds,
|
||||
cmd.getUseVrIpResolver(), cmd.getKeepMacAddressOnPublicNic());
|
||||
|
||||
String sourceNatIP = cmd.getSourceNatIP();
|
||||
boolean forNsx = isVpcForProvider(Provider.Nsx, vpc);
|
||||
|
|
@ -1940,12 +1942,14 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
|
||||
@Override
|
||||
public Vpc updateVpc(UpdateVPCCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
return updateVpc(cmd.getId(), cmd.getVpcName(), cmd.getDisplayText(), cmd.getCustomId(), cmd.isDisplayVpc(), cmd.getPublicMtu(), cmd.getSourceNatIP());
|
||||
return updateVpc(cmd.getId(), cmd.getVpcName(), cmd.getDisplayText(), cmd.getCustomId(),
|
||||
cmd.isDisplayVpc(), cmd.getPublicMtu(), cmd.getSourceNatIP(), cmd.getKeepMacAddressOnPublicNic());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ActionEvent(eventType = EventTypes.EVENT_VPC_UPDATE, eventDescription = "updating vpc")
|
||||
public Vpc updateVpc(final long vpcId, final String vpcName, final String displayText, final String customId, final Boolean displayVpc, Integer mtu, String sourceNatIp) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
public Vpc updateVpc(final long vpcId, final String vpcName, final String displayText, final String customId,
|
||||
final Boolean displayVpc, Integer mtu, String sourceNatIp, Boolean keepMacAddressOnPublicNic) throws ResourceUnavailableException, InsufficientCapacityException {
|
||||
final Account caller = CallContext.current().getCallingAccount();
|
||||
|
||||
// Verify input parameters
|
||||
|
|
@ -1977,6 +1981,10 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
|
|||
vpc.setDisplay(displayVpc);
|
||||
}
|
||||
|
||||
if (keepMacAddressOnPublicNic != null) {
|
||||
vpc.setKeepMacAddressOnPublicNic(keepMacAddressOnPublicNic);
|
||||
}
|
||||
|
||||
mtu = validateMtu(vpcToUpdate, mtu);
|
||||
if (mtu != null) {
|
||||
updateMtuOfVpcNetwork(vpcToUpdate, vpc, mtu);
|
||||
|
|
|
|||
|
|
@ -1042,7 +1042,8 @@ public class ResourceLimitManagerImpl extends ManagerBase implements ResourceLim
|
|||
|
||||
ResourceLimitVO limit = _resourceLimitDao.findByOwnerIdAndTypeAndTag(ownerId, ownerType, resourceType, tag);
|
||||
|
||||
ActionEventUtils.onActionEvent(caller.getId(), caller.getAccountId(),
|
||||
Long callingUserId = CallContext.current().getCallingUserId();
|
||||
ActionEventUtils.onActionEvent(callingUserId, caller.getAccountId(),
|
||||
caller.getDomainId(), EventTypes.EVENT_RESOURCE_LIMIT_UPDATE,
|
||||
"Resource limit updated. Resource Type: " + resourceType + ", New Value: " + max,
|
||||
ownerResourceId, ownerResourceType.toString());
|
||||
|
|
|
|||
|
|
@ -1696,11 +1696,7 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen
|
|||
List<Host> suitableHosts = new ArrayList<>();
|
||||
|
||||
for (final HostAllocator allocator : hostAllocators) {
|
||||
if (CollectionUtils.isNotEmpty(compatibleHosts)) {
|
||||
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, compatibleHosts, HostAllocator.RETURN_UPTO_ALL, false);
|
||||
} else {
|
||||
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, HostAllocator.RETURN_UPTO_ALL, false);
|
||||
}
|
||||
suitableHosts = allocator.allocateTo(vmProfile, plan, Host.Type.Routing, excludes, compatibleHosts, HostAllocator.RETURN_UPTO_ALL, false);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(suitableHosts)) {
|
||||
break;
|
||||
|
|
@ -1709,10 +1705,10 @@ public class ManagementServerImpl extends MutualExclusiveIdsManagerBase implemen
|
|||
|
||||
_dpMgr.reorderHostsByPriority(plan.getHostPriorities(), suitableHosts);
|
||||
|
||||
if (suitableHosts.isEmpty()) {
|
||||
if (CollectionUtils.isEmpty(suitableHosts)) {
|
||||
logger.warn("No suitable hosts found.");
|
||||
} else {
|
||||
logger.debug("Hosts having capacity and suitable for migration: {}", suitableHosts);
|
||||
logger.debug("Hosts having capacity and are suitable for migration: {}", suitableHosts);
|
||||
}
|
||||
|
||||
// Only list hosts of the same architecture as the source Host in a multi-arch zone
|
||||
|
|
|
|||
|
|
@ -4359,9 +4359,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
return resourceLimitService.getResourceLimitStorageTags(diskOfferingVO);
|
||||
}
|
||||
|
||||
private List<CheckedReservation> reserveStorageResourcesForVm(Account owner, Long diskOfferingId, Long diskSize, List<VmDiskInfo> dataDiskInfoList, Long rootDiskOfferingId, ServiceOfferingVO offering, Long rootDiskSize) throws ResourceAllocationException {
|
||||
List <CheckedReservation> checkedReservations = new ArrayList<>();
|
||||
|
||||
private void reserveStorageResourcesForVm(List<Reserver> checkedReservations, Account owner, Long diskOfferingId, Long diskSize, List<VmDiskInfo> dataDiskInfoList, Long rootDiskOfferingId, ServiceOfferingVO offering, Long rootDiskSize) throws ResourceAllocationException {
|
||||
List<String> rootResourceLimitStorageTags = getResourceLimitStorageTags(rootDiskOfferingId != null ? rootDiskOfferingId : offering.getDiskOfferingId());
|
||||
CheckedReservation rootVolumeReservation = new CheckedReservation(owner, ResourceType.volume, rootResourceLimitStorageTags, 1L, reservationDao, resourceLimitService);
|
||||
checkedReservations.add(rootVolumeReservation);
|
||||
|
|
@ -4369,12 +4367,12 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
checkedReservations.add(rootPrimaryStorageReservation);
|
||||
|
||||
if (diskOfferingId != null) {
|
||||
List<String> additionalResourceLimitStorageTags = diskOfferingId != null ? getResourceLimitStorageTags(diskOfferingId) : null;
|
||||
List<String> additionalResourceLimitStorageTags = getResourceLimitStorageTags(diskOfferingId);
|
||||
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
|
||||
Long size = verifyAndGetDiskSize(diskOffering, diskSize);
|
||||
CheckedReservation additionalVolumeReservation = diskOfferingId != null ? new CheckedReservation(owner, ResourceType.volume, additionalResourceLimitStorageTags, 1L, reservationDao, resourceLimitService) : null;
|
||||
CheckedReservation additionalVolumeReservation = new CheckedReservation(owner, ResourceType.volume, additionalResourceLimitStorageTags, 1L, reservationDao, resourceLimitService);
|
||||
checkedReservations.add(additionalVolumeReservation);
|
||||
CheckedReservation additionalPrimaryStorageReservation = diskOfferingId != null ? new CheckedReservation(owner, ResourceType.primary_storage, additionalResourceLimitStorageTags, size, reservationDao, resourceLimitService) : null;
|
||||
CheckedReservation additionalPrimaryStorageReservation = new CheckedReservation(owner, ResourceType.primary_storage, additionalResourceLimitStorageTags, size, reservationDao, resourceLimitService);
|
||||
checkedReservations.add(additionalPrimaryStorageReservation);
|
||||
|
||||
}
|
||||
|
|
@ -4390,7 +4388,6 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
checkedReservations.add(additionalPrimaryStorageReservation);
|
||||
}
|
||||
}
|
||||
return checkedReservations;
|
||||
}
|
||||
|
||||
private UserVm getUncheckedUserVmResource(DataCenter zone, String hostName, String displayName, Account owner,
|
||||
|
|
@ -4402,10 +4399,10 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
Map<String, String> userVmOVFPropertiesMap, boolean dynamicScalingEnabled, String vmType, VMTemplateVO template,
|
||||
HypervisorType hypervisorType, long accountId, ServiceOfferingVO offering, boolean isIso,
|
||||
Long rootDiskOfferingId, long volumesSize, Volume volume, Snapshot snapshot) throws ResourceAllocationException {
|
||||
List<CheckedReservation> checkedReservations = new ArrayList<>();
|
||||
List<Reserver> checkedReservations = new ArrayList<>();
|
||||
|
||||
try {
|
||||
checkedReservations = reserveStorageResourcesForVm(owner, diskOfferingId, diskSize, dataDiskInfoList, rootDiskOfferingId, offering, volumesSize);
|
||||
reserveStorageResourcesForVm(checkedReservations, owner, diskOfferingId, diskSize, dataDiskInfoList, rootDiskOfferingId, offering, volumesSize);
|
||||
|
||||
// verify security group ids
|
||||
if (securityGroupIdList != null) {
|
||||
|
|
@ -4701,14 +4698,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
|
|||
logger.error("error during resource reservation and allocation", e);
|
||||
throw new CloudRuntimeException(e);
|
||||
} finally {
|
||||
for (CheckedReservation checkedReservation : checkedReservations) {
|
||||
try {
|
||||
checkedReservation.close();
|
||||
} catch (Exception e) {
|
||||
logger.error("error during resource reservation and allocation", e);
|
||||
throw new CloudRuntimeException(e);
|
||||
}
|
||||
}
|
||||
ReservationHelper.closeAll(checkedReservations);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -394,7 +394,7 @@ public class RouterDeploymentDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
public void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
sourceNatIp = null;
|
||||
DataCenter zone = dest.getDataCenter();
|
||||
Long zoneId = null;
|
||||
|
|
@ -548,4 +548,8 @@ public class RouterDeploymentDefinition {
|
|||
|
||||
return needReset;
|
||||
}
|
||||
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return guestNetwork == null || guestNetwork.getKeepMacAddressOnPublicNic();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
public void findSourceNatIP() throws InsufficientAddressCapacityException, ConcurrentOperationException {
|
||||
sourceNatIp = null;
|
||||
DataCenter zone = dest.getDataCenter();
|
||||
Long zoneId = null;
|
||||
|
|
@ -219,4 +219,9 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition {
|
|||
public boolean isRollingRestart() {
|
||||
return vpc.isRollingRestart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getKeepMacAddressOnPublicNic() {
|
||||
return vpc == null || vpc.getKeepMacAddressOnPublicNic();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
<bean id="firstFitAllocator"
|
||||
class="com.cloud.agent.manager.allocator.impl.FirstFitAllocator" />
|
||||
|
||||
<bean id="randomAllocator"
|
||||
class="com.cloud.agent.manager.allocator.impl.RandomAllocator" />
|
||||
|
||||
<bean id="FirstFitRouting"
|
||||
class="com.cloud.agent.manager.allocator.impl.FirstFitRoutingAllocator">
|
||||
<property name="name" value="FirstFitRouting" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
// 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.agent.manager.allocator.impl;
|
||||
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BaseAllocatorTest {
|
||||
@Mock
|
||||
HostDao hostDaoMock;
|
||||
|
||||
@Mock
|
||||
CapacityManager capacityManagerMock;
|
||||
|
||||
@InjectMocks
|
||||
@Spy
|
||||
BaseAllocator baseAllocator = new MockBaseAllocator();
|
||||
|
||||
private final Host.Type type = Host.Type.Routing;
|
||||
|
||||
private final Long clusterId = 1L;
|
||||
|
||||
private final Long podId = 2L;
|
||||
|
||||
private final Long dcId = 3L;
|
||||
|
||||
private final HostVO host1 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final HostVO host2 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final HostVO host3 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
|
||||
|
||||
private final String hostTag = "hostTag";
|
||||
|
||||
@Test
|
||||
public void retainHostsMatchingServiceOfferingAndTemplateTagsTestHasServiceOfferingTagShouldRetainHostsWithServiceOfferingTag() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> hostsWithMathingTags = new ArrayList<>(Arrays.asList(host1, host3));
|
||||
String hostTagOnTemplate = "hostTagOnTemplate";
|
||||
String hostTagOnOffering = null;
|
||||
|
||||
Mockito.doReturn(hostsWithMathingTags).when(hostDaoMock).listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
baseAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(suitableHosts, type, dcId, podId, clusterId, hostTagOnOffering, hostTagOnTemplate);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host3, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retainHostsMatchingServiceOfferingAndTemplateTagsTestHasServiceOfferingTagAndHasHostTagOnTemplateShouldRetainHostsWithServiceOfferingTagAndTemplateTag() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> hostsWithMathingServiceTags = new ArrayList<>(Arrays.asList(host1, host3));
|
||||
List<HostVO> hostsWithMathingTemplateTags = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
String hostTagOnTemplate = "hostTagOnTemplate";
|
||||
String hostTagOnOffering = "hostTagOnOffering";
|
||||
|
||||
Mockito.doReturn(hostsWithMathingTemplateTags).when(hostDaoMock).listByHostTag(type, clusterId, podId, dcId, hostTagOnTemplate);
|
||||
Mockito.doReturn(hostsWithMathingServiceTags).when(hostDaoMock).listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering);
|
||||
baseAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(suitableHosts, type, dcId, podId, clusterId, hostTagOnOffering, hostTagOnTemplate);
|
||||
|
||||
Assert.assertEquals(1, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retainHostsMatchingServiceOfferingAndTemplateTagsTestHasHostTagOnTemplateShouldRetainHostsWithTemplateTag() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> hostsWithMathingServiceTags = new ArrayList<>(Arrays.asList(host1, host3));
|
||||
String hostTagOnTemplate = null;
|
||||
String hostTagOnOffering = "hostTagOnOffering";
|
||||
|
||||
Mockito.doReturn(hostsWithMathingServiceTags).when(hostDaoMock).listByHostTag(type, clusterId, podId, dcId, hostTagOnOffering);
|
||||
baseAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(suitableHosts, type, dcId, podId, clusterId, hostTagOnOffering, hostTagOnTemplate);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host3, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retainHostsMatchingServiceOfferingAndTemplateTagsTestNoServiceTagAndNoTemplateTagShouldHaveAllSuitableHosts() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
String hostTagOnTemplate = null;
|
||||
String hostTagOnOffering = null;
|
||||
|
||||
baseAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(suitableHosts, type, dcId, podId, clusterId, hostTagOnOffering, hostTagOnTemplate);
|
||||
|
||||
Assert.assertEquals(3, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
Assert.assertEquals(host3, suitableHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addHostsBasedOnTagRulesTestHostsWithTagRuleIsEmptyShouldNotAddToSuitableHosts() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> emptyList = new ArrayList<>();
|
||||
|
||||
Mockito.doReturn(emptyList).when(hostDaoMock).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.anyString());
|
||||
baseAllocator.addHostsBasedOnTagRules(hostTag, suitableHosts);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addHostsBasedOnTagRulesTestHostsWithTagRuleIsNotEmptyShouldAddToSuitableHosts() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsMatchingRuleTag = new ArrayList<>(Arrays.asList(host3));
|
||||
|
||||
Mockito.doReturn(hostsMatchingRuleTag).when(hostDaoMock).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.anyString());
|
||||
baseAllocator.addHostsBasedOnTagRules(hostTag, suitableHosts);
|
||||
|
||||
Assert.assertEquals(3, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
Assert.assertEquals(host3, suitableHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostHasCpuCapabilityAndCapacityTestHostHasCpuCapabilityAndCpuCapacityShouldReturnTrue() {
|
||||
Boolean hasCpuCapability = true;
|
||||
Boolean hasCpuCapacity = true;
|
||||
Pair<Boolean, Boolean> pair = new Pair<>(hasCpuCapability, hasCpuCapacity);
|
||||
|
||||
Mockito.doReturn(pair).when(capacityManagerMock).checkIfHostHasCpuCapabilityAndCapacity(Mockito.any(Host.class), Mockito.any(ServiceOffering.class), Mockito.anyBoolean());
|
||||
boolean result = baseAllocator.hostHasCpuCapabilityAndCapacity(true, serviceOffering, host1);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostHasCpuCapabilityAndCapacityTestHostHasCpuCapabilityButNoCpuCapacityShouldReturnFalse() {
|
||||
Boolean hasCpuCapability = true;
|
||||
Boolean hasCpuCapacity = false;
|
||||
Pair<Boolean, Boolean> pair = new Pair<>(hasCpuCapability, hasCpuCapacity);
|
||||
|
||||
Mockito.doReturn(pair).when(capacityManagerMock).checkIfHostHasCpuCapabilityAndCapacity(Mockito.any(Host.class), Mockito.any(ServiceOffering.class), Mockito.anyBoolean());
|
||||
boolean result = baseAllocator.hostHasCpuCapabilityAndCapacity(true, serviceOffering, host1);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostHasCpuCapabilityAndCapacityTestHostDoesNotHaveCpuCapabilityButHasCpuCapacityShouldReturnFalse() {
|
||||
Boolean hasCpuCapability = false;
|
||||
Boolean hasCpuCapacity = true;
|
||||
Pair<Boolean, Boolean> pair = new Pair<>(hasCpuCapability, hasCpuCapacity);
|
||||
|
||||
Mockito.doReturn(pair).when(capacityManagerMock).checkIfHostHasCpuCapabilityAndCapacity(Mockito.any(Host.class), Mockito.any(ServiceOffering.class), Mockito.anyBoolean());
|
||||
boolean result = baseAllocator.hostHasCpuCapabilityAndCapacity(true, serviceOffering, host1);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostHasCpuCapabilityAndCapacityTestHostDoesNotHaveCpuCapabilityAndCpuCapacityShouldReturnFalse() {
|
||||
Boolean hasCpuCapability = false;
|
||||
Boolean hasCpuCapacity = false;
|
||||
Pair<Boolean, Boolean> pair = new Pair<>(hasCpuCapability, hasCpuCapacity);
|
||||
|
||||
Mockito.doReturn(pair).when(capacityManagerMock).checkIfHostHasCpuCapabilityAndCapacity(Mockito.any(Host.class), Mockito.any(ServiceOffering.class), Mockito.anyBoolean());
|
||||
boolean result = baseAllocator.hostHasCpuCapabilityAndCapacity(true, serviceOffering, host1);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
}
|
||||
|
||||
class MockBaseAllocator extends BaseAllocator {
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Host.Type type, DeploymentPlanner.ExcludeList avoid, int returnUpTo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Host> allocateTo(VirtualMachineProfile vmProfile, DeploymentPlan plan, Host.Type type, DeploymentPlanner.ExcludeList avoid, List<? extends Host> hosts, int returnUpTo, boolean considerReservedCapacity) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,214 +18,596 @@
|
|||
|
||||
package com.cloud.agent.manager.allocator.impl;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.cloud.agent.manager.allocator.HostAllocator;
|
||||
import com.cloud.capacity.CapacityManager;
|
||||
import com.cloud.capacity.CapacityVO;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.service.ServiceOfferingDetailsVO;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.service.dao.ServiceOfferingDetailsDao;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.vm.VMInstanceDetailVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import com.cloud.vm.dao.VMInstanceDetailsDao;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FirstFitAllocatorTest {
|
||||
private static final double TOLERANCE = 0.0001;
|
||||
private FirstFitAllocator allocator;
|
||||
private CapacityManager capacityMgr;
|
||||
private ServiceOfferingDetailsDao offeringDetailsDao;
|
||||
private ResourceManager resourceMgr;
|
||||
private static final double TOLERANCE = 0.0001;
|
||||
|
||||
private DeploymentPlan plan;
|
||||
private ServiceOffering offering;
|
||||
private DeploymentPlanner.ExcludeList avoid;
|
||||
private Account account;
|
||||
@Mock
|
||||
HostDao hostDaoMock;
|
||||
|
||||
private Host host1;
|
||||
private Host host2;
|
||||
private VirtualMachineProfile vmProfile;
|
||||
ConfigurationDao configDao;
|
||||
@Mock
|
||||
ResourceManager resourceManagerMock;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
allocator = new FirstFitAllocator();
|
||||
capacityMgr = mock(CapacityManager.class);
|
||||
offeringDetailsDao = mock(ServiceOfferingDetailsDao.class);
|
||||
resourceMgr = mock(ResourceManager.class);
|
||||
configDao = mock(ConfigurationDao.class);
|
||||
@Mock
|
||||
VMInstanceDetailsDao userVmDetailsDaoMock;
|
||||
|
||||
allocator._capacityMgr = capacityMgr;
|
||||
allocator._serviceOfferingDetailsDao = offeringDetailsDao;
|
||||
allocator._resourceMgr = resourceMgr;
|
||||
allocator._configDao = configDao;
|
||||
@Mock
|
||||
ServiceOfferingDetailsDao serviceOfferingDetailsDao;
|
||||
|
||||
plan = mock(DeploymentPlan.class);
|
||||
offering = mock(ServiceOffering.class);
|
||||
avoid = mock(DeploymentPlanner.ExcludeList.class);
|
||||
account = mock(Account.class);
|
||||
@Mock
|
||||
CapacityManager capacityMgr;
|
||||
|
||||
host1 = mock(Host.class);
|
||||
host2 = mock(Host.class);
|
||||
@Mock
|
||||
ConfigurationDao configDao;
|
||||
|
||||
vmProfile = mock(VirtualMachineProfile.class);
|
||||
when(vmProfile.getId()).thenReturn(1L);
|
||||
@Spy
|
||||
@InjectMocks
|
||||
FirstFitAllocator firstFitAllocatorSpy;
|
||||
|
||||
when(plan.getDataCenterId()).thenReturn(1L);
|
||||
when(offering.getCpu()).thenReturn(2);
|
||||
when(offering.getSpeed()).thenReturn(1000);
|
||||
when(offering.getRamSize()).thenReturn(2048);
|
||||
when(offering.getId()).thenReturn(123L);
|
||||
when(offering.getHostTag()).thenReturn(null);
|
||||
when(offering.getVgpuProfileId()).thenReturn(null);
|
||||
}
|
||||
private final Host.Type type = Host.Type.Routing;
|
||||
|
||||
@Test
|
||||
public void testConfigure() throws Exception {
|
||||
when(configDao.getConfiguration(anyMap())).thenReturn(new HashMap<>());
|
||||
assertTrue(allocator._checkHvm);
|
||||
assertTrue(allocator.configure("test", new HashMap<>()));
|
||||
}
|
||||
private final Long clusterId = 1L;
|
||||
|
||||
@Test
|
||||
public void testAllocateTo_SuccessfulMatch() {
|
||||
List<Host> inputHosts = Arrays.asList(host1, host2);
|
||||
private final Long podId = 2L;
|
||||
|
||||
// All hosts are allowed
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(false);
|
||||
when(avoid.shouldAvoid(host2)).thenReturn(false);
|
||||
private final Long dcId = 3L;
|
||||
|
||||
// No GPU requirement
|
||||
when(offeringDetailsDao.findDetail(eq(123L), anyString())).thenReturn(null);
|
||||
private final List<HostVO> emptyList = new ArrayList<>();
|
||||
|
||||
// CPU capability and capacity is met
|
||||
when(capacityMgr.checkIfHostReachMaxGuestLimit(any())).thenReturn(false);
|
||||
when(capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(eq(host1), eq(offering), eq(true)))
|
||||
.thenReturn(new Pair<>(true, true));
|
||||
when(capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(eq(host2), eq(offering), eq(true)))
|
||||
.thenReturn(new Pair<>(true, false));
|
||||
private final String hostTag = "hostTag";
|
||||
|
||||
private final String templateTag = "templateTag";
|
||||
|
||||
when(resourceMgr.isGPUDeviceAvailable(offering, host1, vmProfile.getId())).thenReturn(true);
|
||||
when(resourceMgr.isGPUDeviceAvailable(offering, host2, vmProfile.getId())).thenReturn(true);
|
||||
private final HostVO host1 = mock(HostVO.class);
|
||||
|
||||
List<Host> result = allocator.allocateTo(vmProfile, plan, offering, null, avoid, inputHosts, 2, true, account);
|
||||
private final HostVO host2 = mock(HostVO.class);
|
||||
|
||||
// Only host1 should be returned
|
||||
assertEquals(1, result.size());
|
||||
assertTrue(result.contains(host1));
|
||||
assertFalse(result.contains(host2));
|
||||
}
|
||||
private final HostVO host3 = mock(HostVO.class);
|
||||
|
||||
@Test
|
||||
public void testAllocateTo_AvoidSetAndGuestLimit() {
|
||||
List<Host> inputHosts = Arrays.asList(host1, host2);
|
||||
private final ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
|
||||
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(true); // Avoided
|
||||
when(avoid.shouldAvoid(host2)).thenReturn(false);
|
||||
private final DeploymentPlanner.ExcludeList excludeList = mock(DeploymentPlanner.ExcludeList.class);
|
||||
|
||||
when(capacityMgr.checkIfHostReachMaxGuestLimit(host2)).thenReturn(true); // Reached limit
|
||||
private final VirtualMachineProfile virtualMachineProfile = mock(VirtualMachineProfile.class);
|
||||
|
||||
List<Host> result = allocator.allocateTo(vmProfile, plan, offering, null, avoid, inputHosts, 2, true, account);
|
||||
private final VMTemplateVO vmTemplateVO = mock(VMTemplateVO.class);
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
private final Account account = mock(Account.class);
|
||||
|
||||
@Test
|
||||
public void testAllocateTo_GPUNotAvailable() {
|
||||
List<Host> inputHosts = Arrays.asList(host1);
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(false);
|
||||
private final DeploymentPlan deploymentPlan = mock(DeploymentPlan.class);
|
||||
|
||||
// GPU required but not available
|
||||
var vgpuDetail = mock(com.cloud.service.ServiceOfferingDetailsVO.class);
|
||||
var pciDetail = mock(com.cloud.service.ServiceOfferingDetailsVO.class);
|
||||
when(offeringDetailsDao.findDetail(eq(123L), eq("vgpuType"))).thenReturn(vgpuDetail);
|
||||
when(offeringDetailsDao.findDetail(eq(123L), eq("pciDevice"))).thenReturn(pciDetail);
|
||||
when(pciDetail.getValue()).thenReturn("NVIDIA");
|
||||
when(vgpuDetail.getValue()).thenReturn("GRID");
|
||||
private final DeploymentPlanner.ExcludeList avoid = mock(DeploymentPlanner.ExcludeList.class);
|
||||
|
||||
when(resourceMgr.isGPUDeviceAvailable(offering, host1, vmProfile.getId())).thenReturn(false);
|
||||
private final ServiceOffering offering = mock(ServiceOffering.class);
|
||||
|
||||
List<Host> result = allocator.allocateTo(vmProfile, plan, offering, null, avoid, inputHosts, 1, true, account);
|
||||
private final boolean considerReservedCapacity = true;
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
@Test
|
||||
public void testConfigure() throws Exception {
|
||||
when(configDao.getConfiguration(Mockito.anyMap())).thenReturn(new HashMap<>());
|
||||
Assert.assertTrue(firstFitAllocatorSpy._checkHvm);
|
||||
Assert.assertTrue(firstFitAllocatorSpy.configure("test", new HashMap<>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostByCombinedCapacityOrder() {
|
||||
// Test scenario 1: Default capacity usage (0.5 weight)
|
||||
List<CapacityVO> mockCapacity = getHostCapacities();
|
||||
Map<Long, Double> hostByCombinedCapacity = FirstFitAllocator.getHostByCombinedCapacities(mockCapacity, 0.5);
|
||||
@Test
|
||||
public void testAllocateTo_SuccessfulMatch() {
|
||||
List<Host> inputHosts = Arrays.asList(host1, host2);
|
||||
|
||||
// Verify host ordering and capacity values
|
||||
Long firstHostId = hostByCombinedCapacity.keySet().iterator().next();
|
||||
Assert.assertEquals("Host with ID 1 should be first in ordering", Long.valueOf(1L), firstHostId);
|
||||
Assert.assertEquals("Host 1 combined capacity should match expected value",
|
||||
0.9609375, hostByCombinedCapacity.get(1L), TOLERANCE);
|
||||
Assert.assertEquals("Host 2 combined capacity should match expected value",
|
||||
0.9296875, hostByCombinedCapacity.get(2L), TOLERANCE);
|
||||
// All hosts are allowed
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(false);
|
||||
when(avoid.shouldAvoid(host2)).thenReturn(false);
|
||||
|
||||
// Test scenario 2: Modified capacity usage (0.7 weight)
|
||||
when(mockCapacity.get(0).getUsedCapacity()).thenReturn(1500L);
|
||||
hostByCombinedCapacity = FirstFitAllocator.getHostByCombinedCapacities(mockCapacity, 0.7);
|
||||
// CPU capability and capacity is met
|
||||
when(capacityMgr.checkIfHostReachMaxGuestLimit(Mockito.any(Host.class))).thenReturn(false);
|
||||
when(capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host1, offering, true))
|
||||
.thenReturn(new Pair<>(true, true));
|
||||
when(capacityMgr.checkIfHostHasCpuCapabilityAndCapacity(host2, offering,true))
|
||||
.thenReturn(new Pair<>(true, false));
|
||||
|
||||
// Verify new ordering after capacity change
|
||||
firstHostId = hostByCombinedCapacity.keySet().iterator().next();
|
||||
Assert.assertEquals("Host with ID 2 should be first after capacity change", Long.valueOf(2L), firstHostId);
|
||||
Assert.assertEquals("Host 2 combined capacity should match expected value after change",
|
||||
0.9515625, hostByCombinedCapacity.get(2L), TOLERANCE);
|
||||
Assert.assertEquals("Host 1 combined capacity should match expected value after change",
|
||||
0.9484375, hostByCombinedCapacity.get(1L), TOLERANCE);
|
||||
}
|
||||
when(resourceManagerMock.isGPUDeviceAvailable(offering, host1, virtualMachineProfile.getId())).thenReturn(true);
|
||||
when(resourceManagerMock.isGPUDeviceAvailable(offering, host2, virtualMachineProfile.getId())).thenReturn(true);
|
||||
|
||||
List<CapacityVO> getHostCapacities() {
|
||||
CapacityVO cpuCapacity1 = mock(CapacityVO.class);
|
||||
when(cpuCapacity1.getHostOrPoolId()).thenReturn(1L);
|
||||
when(cpuCapacity1.getTotalCapacity()).thenReturn(32000L);
|
||||
when(cpuCapacity1.getReservedCapacity()).thenReturn(0L);
|
||||
when(cpuCapacity1.getUsedCapacity()).thenReturn(500L);
|
||||
when(cpuCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_CPU);
|
||||
List<Host> result = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, offering, null, avoid, inputHosts, 2, true, account);
|
||||
|
||||
CapacityVO cpuCapacity2 = mock(CapacityVO.class);
|
||||
when(cpuCapacity2.getHostOrPoolId()).thenReturn(2L);
|
||||
when(cpuCapacity2.getTotalCapacity()).thenReturn(32000L);
|
||||
when(cpuCapacity2.getReservedCapacity()).thenReturn(0L);
|
||||
when(cpuCapacity2.getUsedCapacity()).thenReturn(500L);
|
||||
when(cpuCapacity2.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_CPU);
|
||||
// Only host1 should be returned
|
||||
Assert.assertEquals(1, result.size());
|
||||
Assert.assertTrue(result.contains(host1));
|
||||
Assert.assertFalse(result.contains(host2));
|
||||
}
|
||||
|
||||
CapacityVO memCapacity1 = mock(CapacityVO.class);
|
||||
when(memCapacity1.getHostOrPoolId()).thenReturn(1L);
|
||||
when(memCapacity1.getTotalCapacity()).thenReturn(8589934592L);
|
||||
when(memCapacity1.getReservedCapacity()).thenReturn(0L);
|
||||
when(memCapacity1.getUsedCapacity()).thenReturn(536870912L);
|
||||
when(memCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
@Test
|
||||
public void testAllocateTo_AvoidSetAndGuestLimit() {
|
||||
List<Host> inputHosts = Arrays.asList(host1, host2);
|
||||
|
||||
CapacityVO memCapacity2 = mock(CapacityVO.class);
|
||||
when(memCapacity2.getHostOrPoolId()).thenReturn(2L);
|
||||
when(memCapacity2.getTotalCapacity()).thenReturn(8589934592L);
|
||||
when(memCapacity2.getReservedCapacity()).thenReturn(0L);
|
||||
when(memCapacity2.getUsedCapacity()).thenReturn(1073741824L);
|
||||
when(memCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
return Arrays.asList(cpuCapacity1, memCapacity1, cpuCapacity2, memCapacity2);
|
||||
}
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(true); // Avoided
|
||||
when(avoid.shouldAvoid(host2)).thenReturn(false);
|
||||
|
||||
when(capacityMgr.checkIfHostReachMaxGuestLimit(host2)).thenReturn(true); // Reached limit
|
||||
|
||||
List<Host> result = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, offering, null, avoid, inputHosts, 2, true, account);
|
||||
|
||||
Assert.assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllocateTo_GPUNotAvailable() {
|
||||
List<Host> inputHosts = Arrays.asList(host1);
|
||||
when(avoid.shouldAvoid(host1)).thenReturn(false);
|
||||
when(resourceManagerMock.isGPUDeviceAvailable(offering, host1, virtualMachineProfile.getId())).thenReturn(false);
|
||||
|
||||
List<Host> result = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, offering, null, avoid, inputHosts, 1, true, account);
|
||||
|
||||
Assert.assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allocateToTestHostTypeStorageShouldReturnNull() {
|
||||
List<Host> suitableHosts = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, Host.Type.Storage, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Assert.assertNull(suitableHosts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allocateToTestSuitableHostsEmptyShouldReturnNull() {
|
||||
Mockito.doReturn(serviceOffering).when(virtualMachineProfile).getServiceOffering();
|
||||
Mockito.doReturn(vmTemplateVO).when(virtualMachineProfile).getTemplate();
|
||||
Mockito.doReturn(account).when(virtualMachineProfile).getOwner();
|
||||
Mockito.doReturn(hostTag).when(serviceOffering).getHostTag();
|
||||
Mockito.doReturn(templateTag).when(vmTemplateVO).getTemplateTag();
|
||||
Mockito.doReturn(emptyList).when(firstFitAllocatorSpy).retrieveHosts(Mockito.any(VirtualMachineProfile.class), Mockito.any(Host.Type.class), Mockito.nullable(List.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString());
|
||||
List<Host> suitableHosts = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, type, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Assert.assertNull(suitableHosts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allocateToTestSuitableHostsNotEmptyShouldCallAllocateToMethod() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
|
||||
Mockito.doReturn(serviceOffering).when(virtualMachineProfile).getServiceOffering();
|
||||
Mockito.doReturn(vmTemplateVO).when(virtualMachineProfile).getTemplate();
|
||||
Mockito.doReturn(account).when(virtualMachineProfile).getOwner();
|
||||
Mockito.doReturn(hostTag).when(serviceOffering).getHostTag();
|
||||
Mockito.doReturn(templateTag).when(vmTemplateVO).getTemplateTag();
|
||||
Mockito.doReturn(hosts).when(firstFitAllocatorSpy).retrieveHosts(Mockito.any(VirtualMachineProfile.class), Mockito.any(Host.Type.class), Mockito.nullable(List.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString());
|
||||
Mockito.doReturn(hosts).when(firstFitAllocatorSpy).allocateTo(Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class), Mockito.any(ServiceOffering.class), Mockito.any(VMTemplateVO.class), Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyList(), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.any(Account.class));
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsToAvoidSet(Mockito.any(Host.Type.class), Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
List<Host> suitableHosts = firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, type, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Mockito.verify(firstFitAllocatorSpy, Mockito.times(1)).allocateTo(virtualMachineProfile, deploymentPlan, serviceOffering, vmTemplateVO, excludeList, hosts, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity, account);
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allocateToTestProvidedHostsNotNullShouldCallAddHostsToAvoidSetMethod() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
|
||||
Mockito.doReturn(serviceOffering).when(virtualMachineProfile).getServiceOffering();
|
||||
Mockito.doReturn(vmTemplateVO).when(virtualMachineProfile).getTemplate();
|
||||
Mockito.doReturn(account).when(virtualMachineProfile).getOwner();
|
||||
Mockito.doReturn(hostTag).when(serviceOffering).getHostTag();
|
||||
Mockito.doReturn(templateTag).when(vmTemplateVO).getTemplateTag();
|
||||
Mockito.doReturn(hosts).when(firstFitAllocatorSpy).retrieveHosts(Mockito.any(VirtualMachineProfile.class), Mockito.any(Host.Type.class), Mockito.nullable(List.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString());
|
||||
Mockito.doReturn(hosts).when(firstFitAllocatorSpy).allocateTo(Mockito.any(VirtualMachineProfile.class), Mockito.any(DeploymentPlan.class), Mockito.any(ServiceOffering.class), Mockito.any(VMTemplateVO.class), Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyList(), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.any(Account.class));
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsToAvoidSet(Mockito.any(Host.Type.class), Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
firstFitAllocatorSpy.allocateTo(virtualMachineProfile, deploymentPlan, type, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Mockito.verify(firstFitAllocatorSpy, Mockito.times(1)).addHostsToAvoidSet(Mockito.any(Host.Type.class), Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestHostsToFilterIsNullAndHaTagNotNullShouldReturnOnlyHostsWithHaTag() {
|
||||
List<HostVO> allUpAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> hostsWithHaTag = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
String hostVmTag = "haVmTag";
|
||||
|
||||
Mockito.doReturn(hostVmTag).when(virtualMachineProfile).getParameter(Mockito.any(VirtualMachineProfile.Param.class));
|
||||
Mockito.doReturn(allUpAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsWithHaTag).when(hostDaoMock).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).filterHostsWithUefiEnabled(Mockito.any(Host.Type.class), Mockito.any(VirtualMachineProfile.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsBasedOnTagRules(Mockito.anyString(), Mockito.anyList());
|
||||
List<HostVO> resultHosts = firstFitAllocatorSpy.retrieveHosts(virtualMachineProfile, type, emptyList, clusterId, podId, dcId, hostTag, templateTag);
|
||||
|
||||
Assert.assertEquals(2, resultHosts.size());
|
||||
Assert.assertEquals(host1, resultHosts.get(0));
|
||||
Assert.assertEquals(host2, resultHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestHostsToFilterIsNotNullAndHaTagNotNullShouldReturnOnlyHostsToFilterWithHaTag() {
|
||||
List<HostVO> hostsToFilter = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> hostsWithHaTag = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
String hostVmTag = "haVmTag";
|
||||
|
||||
Mockito.doReturn(hostVmTag).when(virtualMachineProfile).getParameter(Mockito.any(VirtualMachineProfile.Param.class));
|
||||
Mockito.doReturn(hostsWithHaTag).when(hostDaoMock).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).filterHostsWithUefiEnabled(Mockito.any(Host.Type.class), Mockito.any(VirtualMachineProfile.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsBasedOnTagRules(Mockito.anyString(), Mockito.anyList());
|
||||
List<HostVO> resultHosts = firstFitAllocatorSpy.retrieveHosts(virtualMachineProfile, type, hostsToFilter, clusterId, podId, dcId, hostTag, templateTag);
|
||||
|
||||
Assert.assertEquals(2, resultHosts.size());
|
||||
Assert.assertEquals(host1, resultHosts.get(0));
|
||||
Assert.assertEquals(host2, resultHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestHostsToFilterIsNullAndNoHaTagAndNoHostTagShouldReturnOnlyAllUpAndEnabledNonHaHosts() {
|
||||
List<HostVO> allUpAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> upAndEnabledHostsWithNoHa = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
|
||||
Mockito.doReturn(allUpAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(upAndEnabledHostsWithNoHa).when(resourceManagerMock).listAllUpAndEnabledNonHAHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).filterHostsWithUefiEnabled(Mockito.any(Host.Type.class), Mockito.any(VirtualMachineProfile.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsBasedOnTagRules(Mockito.nullable(String.class), Mockito.anyList());
|
||||
List<HostVO> resultHosts = firstFitAllocatorSpy.retrieveHosts(virtualMachineProfile, type, emptyList, clusterId, podId, dcId, null, null);
|
||||
|
||||
Assert.assertEquals(2, resultHosts.size());
|
||||
Assert.assertEquals(host1, resultHosts.get(0));
|
||||
Assert.assertEquals(host2, resultHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestHostsToFilterIsNullAndNoHaTagWithHostTagShouldCallRetainHostsMatchingServiceOfferingAndTemplateTags() {
|
||||
List<HostVO> allUpAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(allUpAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).retainHostsMatchingServiceOfferingAndTemplateTags(Mockito.anyList(), Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).filterHostsWithUefiEnabled(Mockito.any(Host.Type.class), Mockito.any(VirtualMachineProfile.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyList());
|
||||
Mockito.doNothing().when(firstFitAllocatorSpy).addHostsBasedOnTagRules(Mockito.anyString(), Mockito.anyList());
|
||||
firstFitAllocatorSpy.retrieveHosts(virtualMachineProfile, type, emptyList, clusterId, podId, dcId, hostTag, templateTag);
|
||||
|
||||
Mockito.verify(firstFitAllocatorSpy, Mockito.times(1)).retainHostsMatchingServiceOfferingAndTemplateTags(Mockito.anyList(), Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString(), Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addHostsToAvoidSetTestAllHostsWereConsideredForAllocationShouldNotAddAnyHostToTheAvoidSet() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(suitableHosts).when(hostDaoMock).listAllUpAndEnabledNonHAHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.nullable(String.class));
|
||||
firstFitAllocatorSpy.addHostsToAvoidSet(type, excludeList, clusterId, podId, dcId, suitableHosts);
|
||||
|
||||
Assert.assertTrue(excludeList.getHostsToAvoid().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addHostsToAvoidSetTestNotAllHostsWereConsideredForAllocationShouldAddHostToTheAvoidSet() {
|
||||
List<HostVO> allUpAndEnabledNonHAHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> consideredHosts = new ArrayList<>(Arrays.asList(host2, host3));
|
||||
|
||||
Mockito.doReturn(1L).when(host1).getId();
|
||||
Mockito.doCallRealMethod().when(excludeList).addHost(Mockito.anyLong());
|
||||
Mockito.doCallRealMethod().when(excludeList).getHostsToAvoid();
|
||||
Mockito.doReturn(allUpAndEnabledNonHAHosts).when(hostDaoMock).listAllUpAndEnabledNonHAHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.nullable(String.class));
|
||||
firstFitAllocatorSpy.addHostsToAvoidSet(type, excludeList, clusterId, podId, dcId, consideredHosts);
|
||||
|
||||
Assert.assertEquals(1, excludeList.getHostsToAvoid().size());
|
||||
Assert.assertTrue(excludeList.getHostsToAvoid().contains(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostsWithUefiEnabledTestNoDetailWithUefiShouldNotFilterAnyHost() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
VMInstanceDetailVO userVmDetailVO = null;
|
||||
|
||||
Mockito.doReturn(userVmDetailVO).when(userVmDetailsDaoMock).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
firstFitAllocatorSpy.filterHostsWithUefiEnabled(type, virtualMachineProfile, clusterId, podId, dcId, suitableHosts);
|
||||
|
||||
Assert.assertEquals(3, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
Assert.assertEquals(host3, suitableHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostsWithUefiEnabledTestDetailWithUefiWithInvalidModeShouldNotFilterAnyHost() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
VMInstanceDetailVO userVmDetailVO = mock(VMInstanceDetailVO.class);
|
||||
String bootMode = "Invalid mode";
|
||||
|
||||
Mockito.doReturn(bootMode).when(userVmDetailVO).getValue();
|
||||
Mockito.doReturn(userVmDetailVO).when(userVmDetailsDaoMock).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
firstFitAllocatorSpy.filterHostsWithUefiEnabled(type, virtualMachineProfile, clusterId, podId, dcId, suitableHosts);
|
||||
|
||||
Assert.assertEquals(3, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
Assert.assertEquals(host3, suitableHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostsWithUefiEnabledTestDetailWithUefiWithLegacyModeShouldFilterHost() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> uefiHosts = new ArrayList<>(Arrays.asList(host2, host3));
|
||||
VMInstanceDetailVO userVmDetailVO = mock(VMInstanceDetailVO.class);
|
||||
String bootMode = ApiConstants.BootMode.LEGACY.toString();
|
||||
|
||||
Mockito.doReturn(bootMode).when(userVmDetailVO).getValue();
|
||||
Mockito.doReturn(userVmDetailVO).when(userVmDetailsDaoMock).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(uefiHosts).when(hostDaoMock).listByHostCapability(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
firstFitAllocatorSpy.filterHostsWithUefiEnabled(type, virtualMachineProfile, clusterId, podId, dcId, suitableHosts);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host2, suitableHosts.get(0));
|
||||
Assert.assertEquals(host3, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostsWithUefiEnabledTestDetailWithUefiWithSecureModeShouldFilterHost() {
|
||||
List<HostVO> suitableHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<HostVO> uefiHosts = new ArrayList<>(Arrays.asList(host2, host3));
|
||||
VMInstanceDetailVO userVmDetailVO = mock(VMInstanceDetailVO.class);
|
||||
String bootMode = ApiConstants.BootMode.SECURE.toString();
|
||||
|
||||
Mockito.doReturn(bootMode).when(userVmDetailVO).getValue();
|
||||
Mockito.doReturn(userVmDetailVO).when(userVmDetailsDaoMock).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(uefiHosts).when(hostDaoMock).listByHostCapability(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
firstFitAllocatorSpy.filterHostsWithUefiEnabled(type, virtualMachineProfile, clusterId, podId, dcId, suitableHosts);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host2, suitableHosts.get(0));
|
||||
Assert.assertEquals(host3, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void offeringRequestedVGpuAndHostDoesNotHaveItTestVGpuRequestedButHostDoesNotHaveItShouldReturnTrue() {
|
||||
Mockito.doReturn(1L).when(host1).getId();
|
||||
Mockito.doCallRealMethod().when(excludeList).addHost(Mockito.anyLong());
|
||||
Mockito.doCallRealMethod().when(excludeList).getHostsToAvoid();
|
||||
Mockito.doReturn(false).when(resourceManagerMock).isGPUDeviceAvailable(Mockito.any(ServiceOffering.class), Mockito.any(Host.class), Mockito.any(Long.class));
|
||||
boolean result = firstFitAllocatorSpy.offeringRequestedVGpuAndHostDoesNotHaveIt(serviceOffering, virtualMachineProfile, excludeList, host1);
|
||||
|
||||
Assert.assertTrue(result);
|
||||
Assert.assertEquals(1, excludeList.getHostsToAvoid().size());
|
||||
Assert.assertTrue(excludeList.getHostsToAvoid().contains(1L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void offeringRequestedVGpuAndHostDoesNotHaveItTestVGpuRequestedAndHostDoesHaveItShouldReturnFalse() {
|
||||
Mockito.doReturn(true).when(resourceManagerMock).isGPUDeviceAvailable(Mockito.any(ServiceOffering.class), Mockito.any(Host.class), Mockito.any(Long.class));
|
||||
boolean result = firstFitAllocatorSpy.offeringRequestedVGpuAndHostDoesNotHaveIt(serviceOffering, virtualMachineProfile, excludeList, host1);
|
||||
|
||||
Assert.assertFalse(result);
|
||||
Mockito.verify(excludeList, Mockito.never()).addHost(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostWithNoHvmIfTemplateRequestedTestTemplateDoesNotRequireHvm() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(false).when(vmTemplateVO).isRequiresHvm();
|
||||
List<Host> suitableHosts = firstFitAllocatorSpy.filterHostWithNoHvmIfTemplateRequested(vmTemplateVO, hosts);
|
||||
|
||||
Assert.assertEquals(3, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host2, suitableHosts.get(1));
|
||||
Assert.assertEquals(host3, suitableHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterHostWithNoHvmIfTemplateRequestedTestTemplateRequiresHvmShouldReturnOnlyHvmHosts() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(true).when(vmTemplateVO).isRequiresHvm();
|
||||
Mockito.doReturn(true).when(firstFitAllocatorSpy).hostSupportsHVM(host1);
|
||||
Mockito.doReturn(false).when(firstFitAllocatorSpy).hostSupportsHVM(host2);
|
||||
Mockito.doReturn(true).when(firstFitAllocatorSpy).hostSupportsHVM(host3);
|
||||
List<Host> suitableHosts = firstFitAllocatorSpy.filterHostWithNoHvmIfTemplateRequested(vmTemplateVO, hosts);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
Assert.assertEquals(host1, suitableHosts.get(0));
|
||||
Assert.assertEquals(host3, suitableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByGpuEnabledTestServiceOfferingRequestedVGpuViaDetailShouldDoNothing() {
|
||||
List<Host> hosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
ServiceOfferingDetailsVO requestedVGpuType = mock(ServiceOfferingDetailsVO.class);
|
||||
|
||||
Mockito.doReturn(requestedVGpuType).when(serviceOfferingDetailsDao).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
firstFitAllocatorSpy.prioritizeHostsByGpuEnabled(serviceOffering, hosts);
|
||||
|
||||
Assert.assertEquals(3, hosts.size());
|
||||
Assert.assertEquals(host1, hosts.get(0));
|
||||
Assert.assertEquals(host2, hosts.get(1));
|
||||
Assert.assertEquals(host3, hosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByGpuEnabledTestServiceOfferingRequestedVGpuViaProfileIdShouldDoNothing() {
|
||||
List<Host> hosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(1L).when(serviceOffering).getVgpuProfileId();
|
||||
firstFitAllocatorSpy.prioritizeHostsByGpuEnabled(serviceOffering, hosts);
|
||||
|
||||
Assert.assertEquals(3, hosts.size());
|
||||
Assert.assertEquals(host1, hosts.get(0));
|
||||
Assert.assertEquals(host2, hosts.get(1));
|
||||
Assert.assertEquals(host3, hosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByGpuEnabledTestServiceOfferingDidNotRequestVGpuShouldReorderList() {
|
||||
List<Host> allHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(null).when(serviceOfferingDetailsDao).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(null).when(serviceOffering).getVgpuProfileId();
|
||||
Mockito.doReturn(1L).when(host1).getId();
|
||||
Mockito.doReturn(2L).when(host2).getId();
|
||||
Mockito.doReturn(3L).when(host3).getId();
|
||||
Mockito.doReturn(true).when(resourceManagerMock).isHostGpuEnabled(1L);
|
||||
Mockito.doReturn(false).when(resourceManagerMock).isHostGpuEnabled(2L);
|
||||
Mockito.doReturn(false).when(resourceManagerMock).isHostGpuEnabled(3L);
|
||||
firstFitAllocatorSpy.prioritizeHostsByGpuEnabled(serviceOffering, allHosts);
|
||||
|
||||
Assert.assertEquals(3, allHosts.size());
|
||||
Assert.assertEquals(host2, allHosts.get(0));
|
||||
Assert.assertEquals(host3, allHosts.get(1));
|
||||
Assert.assertEquals(host1, allHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByGpuEnabledTestServiceOfferingDidNotRequestVGpuShouldNotReorderListIfThereIsNoHostWithVGpu() {
|
||||
List<Host> allHosts = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
|
||||
Mockito.doReturn(null).when(serviceOfferingDetailsDao).findDetail(Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(null).when(serviceOffering).getVgpuProfileId();
|
||||
Mockito.doReturn(1L).when(host1).getId();
|
||||
Mockito.doReturn(2L).when(host2).getId();
|
||||
Mockito.doReturn(3L).when(host3).getId();
|
||||
Mockito.doReturn(false).when(resourceManagerMock).isHostGpuEnabled(Mockito.anyLong());
|
||||
firstFitAllocatorSpy.prioritizeHostsByGpuEnabled(serviceOffering, allHosts);
|
||||
|
||||
Assert.assertEquals(3, allHosts.size());
|
||||
Assert.assertEquals(host1, allHosts.get(0));
|
||||
Assert.assertEquals(host2, allHosts.get(1));
|
||||
Assert.assertEquals(host3, allHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByHvmCapabilityTestTemplateDidNotRequestedHvmShouldPutHostThatDoesNotSupportHvmInStartOfThePriorityList() {
|
||||
List<Host> hostsToCheck = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<Host> prioritizedHosts = new ArrayList<>();
|
||||
|
||||
Mockito.doReturn(false).when(vmTemplateVO).isRequiresHvm();
|
||||
Mockito.doReturn(true).when(firstFitAllocatorSpy).hostSupportsHVM(host1);
|
||||
Mockito.doReturn(false).when(firstFitAllocatorSpy).hostSupportsHVM(host2);
|
||||
Mockito.doReturn(true).when(firstFitAllocatorSpy).hostSupportsHVM(host3);
|
||||
firstFitAllocatorSpy.prioritizeHostsByHvmCapability(vmTemplateVO, hostsToCheck, prioritizedHosts);
|
||||
|
||||
Assert.assertEquals(3, prioritizedHosts.size());
|
||||
Assert.assertEquals(host2, prioritizedHosts.get(0));
|
||||
Assert.assertEquals(host1, prioritizedHosts.get(1));
|
||||
Assert.assertEquals(host3, prioritizedHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsByHvmCapabilityTestTemplateRequiresHvmShouldNotReorderList() {
|
||||
List<Host> hostsToCheck = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<Host> prioritizedHosts = new ArrayList<>();
|
||||
|
||||
Mockito.doReturn(true).when(vmTemplateVO).isRequiresHvm();
|
||||
firstFitAllocatorSpy.prioritizeHostsByHvmCapability(vmTemplateVO, hostsToCheck, prioritizedHosts);
|
||||
|
||||
Assert.assertEquals(3, prioritizedHosts.size());
|
||||
Assert.assertEquals(host1, prioritizedHosts.get(0));
|
||||
Assert.assertEquals(host2, prioritizedHosts.get(1));
|
||||
Assert.assertEquals(host3, prioritizedHosts.get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prioritizeHostsWithMatchingGuestOsTestShouldPutMatchingHostInHighPriorityAndHostsThatDoesNotMatchInLowPriorityList() {
|
||||
List<Host> hostsToCheck = new ArrayList<>(Arrays.asList(host1, host2, host3));
|
||||
List<Host> highPriorityHosts = new ArrayList<>();
|
||||
List<Host> lowPriorityHosts = new ArrayList<>();
|
||||
String guestOsCategory1 = "guestOsCategory1";
|
||||
String guestOsCategory2 = "guestOsCategory2";
|
||||
|
||||
Mockito.doReturn(guestOsCategory1).when(firstFitAllocatorSpy).getTemplateGuestOSCategory(vmTemplateVO);
|
||||
Mockito.doReturn(guestOsCategory1).when(firstFitAllocatorSpy).getHostGuestOSCategory(host1);
|
||||
Mockito.doReturn(guestOsCategory2).when(firstFitAllocatorSpy).getHostGuestOSCategory(host2);
|
||||
Mockito.doReturn(null).when(firstFitAllocatorSpy).getHostGuestOSCategory(host3);
|
||||
firstFitAllocatorSpy.prioritizeHostsWithMatchingGuestOs(vmTemplateVO,hostsToCheck, highPriorityHosts, lowPriorityHosts);
|
||||
|
||||
Assert.assertEquals(1, highPriorityHosts.size());
|
||||
Assert.assertEquals(host1, highPriorityHosts.get(0));
|
||||
Assert.assertEquals(1, lowPriorityHosts.size());
|
||||
Assert.assertEquals(host2, lowPriorityHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHostByCombinedCapacityOrder() {
|
||||
// Test scenario 1: Default capacity usage (0.5 weight)
|
||||
List<CapacityVO> mockCapacity = getHostCapacities();
|
||||
Map<Long, Double> hostByCombinedCapacity = FirstFitAllocator.getHostByCombinedCapacities(mockCapacity, 0.5);
|
||||
|
||||
// Verify host ordering and capacity values
|
||||
Long firstHostId = hostByCombinedCapacity.keySet().iterator().next();
|
||||
Assert.assertEquals("Host with ID 1 should be first in ordering", Long.valueOf(1L), firstHostId);
|
||||
Assert.assertEquals("Host 1 combined capacity should match expected value",
|
||||
0.9609375, hostByCombinedCapacity.get(1L), TOLERANCE);
|
||||
Assert.assertEquals("Host 2 combined capacity should match expected value",
|
||||
0.9296875, hostByCombinedCapacity.get(2L), TOLERANCE);
|
||||
|
||||
// Test scenario 2: Modified capacity usage (0.7 weight)
|
||||
when(mockCapacity.get(0).getUsedCapacity()).thenReturn(1500L);
|
||||
hostByCombinedCapacity = FirstFitAllocator.getHostByCombinedCapacities(mockCapacity, 0.7);
|
||||
|
||||
// Verify new ordering after capacity change
|
||||
firstHostId = hostByCombinedCapacity.keySet().iterator().next();
|
||||
Assert.assertEquals("Host with ID 2 should be first after capacity change", Long.valueOf(2L), firstHostId);
|
||||
Assert.assertEquals("Host 2 combined capacity should match expected value after change",
|
||||
0.9515625, hostByCombinedCapacity.get(2L), TOLERANCE);
|
||||
Assert.assertEquals("Host 1 combined capacity should match expected value after change",
|
||||
0.9484375, hostByCombinedCapacity.get(1L), TOLERANCE);
|
||||
}
|
||||
|
||||
List<CapacityVO> getHostCapacities() {
|
||||
CapacityVO cpuCapacity1 = mock(CapacityVO.class);
|
||||
when(cpuCapacity1.getHostOrPoolId()).thenReturn(1L);
|
||||
when(cpuCapacity1.getTotalCapacity()).thenReturn(32000L);
|
||||
when(cpuCapacity1.getReservedCapacity()).thenReturn(0L);
|
||||
when(cpuCapacity1.getUsedCapacity()).thenReturn(500L);
|
||||
when(cpuCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_CPU);
|
||||
|
||||
CapacityVO cpuCapacity2 = mock(CapacityVO.class);
|
||||
when(cpuCapacity2.getHostOrPoolId()).thenReturn(2L);
|
||||
when(cpuCapacity2.getTotalCapacity()).thenReturn(32000L);
|
||||
when(cpuCapacity2.getReservedCapacity()).thenReturn(0L);
|
||||
when(cpuCapacity2.getUsedCapacity()).thenReturn(500L);
|
||||
when(cpuCapacity2.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_CPU);
|
||||
|
||||
CapacityVO memCapacity1 = mock(CapacityVO.class);
|
||||
when(memCapacity1.getHostOrPoolId()).thenReturn(1L);
|
||||
when(memCapacity1.getTotalCapacity()).thenReturn(8589934592L);
|
||||
when(memCapacity1.getReservedCapacity()).thenReturn(0L);
|
||||
when(memCapacity1.getUsedCapacity()).thenReturn(536870912L);
|
||||
when(memCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
|
||||
CapacityVO memCapacity2 = mock(CapacityVO.class);
|
||||
when(memCapacity2.getHostOrPoolId()).thenReturn(2L);
|
||||
when(memCapacity2.getTotalCapacity()).thenReturn(8589934592L);
|
||||
when(memCapacity2.getReservedCapacity()).thenReturn(0L);
|
||||
when(memCapacity2.getUsedCapacity()).thenReturn(1073741824L);
|
||||
when(memCapacity1.getCapacityType()).thenReturn(CapacityVO.CAPACITY_TYPE_MEMORY);
|
||||
return Arrays.asList(cpuCapacity1, memCapacity1, cpuCapacity2, memCapacity2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,332 @@
|
|||
// 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.agent.manager.allocator.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.cloud.agent.manager.allocator.HostAllocator;
|
||||
import com.cloud.deploy.DeploymentPlan;
|
||||
import com.cloud.deploy.DeploymentPlanner;
|
||||
import com.cloud.offering.ServiceOffering;
|
||||
import com.cloud.resource.ResourceManager;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class RandomAllocatorTest {
|
||||
|
||||
@Mock
|
||||
HostDao hostDao;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
RandomAllocator randomAllocator;
|
||||
|
||||
@Mock
|
||||
ResourceManager resourceManagerMock;
|
||||
|
||||
private final Host.Type type = Host.Type.Routing;
|
||||
|
||||
private final Long clusterId = 1L;
|
||||
|
||||
private final Long podId = 2L;
|
||||
|
||||
private final Long zoneId = 3L;
|
||||
|
||||
private final List<HostVO> emptyList = new ArrayList<>();
|
||||
|
||||
private final String hostTag = "hostTag";
|
||||
|
||||
private final HostVO host1 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final HostVO host2 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final HostVO host3 = Mockito.mock(HostVO.class);
|
||||
|
||||
private final VMTemplateVO vmTemplateVO = Mockito.mock(VMTemplateVO.class);
|
||||
|
||||
private final ServiceOfferingVO serviceOffering = Mockito.mock(ServiceOfferingVO.class);
|
||||
|
||||
private final DeploymentPlanner.ExcludeList excludeList = Mockito.mock(DeploymentPlanner.ExcludeList.class);
|
||||
|
||||
private final VirtualMachineProfile virtualMachineProfile = Mockito.mock(VirtualMachineProfile.class);
|
||||
|
||||
private final DeploymentPlan deploymentPlan = Mockito.mock(DeploymentPlan.class);
|
||||
|
||||
private final boolean considerReservedCapacity = true;
|
||||
|
||||
|
||||
@Test
|
||||
public void testListHostsByTags() {
|
||||
Host.Type type = Host.Type.Routing;
|
||||
Long id = 1L;
|
||||
String templateTag = "tag1";
|
||||
String offeringTag = "tag2";
|
||||
HostVO host1 = Mockito.mock(HostVO.class);
|
||||
HostVO host2 = Mockito.mock(HostVO.class);
|
||||
Mockito.when(hostDao.listByHostTag(type, clusterId, podId, zoneId, offeringTag)).thenReturn(List.of(host1, host2));
|
||||
|
||||
// No template tagged host
|
||||
ArrayList<HostVO> noTemplateTaggedHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
Mockito.when(hostDao.listByHostTag(type, clusterId, podId, zoneId, templateTag)).thenReturn(new ArrayList<>());
|
||||
randomAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(noTemplateTaggedHosts, type, zoneId, podId, clusterId, offeringTag, templateTag);
|
||||
Assert.assertTrue(CollectionUtils.isEmpty(noTemplateTaggedHosts));
|
||||
|
||||
// Different template tagged host
|
||||
ArrayList<HostVO> differentTemplateTaggedHost = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
HostVO host3 = Mockito.mock(HostVO.class);
|
||||
Mockito.when(hostDao.listByHostTag(type, clusterId, podId, zoneId, templateTag)).thenReturn(List.of(host3));
|
||||
randomAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(differentTemplateTaggedHost, type, zoneId, podId, clusterId, offeringTag, templateTag);
|
||||
Assert.assertTrue(CollectionUtils.isEmpty(differentTemplateTaggedHost));
|
||||
|
||||
// Matching template tagged host
|
||||
ArrayList<HostVO> matchingTemplateTaggedHost = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
Mockito.when(hostDao.listByHostTag(type, clusterId, podId, zoneId, templateTag)).thenReturn(List.of(host1));
|
||||
randomAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(matchingTemplateTaggedHost, type, zoneId, podId, clusterId, offeringTag, templateTag);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(matchingTemplateTaggedHost));
|
||||
Assert.assertEquals(1, matchingTemplateTaggedHost.size());
|
||||
|
||||
// No template tag
|
||||
ArrayList<HostVO> noTemplateTag = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
randomAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(noTemplateTag, type, zoneId, podId, clusterId, offeringTag, null);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(noTemplateTag));
|
||||
Assert.assertEquals(2, noTemplateTag.size());
|
||||
|
||||
// No offering tag
|
||||
ArrayList<HostVO> noOfferingTag = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
randomAllocator.retainHostsMatchingServiceOfferingAndTemplateTags(noOfferingTag, type, zoneId, podId, clusterId, null, templateTag);
|
||||
Assert.assertFalse(CollectionUtils.isEmpty(noOfferingTag));
|
||||
Assert.assertEquals(1, noOfferingTag.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findSuitableHostsTestHostTypeStorageShouldReturnNull() {
|
||||
List<Host> suitableHosts = randomAllocator.findSuitableHosts(virtualMachineProfile, deploymentPlan, Host.Type.Storage, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Assert.assertNull(suitableHosts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findSuitableHostsTestNoAvailableHostsShouldReturnNull() {
|
||||
Mockito.doReturn(serviceOffering).when(virtualMachineProfile).getServiceOffering();
|
||||
Mockito.doReturn(vmTemplateVO).when(virtualMachineProfile).getTemplate();
|
||||
Mockito.doReturn(hostTag).when(serviceOffering).getHostTag();
|
||||
Mockito.doReturn(emptyList).when(randomAllocator).retrieveHosts(Mockito.any(Host.Type.class), Mockito.nullable(List.class), Mockito.any(VMTemplateVO.class), Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
List<Host> suitableHosts = randomAllocator.findSuitableHosts(virtualMachineProfile, deploymentPlan, type, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Assert.assertNull(suitableHosts);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findSuitableHostsTestAvailableHostsShouldCallFilterAvailableHostsOnce() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
|
||||
Mockito.doReturn(serviceOffering).when(virtualMachineProfile).getServiceOffering();
|
||||
Mockito.doReturn(vmTemplateVO).when(virtualMachineProfile).getTemplate();
|
||||
Mockito.doReturn(hostTag).when(serviceOffering).getHostTag();
|
||||
Mockito.doReturn(hosts).when(randomAllocator).retrieveHosts(Mockito.any(Host.Type.class), Mockito.nullable(List.class), Mockito.any(VMTemplateVO.class), Mockito.anyString(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hosts).when(randomAllocator).filterAvailableHosts(Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any(ServiceOffering.class));
|
||||
List<Host> suitableHosts = randomAllocator.findSuitableHosts(virtualMachineProfile, deploymentPlan, type, excludeList, null, HostAllocator.RETURN_UPTO_ALL, considerReservedCapacity);
|
||||
|
||||
Mockito.verify(randomAllocator, Mockito.times(1)).filterAvailableHosts(Mockito.any(DeploymentPlanner.ExcludeList.class), Mockito.anyInt(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any(ServiceOffering.class));
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterAvailableHostsTestAvailableHostsReachedReturnUpToLimitShouldReturnOnlyHostsWithinLimit() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
int returnUpTo = 1;
|
||||
|
||||
Mockito.doReturn(false).when(excludeList).shouldAvoid(Mockito.any(Host.class));
|
||||
Mockito.doReturn(true).when(randomAllocator).hostHasCpuCapabilityAndCapacity(Mockito.anyBoolean(), Mockito.any(ServiceOffering.class), Mockito.any(Host.class));
|
||||
List<Host> suitableHosts = randomAllocator.filterAvailableHosts(excludeList, returnUpTo, considerReservedCapacity, hosts, serviceOffering);
|
||||
|
||||
Assert.assertEquals(1, suitableHosts.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterAvailableHostsTestReturnUpToAllShouldReturnAllAvailableHosts() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
int returnUpTo = HostAllocator.RETURN_UPTO_ALL;
|
||||
|
||||
Mockito.doReturn(false).when(excludeList).shouldAvoid(Mockito.any(Host.class));
|
||||
Mockito.doReturn(true).when(randomAllocator).hostHasCpuCapabilityAndCapacity(Mockito.anyBoolean(), Mockito.any(ServiceOffering.class), Mockito.any(Host.class));
|
||||
List<Host> suitableHosts = randomAllocator.filterAvailableHosts(excludeList, returnUpTo, considerReservedCapacity, hosts, serviceOffering);
|
||||
|
||||
Assert.assertEquals(2, suitableHosts.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterAvailableHostsTestHost1InAvoidShouldOnlyReturnHost2() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
int returnUpTo = HostAllocator.RETURN_UPTO_ALL;
|
||||
|
||||
Mockito.doReturn(true).when(excludeList).shouldAvoid(host1);
|
||||
Mockito.doReturn(false).when(excludeList).shouldAvoid(host2);
|
||||
Mockito.doReturn(true).when(randomAllocator).hostHasCpuCapabilityAndCapacity(Mockito.anyBoolean(), Mockito.any(ServiceOffering.class), Mockito.any(Host.class));
|
||||
List<Host> suitableHosts = randomAllocator.filterAvailableHosts(excludeList, returnUpTo, considerReservedCapacity, hosts, serviceOffering);
|
||||
|
||||
Assert.assertEquals(1, suitableHosts.size());
|
||||
Assert.assertEquals(host2, suitableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void filterAvailableHostsTestOnlyHost2HasCpuCapacityAndCapabilityShouldReturnOnlyHost2() {
|
||||
List<HostVO> hosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
int returnUpTo = HostAllocator.RETURN_UPTO_ALL;
|
||||
|
||||
Mockito.doReturn(false).when(excludeList).shouldAvoid(Mockito.any(Host.class));
|
||||
Mockito.doReturn(false).when(randomAllocator).hostHasCpuCapabilityAndCapacity(considerReservedCapacity, serviceOffering, host1);
|
||||
Mockito.doReturn(true).when(randomAllocator).hostHasCpuCapabilityAndCapacity(considerReservedCapacity, serviceOffering, host2);
|
||||
List<Host> suitableHosts = randomAllocator.filterAvailableHosts(excludeList, returnUpTo, considerReservedCapacity, hosts, serviceOffering);
|
||||
|
||||
Assert.assertEquals(1, suitableHosts.size());
|
||||
Assert.assertEquals(host2, suitableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNullAndNoHostTagAndNoTagRuleShouldOnlyReturnHostsWithNoTags() {
|
||||
List<HostVO> upAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithNoRuleTagsAndHostTags = new ArrayList<>(Arrays.asList(host1));
|
||||
|
||||
Mockito.doReturn(upAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsWithNoRuleTagsAndHostTags).when(hostDao).listAllHostsThatHaveNoRuleTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(emptyList).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, null, vmTemplateVO, null, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(1, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNullAndOnlyHostTagsRulesShouldReturnHostsThatMatchRuleTagsAndHostsWithNoTags() {
|
||||
List<HostVO> upAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithNoRuleTagsAndHostTags = new ArrayList<>(Arrays.asList(host1));
|
||||
List<HostVO> hostsMatchingRuleTags = new ArrayList<>(Arrays.asList(host2));
|
||||
|
||||
Mockito.doReturn(upAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsWithNoRuleTagsAndHostTags).when(hostDao).listAllHostsThatHaveNoRuleTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsMatchingRuleTags).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, null, vmTemplateVO, null, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(2, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
Assert.assertEquals(host2, availableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNullProvidedHostTagsNotNullAndNoHostWithMatchingRuleTagsShouldReturnHostWithMatchingTags() {
|
||||
List<HostVO> upAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithMatchingTags = new ArrayList<>(Arrays.asList(host1));
|
||||
|
||||
Mockito.doReturn(upAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsWithMatchingTags).when(hostDao).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(emptyList).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, null, vmTemplateVO, hostTag, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(1, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNullProvidedHostTagsNotNullAndHostWithMatchingRuleTagsShouldReturnHostWithHostMatchingTagsAndRuleTags() {
|
||||
List<HostVO> upAndEnabledHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithMatchingTags = new ArrayList<>(Arrays.asList(host1));
|
||||
List<HostVO> hostsMatchingRuleTags = new ArrayList<>(Arrays.asList(host3));
|
||||
|
||||
Mockito.doReturn(upAndEnabledHosts).when(resourceManagerMock).listAllUpAndEnabledHosts(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsWithMatchingTags).when(hostDao).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(hostsMatchingRuleTags).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, null, vmTemplateVO, hostTag, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(2, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
Assert.assertEquals(host3, availableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNotNullAndNoHostTagAndNoTagRuleShouldOnlyReturnHostsWithNoTags() {
|
||||
List<HostVO> providedHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithNoRuleTagsAndHostTags = new ArrayList<>(Arrays.asList(host1));
|
||||
|
||||
Mockito.doReturn(hostsWithNoRuleTagsAndHostTags).when(hostDao).listAllHostsThatHaveNoRuleTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(emptyList).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, providedHosts, vmTemplateVO, null, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(1, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNotNullAndOnlyHostTagsRulesShouldReturnHostsThatMatchRuleTagsAndHostsWithNoTags() {
|
||||
List<HostVO> providedHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithNoRuleTagsAndHostTags = new ArrayList<>(Arrays.asList(host1));
|
||||
List<HostVO> hostsMatchingRuleTags = new ArrayList<>(Arrays.asList(host2));
|
||||
|
||||
Mockito.doReturn(hostsWithNoRuleTagsAndHostTags).when(hostDao).listAllHostsThatHaveNoRuleTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(hostsMatchingRuleTags).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, providedHosts, vmTemplateVO, null, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(2, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
Assert.assertEquals(host2, availableHosts.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNotNullProvidedHostTagsNotNullAndNoHostWithMatchingRuleTagsShouldReturnHostWithMatchingTags() {
|
||||
List<HostVO> providedHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithMatchingTags = new ArrayList<>(Arrays.asList(host1));
|
||||
|
||||
Mockito.doReturn(hostsWithMatchingTags).when(hostDao).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(emptyList).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, providedHosts, vmTemplateVO, hostTag, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(1, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void retrieveHostsTestProvidedHostsNullNotProvidedHostTagsNotNullAndHostWithMatchingRuleTagsShouldReturnHostWithHostMatchingTagsAndRuleTags() {
|
||||
List<HostVO> providedHosts = new ArrayList<>(Arrays.asList(host1, host2));
|
||||
List<HostVO> hostsWithMatchingTags = new ArrayList<>(Arrays.asList(host1));
|
||||
List<HostVO> hostsMatchingRuleTags = new ArrayList<>(Arrays.asList(host3));
|
||||
|
||||
Mockito.doReturn(hostsWithMatchingTags).when(hostDao).listByHostTag(Mockito.any(Host.Type.class), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString());
|
||||
Mockito.doReturn(hostsMatchingRuleTags).when(hostDao).findHostsWithTagRuleThatMatchComputeOfferingTags(Mockito.nullable(String.class));
|
||||
List<HostVO> availableHosts = randomAllocator.retrieveHosts(type, providedHosts, vmTemplateVO, hostTag, clusterId, podId, zoneId);
|
||||
|
||||
Assert.assertEquals(2, availableHosts.size());
|
||||
Assert.assertEquals(host1, availableHosts.get(0));
|
||||
Assert.assertEquals(host3, availableHosts.get(1));
|
||||
}
|
||||
}
|
||||
|
|
@ -460,7 +460,7 @@ public class NetworkServiceImplTest {
|
|||
null, null, false, null, accountMock, null, phyNet,
|
||||
1L, null, null, null, null, null,
|
||||
true, null, null, null, null, null,
|
||||
null, null, null, null, new Pair<>(1500, privateMtu), null);
|
||||
null, null, null, null, new Pair<>(1500, privateMtu), null, true);
|
||||
}
|
||||
@Test
|
||||
public void testValidateMtuConfigWhenMtusExceedThreshold() {
|
||||
|
|
@ -1330,4 +1330,52 @@ public class NetworkServiceImplTest {
|
|||
Mockito.verify(accountJoin).addAnd("type", SearchCriteria.Op.EQ, Account.Type.PROJECT);
|
||||
Mockito.verify(sc).addAnd("id", SearchCriteria.Op.SC, accountJoin);
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestThrowExceptionWhenParamIsSpecifiedOnTiersCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.isForVpc()).thenReturn(true);
|
||||
|
||||
service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(true, networkOfferingVO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestReturnTrueByDefaultOnTiersCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.isForVpc()).thenReturn(true);
|
||||
|
||||
Assert.assertTrue(service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(null, networkOfferingVO));
|
||||
}
|
||||
|
||||
@Test(expected = InvalidParameterValueException.class)
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestThrowExceptionWhenParamIsSpecifiedOnNonIsolatedNetworksCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.getGuestType()).thenReturn(Network.GuestType.Shared);
|
||||
|
||||
service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(true, networkOfferingVO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestReturnTrueByDefaultOnNonIsolatedNetworksCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.getGuestType()).thenReturn(Network.GuestType.L2);
|
||||
|
||||
Assert.assertTrue(service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(null, networkOfferingVO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestReturnTrueByDefaultOnIsolatedNetworksCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.getGuestType()).thenReturn(Network.GuestType.Isolated);
|
||||
|
||||
Assert.assertTrue(service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(null, networkOfferingVO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAndValidateSupportForKeepMacAddressOnPublicNicParameterTestReturnSpecifiedValueOnIsolatedNetworksCreation() {
|
||||
networkOfferingVO = Mockito.mock(NetworkOfferingVO.class);
|
||||
Mockito.when(networkOfferingVO.getGuestType()).thenReturn(Network.GuestType.Isolated);
|
||||
|
||||
Assert.assertFalse(service.getAndValidateSupportForKeepMacAddressOnPublicNicParameter(false, networkOfferingVO));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,18 +24,31 @@ import static org.mockito.ArgumentMatchers.any;
|
|||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.InsufficientAddressCapacityException;
|
||||
import com.cloud.network.Ipv6Service;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.Networks;
|
||||
import com.cloud.network.addr.PublicIp;
|
||||
import com.cloud.network.dao.NetworkVO;
|
||||
import com.cloud.offering.NetworkOffering;
|
||||
import com.cloud.utils.net.Ip;
|
||||
import com.cloud.vm.NicProfile;
|
||||
import com.cloud.vm.NicVO;
|
||||
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
|
||||
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinition;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
|
|
@ -57,6 +70,9 @@ import com.cloud.vm.VirtualMachineName;
|
|||
import com.cloud.vm.dao.DomainRouterDao;
|
||||
import com.cloud.vm.dao.NicDao;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class NetworkHelperImplTest {
|
||||
|
|
@ -69,32 +85,59 @@ public class NetworkHelperImplTest {
|
|||
@Mock
|
||||
DomainRouterDao routerDao;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
protected NetworkHelperImpl nwHelper = new NetworkHelperImpl();
|
||||
protected NetworkHelperImpl networkHelperSpy = new NetworkHelperImpl();
|
||||
|
||||
@Mock
|
||||
NetworkOrchestrationService networkOrchestrationService;
|
||||
|
||||
@Mock
|
||||
NetworkDao networkDao;
|
||||
|
||||
@Mock
|
||||
NetworkModel networkModel;
|
||||
|
||||
@Mock
|
||||
NicDao nicDao;
|
||||
private NicDao nicDaoMock;
|
||||
|
||||
@Mock
|
||||
private RouterDeploymentDefinition routerDeploymentDefinition;
|
||||
|
||||
@Mock
|
||||
private VirtualRouterProvider virtualProvider;
|
||||
|
||||
@Mock
|
||||
private Account owner;
|
||||
|
||||
@Mock
|
||||
private ServiceOfferingVO routerOffering;
|
||||
|
||||
@Mock
|
||||
private VMTemplateVO template;
|
||||
|
||||
@Mock
|
||||
private PublicIp publicIpMock;
|
||||
|
||||
@Mock
|
||||
private RouterDeploymentDefinition routerDeploymentDefinitionMock;
|
||||
|
||||
@Mock
|
||||
private Ipv6Service ipv6ServiceMock;
|
||||
|
||||
@Mock
|
||||
private NicVO nicVoMock;
|
||||
|
||||
@Mock
|
||||
private Network networkMock;
|
||||
|
||||
private NicProfile nicProfile = new NicProfile();
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
nwHelper._networkDao = networkDao;
|
||||
nwHelper._networkModel = networkModel;
|
||||
networkHelperSpy._networkDao = networkDao;
|
||||
networkHelperSpy._networkModel = networkModel;
|
||||
|
||||
when(template.getId()).thenReturn(1L);
|
||||
when(template.isDynamicallyScalable()).thenReturn(true);
|
||||
when(virtualProvider.getId()).thenReturn(1L);
|
||||
|
|
@ -107,7 +150,7 @@ public class NetworkHelperImplTest {
|
|||
public void testSendCommandsToRouterWrongRouterVersion()
|
||||
throws AgentUnavailableException, OperationTimedoutException, ResourceUnavailableException {
|
||||
// Prepare
|
||||
NetworkHelperImpl nwHelperUT = spy(this.nwHelper);
|
||||
NetworkHelperImpl nwHelperUT = networkHelperSpy;
|
||||
VirtualRouter vr = mock(VirtualRouter.class);
|
||||
doReturn(false).when(nwHelperUT).checkRouterVersion(vr);
|
||||
|
||||
|
|
@ -122,7 +165,7 @@ public class NetworkHelperImplTest {
|
|||
public void testSendCommandsToRouter()
|
||||
throws AgentUnavailableException, OperationTimedoutException, ResourceUnavailableException {
|
||||
// Prepare
|
||||
NetworkHelperImpl nwHelperUT = spy(this.nwHelper);
|
||||
NetworkHelperImpl nwHelperUT = networkHelperSpy;
|
||||
VirtualRouter vr = mock(VirtualRouter.class);
|
||||
when(vr.getHostId()).thenReturn(HOST_ID);
|
||||
doReturn(true).when(nwHelperUT).checkRouterVersion(vr);
|
||||
|
|
@ -160,7 +203,7 @@ public class NetworkHelperImplTest {
|
|||
public void testSendCommandsToRouterWithTrueResult()
|
||||
throws AgentUnavailableException, OperationTimedoutException, ResourceUnavailableException {
|
||||
// Prepare
|
||||
NetworkHelperImpl nwHelperUT = spy(this.nwHelper);
|
||||
NetworkHelperImpl nwHelperUT = networkHelperSpy;
|
||||
VirtualRouter vr = mock(VirtualRouter.class);
|
||||
when(vr.getHostId()).thenReturn(HOST_ID);
|
||||
doReturn(true).when(nwHelperUT).checkRouterVersion(vr);
|
||||
|
|
@ -198,7 +241,7 @@ public class NetworkHelperImplTest {
|
|||
public void testSendCommandsToRouterWithNoAnswers()
|
||||
throws AgentUnavailableException, OperationTimedoutException, ResourceUnavailableException {
|
||||
// Prepare
|
||||
NetworkHelperImpl nwHelperUT = spy(this.nwHelper);
|
||||
NetworkHelperImpl nwHelperUT = networkHelperSpy;
|
||||
VirtualRouter vr = mock(VirtualRouter.class);
|
||||
when(vr.getHostId()).thenReturn(HOST_ID);
|
||||
doReturn(true).when(nwHelperUT).checkRouterVersion(vr);
|
||||
|
|
@ -227,7 +270,7 @@ public class NetworkHelperImplTest {
|
|||
boolean offerHA = false;
|
||||
Long vpcId = 900L;
|
||||
when(routerDao.persist(any(DomainRouterVO.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
DomainRouterVO result = nwHelper.createOrUpdateDomainRouter(
|
||||
DomainRouterVO result = networkHelperSpy.createOrUpdateDomainRouter(
|
||||
null, id, routerDeploymentDefinition, owner, userId, routerOffering, offerHA, vpcId, template);
|
||||
assertNotNull(result);
|
||||
assertEquals(id, result.getId());
|
||||
|
|
@ -261,11 +304,234 @@ public class NetworkHelperImplTest {
|
|||
owner.getDomainId(), owner.getId(), userId, routerDeploymentDefinition.isRedundant(), VirtualRouter.RedundantState.UNKNOWN,
|
||||
offerHA, false, vpcId);
|
||||
existing.setDynamicallyScalable(false);
|
||||
DomainRouterVO result = nwHelper.createOrUpdateDomainRouter(
|
||||
DomainRouterVO result = networkHelperSpy.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());
|
||||
}
|
||||
|
||||
|
||||
private NicProfile getExpectedNicProfile(boolean vxlan, String vlanTag) {
|
||||
NicProfile nic = new NicProfile();
|
||||
nic.setDefaultNic(true);
|
||||
nic.setIPv4Address("192.168.0.10");
|
||||
nic.setIPv4Gateway("192.168.0.1");
|
||||
nic.setIPv4Netmask("255.255.255.0");
|
||||
nic.setMacAddress("ff-ff-ff-ff-ff-ff");
|
||||
|
||||
if (vxlan) {
|
||||
nic.setBroadcastType(Networks.BroadcastDomainType.Vxlan);
|
||||
nic.setBroadcastUri(Networks.BroadcastDomainType.Vxlan.toUri(vlanTag));
|
||||
nic.setIsolationUri(Networks.BroadcastDomainType.Vxlan.toUri(vlanTag));
|
||||
} else {
|
||||
nic.setBroadcastType(Networks.BroadcastDomainType.Vlan);
|
||||
nic.setBroadcastUri(vlanTag != null ? Networks.BroadcastDomainType.Vlan.toUri(vlanTag) : null);
|
||||
nic.setIsolationUri(vlanTag != null ? Networks.IsolationType.Vlan.toUri(vlanTag) : null);
|
||||
}
|
||||
|
||||
return nic;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicVrNicBasedOnSourceNatIpTestConfigureVxLanNic() {
|
||||
String vlanTag = "200";
|
||||
NicProfile expected = getExpectedNicProfile(true, vlanTag);
|
||||
|
||||
Ip ipMock = Mockito.mock(Ip.class);
|
||||
NetworkVO publicNetworkMock = Mockito.mock(NetworkVO.class);
|
||||
long networkId = 1L;
|
||||
Mockito.when(publicIpMock.getAddress()).thenReturn(ipMock);
|
||||
Mockito.when(ipMock.addr()).thenReturn(expected.getIPv4Address());
|
||||
Mockito.when(publicIpMock.getGateway()).thenReturn(expected.getIPv4Gateway());
|
||||
Mockito.when(publicIpMock.getNetmask()).thenReturn(expected.getIPv4Netmask());
|
||||
Mockito.when(publicIpMock.getMacAddress()).thenReturn(expected.getMacAddress());
|
||||
Mockito.when(publicIpMock.getNetworkId()).thenReturn(networkId);
|
||||
Mockito.when(networkDao.findById(networkId)).thenReturn(publicNetworkMock);
|
||||
Mockito.when(publicNetworkMock.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.Vxlan);
|
||||
Mockito.when(publicIpMock.getVlanTag()).thenReturn(vlanTag);
|
||||
|
||||
networkHelperSpy.configurePublicVrNicBasedOnSourceNatIp(nicProfile, publicIpMock);
|
||||
|
||||
Assert.assertTrue(nicProfile.isDefaultNic());
|
||||
Assert.assertEquals(expected.getIPv4Address(), nicProfile.getIPv4Address());
|
||||
Assert.assertEquals(expected.getIPv4Gateway(), nicProfile.getIPv4Gateway());
|
||||
Assert.assertEquals(expected.getIPv4Netmask(), nicProfile.getIPv4Netmask());
|
||||
Assert.assertEquals(expected.getMacAddress(), nicProfile.getMacAddress());
|
||||
Assert.assertEquals(expected.getBroadcastType(), nicProfile.getBroadcastType());
|
||||
Assert.assertEquals(expected.getBroadCastUri(), nicProfile.getBroadCastUri());
|
||||
Assert.assertEquals(expected.getIsolationUri(), nicProfile.getIsolationUri());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicVrNicBasedOnSourceNatIpTestConfigureVlanNicWithVlanTag() {
|
||||
String vlanTag = "200";
|
||||
NicProfile expected = getExpectedNicProfile(false, vlanTag);
|
||||
|
||||
Ip ipMock = Mockito.mock(Ip.class);
|
||||
NetworkVO publicNetworkMock = Mockito.mock(NetworkVO.class);
|
||||
long networkId = 1L;
|
||||
Mockito.when(publicIpMock.getAddress()).thenReturn(ipMock);
|
||||
Mockito.when(ipMock.addr()).thenReturn(expected.getIPv4Address());
|
||||
Mockito.when(publicIpMock.getGateway()).thenReturn(expected.getIPv4Gateway());
|
||||
Mockito.when(publicIpMock.getNetmask()).thenReturn(expected.getIPv4Netmask());
|
||||
Mockito.when(publicIpMock.getMacAddress()).thenReturn(expected.getMacAddress());
|
||||
Mockito.when(publicIpMock.getNetworkId()).thenReturn(networkId);
|
||||
Mockito.when(networkDao.findById(networkId)).thenReturn(publicNetworkMock);
|
||||
Mockito.when(publicNetworkMock.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.Vlan);
|
||||
Mockito.when(publicIpMock.getVlanTag()).thenReturn(vlanTag);
|
||||
|
||||
networkHelperSpy.configurePublicVrNicBasedOnSourceNatIp(nicProfile, publicIpMock);
|
||||
|
||||
Assert.assertTrue(nicProfile.isDefaultNic());
|
||||
Assert.assertEquals(expected.getIPv4Address(), nicProfile.getIPv4Address());
|
||||
Assert.assertEquals(expected.getIPv4Gateway(), nicProfile.getIPv4Gateway());
|
||||
Assert.assertEquals(expected.getIPv4Netmask(), nicProfile.getIPv4Netmask());
|
||||
Assert.assertEquals(expected.getMacAddress(), nicProfile.getMacAddress());
|
||||
Assert.assertEquals(expected.getBroadcastType(), nicProfile.getBroadcastType());
|
||||
Assert.assertEquals(expected.getBroadCastUri(), nicProfile.getBroadCastUri());
|
||||
Assert.assertEquals(expected.getIsolationUri(), nicProfile.getIsolationUri());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicVrNicBasedOnSourceNatIpTestConfigureVlanNicWithNoVlanTag() {
|
||||
String vlanTag = null;
|
||||
NicProfile expected = getExpectedNicProfile(false, vlanTag);
|
||||
|
||||
Ip ipMock = Mockito.mock(Ip.class);
|
||||
NetworkVO publicNetworkMock = Mockito.mock(NetworkVO.class);
|
||||
long networkId = 1L;
|
||||
Mockito.when(publicIpMock.getAddress()).thenReturn(ipMock);
|
||||
Mockito.when(ipMock.addr()).thenReturn(expected.getIPv4Address());
|
||||
Mockito.when(publicIpMock.getGateway()).thenReturn(expected.getIPv4Gateway());
|
||||
Mockito.when(publicIpMock.getNetmask()).thenReturn(expected.getIPv4Netmask());
|
||||
Mockito.when(publicIpMock.getMacAddress()).thenReturn(expected.getMacAddress());
|
||||
Mockito.when(publicIpMock.getNetworkId()).thenReturn(networkId);
|
||||
Mockito.when(networkDao.findById(networkId)).thenReturn(publicNetworkMock);
|
||||
Mockito.when(publicNetworkMock.getBroadcastDomainType()).thenReturn(Networks.BroadcastDomainType.Vlan);
|
||||
Mockito.when(publicIpMock.getVlanTag()).thenReturn(vlanTag);
|
||||
|
||||
networkHelperSpy.configurePublicVrNicBasedOnSourceNatIp(nicProfile, publicIpMock);
|
||||
|
||||
Assert.assertTrue(nicProfile.isDefaultNic());
|
||||
Assert.assertEquals(expected.getIPv4Address(), nicProfile.getIPv4Address());
|
||||
Assert.assertEquals(expected.getIPv4Gateway(), nicProfile.getIPv4Gateway());
|
||||
Assert.assertEquals(expected.getIPv4Netmask(), nicProfile.getIPv4Netmask());
|
||||
Assert.assertEquals(expected.getMacAddress(), nicProfile.getMacAddress());
|
||||
Assert.assertEquals(expected.getBroadcastType(), nicProfile.getBroadcastType());
|
||||
Assert.assertEquals(expected.getBroadCastUri(), nicProfile.getBroadCastUri());
|
||||
Assert.assertEquals(expected.getIsolationUri(), nicProfile.getIsolationUri());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPublicNicMacAddressSameAsPeerNicTestDoNothingWhenThereIsNoPeer() throws InsufficientAddressCapacityException {
|
||||
String newMacAddress = "ff-ff-ff-ff-ff-ff";
|
||||
nicProfile.setIPv4Address("10.0.0.1");
|
||||
nicProfile.setMacAddress(newMacAddress);
|
||||
Mockito.when(nicDaoMock.findByIp4AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong())).thenReturn(null);
|
||||
|
||||
networkHelperSpy.setPublicNicMacAddressSameAsPeerNic(nicProfile, networkMock, routerDeploymentDefinitionMock);
|
||||
|
||||
Assert.assertEquals(newMacAddress, nicProfile.getMacAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPublicNicMacAddressSameAsPeerNicTestKeepMacAddress() throws InsufficientAddressCapacityException {
|
||||
String peerMacAddress = "ff-ff-ff-ff-ff-ff";
|
||||
nicProfile.setIPv4Address("10.0.0.1");
|
||||
nicProfile.setMacAddress("ff-ff-ff-ff-ff-f1");
|
||||
|
||||
Mockito.when(nicDaoMock.findByIp4AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong())).thenReturn(nicVoMock);
|
||||
Mockito.when(nicVoMock.getMacAddress()).thenReturn(peerMacAddress);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getKeepMacAddressOnPublicNic()).thenReturn(true);
|
||||
|
||||
networkHelperSpy.setPublicNicMacAddressSameAsPeerNic(nicProfile, networkMock, routerDeploymentDefinitionMock);
|
||||
|
||||
Assert.assertEquals(peerMacAddress, nicProfile.getMacAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPublicNicMacAddressSameAsPeerNicTestDifferentMacAddressFetchingNewSourceNatIp() throws InsufficientAddressCapacityException {
|
||||
String macAddress = "ff-ff-ff-ff-ff-f1";
|
||||
nicProfile.setIPv4Address("10.0.0.1");
|
||||
nicProfile.setMacAddress(macAddress);
|
||||
PublicIp publicIpMock = Mockito.mock(PublicIp.class);
|
||||
|
||||
Mockito.when(nicDaoMock.findByIp4AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong())).thenReturn(nicVoMock);
|
||||
Mockito.when(nicVoMock.getMacAddress()).thenReturn(macAddress);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getKeepMacAddressOnPublicNic()).thenReturn(false);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getSourceNatIP()).thenReturn(publicIpMock);
|
||||
Mockito.doNothing().when(networkHelperSpy).configurePublicVrNicBasedOnSourceNatIp(nicProfile, publicIpMock);
|
||||
|
||||
networkHelperSpy.setPublicNicMacAddressSameAsPeerNic(nicProfile, networkMock, routerDeploymentDefinitionMock);
|
||||
|
||||
Mockito.verify(routerDeploymentDefinitionMock).findSourceNatIP();
|
||||
Mockito.verify(networkHelperSpy).configurePublicVrNicBasedOnSourceNatIp(nicProfile, publicIpMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setPublicNicMacAddressSameAsPeerNicTestDifferentMacAddressNotFetchingNewSourceNatIp() throws InsufficientAddressCapacityException {
|
||||
String newMacAddress = "ff-ff-ff-ff-ff-ff";
|
||||
nicProfile.setIPv4Address("10.0.0.1");
|
||||
nicProfile.setMacAddress(newMacAddress);
|
||||
|
||||
Mockito.when(nicDaoMock.findByIp4AddressAndNetworkId(Mockito.anyString(), Mockito.anyLong())).thenReturn(nicVoMock);
|
||||
Mockito.when(nicVoMock.getMacAddress()).thenReturn("ff-ff-ff-ff-ff-f1");
|
||||
Mockito.when(routerDeploymentDefinitionMock.getKeepMacAddressOnPublicNic()).thenReturn(false);
|
||||
|
||||
networkHelperSpy.setPublicNicMacAddressSameAsPeerNic(nicProfile, networkMock, routerDeploymentDefinitionMock);
|
||||
|
||||
Mockito.verify(routerDeploymentDefinitionMock, Mockito.never()).findSourceNatIP();
|
||||
Mockito.verify(networkHelperSpy, Mockito.never()).configurePublicVrNicBasedOnSourceNatIp(Mockito.any(), Mockito.any());
|
||||
Assert.assertEquals(newMacAddress, nicProfile.getMacAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicNicTestReturnEmptyMapWhenNetworkIsNotPublic() throws InsufficientAddressCapacityException {
|
||||
Mockito.when(routerDeploymentDefinitionMock.isPublicNetwork()).thenReturn(false);
|
||||
|
||||
Map<Network, List<? extends NicProfile>> nic = networkHelperSpy.configurePublicNic(routerDeploymentDefinitionMock, false);
|
||||
Assert.assertTrue(nic.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicNicTestConfigureDeviceId() throws InsufficientAddressCapacityException {
|
||||
PublicIp publicIpMock = Mockito.mock(PublicIp.class);
|
||||
NetworkOffering networkOfferingMock = Mockito.mock(NetworkOffering.class);
|
||||
|
||||
Mockito.when(routerDeploymentDefinitionMock.isPublicNetwork()).thenReturn(true);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getSourceNatIP()).thenReturn(publicIpMock);
|
||||
Mockito.doNothing().when(networkHelperSpy).configurePublicVrNicBasedOnSourceNatIp(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn(List.of(networkOfferingMock)).when(networkModel).getSystemAccountNetworkOfferings(Mockito.any());
|
||||
Mockito.doReturn(List.of(networkMock)).when(networkOrchestrationService).setupNetwork(
|
||||
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()
|
||||
);
|
||||
Mockito.doNothing().when(networkHelperSpy).setPublicNicMacAddressSameAsPeerNic(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
|
||||
Map<Network, List<? extends NicProfile>> nic = networkHelperSpy.configurePublicNic(routerDeploymentDefinitionMock, true);
|
||||
Integer nicDeviceId = nic.get(networkMock).get(0).getDeviceId();
|
||||
Assert.assertEquals(2, nicDeviceId.intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configurePublicNicTestUpdateGuestNetworksIpv6Nic() throws InsufficientAddressCapacityException {
|
||||
PublicIp publicIpMock = Mockito.mock(PublicIp.class);
|
||||
NetworkOffering networkOfferingMock = Mockito.mock(NetworkOffering.class);
|
||||
DeployDestination deployDestinationMock = Mockito.mock(DeployDestination.class);
|
||||
|
||||
Mockito.when(routerDeploymentDefinitionMock.isPublicNetwork()).thenReturn(true);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getSourceNatIP()).thenReturn(publicIpMock);
|
||||
Mockito.doNothing().when(networkHelperSpy).configurePublicVrNicBasedOnSourceNatIp(Mockito.any(), Mockito.any());
|
||||
Mockito.doReturn(List.of(networkOfferingMock)).when(networkModel).getSystemAccountNetworkOfferings(Mockito.any());
|
||||
Mockito.doReturn(List.of(networkMock)).when(networkOrchestrationService).setupNetwork(
|
||||
Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(), Mockito.anyBoolean()
|
||||
);
|
||||
Mockito.doNothing().when(networkHelperSpy).setPublicNicMacAddressSameAsPeerNic(Mockito.any(), Mockito.any(), Mockito.any());
|
||||
Mockito.when(routerDeploymentDefinitionMock.getGuestNetwork()).thenReturn(networkMock);
|
||||
Mockito.when(routerDeploymentDefinitionMock.getDest()).thenReturn(deployDestinationMock);
|
||||
|
||||
Map<Network, List<? extends NicProfile>> nic = networkHelperSpy.configurePublicNic(routerDeploymentDefinitionMock, false);
|
||||
Mockito.verify(ipv6ServiceMock).updateNicIpv6(Mockito.eq(nic.get(networkMock).get(0)), Mockito.any(), Mockito.eq(networkMock));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ public class VpcManagerImplTest {
|
|||
mockVpcDnsResources(false, false);
|
||||
try {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], null, null, null, true, 1500, null, null, null, false);
|
||||
ip4Dns[0], null, null, null, true, 1500, null, null, null, false, true);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
|
|
@ -503,7 +503,7 @@ public class VpcManagerImplTest {
|
|||
mockVpcDnsResources(true, false);
|
||||
try {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], ip6Dns[0], null, true, 1500, null, null, null, false);
|
||||
ip4Dns[0], ip4Dns[1], ip6Dns[0], null, true, 1500, null, null, null, false, true);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
|
|
@ -517,7 +517,7 @@ public class VpcManagerImplTest {
|
|||
Mockito.when(vpc.getUuid()).thenReturn("uuid");
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false);
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false, true);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
|
|
@ -533,7 +533,7 @@ public class VpcManagerImplTest {
|
|||
doNothing().when(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyString());
|
||||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, ip4Cidr, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false);
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, null, null, null, false, true);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
|
|
@ -556,7 +556,7 @@ public class VpcManagerImplTest {
|
|||
try (MockedConstruction<CheckedReservation> mockCheckedReservation = Mockito.mockConstruction(CheckedReservation.class)) {
|
||||
|
||||
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, null, vpcDomain,
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds, false);
|
||||
ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds, false, true);
|
||||
} catch (ResourceAllocationException e) {
|
||||
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -704,11 +704,19 @@ public class MockNetworkManagerImpl extends ManagerBase implements NetworkOrches
|
|||
public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain,
|
||||
Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
|
||||
String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId, String routerIp, String routerIpv6,
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize) throws ConcurrentOperationException, ResourceAllocationException {
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize) throws ConcurrentOperationException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Network createGuestNetwork(long networkOfferingId, String name, String displayText, String gateway, String cidr, String vlanId, boolean bypassVlanOverlapCheck, String networkDomain,
|
||||
Account owner, Long domainId, PhysicalNetwork physicalNetwork, long zoneId, ACLType aclType, Boolean subdomainAccess, Long vpcId, String gatewayv6,
|
||||
String cidrv6, Boolean displayNetworkEnabled, String isolatedPvlan, Network.PVlanType isolatedPvlanType, String externalId, String routerIp, String routerIpv6,
|
||||
String ip4Dns1, String ip4Dns2, String ip6Dns1, String ip6Dns2, Pair<Integer, Integer> vrIfaceMTUs, Integer networkCidrSize, boolean keepMacAddressOnPublicNic) throws ConcurrentOperationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.cloud.network.NetworkManager#getPasswordResetProvider(com.cloud.network.Network)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ class TestRestoreVMStrictTags(cloudstackTestCase):
|
|||
vm.restore(self.apiclient, templateid=self.template_t2.id, expunge=True)
|
||||
self.fail("VM should not be restored")
|
||||
except Exception as e:
|
||||
self.assertTrue("Unable to start VM with specified id" in str(e))
|
||||
self.assertTrue("Unable to create a deployment for " in str(e))
|
||||
|
||||
|
||||
class TestMigrateVMStrictTags(cloudstackTestCase):
|
||||
|
|
|
|||
|
|
@ -1433,6 +1433,7 @@
|
|||
"label.javadistribution": "Java Runtime Distribution",
|
||||
"label.javaversion": "Java Runtime Version",
|
||||
"label.keep": "Keep",
|
||||
"label.keep.mac.address.on.public.nic": "Use same MAC address for public NIC of VRs",
|
||||
"label.kernelversion": "Kernel Version",
|
||||
"label.key": "Key",
|
||||
"label.keyboard": "Keyboard language",
|
||||
|
|
@ -4167,6 +4168,7 @@
|
|||
"message.warn.select.template": "Please select a Template for Registration.",
|
||||
"message.warn.zone.mtu.update": "Please note that this limit won't affect pre-existing Network's MTU settings",
|
||||
"message.webhook.deliveries.time.filter": "Webhook deliveries list can be filtered based on date-time. Select 'Custom' for specifying start and end date range.",
|
||||
"message.webhook.filter.add": "Webhook deliveries can be controlled using filters (currently by Event type). Please select the parameters to add to the applied filters list.",
|
||||
"message.zone.creation.complete": "Zone creation complete.",
|
||||
"message.zone.detail.description": "Populate Zone details.",
|
||||
"message.zone.detail.hint": "A Zone is the largest organizational unit in CloudStack, and it typically corresponds to a single datacenter. Zones provide physical isolation and redundancy. A zone consists of one or more Pods (each of which contains hosts and primary storage servers) and a secondary storage server which is shared by all pods in the zone.",
|
||||
|
|
|
|||
|
|
@ -904,6 +904,7 @@
|
|||
"label.items.selected": "item(ns) selecionados",
|
||||
"label.japanese.keyboard": "Teclado japon\u00eas",
|
||||
"label.keep": "Manter",
|
||||
"label.keep.mac.address.on.public.nic": "Utilizar o mesmo endere\u00e7o MAC para a NIC p\u00fablica dos VRs",
|
||||
"label.key": "Chave",
|
||||
"label.keyboard": "Linguagem do teclado",
|
||||
"label.keyboardtype": "Tipo de teclado",
|
||||
|
|
|
|||
|
|
@ -949,7 +949,7 @@
|
|||
style="margin-left: 5px"
|
||||
:actions="actions"
|
||||
:resource="record"
|
||||
:enabled="quickViewEnabled() && actions.length > 0"
|
||||
:enabled="quickViewEnabled(actions, columns, column.key)"
|
||||
@exec-action="$parent.execAction"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="add-row">
|
||||
<p>{{ $t('message.webhook.filter.add') }}</p>
|
||||
<a-form
|
||||
:ref="addFormRef"
|
||||
:model="addFilterForm"
|
||||
|
|
@ -90,7 +91,7 @@
|
|||
{{ (selectedRowKeys && selectedRowKeys.length > 0) ? $t('label.action.delete.webhook.filters') : $t('label.action.clear.webhook.filters') }}
|
||||
</a-button>
|
||||
<list-view
|
||||
:tabLoading="tabLoading"
|
||||
:loading="tabLoading"
|
||||
:columns="columns"
|
||||
:items="filters"
|
||||
:actions="actions"
|
||||
|
|
|
|||
|
|
@ -49,9 +49,14 @@ export default {
|
|||
return fields
|
||||
},
|
||||
details: () => {
|
||||
var fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'broadcasturi', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'asnumber', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domainpath', 'associatednetwork', 'associatednetworkid', 'ip4routing', 'ip6firewall', 'ip6routing', 'ip6routes', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu']
|
||||
if (!isAdmin()) {
|
||||
fields = fields.filter(function (e) { return e !== 'broadcasturi' })
|
||||
const fields = ['name', 'id', 'description', 'type', 'traffictype', 'vpcid', 'vlan', 'cidr', 'ip6cidr', 'netmask', 'gateway', 'asnumber', 'aclname', 'ispersistent', 'restartrequired', 'reservediprange', 'redundantrouter', 'networkdomain', 'egressdefaultpolicy', 'zonename', 'account', 'domainpath', 'associatednetwork', 'associatednetworkid', 'ip4routing', 'ip6firewall', 'ip6routing', 'ip6routes', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu', 'privatemtu']
|
||||
if (isAdmin()) {
|
||||
const vlanIndex = fields.findIndex(detail => detail === 'vlan')
|
||||
fields.splice(vlanIndex + 1, 0, 'broadcasturi')
|
||||
fields.push({
|
||||
field: 'keepmacaddressonpublicnic',
|
||||
customTitle: 'keep.mac.address.on.public.nic'
|
||||
})
|
||||
}
|
||||
return fields
|
||||
},
|
||||
|
|
@ -233,7 +238,16 @@ export default {
|
|||
fields.push(...['domain', 'zonename'])
|
||||
return fields
|
||||
},
|
||||
details: ['name', 'id', 'displaytext', 'cidr', 'networkdomain', 'ip4routing', 'ip4routes', 'ip6routes', 'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account', 'domain', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu'],
|
||||
details: () => {
|
||||
const fields = ['name', 'id', 'displaytext', 'cidr', 'networkdomain', 'ip4routing', 'ip4routes', 'ip6routes', 'ispersistent', 'redundantvpcrouter', 'restartrequired', 'zonename', 'account', 'domain', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'publicmtu']
|
||||
if (isAdmin()) {
|
||||
fields.push({
|
||||
field: 'keepmacaddressonpublicnic',
|
||||
customTitle: 'keep.mac.address.on.public.nic'
|
||||
})
|
||||
}
|
||||
return fields
|
||||
},
|
||||
searchFilters: ['name', 'zoneid', 'domainid', 'account', 'restartrequired', 'tags'],
|
||||
related: [{
|
||||
name: 'vm',
|
||||
|
|
@ -268,7 +282,13 @@ export default {
|
|||
icon: 'edit-outlined',
|
||||
label: 'label.edit',
|
||||
dataView: true,
|
||||
args: ['name', 'displaytext', 'publicmtu', 'sourcenatipaddress']
|
||||
args: () => {
|
||||
const fields = ['name', 'displaytext', 'publicmtu', 'sourcenatipaddress']
|
||||
if (isAdmin()) {
|
||||
fields.push('keepmacaddressonpublicnic')
|
||||
}
|
||||
return fields
|
||||
}
|
||||
},
|
||||
{
|
||||
api: 'restartVPC',
|
||||
|
|
|
|||
|
|
@ -294,6 +294,11 @@
|
|||
:title="$t('label.default.network.' + field.name + '.isolated.network')"
|
||||
:tooltip="field.description"
|
||||
/>
|
||||
<tooltip-label
|
||||
v-else-if="field.name === 'keepmacaddressonpublicnic' && currentAction.api === 'updateVPC'"
|
||||
:title="$t('label.keep.mac.address.on.public.nic')"
|
||||
:tooltip="field.description"
|
||||
/>
|
||||
<tooltip-label
|
||||
v-else
|
||||
:title="$t('label.' + field.name)"
|
||||
|
|
|
|||
|
|
@ -294,6 +294,15 @@
|
|||
v-model:value="form.sourcenatipaddress"
|
||||
:placeholder="apiParams.sourcenatipaddress?.description"/>
|
||||
</a-form-item>
|
||||
<a-form-item name="keepMacAddressOnPublicNic" ref="keepMacAddressOnPublicNic" v-if="isAdmin() && !selectedNetworkOffering?.forvpc">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.keep.mac.address.on.public.nic')"
|
||||
:tooltip="apiParams.keepmacaddressonpublicnic?.description"
|
||||
/>
|
||||
</template>
|
||||
<a-switch v-model:checked="form.keepMacAddressOnPublicNic" />
|
||||
</a-form-item>
|
||||
<div :span="24" class="action-button">
|
||||
<a-button
|
||||
:loading="actionLoading"
|
||||
|
|
@ -408,7 +417,9 @@ export default {
|
|||
methods: {
|
||||
initForm () {
|
||||
this.formRef = ref()
|
||||
this.form = reactive({})
|
||||
this.form = reactive({
|
||||
keepMacAddressOnPublicNic: true
|
||||
})
|
||||
this.rules = reactive({
|
||||
name: [{ required: true, message: this.$t('message.error.name') }],
|
||||
zoneid: [{ type: 'number', required: true, message: this.$t('message.error.select') }],
|
||||
|
|
@ -600,14 +611,15 @@ export default {
|
|||
const formRaw = toRaw(this.form)
|
||||
const values = this.handleRemoveFields(formRaw)
|
||||
this.actionLoading = true
|
||||
var params = {
|
||||
const params = {
|
||||
zoneId: this.selectedZone.id,
|
||||
name: values.name,
|
||||
displayText: values.displaytext,
|
||||
networkOfferingId: this.selectedNetworkOffering.id
|
||||
networkOfferingId: this.selectedNetworkOffering.id,
|
||||
keepmacaddressonpublicnic: values.keepMacAddressOnPublicNic
|
||||
}
|
||||
var usefulFields = ['gateway', 'netmask', 'cidrsize', 'startip', 'startipv4', 'endip', 'endipv4', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'sourcenatipaddress', 'externalid', 'vpcid', 'vlan', 'networkdomain']
|
||||
for (var field of usefulFields) {
|
||||
const usefulFields = ['gateway', 'netmask', 'cidrsize', 'startip', 'startipv4', 'endip', 'endipv4', 'dns1', 'dns2', 'ip6dns1', 'ip6dns2', 'sourcenatipaddress', 'externalid', 'vpcid', 'vlan', 'networkdomain']
|
||||
for (const field of usefulFields) {
|
||||
if (this.isValidTextValueForKey(values, field)) {
|
||||
params[field] = values[field]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,15 @@
|
|||
v-model:value="form.sourcenatipaddress"
|
||||
:placeholder="apiParams.sourcenatipaddress?.description"/>
|
||||
</a-form-item>
|
||||
<a-form-item name="keepMacAddressOnPublicNic" ref="keepMacAddressOnPublicNic" v-if="isAdmin()">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.keep.mac.address.on.public.nic')"
|
||||
:tooltip="apiParams.keepmacaddressonpublicnic?.description"
|
||||
/>
|
||||
</template>
|
||||
<a-switch v-model:checked="form.keepMacAddressOnPublicNic" />
|
||||
</a-form-item>
|
||||
<a-form-item name="start" ref="start">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.start')" :tooltip="apiParams.start.description"/>
|
||||
|
|
@ -287,7 +296,8 @@ export default {
|
|||
initForm () {
|
||||
this.formRef = ref()
|
||||
this.form = reactive({
|
||||
start: true
|
||||
start: true,
|
||||
keepMacAddressOnPublicNic: true
|
||||
})
|
||||
this.rules = reactive({
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
|
|
@ -447,7 +457,7 @@ export default {
|
|||
if (this.loading) return
|
||||
this.formRef.value.validate().then(() => {
|
||||
const values = toRaw(this.form)
|
||||
var params = {}
|
||||
const params = {}
|
||||
if (this.owner?.account) {
|
||||
params.account = this.owner.account
|
||||
params.domainid = this.owner.domainid
|
||||
|
|
@ -460,7 +470,11 @@ export default {
|
|||
if (input === '' || input === null || input === undefined) {
|
||||
continue
|
||||
}
|
||||
params[key] = input
|
||||
if (key === 'keepMacAddressOnPublicNic') {
|
||||
params.keepmacaddressonpublicnic = input
|
||||
} else {
|
||||
params[key] = input
|
||||
}
|
||||
}
|
||||
if (this.selectedVpcOffering.networkmode === 'ROUTED') {
|
||||
if ((values.cidr === undefined || values.cidr === '') && (values.cidrsize === undefined || values.cidrsize === '')) {
|
||||
|
|
|
|||
|
|
@ -208,6 +208,15 @@
|
|||
</template>
|
||||
<a-switch v-model:checked="form.displaynetwork" />
|
||||
</a-form-item>
|
||||
<a-form-item name="keepMacAddressOnPublicNic" ref="keepMacAddressOnPublicNic" v-if="isAdmin() && isUpdatingIsolatedNetwork && !resource?.vpcid">
|
||||
<template #label>
|
||||
<tooltip-label
|
||||
:title="$t('label.keep.mac.address.on.public.nic')"
|
||||
:tooltip="apiParams.keepmacaddressonpublicnic?.description"
|
||||
/>
|
||||
</template>
|
||||
<a-switch v-model:checked="form.keepMacAddressOnPublicNic" />
|
||||
</a-form-item>
|
||||
<a-form-item name="forced" ref="forced" v-if="isAdmin()">
|
||||
<template #label>
|
||||
<tooltip-label :title="$t('label.forced')" :tooltip="apiParams.forced.description"/>
|
||||
|
|
@ -310,7 +319,8 @@ export default {
|
|||
this.form = reactive({
|
||||
displaynetwork: this.resource.displaynetwork,
|
||||
privatemtu: this.resource.privatemtu,
|
||||
publicmtu: this.resource.publicmtu
|
||||
publicmtu: this.resource.publicmtu,
|
||||
keepMacAddressOnPublicNic: this.resource.keepmacaddressonpublicnic
|
||||
})
|
||||
this.rules = reactive({
|
||||
name: [{ required: true, message: this.$t('message.error.required.input') }],
|
||||
|
|
@ -393,18 +403,20 @@ export default {
|
|||
const formRaw = toRaw(this.form)
|
||||
const values = this.handleRemoveFields(formRaw)
|
||||
this.loading = true
|
||||
var manualFields = ['name', 'networkofferingid']
|
||||
const manualFields = ['name', 'networkofferingid']
|
||||
const params = {
|
||||
id: this.resource.id,
|
||||
name: values.name
|
||||
}
|
||||
for (var field in values) {
|
||||
for (const field in values) {
|
||||
if (manualFields.includes(field)) continue
|
||||
var fieldValue = values[field]
|
||||
if (fieldValue !== undefined &&
|
||||
fieldValue !== null &&
|
||||
(!(field in this.resourceValues) || this.resourceValues[field] !== fieldValue)) {
|
||||
params[field] = fieldValue
|
||||
const fieldValue = values[field]
|
||||
if (fieldValue !== undefined && fieldValue !== null && (!(field in this.resourceValues) || this.resourceValues[field] !== fieldValue)) {
|
||||
if (field === 'keepMacAddressOnPublicNic') {
|
||||
params.keepmacaddressonpublicnic = fieldValue
|
||||
} else {
|
||||
params[field] = fieldValue
|
||||
}
|
||||
}
|
||||
}
|
||||
if (values.networkofferingid !== undefined &&
|
||||
|
|
|
|||
|
|
@ -372,9 +372,13 @@ export default {
|
|||
'Group 15': 'modp3072',
|
||||
'Group 16': 'modp4096',
|
||||
'Group 17': 'modp6144',
|
||||
'Group 18': 'modp8192'
|
||||
'Group 18': 'modp8192',
|
||||
'Group 22': 'modp1024s160',
|
||||
'Group 23': 'modp2048s224',
|
||||
'Group 24': 'modp2048s256',
|
||||
'Group 31': 'curve25519'
|
||||
},
|
||||
ikeDhGroupInitialKey: 'Group 5',
|
||||
ikeDhGroupInitialKey: 'Group 31',
|
||||
isSubmitted: false,
|
||||
ikeversion: 'ike',
|
||||
allowedEncryptionAlgos: [],
|
||||
|
|
@ -401,12 +405,12 @@ export default {
|
|||
gateway: '',
|
||||
cidrlist: '',
|
||||
ipsecpsk: '',
|
||||
ikeEncryption: '',
|
||||
ikeHash: '',
|
||||
ikeversion: '',
|
||||
ikeDh: '',
|
||||
espEncryption: '',
|
||||
espHash: '',
|
||||
ikeEncryption: 'aes256',
|
||||
ikeHash: 'sha1',
|
||||
ikeversion: 'ike',
|
||||
ikeDh: 'Group 31(curve 25519)',
|
||||
espEncryption: 'aes256',
|
||||
espHash: 'sha256',
|
||||
perfectForwardSecrecy: 'None',
|
||||
ikelifetime: '86400',
|
||||
esplifetime: '3600',
|
||||
|
|
|
|||
|
|
@ -1265,7 +1265,7 @@ public class NetUtils {
|
|||
if (group == null && policyType.toLowerCase().matches("ike")) {
|
||||
return false; // StrongSwan requires a DH group for the IKE policy
|
||||
}
|
||||
if (group != null && !group.matches("modp1024|modp1536|modp2048|modp3072|modp4096|modp6144|modp8192")) {
|
||||
if (group != null && !group.matches("modp1024|modp1536|modp2048|modp3072|modp4096|modp6144|modp8192|modp1024s160|modp2048s224|modp2048s256|curve25519")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -131,6 +131,10 @@ public class NetUtilsTest {
|
|||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "3des-md5;modp1024"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "3des-sha1;modp3072,aes128-sha1;modp1536"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "3des-sha256;modp3072,aes128-sha512;modp1536"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "aes256-sha256;modp1024s160"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "aes256-sha256;modp2048s224"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "aes256-sha256;modp2048s256"));
|
||||
assertTrue(NetUtils.isValidS2SVpnPolicy("ike", "aes256-sha256;curve25519"));
|
||||
assertFalse(NetUtils.isValidS2SVpnPolicy("ike", "aes128-sha1"));
|
||||
assertFalse(NetUtils.isValidS2SVpnPolicy("ike", "3des-sha1"));
|
||||
assertFalse(NetUtils.isValidS2SVpnPolicy("ike", "3des-sha1,aes256-sha1"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue