Merge remote-tracking branch 'apache/main' into integration-veeam-kvm

This commit is contained in:
Abhishek Kumar 2026-05-07 08:54:28 +05:30
commit ebfe83d2ab
76 changed files with 2463 additions and 1139 deletions

View File

@ -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

View File

@ -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 {

View File

@ -510,4 +510,6 @@ public interface Network extends ControlledEntity, StateObject<Network.State>, I
Integer getPrivateMtu();
Integer getNetworkCidrSize();
boolean getKeepMacAddressOnPublicNic();
}

View File

@ -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",

View File

@ -107,4 +107,6 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity {
String getIp6Dns2();
boolean useRouterIpAsResolver();
boolean getKeepMacAddressOnPublicNic();
}

View File

@ -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

View File

@ -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 " +

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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///////////////////
/////////////////////////////////////////////////////

View File

@ -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///////////////////
/////////////////////////////////////////////////////

View File

@ -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///////////////////
/////////////////////////////////////////////////////

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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>

View File

@ -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);

View File

@ -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);

View File

@ -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())) {

View File

@ -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;

View File

@ -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);

View File

@ -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());
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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`;

View File

@ -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',

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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);
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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;
}

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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());

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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" />

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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));
}
}

View File

@ -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()));
}

View File

@ -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)
*/

View File

@ -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):

View File

@ -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.",

View File

@ -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",

View File

@ -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>

View File

@ -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"

View File

@ -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',

View File

@ -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)"

View File

@ -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]
}

View File

@ -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 === '')) {

View File

@ -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 &&

View File

@ -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',

View File

@ -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;
}
}

View File

@ -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"));