Routed mode: minor improvements and fixes (#9697)

* Routed: add global setting to enable/disable routed mode

* Routed: add unit tests

* Routed: add unit tests RoutedIpv4ManagerImplTest

* PR9697: fix end of files lint error

* PR9697: fix unit tests error with JDK17

* Routed: do not show ROUTED mode when create network/vpc offering if routed is disabled

* Routed: check if routed network is enabled when create ipv4 subnet/bgp peer/ASN range/network/vpc

* Routed: UI bug fix and improvements

* Routed: apply available BGP peers when VR is restarted
This commit is contained in:
Wei Zhou 2024-11-30 08:45:15 +01:00 committed by GitHub
parent 8f63660424
commit 22a6604491
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 1902 additions and 90 deletions

View File

@ -21,6 +21,7 @@ import com.cloud.network.Network;
import com.cloud.network.vpc.Vpc;
import com.cloud.utils.Pair;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.network.BgpPeer;
import java.util.List;
@ -36,4 +37,8 @@ public interface BGPService {
boolean applyBgpPeers(Network network, boolean continueOnError) throws ResourceUnavailableException;
boolean applyBgpPeers(Vpc vpc, boolean continueOnError) throws ResourceUnavailableException;
List<? extends BgpPeer> getBgpPeersForNetwork(Network network);
List<? extends BgpPeer> getBgpPeersForVpc(Vpc vpc);
}

View File

@ -986,6 +986,7 @@ public class ApiConstants {
public static final String ACL_NAME = "aclname";
public static final String NUMBER = "number";
public static final String IS_DYNAMICALLY_SCALABLE = "isdynamicallyscalable";
public static final String ROUTED_MODE_ENABLED = "routedmodeenabled";
public static final String ROUTING = "isrouting";
public static final String ROUTING_MODE = "routingmode";
public static final String MAX_CONNECTIONS = "maxconnections";

View File

@ -157,6 +157,11 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
@Param(description = "AS Number Range")
private String asnRange;
@SerializedName(ApiConstants.ROUTED_MODE_ENABLED)
@Param(description = "true, if routed network/vpc is enabled", since = "4.20.1")
private boolean routedModeEnabled = false;
public ZoneResponse() {
tags = new LinkedHashSet<ResourceTagResponse>();
}
@ -412,4 +417,12 @@ public class ZoneResponse extends BaseResponseWithAnnotations implements SetReso
public String getAsnRange() {
return asnRange;
}
public boolean isRoutedModeEnabled() {
return routedModeEnabled;
}
public void setRoutedModeEnabled(boolean routedModeEnabled) {
this.routedModeEnabled = routedModeEnabled;
}
}

View File

@ -57,6 +57,13 @@ import java.util.List;
public interface RoutedIpv4Manager extends PluggableService, Configurable {
ConfigKey<Boolean> RoutedNetworkVpcEnabled = new ConfigKey<>(ConfigKey.CATEGORY_NETWORK, Boolean.class,
"routed.network.vpc.enabled",
"true",
"If true, the Routed network and VPC are enabled in the zone.",
true,
ConfigKey.Scope.Zone);
ConfigKey<Integer> RoutedNetworkIPv4MaxCidrSize = new ConfigKey<>(ConfigKey.CATEGORY_NETWORK, Integer.class,
"routed.network.ipv4.max.cidr.size", "30", "The maximum value of the cidr size for isolated networks in ROUTED mode",
true, ConfigKey.Scope.Account);
@ -196,4 +203,6 @@ public interface RoutedIpv4Manager extends PluggableService, Configurable {
void removeBgpPeersByAccountId(long accountId);
void removeBgpPeersByDomainId(long domainId);
Boolean isRoutedNetworkVpcEnabled(long zoneId);
}

View File

@ -34,6 +34,7 @@ import org.apache.cloudstack.api.response.ResourceIconResponse;
import org.apache.cloudstack.api.response.ResourceTagResponse;
import org.apache.cloudstack.api.response.ZoneResponse;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;
@ -141,6 +142,8 @@ public class DataCenterJoinDaoImpl extends GenericDaoBase<DataCenterJoinVO, Long
String asRange = asNumberRange.stream().map(range -> range.getStartASNumber() + "-" + range.getEndASNumber()).collect(Collectors.joining(", "));
zoneResponse.setAsnRange(asRange);
zoneResponse.setRoutedModeEnabled(RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(dataCenter.getId()));
zoneResponse.setResourceDetails(ApiDBUtils.getResourceDetails(dataCenter.getId(), ResourceObjectType.Zone));
zoneResponse.setHasAnnotation(annotationDao.hasAnnotations(dataCenter.getUuid(), AnnotationService.EntityType.ZONE.name(),
_accountMgr.isRootAdmin(CallContext.current().getCallingAccount().getId())));

View File

@ -24,6 +24,7 @@ import com.cloud.dc.dao.ASNumberRangeDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
@ -54,6 +55,7 @@ import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
@ -116,6 +118,9 @@ public class BGPServiceImpl implements BGPService {
LOGGER.error(msg);
throw new InvalidParameterException(msg);
}
if (!routedIpv4Manager.isRoutedNetworkVpcEnabled(zoneId)) {
throw new InvalidParameterValueException("Cannot create ASN range as Routed networks and VPCs are not enabled for the zone.");
}
if (startASNumber > endASNumber) {
String msg = "Please specify a valid AS Number range";
LOGGER.error(msg);
@ -391,19 +396,7 @@ public class BGPServiceImpl implements BGPService {
if (gatewayProviderStr != null) {
NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
if (provider != null && provider instanceof BgpServiceProvider) {
List<BgpPeerVO> bgpPeers;
if (network.getVpcId() != null) {
bgpPeers = bgpPeerDao.listNonRevokeByVpcId(network.getVpcId());
} else {
bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(network.getId());
}
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(network.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
List<? extends BgpPeer> bgpPeers = getBgpPeersForNetwork(network);
LOGGER.debug(String.format("Applying BPG Peers for network [%s]: [%s]", network, bgpPeers));
return ((BgpServiceProvider) provider).applyBgpPeers(null, network, bgpPeers);
}
@ -420,14 +413,7 @@ public class BGPServiceImpl implements BGPService {
if (gatewayProviderStr != null) {
NetworkElement provider = networkModel.getElementImplementingProvider(gatewayProviderStr);
if (provider != null && provider instanceof BgpServiceProvider) {
List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId());
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, vpc.getZoneId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
List<? extends BgpPeer> bgpPeers = getBgpPeersForVpc(vpc);
LOGGER.debug(String.format("Applying BPG Peers for VPC [%s]: [%s]", vpc, bgpPeers));
return ((BgpServiceProvider) provider).applyBgpPeers(vpc, null, bgpPeers);
@ -435,4 +421,35 @@ public class BGPServiceImpl implements BGPService {
}
return true;
}
@Override
public List<? extends BgpPeer> getBgpPeersForNetwork(Network network) {
List<BgpPeerVO> bgpPeers;
if (network.getVpcId() != null) {
bgpPeers = bgpPeerDao.listNonRevokeByVpcId(network.getVpcId());
} else {
bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(network.getId());
}
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(network.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
return bgpPeers;
}
@Override
public List<? extends BgpPeer> getBgpPeersForVpc(Vpc vpc) {
List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId());
if (CollectionUtils.isEmpty(bgpPeers)) {
Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId());
List<Long> bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, vpc.getZoneId());
bgpPeers = bgpPeerIds.stream()
.map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId))
.collect(Collectors.toList());
}
return bgpPeers;
}
}

View File

@ -106,6 +106,7 @@ import org.apache.cloudstack.framework.config.impl.ConfigurationVO;
import org.apache.cloudstack.framework.messagebus.MessageBus;
import org.apache.cloudstack.framework.messagebus.MessageSubscriber;
import org.apache.cloudstack.framework.messagebus.PublishScope;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.query.QueryService;
import org.apache.cloudstack.region.PortableIp;
import org.apache.cloudstack.region.PortableIpDao;
@ -6673,6 +6674,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
throw new InvalidParameterValueException("networkMode should be set only for Isolated network offerings");
}
if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.value()) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key()));
}
if (zoneIds != null) {
for (Long zoneId: zoneIds) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed networks in zone (ID: %s)", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key(), zoneId));
}
}
}
boolean useVirtualRouterOnly = true;
for (Service service : serviceProviderMap.keySet()) {
Set<Provider> providers = serviceProviderMap.get(service);

View File

@ -1384,7 +1384,7 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
}
void validateNetworkCidrSize(Account caller, Integer cidrSize, String cidr, NetworkOffering networkOffering, long accountId) {
void validateNetworkCidrSize(Account caller, Integer cidrSize, String cidr, NetworkOffering networkOffering, long accountId, long zoneId) {
if (!GuestType.Isolated.equals(networkOffering.getGuestType())) {
if (cidrSize != null) {
throw new InvalidParameterValueException("network cidr size is only applicable on Isolated networks");
@ -1405,11 +1405,11 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
if (cidrSize == null) {
throw new InvalidParameterValueException("network cidr or cidr size is required for Isolated networks with ROUTED mode");
}
Integer maxCidrSize = routedIpv4Manager.RoutedNetworkIPv4MaxCidrSize.valueIn(accountId);
Integer maxCidrSize = RoutedIpv4Manager.RoutedNetworkIPv4MaxCidrSize.valueIn(accountId);
if (cidrSize > maxCidrSize) {
throw new InvalidParameterValueException("network cidr size cannot be bigger than maximum cidr size " + maxCidrSize);
}
Integer minCidrSize = routedIpv4Manager.RoutedNetworkIPv4MinCidrSize.valueIn(accountId);
Integer minCidrSize = RoutedIpv4Manager.RoutedNetworkIPv4MinCidrSize.valueIn(accountId);
if (cidrSize < minCidrSize) {
throw new InvalidParameterValueException("network cidr size cannot be smaller than minimum cidr size " + minCidrSize);
}
@ -1651,11 +1651,16 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService, C
}
}
if (NetworkOffering.NetworkMode.ROUTED.equals(ntwkOff.getNetworkMode())
&& !routedIpv4Manager.isRoutedNetworkVpcEnabled(zone.getId())) {
throw new InvalidParameterValueException("Routed network is not enabled in this zone");
}
if (isNonVpcNetworkSupportingDynamicRouting(ntwkOff) && ntwkOff.isSpecifyAsNumber() && asNumber == null) {
throw new InvalidParameterValueException("AS number is required for the network but not passed.");
}
validateNetworkCidrSize(caller, networkCidrSize, cidr, ntwkOff, owner.getAccountId());
validateNetworkCidrSize(caller, networkCidrSize, cidr, ntwkOff, owner.getAccountId(), zone.getId());
validateSharedNetworkRouterIPs(gateway, startIP, endIP, netmask, routerIPv4, routerIPv6, startIPv6, endIPv6, ip6Cidr, ntwkOff);

View File

@ -65,10 +65,8 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.apache.cloudstack.lb.ApplicationLoadBalancerRuleVO;
import org.apache.cloudstack.lb.dao.ApplicationLoadBalancerRuleDao;
import org.apache.cloudstack.managed.context.ManagedContextRunnable;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
import org.apache.cloudstack.network.dao.BgpPeerNetworkMapDao;
import org.apache.cloudstack.network.topology.NetworkTopology;
import org.apache.cloudstack.network.topology.NetworkTopologyContext;
import org.apache.cloudstack.utils.CloudStackVersion;
@ -114,6 +112,7 @@ import com.cloud.api.query.dao.DomainRouterJoinDao;
import com.cloud.api.query.dao.UserVmJoinDao;
import com.cloud.api.query.vo.DomainRouterJoinVO;
import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.bgp.BGPService;
import com.cloud.cluster.ManagementServerHostVO;
import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.configuration.Config;
@ -348,9 +347,7 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
@Inject
RoutedIpv4Manager routedIpv4Manager;
@Inject
BgpPeerDao bgpPeerDao;
@Inject
BgpPeerNetworkMapDao bgpPeerNetworkMapDao;
BGPService bgpService;
private int _routerRamSize;
private int _routerCpuMHz;
@ -2508,12 +2505,12 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
if (guestNetwork.getVpcId() != null) {
final Vpc vpc = _vpcDao.findById(guestNetwork.getVpcId());
if (routedIpv4Manager.isDynamicRoutedVpc(vpc)) {
final List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByVpcId(guestNetwork.getVpcId());
List<? extends BgpPeer> bgpPeers = bgpService.getBgpPeersForVpc(vpc);
_commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork);
}
} else {
if (routedIpv4Manager.isDynamicRoutedNetwork(guestNetwork)) {
final List<BgpPeerVO> bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(guestNetworkId);
List<? extends BgpPeer> bgpPeers = bgpService.getBgpPeersForNetwork(guestNetwork);
_commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork);
}
}

View File

@ -500,6 +500,18 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
}
networkMode = NetworkOffering.NetworkMode.valueOf(networkModeStr);
}
if (NetworkOffering.NetworkMode.ROUTED.equals(networkMode)) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.value()) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed VPCs", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key()));
}
if (zoneIds != null) {
for (Long zoneId: zoneIds) {
if (!RoutedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException(String.format("Configuration %s needs to be enabled for Routed VPCs in zone (ID: %s)", RoutedIpv4Manager.RoutedNetworkVpcEnabled.key(), zoneId));
}
}
}
}
boolean specifyAsNumber = cmd.getSpecifyAsNumber();
String routingModeString = cmd.getRoutingMode();
@ -1161,12 +1173,17 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
throw ex;
}
if (NetworkOffering.NetworkMode.ROUTED.equals(vpcOff.getNetworkMode())
&& !routedIpv4Manager.RoutedNetworkVpcEnabled.valueIn(zoneId)) {
throw new InvalidParameterValueException("Routed VPC is not enabled in this zone");
}
if (NetworkOffering.RoutingMode.Dynamic.equals(vpcOff.getRoutingMode()) && vpcOff.isSpecifyAsNumber() && asNumber == null) {
throw new InvalidParameterValueException("AS number is required for the VPC but not passed.");
}
// Validate VPC cidr/cidrsize
validateVpcCidrSize(caller, owner.getAccountId(), vpcOff, cidr, cidrSize);
validateVpcCidrSize(caller, owner.getAccountId(), vpcOff, cidr, cidrSize, zoneId);
// Validate BGP peers
if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
@ -1251,7 +1268,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis
return newVpc;
}
private void validateVpcCidrSize(Account caller, long accountId, VpcOffering vpcOffering, String cidr, Integer cidrSize) {
private void validateVpcCidrSize(Account caller, long accountId, VpcOffering vpcOffering, String cidr, Integer cidrSize, long zoneId) {
if (ObjectUtils.allNull(cidr, cidrSize)) {
throw new InvalidParameterValueException("VPC cidr or cidr size must be specified");
}

View File

@ -68,11 +68,6 @@ import org.apache.cloudstack.api.command.admin.affinitygroup.UpdateVMAffinityGro
import org.apache.cloudstack.api.command.admin.alert.GenerateAlertCmd;
import org.apache.cloudstack.api.command.admin.autoscale.CreateCounterCmd;
import org.apache.cloudstack.api.command.admin.autoscale.DeleteCounterCmd;
import org.apache.cloudstack.api.command.admin.bgp.CreateASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.DeleteASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.ListASNRangesCmd;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.api.command.admin.bgp.ReleaseASNumberCmd;
import org.apache.cloudstack.api.command.admin.cluster.AddClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.DeleteClusterCmd;
import org.apache.cloudstack.api.command.admin.cluster.ListClustersCmd;
@ -4017,12 +4012,6 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
cmdList.add(RemoveSecondaryStorageSelectorCmd.class);
cmdList.add(ListAffectedVmsForStorageScopeChangeCmd.class);
cmdList.add(CreateASNRangeCmd.class);
cmdList.add(ListASNRangesCmd.class);
cmdList.add(DeleteASNRangeCmd.class);
cmdList.add(ListASNumbersCmd.class);
cmdList.add(ReleaseASNumberCmd.class);
// Out-of-band management APIs for admins
cmdList.add(EnableOutOfBandManagementForHostCmd.class);
cmdList.add(DisableOutOfBandManagementForHostCmd.class);

View File

@ -57,6 +57,10 @@ import com.cloud.utils.db.TransactionStatus;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
import org.apache.cloudstack.api.command.admin.bgp.CreateASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.DeleteASNRangeCmd;
import org.apache.cloudstack.api.command.admin.bgp.ListASNRangesCmd;
import org.apache.cloudstack.api.command.admin.bgp.ReleaseASNumberCmd;
import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForZoneCmd;
import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForGuestNetworkCmd;
import org.apache.cloudstack.api.command.admin.network.DedicateIpv4SubnetForZoneCmd;
@ -74,6 +78,7 @@ import org.apache.cloudstack.api.command.admin.network.bgp.DeleteBgpPeerCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.ListBgpPeersCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.ReleaseDedicatedBgpPeerCmd;
import org.apache.cloudstack.api.command.admin.network.bgp.UpdateBgpPeerCmd;
import org.apache.cloudstack.api.command.user.bgp.ListASNumbersCmd;
import org.apache.cloudstack.api.command.user.network.routing.CreateRoutingFirewallRuleCmd;
import org.apache.cloudstack.api.command.user.network.routing.DeleteRoutingFirewallRuleCmd;
import org.apache.cloudstack.api.command.user.network.routing.ListRoutingFirewallRulesCmd;
@ -154,6 +159,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
@Override
public ConfigKey<?>[] getConfigKeys() {
return new ConfigKey[] {
RoutedNetworkVpcEnabled,
RoutedNetworkIPv4MaxCidrSize, RoutedNetworkIPv4MinCidrSize, RoutedIPv4NetworkCidrAutoAllocationEnabled,
RoutedVpcIPv4MaxCidrSize, RoutedVpcIPv4MinCidrSize, UseSystemBgpPeers
};
@ -162,19 +168,25 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
@Override
public List<Class<?>> getCommands() {
final List<Class<?>> cmdList = new ArrayList<Class<?>>();
if (!RoutedNetworkVpcEnabled.value()) {
return cmdList;
}
cmdList.add(CreateIpv4SubnetForZoneCmd.class);
cmdList.add(DeleteIpv4SubnetForZoneCmd.class);
cmdList.add(ListIpv4SubnetsForZoneCmd.class);
cmdList.add(UpdateIpv4SubnetForZoneCmd.class);
cmdList.add(DedicateIpv4SubnetForZoneCmd.class);
cmdList.add(ReleaseDedicatedIpv4SubnetForZoneCmd.class);
cmdList.add(CreateIpv4SubnetForGuestNetworkCmd.class);
cmdList.add(ListIpv4SubnetsForGuestNetworkCmd.class);
cmdList.add(DeleteIpv4SubnetForGuestNetworkCmd.class);
cmdList.add(CreateRoutingFirewallRuleCmd.class);
cmdList.add(ListRoutingFirewallRulesCmd.class);
cmdList.add(UpdateRoutingFirewallRuleCmd.class);
cmdList.add(DeleteRoutingFirewallRuleCmd.class);
cmdList.add(CreateBgpPeerCmd.class);
cmdList.add(DeleteBgpPeerCmd.class);
cmdList.add(ListBgpPeersCmd.class);
@ -183,6 +195,13 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
cmdList.add(ReleaseDedicatedBgpPeerCmd.class);
cmdList.add(ChangeBgpPeersForNetworkCmd.class);
cmdList.add(ChangeBgpPeersForVpcCmd.class);
cmdList.add(CreateASNRangeCmd.class);
cmdList.add(ListASNRangesCmd.class);
cmdList.add(DeleteASNRangeCmd.class);
cmdList.add(ListASNumbersCmd.class);
cmdList.add(ReleaseASNumberCmd.class);
return cmdList;
}
@ -198,6 +217,8 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
throw new InvalidParameterValueException("Invalid IPv4 subnet: " + subnet);
}
checkIfRoutedNetworkVpcEnabled(zoneId);
// check conflicts
List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId);
checkConflicts(existingSubnets, subnet, null);
@ -319,7 +340,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return dataCenterIpv4GuestSubnetDao.findById(subnetId);
}
private void checkConflicts(List<DataCenterIpv4GuestSubnetVO> existingSubnets, String newSubnet, Long ignoreSubnetId) {
protected void checkConflicts(List<DataCenterIpv4GuestSubnetVO> existingSubnets, String newSubnet, Long ignoreSubnetId) {
for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) {
if ((ignoreSubnetId == null || existing.getId() != ignoreSubnetId) && NetUtils.isNetworksOverlap(existing.getSubnet(), newSubnet)) {
throw new InvalidParameterValueException(String.format("Existing zone subnet %s has overlap with: %s", existing.getSubnet(), newSubnet));
@ -553,11 +574,6 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
response.setParentSubnet(parent.getSubnet());
zoneId = parent.getDataCenterId();
}
} else if (subnet.getNetworkId() != null) {
Network network = ApiDBUtils.findNetworkById(subnet.getNetworkId());
if (network != null) {
zoneId = network.getDataCenterId();
}
}
if (zoneId != null) {
DataCenter zone = ApiDBUtils.findZoneById(zoneId);
@ -590,7 +606,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(vpcCidrSize, vpc.getDomainId(), vpc.getAccountId(), vpc.getZoneId());
}
private Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
protected Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
validateNetworkCidrSize(ownerAccountId, cidrSize);
List<DataCenterIpv4GuestSubnetVO> subnets = getZoneSubnetsForAccount(ownerDomainId, ownerAccountId, zoneId);
for (DataCenterIpv4GuestSubnetVO subnet : subnets) {
@ -602,7 +618,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null;
}
private Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, DataCenterIpv4GuestSubnetVO subnet) {
protected Ipv4GuestSubnetNetworkMap getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(Integer cidrSize, DataCenterIpv4GuestSubnetVO subnet) {
Ipv4GuestSubnetNetworkMap map = ipv4GuestSubnetNetworkMapDao.findFirstAvailable(subnet.getId(), cidrSize);
if (map != null) {
return map;
@ -615,7 +631,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null;
}
private void getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(String networkCidr, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
protected void getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(String networkCidr, Long ownerDomainId, Long ownerAccountId, Long zoneId) {
Ipv4GuestSubnetNetworkMapVO subnetMap = ipv4GuestSubnetNetworkMapDao.findBySubnet(networkCidr);
if (subnetMap != null) {
// check if the subnet is in use
@ -650,7 +666,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
}
}
private DataCenterIpv4GuestSubnet getParentOfNetworkCidr(Long zoneId, String networkCidr) {
protected DataCenterIpv4GuestSubnet getParentOfNetworkCidr(Long zoneId, String networkCidr) {
List<DataCenterIpv4GuestSubnetVO> existingSubnets = dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId);
for (DataCenterIpv4GuestSubnetVO existing : existingSubnets) {
if (NetUtils.isNetworkAWithinNetworkB(networkCidr, existing.getSubnet())) {
@ -689,14 +705,22 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
private List<DataCenterIpv4GuestSubnetVO> getZoneSubnetsForAccount(long domainId, long accountId, long zoneId) {
// Get dedicated guest subnets for the account
List<DataCenterIpv4GuestSubnetVO> subnets = dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId);
List<DataCenterIpv4GuestSubnetVO> subnets = new ArrayList<>();
subnets.addAll(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId));
subnets.addAll(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndDomainId(zoneId, domainId));
// Get non-dedicated zone guest subnets for the account
subnets.addAll(dataCenterIpv4GuestSubnetDao.listNonDedicatedByDataCenterId(zoneId));
return subnets;
}
private Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) {
protected Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) {
String networkCidr = createIpv4SubnetStringFromParentSubnet(parent, networkCidrSize);
// create DB record
Ipv4GuestSubnetNetworkMapVO subnetMap = new Ipv4GuestSubnetNetworkMapVO(parent.getId(), NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
}
protected String createIpv4SubnetStringFromParentSubnet(DataCenterIpv4GuestSubnet parent, Integer networkCidrSize) {
DataCenterIpv4GuestSubnetVO subnetVO = dataCenterIpv4GuestSubnetDao.findById(parent.getId());
if (subnetVO == null) {
throw new InvalidParameterValueException(String.format("Invalid subnet ID: %s", parent.getId()));
@ -733,9 +757,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
if (networkCidr == null) {
throw new CloudRuntimeException("Failed to automatically allocate a subnet with specified cidrsize");
}
// create DB record
Ipv4GuestSubnetNetworkMapVO subnetMap = new Ipv4GuestSubnetNetworkMapVO(parent.getId(), NetUtils.transformCidr(networkCidr), null, State.Free);
return ipv4GuestSubnetNetworkMapDao.persist(subnetMap);
return networkCidr;
}
private String getFreeNetworkCidr(List<Pair<Long, Integer>> subnetsInFreeIpRanges, int networkCidrSize) {
@ -752,7 +774,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return null;
}
private Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, String networkCidr) {
protected Ipv4GuestSubnetNetworkMap createIpv4SubnetFromParentSubnet(DataCenterIpv4GuestSubnet parent, String networkCidr) {
// Validate the network cidr
if (!NetUtils.isNetworkAWithinNetworkB(networkCidr, parent.getSubnet())) {
throw new InvalidParameterValueException(String.format("networkCidr %s is not within parent cidr: %s", networkCidr, parent.getSubnet()));
@ -941,9 +963,11 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
}
if (!FirewallRule.Purpose.Firewall.equals(rule.getPurpose())) {
logger.error(String.format("Cannot apply routing firewall rule with ID: %d as purpose %s is not %s", id, rule.getPurpose(), FirewallRule.Purpose.Firewall));
return false;
}
logger.debug(String.format("Applying routing firewall rules for rule with ID: %s", rule.getUuid()));
List<FirewallRuleVO> rules = firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Egress);
List<FirewallRuleVO> rules = new ArrayList<>();
rules.addAll(firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Egress));
rules.addAll(firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Ingress));
return firewallManager.applyFirewallRules(rules, false, CallContext.current().getCallingAccount());
}
@ -1014,6 +1038,8 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
String password = createBgpPeerCmd.getPassword();
Map<String, String> detailsStr = createBgpPeerCmd.getDetails();
checkIfRoutedNetworkVpcEnabled(zoneId);
if (ObjectUtils.allNull(ip4Address, ip6Address)) {
throw new InvalidParameterValueException("At least one of IPv4 and IPv6 address must be specified.");
}
@ -1398,7 +1424,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return changeBgpPeersForNetworkInternal(network, null);
}
private Network changeBgpPeersForNetworkInternal(Network network, List<Long> bgpPeerIds) {
protected Network changeBgpPeersForNetworkInternal(Network network, List<Long> bgpPeerIds) {
final List<Long> bgpPeerIdsToBeAdded;
if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds);
@ -1529,7 +1555,7 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
return bgpPeerDao.listAvailableBgpPeerIdsForAccount(zoneId, owner.getDomainId(), owner.getId(), UseSystemBgpPeers.valueIn(owner.getId()));
}
private Vpc changeBgpPeersForVpcInternal(Vpc vpc, List<Long> bgpPeerIds) {
protected Vpc changeBgpPeersForVpcInternal(Vpc vpc, List<Long> bgpPeerIds) {
final List<Long> bgpPeerIdsToBeAdded;
if (CollectionUtils.isNotEmpty(bgpPeerIds)) {
bgpPeerIdsToBeAdded = new ArrayList<>(bgpPeerIds);
@ -1618,4 +1644,15 @@ public class RoutedIpv4ManagerImpl extends ComponentLifecycleBase implements Rou
public void removeBgpPeersByDomainId(long domainId) {
bgpPeerDao.removeByDomainId(domainId);
}
@Override
public Boolean isRoutedNetworkVpcEnabled(long zoneId) {
return RoutedNetworkVpcEnabled.valueIn(zoneId);
}
private void checkIfRoutedNetworkVpcEnabled(long zoneId) {
if (!isRoutedNetworkVpcEnabled(zoneId)) {
throw new InvalidParameterValueException("Routed networks and VPCs are not enabled for the zone.");
}
}
}

View File

@ -18,14 +18,39 @@
package com.cloud.bgp;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkServiceMapDao;
import com.cloud.network.element.VirtualRouterElement;
import com.cloud.network.element.VpcVirtualRouterElement;
import com.cloud.network.vpc.Vpc;
import com.cloud.network.vpc.dao.VpcServiceMapDao;
import com.cloud.user.AccountVO;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.network.dao.BgpPeerDao;
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;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class BGPServiceImplTest {
@ -33,6 +58,24 @@ public class BGPServiceImplTest {
@InjectMocks
BGPServiceImpl bGPServiceImplSpy = new BGPServiceImpl();
@Mock
RoutedIpv4Manager routedIpv4Manager;
@Mock
NetworkServiceMapDao ntwkSrvcDao;
@Mock
NetworkModel networkModel;
@Mock
BgpPeerDao bgpPeerDao;
@Mock
AccountDao accountDao;
@Mock
VpcServiceMapDao vpcServiceMapDao;
@Test
public void testASNumbersOverlap() {
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,2,3,4), false);
@ -42,4 +85,92 @@ public class BGPServiceImplTest {
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(1,4,2,3), true);
Assert.assertEquals(bGPServiceImplSpy.isASNumbersOverlap(3,4,1,2), false);
}
@Test
public void testApplyBgpPeersForIsolatedNetwork() throws ResourceUnavailableException {
Long networkId = 11L;
Network network = Mockito.mock(Network.class);
when(network.getId()).thenReturn(networkId);
when(network.getVpcId()).thenReturn(null);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
when(ntwkSrvcDao.getProviderForServiceInNetwork(networkId, Network.Service.Gateway)).thenReturn("VirtualRouter");
VirtualRouterElement virtualRouterElement = Mockito.mock(VirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VirtualRouter")).thenReturn(virtualRouterElement);
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1);
when(bgpPeerDao.listNonRevokeByNetworkId(networkId)).thenReturn(bgpPeers);
doReturn(true).when(virtualRouterElement).applyBgpPeers(null, network, bgpPeers);
bGPServiceImplSpy.applyBgpPeers(network, true);
verify(virtualRouterElement).applyBgpPeers(null, network, bgpPeers);
}
@Test
public void testApplyBgpPeersForVpcTier() throws ResourceUnavailableException {
Long networkId = 11L;
Long accountId = 12L;
Long vpcId = 13L;
Long zoneId = 1L;
Network network = Mockito.mock(Network.class);
when(network.getId()).thenReturn(networkId);
when(network.getVpcId()).thenReturn(vpcId);
when(network.getAccountId()).thenReturn(accountId);
when(network.getDataCenterId()).thenReturn(zoneId);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
when(ntwkSrvcDao.getProviderForServiceInNetwork(networkId, Network.Service.Gateway)).thenReturn("VirtualRouter");
VirtualRouterElement virtualRouterElement = Mockito.mock(VirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VirtualRouter")).thenReturn(virtualRouterElement);
when(bgpPeerDao.listNonRevokeByVpcId(vpcId)).thenReturn(new ArrayList<>());
AccountVO owner = Mockito.mock(AccountVO.class);
when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(owner);
Long bgpPeerId1 = 14L;
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
when(bgpPeerDao.findById(bgpPeerId1)).thenReturn(bgpPeer1);
when(routedIpv4Manager.getBgpPeerIdsForAccount(owner, zoneId)).thenReturn(Arrays.asList(bgpPeerId1));
doReturn(true).when(virtualRouterElement).applyBgpPeers(eq(null), eq(network), any());
bGPServiceImplSpy.applyBgpPeers(network, true);
verify(virtualRouterElement).applyBgpPeers(eq(null), eq(network), any());
}
@Test
public void testApplyBgpPeersForVpcWithBgpPeers() throws ResourceUnavailableException {
Long accountId = 12L;
Long vpcId = 13L;
Long zoneId = 1L;
Vpc vpc = Mockito.mock(Vpc.class);
when(vpc.getId()).thenReturn(vpcId);
when(vpc.getAccountId()).thenReturn(accountId);
when(vpc.getZoneId()).thenReturn(zoneId);
when(routedIpv4Manager.isDynamicRoutedVpc(vpc)).thenReturn(true);
when(vpcServiceMapDao.getProviderForServiceInVpc(vpcId, Network.Service.Gateway)).thenReturn("VPCVirtualRouter");
VpcVirtualRouterElement vpcVirtualRouterElement = Mockito.mock(VpcVirtualRouterElement.class);
when(networkModel.getElementImplementingProvider("VPCVirtualRouter")).thenReturn(vpcVirtualRouterElement);
when(bgpPeerDao.listNonRevokeByVpcId(vpcId)).thenReturn(new ArrayList<>());
AccountVO owner = Mockito.mock(AccountVO.class);
when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(owner);
Long bgpPeerId1 = 14L;
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
when(bgpPeerDao.findById(bgpPeerId1)).thenReturn(bgpPeer1);
when(routedIpv4Manager.getBgpPeerIdsForAccount(owner, zoneId)).thenReturn(Arrays.asList(bgpPeerId1));
doReturn(true).when(vpcVirtualRouterElement).applyBgpPeers(eq(vpc), eq(null), any());
bGPServiceImplSpy.applyBgpPeers(vpc, true);
verify(vpcVirtualRouterElement).applyBgpPeers(eq(vpc), eq(null), any());
}
}

View File

@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
@ -29,6 +30,7 @@ import static org.mockito.Mockito.doReturn;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
@ -46,6 +48,7 @@ import com.cloud.user.dao.AccountDao;
import com.cloud.utils.net.Ip;
import com.cloud.exception.InsufficientAddressCapacityException;
import org.apache.cloudstack.alert.AlertService;
import org.apache.cloudstack.api.command.admin.network.CreateNetworkCmdByAdmin;
import org.apache.cloudstack.api.command.user.address.UpdateQuarantinedIpCmd;
import org.apache.cloudstack.api.command.user.network.CreateNetworkCmd;
import org.apache.cloudstack.api.command.user.network.UpdateNetworkCmd;
@ -753,13 +756,14 @@ public class NetworkServiceImplTest {
}
@Test
public void testCreateIpv4RoutedNetwork() throws InsufficientCapacityException, ResourceAllocationException {
public void testCreateIpv4RoutedNetwork() {
registerCallContext();
CreateNetworkCmd cmd = Mockito.mock(CreateNetworkCmd.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
doNothing().when(routedIpv4Manager).assignIpv4SubnetToNetwork(nullable(Network.class));
@ -777,6 +781,92 @@ public class NetworkServiceImplTest {
Mockito.verify(routedIpv4Manager).assignIpv4SubnetToNetwork(nullable(Network.class));
}
@Test
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure1() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, true, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("The BGP peers of VPC tiers will inherit from the VPC, do not add separately.", ex.getMessage());
}
}
@Test
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure2() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("The network offering does not support Dynamic routing", ex.getMessage());
}
}
@Test
public void testCreateIpv4RoutedNetworkWithBgpPeersFailure3() {
registerCallContext();
CreateNetworkCmdByAdmin cmd = Mockito.mock(CreateNetworkCmdByAdmin.class);
Mockito.when(cmd.getCidrSize()).thenReturn(24);
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
Mockito.when(cmd.getBgpPeerIds()).thenReturn(bgpPeerIds);
prepareCreateNetworkDnsMocks(cmd, Network.GuestType.Isolated, false, false, true);
when(networkOfferingVO.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
when(networkOfferingVO.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
when(routedIpv4Manager.isRoutedNetworkVpcEnabled(nullable(Long.class))).thenReturn(true);
when(routedIpv4Manager.isVirtualRouterGateway(networkOfferingVO)).thenReturn(true);
when(routedIpv4Manager.isDynamicRoutedNetwork(networkOfferingVO)).thenReturn(true);
doThrow(new InvalidParameterValueException("validation error")).when(routedIpv4Manager).validateBgpPeers(nullable(Account.class), nullable(Long.class), any(List.class));
DataCenterVO zone = Mockito.mock(DataCenterVO.class);
when(cmd.getZoneId()).thenReturn(zoneId);
when(dcDao.findById(zoneId)).thenReturn(zone);
when(zone.getId()).thenReturn(zoneId);
try {
service.createGuestNetwork(cmd);
} catch (InsufficientCapacityException | ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
} catch (InvalidParameterValueException ex) {
Assert.assertEquals("validation error", ex.getMessage());
}
}
@Test
public void testCheckAndUpdateNetworkResetSuccess() {
NetworkVO networkVO = new NetworkVO();

View File

@ -65,6 +65,7 @@ import com.cloud.network.router.VirtualRouter;
import com.cloud.network.router.VirtualRouter.RedundantState;
import com.cloud.network.router.VpcVirtualNetworkApplianceManagerImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.offering.NetworkOffering;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.offerings.dao.NetworkOfferingDao;
@ -98,7 +99,11 @@ import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.router.deployment.RouterDeploymentDefinitionBuilder;
import org.apache.cloudstack.network.topology.NetworkTopology;
import org.apache.cloudstack.network.topology.NetworkTopologyContext;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -111,6 +116,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -122,6 +128,7 @@ import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
@ -178,6 +185,7 @@ public class VirtualRouterElementTest {
@Mock private ResourceManager _resourceMgr;
@Mock private UserVmManager _userVmMgr;
@Mock private VirtualMachineManager _itMgr;
@Mock private NetworkTopologyContext networkTopologyContext;
@InjectMocks
private RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder;
@ -517,4 +525,52 @@ public class VirtualRouterElementTest {
assertTrue(counterNames.contains(AutoScaleCounterType.Memory.getName()));
assertTrue(counterNames.contains(AutoScaleCounterType.VirtualRouter.getName()));
}
@Test
public void testApplyBgpPeersForVpc() throws ResourceUnavailableException {
List<BgpPeerVO> bgpPeers = Mockito.mock(List.class);
VpcVO vpc = Mockito.mock(VpcVO.class);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
when(router.getState()).thenReturn(VirtualMachine.State.Running);
long zoneId = 10L;
long vpcId = 11L;
when(vpc.getId()).thenReturn(vpcId);
when(vpc.getZoneId()).thenReturn(zoneId);
when(_routerDao.listByVpcId(vpcId)).thenReturn(Arrays.asList(router));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(_dcDao.findById(zoneId)).thenReturn(dc);
NetworkTopology networkTopology = Mockito.mock(NetworkTopology.class);
when(networkTopologyContext.retrieveNetworkTopology(dc)).thenReturn(networkTopology);
doReturn(true).when(networkTopology).applyBgpPeers(any(), any(), any());
boolean result = virtualRouterElement.applyBgpPeers(vpc, null, bgpPeers);
Assert.assertTrue(result);
verify(networkTopology).applyBgpPeers(any(), any(), any());
}
@Test
public void testApplyBgpPeersForNetwork() throws ResourceUnavailableException {
List<BgpPeerVO> bgpPeers = Mockito.mock(List.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
when(router.getState()).thenReturn(VirtualMachine.State.Running);
long zoneId = 10L;
long networkId = 11L;
when(network.getId()).thenReturn(networkId);
when(network.getDataCenterId()).thenReturn(zoneId);
when(_routerDao.listByNetworkAndRole(networkId, VirtualRouter.Role.VIRTUAL_ROUTER)).thenReturn(Arrays.asList(router));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(_dcDao.findById(zoneId)).thenReturn(dc);
NetworkTopology networkTopology = Mockito.mock(NetworkTopology.class);
when(networkTopologyContext.retrieveNetworkTopology(dc)).thenReturn(networkTopology);
doReturn(true).when(networkTopology).applyBgpPeers(any(), any(), any());
boolean result = virtualRouterElement.applyBgpPeers(null, network, bgpPeers);
Assert.assertTrue(result);
verify(networkTopology).applyBgpPeers(any(), any(), any());
}
}

View File

@ -17,12 +17,15 @@
package com.cloud.network.router;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.routing.SetBgpPeersCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.agent.manager.Commands;
import com.cloud.configuration.ConfigurationManager;
import com.cloud.dc.ASNumberVO;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.VlanVO;
import com.cloud.dc.dao.ASNumberDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.network.NetworkModel;
@ -43,6 +46,8 @@ import com.cloud.utils.net.Ip;
import com.cloud.vm.NicVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.NicDao;
import org.apache.cloudstack.network.BgpPeerVO;
import org.apache.cloudstack.network.dao.BgpPeerDetailsDao;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -55,10 +60,13 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class CommandSetupHelperTest {
@ -88,6 +96,10 @@ public class CommandSetupHelperTest {
RouterControlHelper routerControlHelper;
@Mock
DataCenterDao dcDao;
@Mock
ASNumberDao asNumberDao;
@Mock
BgpPeerDetailsDao bgpPeerDetailsDao;
@Before
public void setUp() {
@ -173,24 +185,90 @@ public class CommandSetupHelperTest {
VpcVO vpc = new VpcVO();
DataCenterVO dc = new DataCenterVO(1L, null, null, null, null, null, null, null, null, null, DataCenter.NetworkType.Advanced, null, null);
Mockito.when(router.getId()).thenReturn(14L);
Mockito.when(router.getDataCenterId()).thenReturn(4L);
Mockito.when(nicDao.listByVmId(ArgumentMatchers.anyLong())).thenReturn(List.of(nicVO));
Mockito.when(networkDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkVO);
Mockito.when(ipAddressDao.listByAssociatedVpc(ArgumentMatchers.anyLong(), ArgumentMatchers.nullable(Boolean.class))).thenReturn(userIps);
Mockito.when(vlanDao.findById(ArgumentMatchers.anyLong())).thenReturn(vlanVO);
Mockito.when(networkModel.getNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
Mockito.when(networkModel.getNetwork(ArgumentMatchers.anyLong())).thenReturn(networkVO);
Mockito.when(networkOfferingDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkOfferingVO);
Mockito.when(configurationManager.getNetworkOfferingNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
Mockito.when(networkModel.isSecurityGroupSupportedInNetwork(networkVO)).thenReturn(false);
Mockito.when(networkOfferingDetailsDao.getNtwkOffDetails(ArgumentMatchers.anyLong())).thenReturn(details);
Mockito.when(networkDetailsDao.findDetail(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString())).thenReturn(null);
Mockito.when(vpcDao.findById(ArgumentMatchers.anyLong())).thenReturn(vpc);
Mockito.when(routerControlHelper.getRouterControlIp(ArgumentMatchers.anyLong())).thenReturn("10.1.11.101");
Mockito.when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dc);
when(router.getId()).thenReturn(14L);
when(router.getDataCenterId()).thenReturn(4L);
when(nicDao.listByVmId(ArgumentMatchers.anyLong())).thenReturn(List.of(nicVO));
when(networkDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkVO);
when(ipAddressDao.listByAssociatedVpc(ArgumentMatchers.anyLong(), ArgumentMatchers.nullable(Boolean.class))).thenReturn(userIps);
when(vlanDao.findById(ArgumentMatchers.anyLong())).thenReturn(vlanVO);
when(networkModel.getNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
when(networkModel.getNetwork(ArgumentMatchers.anyLong())).thenReturn(networkVO);
when(networkOfferingDao.findById(ArgumentMatchers.anyLong())).thenReturn(networkOfferingVO);
when(configurationManager.getNetworkOfferingNetworkRate(ArgumentMatchers.anyLong(), ArgumentMatchers.anyLong())).thenReturn(1200);
when(networkModel.isSecurityGroupSupportedInNetwork(networkVO)).thenReturn(false);
when(networkOfferingDetailsDao.getNtwkOffDetails(ArgumentMatchers.anyLong())).thenReturn(details);
when(networkDetailsDao.findDetail(ArgumentMatchers.anyLong(), ArgumentMatchers.anyString())).thenReturn(null);
when(vpcDao.findById(ArgumentMatchers.anyLong())).thenReturn(vpc);
when(routerControlHelper.getRouterControlIp(ArgumentMatchers.anyLong())).thenReturn("10.1.11.101");
when(dcDao.findById(ArgumentMatchers.anyLong())).thenReturn(dc);
commandSetupHelper.createVpcAssociatePublicIPCommands(router, pubIpList, commands, vlanMacAddress);
Assert.assertEquals(2, commands.size());
}
@Test
public void testCreateBgpPeersCommandsForNetwork() {
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
BgpPeerVO bgpPeer2 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1, bgpPeer2);
Commands cmds = new Commands(Command.OnError.Stop);
VirtualRouter router = Mockito.mock(VirtualRouter.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
long zoneId = 10L;
long networkId = 11L;
when(router.getDataCenterId()).thenReturn(zoneId);
when(router.getVpcId()).thenReturn(null);
when(network.getId()).thenReturn(networkId);
ASNumberVO asNumberVO = Mockito.mock(ASNumberVO.class);
when(asNumberDao.findByZoneAndNetworkId(zoneId, networkId)).thenReturn(asNumberVO);
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(dcDao.findById(zoneId)).thenReturn(dc);
when(dc.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, network);
Assert.assertEquals(1, cmds.size());
Command cmd = cmds.toCommands()[0];
Assert.assertTrue(cmd instanceof SetBgpPeersCommand);
Assert.assertEquals(2, ((SetBgpPeersCommand) cmd).getBpgPeers().length);
}
@Test
public void testCreateBgpPeersCommandsForVpc() {
BgpPeerVO bgpPeer1 = Mockito.mock(BgpPeerVO.class);
BgpPeerVO bgpPeer2 = Mockito.mock(BgpPeerVO.class);
List<BgpPeerVO> bgpPeers = Arrays.asList(bgpPeer1, bgpPeer2);
Commands cmds = new Commands(Command.OnError.Stop);
VirtualRouter router = Mockito.mock(VirtualRouter.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
long zoneId = 10L;
long vpcId = 11L;
when(router.getDataCenterId()).thenReturn(zoneId);
when(router.getVpcId()).thenReturn(vpcId);
ASNumberVO asNumberVO = Mockito.mock(ASNumberVO.class);
when(asNumberDao.findByZoneAndVpcId(zoneId, vpcId)).thenReturn(asNumberVO);
long networkOfferingId = 12L;
NetworkOfferingVO offering = Mockito.mock(NetworkOfferingVO.class);
when(networkOfferingDao.findByIdIncludingRemoved(networkOfferingId)).thenReturn(offering);
when(offering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Dynamic);
NetworkVO network1 = Mockito.mock(NetworkVO.class);
when(network1.getNetworkOfferingId()).thenReturn(networkOfferingId);
NetworkVO network2 = Mockito.mock(NetworkVO.class);
when(network2.getNetworkOfferingId()).thenReturn(networkOfferingId);
when(networkDao.listByVpc(vpcId)).thenReturn(Arrays.asList(network1, network2));
DataCenterVO dc = Mockito.mock(DataCenterVO.class);
when(dcDao.findById(zoneId)).thenReturn(dc);
when(dc.getNetworkType()).thenReturn(DataCenter.NetworkType.Advanced);
commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, network);
Assert.assertEquals(1, cmds.size());
Command cmd = cmds.toCommands()[0];
Assert.assertTrue(cmd instanceof SetBgpPeersCommand);
Assert.assertEquals(4, ((SetBgpPeersCommand) cmd).getBpgPeers().length);
}
}

View File

@ -19,7 +19,10 @@ package com.cloud.network.router;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.CheckS2SVpnConnectionsAnswer;
import com.cloud.agent.api.CheckS2SVpnConnectionsCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.manager.Commands;
import com.cloud.alert.AlertManager;
import com.cloud.bgp.BGPService;
import com.cloud.cluster.dao.ManagementServerHostDao;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
@ -30,6 +33,8 @@ import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.Network;
import com.cloud.network.NetworkModel;
import com.cloud.network.Site2SiteVpnConnection;
import com.cloud.network.dao.FirewallRulesDao;
import com.cloud.network.dao.IPAddressDao;
@ -37,6 +42,7 @@ import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.MonitoringServiceDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.network.dao.OpRouterMonitorServiceDao;
import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.RemoteAccessVpnDao;
@ -49,6 +55,8 @@ import com.cloud.network.dao.UserIpv6AddressDao;
import com.cloud.network.dao.VirtualRouterProviderDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.network.vpc.VpcVO;
import com.cloud.network.vpc.dao.VpcDao;
import com.cloud.network.vpn.Site2SiteVpnManager;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.service.dao.ServiceOfferingDao;
@ -69,12 +77,15 @@ import com.cloud.vm.dao.UserVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.network.BgpPeer;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.apache.cloudstack.utils.identity.ManagementServerNode;
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 java.util.ArrayList;
@ -233,6 +244,20 @@ public class VirtualNetworkApplianceManagerImplTest {
@InjectMocks
private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl;
@Mock
private NetworkModel _networkModel;
@Mock
private RoutedIpv4Manager routedIpv4Manager;
@Mock
private CommandSetupHelper _commandSetupHelper;
@Mock
private VpcDao _vpcDao;
@Mock
private BGPService bgpService;
// @InjectMocks
// private VirtualNetworkApplianceManagerImpl virtualNetworkApplianceManagerImpl;
@ -328,4 +353,42 @@ public class VirtualNetworkApplianceManagerImplTest {
result = virtualNetworkApplianceManagerImpl.checkLogrotateTimerPattern(foo);
Assert.assertTrue(result);
}
@Test
public void testFinalizeNetworkRulesForNetwork() {
Long guestNetworkId = 10L;
Commands cmds = new Commands(Command.OnError.Stop);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
when(_networkDao.findById(guestNetworkId)).thenReturn(network);
when(network.getVpcId()).thenReturn(null);
when(routedIpv4Manager.isDynamicRoutedNetwork(network)).thenReturn(true);
List<? extends BgpPeer> bgpPeers = Mockito.mock(List.class);
doReturn(bgpPeers).when(bgpService).getBgpPeersForNetwork(network);
virtualNetworkApplianceManagerImpl.finalizeNetworkRulesForNetwork(cmds, router, Network.Provider.VirtualRouter, guestNetworkId);
Mockito.verify(_commandSetupHelper).createBgpPeersCommands(bgpPeers, router, cmds, network);
}
@Test
public void testFinalizeNetworkRulesForVpcNetwork() {
Long guestNetworkId = 10L;
Long vpcId = 11L;
Commands cmds = new Commands(Command.OnError.Stop);
DomainRouterVO router = Mockito.mock(DomainRouterVO.class);
NetworkVO network = Mockito.mock(NetworkVO.class);
when(_networkDao.findById(guestNetworkId)).thenReturn(network);
when(network.getVpcId()).thenReturn(vpcId);
VpcVO vpc = Mockito.mock(VpcVO.class);
when(_vpcDao.findById(vpcId)).thenReturn(vpc);
when(routedIpv4Manager.isDynamicRoutedVpc(vpc)).thenReturn(true);
List<? extends BgpPeer> bgpPeers = Mockito.mock(List.class);
doReturn(bgpPeers).when(bgpService).getBgpPeersForVpc(vpc);
virtualNetworkApplianceManagerImpl.finalizeNetworkRulesForNetwork(cmds, router, Network.Provider.VirtualRouter, guestNetworkId);
Mockito.verify(_commandSetupHelper).createBgpPeersCommands(bgpPeers, router, cmds, network);
}
}

View File

@ -73,6 +73,7 @@ import org.apache.cloudstack.api.command.user.vpc.UpdateVPCCmd;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.network.Ipv4GuestSubnetNetworkMap;
import org.apache.cloudstack.network.RoutedIpv4Manager;
import org.junit.After;
import org.junit.Assert;
@ -87,6 +88,7 @@ import org.springframework.test.util.ReflectionTestUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -98,6 +100,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
@ -541,6 +544,30 @@ public class VpcManagerImplTest {
verify(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyString());
}
@Test
public void testCreateRoutedVpcWithDynamicRouting() {
mockVpcDnsResources(true, false);
VpcVO vpc = Mockito.mock(VpcVO.class);
Mockito.when(vpcDao.persist(any(), anyMap())).thenReturn(vpc);
Mockito.when(vpc.getUuid()).thenReturn("uuid");
doReturn(true).when(routedIpv4Manager).isRoutedVpc(any());
doReturn(true).when(routedIpv4Manager).isVpcVirtualRouterGateway(vpcOfferingVO);
doReturn(true).when(routedIpv4Manager).isDynamicRoutedVpc(vpcOfferingVO);
Ipv4GuestSubnetNetworkMap ipv4GuestSubnetNetworkMap = Mockito.mock(Ipv4GuestSubnetNetworkMap.class);
doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyInt());
List<Long> bgpPeerIds = Arrays.asList(11L, 12L);
try {
doNothing().when(resourceLimitService).checkResourceLimit(account, Resource.ResourceType.vpc);
manager.createVpc(zoneId, vpcOfferingId, vpcOwnerId, vpcName, vpcName, null, vpcDomain,
ip4Dns[0], ip4Dns[1], null, null, true, 1500, 24, null, bgpPeerIds);
} catch (ResourceAllocationException e) {
Assert.fail(String.format("failure with exception: %s", e.getMessage()));
}
verify(routedIpv4Manager).getOrCreateIpv4SubnetForVpc(any(), anyInt());
verify(routedIpv4Manager).validateBgpPeers(any(), any(), any());
}
@Test
public void validateVpcPrivateGatewayAclIdTestNullAclVoThrowsInvalidParameterValueException() {
Mockito.doReturn(null).when(networkACLDaoMock).findById(aclId);

File diff suppressed because it is too large Load Diff

View File

@ -74,13 +74,16 @@ export default {
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/PhysicalNetworksTab.vue')))
}, {
name: 'ipv4.subnets',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/Ipv4GuestSubnetsTab.vue')))
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/Ipv4GuestSubnetsTab.vue'))),
show: (record) => { return record.routedmodeenabled && 'listIpv4SubnetsForZone' in store.getters.apis }
}, {
name: 'asnumber',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/AsNumbersTab.vue')))
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/AsNumbersTab.vue'))),
show: (record) => { return record.routedmodeenabled && 'listASNumbers' in store.getters.apis }
}, {
name: 'bgp.peers',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/BgpPeersTab.vue')))
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/BgpPeersTab.vue'))),
show: (record) => { return record.routedmodeenabled && 'listBgpPeers' in store.getters.apis }
}, {
name: 'system.vms',
component: shallowRef(defineAsyncComponent(() => import('@/views/infra/zone/SystemVmsTab.vue'))),

View File

@ -872,7 +872,14 @@ export default {
icon: 'partition-outlined',
permission: ['listASNumbers'],
show: () => {
return ['Admin'].includes(store.getters.userInfo.roletype)
if (!store.getters.zones || store.getters.zones.length === 0) {
return false
}
const AdvancedZonesWithRoutedmode = store.getters.zones.filter(zone => zone.routedmodeenabled)
if (isAdmin() && (AdvancedZonesWithRoutedmode && AdvancedZonesWithRoutedmode.length > 0)) {
return true
}
return false
},
filters: ['all', 'allocatedonly', 'free'],
columns: ['asnumber', 'allocationstate', 'asnrange', 'associatednetworkname', 'vpcname', 'allocated', 'account', 'domain', 'zonename'],
@ -1446,7 +1453,11 @@ export default {
if (!store.getters.zones || store.getters.zones.length === 0) {
return false
}
return isAdmin()
const AdvancedZonesWithRoutedmode = store.getters.zones.filter(zone => zone.routedmodeenabled)
if (isAdmin() && (AdvancedZonesWithRoutedmode && AdvancedZonesWithRoutedmode.length > 0)) {
return true
}
return false
},
actions: [
{

View File

@ -150,6 +150,7 @@ export default {
const params = { showicon: true }
api('listZones', params).then(json => {
this.zones = json.listzonesresponse.zone || []
this.zones = this.zones.filter(zone => zone.routedmodeenabled)
this.form.zoneid = this.zones[0].id || ''
this.fetchParentSubnets(this.form.zoneid)
}).finally(() => {

View File

@ -552,8 +552,9 @@ export default {
this.selectedNetworkOffering = {}
api('listNetworkOfferings', params).then(json => {
this.networkOfferings = json.listnetworkofferingsresponse.networkoffering
if (this.selectedZone.isnsxenabled) {
this.networkOfferings = this.networkOfferings.filter(offering => offering.fornsx)
this.networkOfferings = this.networkOfferings.filter(offering => offering.fornsx === this.selectedZone.isnsxenabled)
if (!this.selectedZone.routedmodeenabled) {
this.networkOfferings = this.networkOfferings.filter(offering => offering.networkmode !== 'ROUTED')
}
}).catch(error => {
this.$notifyError(error)

View File

@ -345,6 +345,10 @@ export default {
this.loadingOffering = true
api('listVPCOfferings', { zoneid: this.form.zoneid, state: 'Enabled' }).then((response) => {
this.vpcOfferings = response.listvpcofferingsresponse.vpcoffering
this.vpcOfferings = this.vpcOfferings.filter(offering => offering.fornsx === this.selectedZone.isnsxenabled)
if (!this.selectedZone.routedmodeenabled) {
this.vpcOfferings = this.vpcOfferings.filter(offering => offering.networkmode !== 'ROUTED')
}
this.form.vpcofferingid = this.vpcOfferings[0].id || ''
this.selectedVpcOffering = this.vpcOfferings[0] || {}
}).finally(() => {

View File

@ -615,6 +615,7 @@ export default {
zones: [],
zoneLoading: false,
ipv6NetworkOfferingEnabled: false,
routedNetworkEnabled: false,
loading: false,
networkmode: '',
networkmodes: [
@ -704,6 +705,7 @@ export default {
this.fetchSupportedServiceData()
this.fetchServiceOfferingData()
this.fetchIpv6NetworkOfferingConfiguration()
this.fetchRoutedNetworkConfiguration()
},
isAdmin () {
return isAdmin()
@ -732,6 +734,17 @@ export default {
this.ipv6NetworkOfferingEnabled = value === 'true'
})
},
fetchRoutedNetworkConfiguration () {
this.routedNetworkEnabled = false
var params = { name: 'routed.network.vpc.enabled' }
api('listConfigurations', params).then(json => {
var value = json?.listconfigurationsresponse?.configuration?.[0].value || null
this.routedNetworkEnabled = value === 'true'
if (!this.routedNetworkEnabled) {
this.networkmodes.pop()
}
})
},
fetchZoneData () {
const params = {}
params.showicon = true

View File

@ -283,6 +283,7 @@ export default {
sourceNatServiceChecked: false,
selectedServiceProviderMap: {},
ipv6NetworkOfferingEnabled: false,
routedNetworkEnabled: false,
routingMode: 'static',
networkmode: '',
networkmodes: [
@ -351,6 +352,7 @@ export default {
this.fetchZoneData()
this.fetchSupportedServiceData()
this.fetchIpv6NetworkOfferingConfiguration()
this.fetchRoutedNetworkConfiguration()
},
isAdmin () {
return isAdmin()
@ -363,6 +365,17 @@ export default {
this.ipv6NetworkOfferingEnabled = value === 'true'
})
},
fetchRoutedNetworkConfiguration () {
this.routedNetworkEnabled = false
var params = { name: 'routed.network.vpc.enabled' }
api('listConfigurations', params).then(json => {
var value = json?.listconfigurationsresponse?.configuration?.[0].value || null
this.routedNetworkEnabled = value === 'true'
if (!this.routedNetworkEnabled) {
this.networkmodes.pop()
}
})
},
fetchDomainData () {
const params = {}
params.listAll = true