You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by we...@apache.org on 2024/11/30 07:45:23 UTC
(cloudstack) branch 4.20 updated: Routed mode: minor improvements and fixes (#9697)
This is an automated email from the ASF dual-hosted git repository.
weizhou pushed a commit to branch 4.20
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/4.20 by this push:
new 22a66044918 Routed mode: minor improvements and fixes (#9697)
22a66044918 is described below
commit 22a66044918ce37370ee4aa01ae1e20fbc41f581
Author: Wei Zhou <we...@apache.org>
AuthorDate: Sat Nov 30 08:45:15 2024 +0100
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
---
api/src/main/java/com/cloud/bgp/BGPService.java | 5 +
.../org/apache/cloudstack/api/ApiConstants.java | 1 +
.../cloudstack/api/response/ZoneResponse.java | 13 +
.../cloudstack/network/RoutedIpv4Manager.java | 9 +
.../cloud/api/query/dao/DataCenterJoinDaoImpl.java | 3 +
.../main/java/com/cloud/bgp/BGPServiceImpl.java | 59 +-
.../configuration/ConfigurationManagerImpl.java | 11 +
.../java/com/cloud/network/NetworkServiceImpl.java | 13 +-
.../router/VirtualNetworkApplianceManagerImpl.java | 13 +-
.../java/com/cloud/network/vpc/VpcManagerImpl.java | 21 +-
.../com/cloud/server/ManagementServerImpl.java | 11 -
.../cloudstack/network/RoutedIpv4ManagerImpl.java | 75 +-
.../java/com/cloud/bgp/BGPServiceImplTest.java | 133 ++-
.../com/cloud/network/NetworkServiceImplTest.java | 92 +-
.../network/element/VirtualRouterElementTest.java | 56 +
.../network/router/CommandSetupHelperTest.java | 110 +-
.../VirtualNetworkApplianceManagerImplTest.java | 63 +
.../com/cloud/network/vpc/VpcManagerImplTest.java | 27 +
.../network/RoutedIpv4ManagerImplTest.java | 1217 ++++++++++++++++++++
ui/src/config/section/infra/zones.js | 9 +-
ui/src/config/section/network.js | 15 +-
.../views/network/CreateIpv4SubnetForNetwork.vue | 1 +
ui/src/views/network/CreateIsolatedNetworkForm.vue | 5 +-
ui/src/views/network/CreateVpc.vue | 4 +
ui/src/views/offering/AddNetworkOffering.vue | 13 +
ui/src/views/offering/AddVpcOffering.vue | 13 +
26 files changed, 1902 insertions(+), 90 deletions(-)
diff --git a/api/src/main/java/com/cloud/bgp/BGPService.java b/api/src/main/java/com/cloud/bgp/BGPService.java
index 935237092dd..61d149f2847 100644
--- a/api/src/main/java/com/cloud/bgp/BGPService.java
+++ b/api/src/main/java/com/cloud/bgp/BGPService.java
@@ -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);
}
diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index bb16b0ff90d..6df8d7f5f18 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -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";
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java
index 143dfad0eaf..4a5279753a1 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/ZoneResponse.java
@@ -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;
+ }
}
diff --git a/api/src/main/java/org/apache/cloudstack/network/RoutedIpv4Manager.java b/api/src/main/java/org/apache/cloudstack/network/RoutedIpv4Manager.java
index 2f704e9f47d..221a550ad63 100644
--- a/api/src/main/java/org/apache/cloudstack/network/RoutedIpv4Manager.java
+++ b/api/src/main/java/org/apache/cloudstack/network/RoutedIpv4Manager.java
@@ -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);
}
diff --git a/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java b/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
index 2b3be728bd3..d457f8f7931 100644
--- a/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
+++ b/server/src/main/java/com/cloud/api/query/dao/DataCenterJoinDaoImpl.java
@@ -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())));
diff --git a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java
index 0e6ae7ade1a..672c6b7cd60 100644
--- a/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java
+++ b/server/src/main/java/com/cloud/bgp/BGPServiceImpl.java
@@ -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;
+ }
}
diff --git a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
index 25cbd10de0a..4a9e03ba67e 100644
--- a/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
+++ b/server/src/main/java/com/cloud/configuration/ConfigurationManagerImpl.java
@@ -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);
diff --git a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
index 2ccd5fdd820..ffb0be83494 100644
--- a/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/main/java/com/cloud/network/NetworkServiceImpl.java
@@ -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);
diff --git a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index 8f07fcfca3b..8a28eeabe21 100644
--- a/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -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);
}
}
diff --git a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java
index b956ccc16ed..6d24c0fe700 100644
--- a/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java
+++ b/server/src/main/java/com/cloud/network/vpc/VpcManagerImpl.java
@@ -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");
}
diff --git a/server/src/main/java/com/cloud/server/ManagementServerImpl.java b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
index 87b3dd3cbd9..2062ee1e94d 100644
--- a/server/src/main/java/com/cloud/server/ManagementServerImpl.java
+++ b/server/src/main/java/com/cloud/server/ManagementServerImpl.java
@@ -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);
diff --git a/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java b/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
index bbad93737f1..ab05895b8d2 100644
--- a/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/network/RoutedIpv4ManagerImpl.java
@@ -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.");
+ }
+ }
}
diff --git a/server/src/test/java/com/cloud/bgp/BGPServiceImplTest.java b/server/src/test/java/com/cloud/bgp/BGPServiceImplTest.java
index ace7bc85691..be31a1c6502 100644
--- a/server/src/test/java/com/cloud/bgp/BGPServiceImplTest.java
+++ b/server/src/test/java/com/cloud/bgp/BGPServiceImplTest.java
@@ -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());
+ }
}
diff --git a/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java
index 64d813c9ba8..51d5a61cbca 100644
--- a/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java
+++ b/server/src/test/java/com/cloud/network/NetworkServiceImplTest.java
@@ -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();
diff --git a/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java b/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java
index b0d9cdc9dc4..de9858d2f07 100644
--- a/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java
+++ b/server/src/test/java/com/cloud/network/element/VirtualRouterElementTest.java
@@ -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());
+ }
}
diff --git a/server/src/test/java/com/cloud/network/router/CommandSetupHelperTest.java b/server/src/test/java/com/cloud/network/router/CommandSetupHelperTest.java
index 37fa13baf98..bdd905841f9 100644
--- a/server/src/test/java/com/cloud/network/router/CommandSetupHelperTest.java
+++ b/server/src/test/java/com/cloud/network/router/CommandSetupHelperTest.java
@@ -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);
+ }
}
diff --git a/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java b/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java
index ec5fdc0730f..1e55f55fbd6 100644
--- a/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java
+++ b/server/src/test/java/com/cloud/network/router/VirtualNetworkApplianceManagerImplTest.java
@@ -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);
+ }
}
diff --git a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java
index 54acaa58acc..ee56a092dd1 100644
--- a/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java
+++ b/server/src/test/java/com/cloud/network/vpc/VpcManagerImplTest.java
@@ -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);
diff --git a/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java b/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
new file mode 100644
index 00000000000..5351abe2e2d
--- /dev/null
+++ b/server/src/test/java/org/apache/cloudstack/network/RoutedIpv4ManagerImplTest.java
@@ -0,0 +1,1217 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+
+package org.apache.cloudstack.network;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.bgp.BGPService;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.domain.DomainVO;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.dao.FirewallRulesDao;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkServiceMapDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.element.VirtualRouterElement;
+import com.cloud.network.firewall.FirewallService;
+import com.cloud.network.rules.FirewallManager;
+import com.cloud.network.rules.FirewallRule;
+import com.cloud.network.rules.FirewallRuleVO;
+import com.cloud.network.vpc.Vpc;
+import com.cloud.network.vpc.VpcOfferingVO;
+import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.dao.VpcDao;
+import com.cloud.network.vpc.dao.VpcOfferingDao;
+import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.offerings.NetworkOfferingVO;
+import com.cloud.offerings.dao.NetworkOfferingDao;
+import com.cloud.offerings.dao.NetworkOfferingServiceMapDao;
+import com.cloud.projects.ProjectVO;
+import com.cloud.user.Account;
+import com.cloud.user.AccountManager;
+import com.cloud.user.AccountVO;
+import com.cloud.user.User;
+import com.cloud.user.UserVO;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.net.NetUtils;
+
+import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForGuestNetworkCmd;
+import org.apache.cloudstack.api.command.admin.network.CreateIpv4SubnetForZoneCmd;
+import org.apache.cloudstack.api.command.admin.network.DedicateIpv4SubnetForZoneCmd;
+import org.apache.cloudstack.api.command.admin.network.DeleteIpv4SubnetForGuestNetworkCmd;
+import org.apache.cloudstack.api.command.admin.network.DeleteIpv4SubnetForZoneCmd;
+import org.apache.cloudstack.api.command.admin.network.ReleaseDedicatedIpv4SubnetForZoneCmd;
+import org.apache.cloudstack.api.command.admin.network.UpdateIpv4SubnetForZoneCmd;
+import org.apache.cloudstack.api.command.admin.network.bgp.ChangeBgpPeersForNetworkCmd;
+import org.apache.cloudstack.api.command.admin.network.bgp.ChangeBgpPeersForVpcCmd;
+import org.apache.cloudstack.api.command.admin.network.bgp.CreateBgpPeerCmd;
+import org.apache.cloudstack.api.command.admin.network.bgp.DedicateBgpPeerCmd;
+import org.apache.cloudstack.api.command.admin.network.bgp.DeleteBgpPeerCmd;
+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.network.routing.CreateRoutingFirewallRuleCmd;
+import org.apache.cloudstack.api.command.user.network.routing.UpdateRoutingFirewallRuleCmd;
+import org.apache.cloudstack.api.response.BgpPeerResponse;
+import org.apache.cloudstack.api.response.DataCenterIpv4SubnetResponse;
+import org.apache.cloudstack.api.response.Ipv4SubnetForGuestNetworkResponse;
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnet;
+import org.apache.cloudstack.datacenter.DataCenterIpv4GuestSubnetVO;
+import org.apache.cloudstack.datacenter.dao.DataCenterIpv4GuestSubnetDao;
+import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.network.dao.BgpPeerDao;
+import org.apache.cloudstack.network.dao.BgpPeerDetailsDao;
+import org.apache.cloudstack.network.dao.BgpPeerNetworkMapDao;
+import org.apache.cloudstack.network.dao.Ipv4GuestSubnetNetworkMapDao;
+import org.apache.commons.collections.CollectionUtils;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockedStatic;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RoutedIpv4ManagerImplTest {
+
+ @Spy
+ @InjectMocks
+ RoutedIpv4ManagerImpl routedIpv4Manager = new RoutedIpv4ManagerImpl();
+
+ @Mock
+ DataCenterIpv4GuestSubnetDao dataCenterIpv4GuestSubnetDao;
+ @Mock
+ Ipv4GuestSubnetNetworkMapDao ipv4GuestSubnetNetworkMapDao;
+ @Mock
+ FirewallService firewallService;
+ @Mock
+ FirewallManager firewallManager;
+ @Mock
+ FirewallRulesDao firewallDao;
+ @Mock
+ NetworkServiceMapDao networkServiceMapDao;
+ @Mock
+ NetworkOfferingServiceMapDao networkOfferingServiceMapDao;
+ @Mock
+ NetworkOfferingDao networkOfferingDao;
+ @Mock
+ NetworkModel networkModel;
+ @Mock
+ AccountManager accountManager;
+ @Mock
+ VpcOfferingDao vpcOfferingDao;
+ @Mock
+ VpcOfferingServiceMapDao vpcOfferingServiceMapDao;
+ @Mock
+ VpcDao vpcDao;
+ @Mock
+ BgpPeerDao bgpPeerDao;
+ @Mock
+ BgpPeerDetailsDao bgpPeerDetailsDao;
+ @Mock
+ BgpPeerNetworkMapDao bgpPeerNetworkMapDao;
+ @Mock
+ NetworkDao networkDao;
+ @Mock
+ BGPService bgpService;
+
+ static MockedStatic<ApiDBUtils> apiDBUtilsMocked;
+
+ @Mock
+ DataCenterIpv4GuestSubnetVO subnetVO;
+ @Mock
+ DomainVO domain;
+ @Mock
+ AccountVO account;
+ @Mock
+ ProjectVO project;
+ @Mock
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap;
+ @Mock
+ NetworkVO network;
+ @Mock
+ VpcVO vpc;
+ @Mock
+ DataCenterVO zone;
+ @Mock
+ FirewallRuleVO rule;
+ @Mock
+ BgpPeerVO bgpPeer;
+ @Mock
+ NetworkOfferingVO networkOffering;
+ @Mock
+ VpcOfferingVO vpcOffering;
+
+ Long zoneId = 1L;
+ String zoneUuid = "zone-uuid";
+ String zoneName = "zone-name";
+ Long zoneSubnetId = 2L;
+ String zoneSubnetUuid = "zone-subnet-uuid";
+ Long domainId = 3L;
+ Long accountId = 4L;
+ Long ipv4GuestSubnetNetworkMapId = 5L;
+ Long networkId = 6L;
+ String networkUuid = "network-uuid";
+ String networkName = "network-name";
+ Long vpcId = 7L;
+ String vpcUuid = "vpc-uuid";
+ String vpcName = "vpc-name";
+ String domainName = "domain";
+ String domainUuid = "domain-uuid";
+ String accountName = "user";
+ String subnet = "172.16.1.0/24";
+ String newSubnet = "172.16.2.0/24";
+ String subnetForNetwork = "172.16.1.0/28";
+ String newSubnetForNetwork = "172.16.1.64/28";
+ String newSubnetForNetworkTooSmall = "172.16.1.0/30";
+ String newSubnetForNetworkTooBig = "172.16.1.0/23";
+ Integer cidrSize = 28;
+ Ipv4GuestSubnetNetworkMap.State ipv4GuestSubnetNetworkMapState = Ipv4GuestSubnetNetworkMap.State.Free;
+ Date created = new Date();
+ String uuid = "xxx-yyy-zzz";
+ Long ruleId = 8L;
+ String ip4Address = "10.10.11.11";
+ String ip6Address = "fd00:10:10:11:11::1";
+ Long asNumber = 9999L;
+ String password = "password-text";
+ Long bgpPeerId = 9L;
+ String bgpPeerUuid = "bgp-peer-uuid";
+ Long projectId = 10L;
+ String projectName = "project";
+ String projectUuid = "project-uuid";
+ Long networkOfferingId = 11L;
+ Long vpcOfferingId = 12L;
+
+ @BeforeClass
+ public static void setup() {
+ apiDBUtilsMocked = Mockito.mockStatic(ApiDBUtils.class);
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findZoneById(Mockito.anyLong())).thenReturn(Mockito.mock(DataCenterVO.class));
+
+ CallContext.unregister();
+ AccountVO account = new AccountVO("admin", 1L, "", Account.Type.ADMIN, "uuid");
+ account.setId(2L);
+ UserVO user = new UserVO(1, "admin", "password", "firstname", "lastName", "email", "timezone", UUID.randomUUID().toString(), User.Source.UNKNOWN);
+ CallContext.register(user, account);
+ }
+
+ @AfterClass
+ public static void close() {
+ apiDBUtilsMocked.close();
+
+ CallContext.unregister();
+ }
+
+ @Test
+ public void testGetCommands() throws NoSuchFieldException, IllegalAccessException {
+ Assert.assertTrue(CollectionUtils.isNotEmpty(routedIpv4Manager.getCommands()));
+ Assert.assertEquals(26, routedIpv4Manager.getCommands().size());
+
+ overrideDefaultConfigValue(RoutedIpv4Manager.RoutedNetworkVpcEnabled, "_defaultValue", "false");
+ Assert.assertTrue(CollectionUtils.isEmpty(routedIpv4Manager.getCommands()));
+ }
+
+ private static void overrideDefaultConfigValue(final ConfigKey configKey, final String name, final Object o) throws IllegalAccessException, NoSuchFieldException {
+ Field f = ConfigKey.class.getDeclaredField(name);
+ f.setAccessible(true);
+ f.set(configKey, o);
+ }
+
+ @Test
+ public void testCreateDataCenterIpv4GuestSubnet() {
+ CreateIpv4SubnetForZoneCmd cmd = new CreateIpv4SubnetForZoneCmd();
+ ReflectionTestUtils.setField(cmd,"zoneId", zoneId);
+ ReflectionTestUtils.setField(cmd,"subnet", subnet);
+
+ routedIpv4Manager.createDataCenterIpv4GuestSubnet(cmd);
+
+ verify(routedIpv4Manager).checkConflicts(new ArrayList<>(), subnet, null);
+ verify(dataCenterIpv4GuestSubnetDao).persist(any());
+ }
+
+ @Test
+ public void testCreateDataCenterIpv4SubnetResponse() {
+ DataCenterIpv4GuestSubnetVO subnetVO = new DataCenterIpv4GuestSubnetVO(zoneId, NetUtils.transformCidr(subnet));
+ DataCenterIpv4SubnetResponse response = routedIpv4Manager.createDataCenterIpv4SubnetResponse(subnetVO);
+
+ Assert.assertEquals(subnet, response.getSubnet());
+ Assert.assertEquals(subnetVO.getUuid(), response.getId());
+ Assert.assertEquals("zoneipv4subnet", response.getObjectName());
+ }
+
+ @Test
+ public void testDeleteDataCenterIpv4GuestSubnet() {
+ DeleteIpv4SubnetForZoneCmd cmd = new DeleteIpv4SubnetForZoneCmd();
+ ReflectionTestUtils.setField(cmd,"id", zoneSubnetId);
+
+ routedIpv4Manager.deleteDataCenterIpv4GuestSubnet(cmd);
+
+ verify(ipv4GuestSubnetNetworkMapDao).deleteByParentId(zoneSubnetId);
+ verify(dataCenterIpv4GuestSubnetDao).remove(zoneSubnetId);
+ }
+
+ @Test
+ public void testUpdateDataCenterIpv4GuestSubnet() {
+ UpdateIpv4SubnetForZoneCmd cmd = new UpdateIpv4SubnetForZoneCmd();
+ ReflectionTestUtils.setField(cmd,"id", zoneSubnetId);
+ ReflectionTestUtils.setField(cmd,"subnet", newSubnet);
+
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+
+ routedIpv4Manager.updateDataCenterIpv4GuestSubnet(cmd);
+
+ verify(routedIpv4Manager).checkConflicts(new ArrayList<>(), newSubnet, zoneSubnetId);
+ verify(ipv4GuestSubnetNetworkMapDao).listByParent(zoneSubnetId);
+ verify(dataCenterIpv4GuestSubnetDao).update(eq(zoneSubnetId), any(DataCenterIpv4GuestSubnetVO.class));
+ }
+
+ @Test
+ public void testCheckConflicts1() {
+ DataCenterIpv4GuestSubnetVO existingSubnet = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(existingSubnet.getSubnet()).thenReturn(subnet);
+ List<DataCenterIpv4GuestSubnetVO> existingSubnets = Arrays.asList(existingSubnet);
+ routedIpv4Manager.checkConflicts(existingSubnets, newSubnet, null);
+ }
+
+ @Test(expected = InvalidParameterValueException.class)
+ public void testCheckConflicts2() {
+ DataCenterIpv4GuestSubnetVO existingSubnet = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(existingSubnet.getSubnet()).thenReturn(subnet);
+ List<DataCenterIpv4GuestSubnetVO> existingSubnets = Arrays.asList(existingSubnet);
+ routedIpv4Manager.checkConflicts(existingSubnets, subnet, null);
+ }
+
+ @Test
+ public void testCheckConflicts3() {
+ DataCenterIpv4GuestSubnetVO existingSubnet = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(existingSubnet.getId()).thenReturn(zoneSubnetId);
+ List<DataCenterIpv4GuestSubnetVO> existingSubnets = Arrays.asList(existingSubnet);
+ routedIpv4Manager.checkConflicts(existingSubnets, subnet, zoneSubnetId);
+ }
+
+ @Test
+ public void testDedicateDataCenterIpv4GuestSubnet() {
+ DedicateIpv4SubnetForZoneCmd cmd = new DedicateIpv4SubnetForZoneCmd();
+ ReflectionTestUtils.setField(cmd,"id", zoneSubnetId);
+ ReflectionTestUtils.setField(cmd,"domainId", domainId);
+ ReflectionTestUtils.setField(cmd,"accountName", accountName);
+ ReflectionTestUtils.setField(cmd,"projectId", null);
+
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+
+ when(accountManager.finalyzeAccountId(accountName, domainId, null, false)).thenReturn(accountId);
+ when(accountManager.getAccount(accountId)).thenReturn(account);
+ when(account.getDomainId()).thenReturn(domainId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+
+ routedIpv4Manager.dedicateDataCenterIpv4GuestSubnet(cmd);
+
+ verify(subnetVO).setDomainId(domainId);
+ verify(subnetVO).setAccountId(accountId);
+ verify(dataCenterIpv4GuestSubnetDao).update(zoneSubnetId, subnetVO);
+ }
+
+ @Test
+ public void testReleaseDedicatedDataCenterIpv4GuestSubnet() {
+ ReleaseDedicatedIpv4SubnetForZoneCmd cmd = new ReleaseDedicatedIpv4SubnetForZoneCmd();
+ ReflectionTestUtils.setField(cmd,"id", zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+
+ routedIpv4Manager.releaseDedicatedDataCenterIpv4GuestSubnet(cmd);
+
+ verify(subnetVO).setDomainId(null);
+ verify(subnetVO).setAccountId(null);
+ verify(dataCenterIpv4GuestSubnetDao).update(zoneSubnetId, subnetVO);
+ }
+
+ @Test
+ public void testCreateIpv4SubnetForGuestNetwork1() {
+ CreateIpv4SubnetForGuestNetworkCmd cmd = new CreateIpv4SubnetForGuestNetworkCmd();
+
+ try {
+ routedIpv4Manager.createIpv4SubnetForGuestNetwork(cmd);
+ Assert.fail("creating IPv4 subnet for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("One of subnet and cidrsize must be specified", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testCreateIpv4SubnetForGuestNetwork2() {
+ CreateIpv4SubnetForGuestNetworkCmd cmd = new CreateIpv4SubnetForGuestNetworkCmd();
+ ReflectionTestUtils.setField(cmd,"subnet", subnet);
+ ReflectionTestUtils.setField(cmd,"cidrSize", cidrSize);
+ try {
+ routedIpv4Manager.createIpv4SubnetForGuestNetwork(cmd);
+ Assert.fail("creating IPv4 subnet for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("subnet and cidrsize are mutually exclusive", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testCreateIpv4SubnetForGuestNetwork3() {
+ CreateIpv4SubnetForGuestNetworkCmd cmd = new CreateIpv4SubnetForGuestNetworkCmd();
+ ReflectionTestUtils.setField(cmd,"subnet", subnet);
+ ReflectionTestUtils.setField(cmd,"parentId", zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+ doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).createIpv4SubnetFromParentSubnet(subnetVO, subnet);
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.createIpv4SubnetForGuestNetwork(cmd);
+
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ }
+
+ @Test
+ public void testCreateIpv4SubnetForGuestNetwork4() {
+ CreateIpv4SubnetForGuestNetworkCmd cmd = new CreateIpv4SubnetForGuestNetworkCmd();
+ ReflectionTestUtils.setField(cmd,"cidrSize", cidrSize);
+ ReflectionTestUtils.setField(cmd,"parentId", zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+ doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).createIpv4SubnetFromParentSubnet(subnetVO, cidrSize);
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.createIpv4SubnetForGuestNetwork(cmd);
+
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ }
+
+ @Test
+ public void testDeleteIpv4SubnetForGuestNetwork() {
+ DeleteIpv4SubnetForGuestNetworkCmd cmd = new DeleteIpv4SubnetForGuestNetworkCmd();
+ ReflectionTestUtils.setField(cmd,"id", ipv4GuestSubnetNetworkMapId);
+
+ when(ipv4GuestSubnetNetworkMapDao.findById(ipv4GuestSubnetNetworkMapId)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getState()).thenReturn(ipv4GuestSubnetNetworkMapState);
+ when(ipv4GuestSubnetNetworkMap.getNetworkId()).thenReturn(null);
+
+ routedIpv4Manager.deleteIpv4SubnetForGuestNetwork(cmd);
+
+ verify(ipv4GuestSubnetNetworkMapDao).remove(ipv4GuestSubnetNetworkMapId);
+ }
+
+ @Test
+ public void testReleaseIpv4SubnetForGuestNetwork() {
+ when(ipv4GuestSubnetNetworkMapDao.findByNetworkId(networkId)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
+
+ routedIpv4Manager.releaseIpv4SubnetForGuestNetwork(networkId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).remove(ipv4GuestSubnetNetworkMapId);
+ }
+
+ @Test
+ public void testReleaseIpv4SubnetForVpc() {
+ when(ipv4GuestSubnetNetworkMapDao.findByVpcId(vpcId)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
+
+ routedIpv4Manager.releaseIpv4SubnetForVpc(vpcId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).remove(ipv4GuestSubnetNetworkMapId);
+ }
+
+ @Test
+ public void testCreateIpv4SubnetForGuestNetworkResponse() {
+ when(ipv4GuestSubnetNetworkMap.getCreated()).thenReturn(created);
+ when(ipv4GuestSubnetNetworkMap.getSubnet()).thenReturn(subnet);
+ when(ipv4GuestSubnetNetworkMap.getState()).thenReturn(ipv4GuestSubnetNetworkMapState);
+ when(ipv4GuestSubnetNetworkMap.getUuid()).thenReturn(uuid);
+
+ when(ipv4GuestSubnetNetworkMap.getNetworkId()).thenReturn(networkId);
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findNetworkById(Mockito.anyLong())).thenReturn(network);
+ when(network.getName()).thenReturn(networkName);
+ when(network.getUuid()).thenReturn(networkUuid);
+ when(network.getDataCenterId()).thenReturn(zoneId);
+
+ when(ipv4GuestSubnetNetworkMap.getVpcId()).thenReturn(vpcId);
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findVpcById(Mockito.anyLong())).thenReturn(vpc);
+ when(vpc.getName()).thenReturn(vpcName);
+ when(vpc.getUuid()).thenReturn(vpcUuid);
+ when(vpc.getZoneId()).thenReturn(zoneId);
+
+ when(ipv4GuestSubnetNetworkMap.getParentId()).thenReturn(zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+ when(subnetVO.getSubnet()).thenReturn(subnet);
+ when(subnetVO.getUuid()).thenReturn(zoneSubnetUuid);
+ when(subnetVO.getDataCenterId()).thenReturn(zoneId);
+
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findZoneById(zoneId)).thenReturn(zone);
+ when(zone.getName()).thenReturn(zoneName);
+ when(zone.getUuid()).thenReturn(zoneUuid);
+
+ Ipv4SubnetForGuestNetworkResponse response = routedIpv4Manager.createIpv4SubnetForGuestNetworkResponse(ipv4GuestSubnetNetworkMap);
+
+ Assert.assertEquals(created, response.getCreated());
+ Assert.assertEquals(subnet, response.getSubnet());
+ Assert.assertEquals(ipv4GuestSubnetNetworkMapState.name(), response.getState());
+ Assert.assertEquals(uuid, response.getId());
+ Assert.assertEquals(networkName, response.getNetworkName());
+ Assert.assertEquals(networkUuid, response.getNetworkId());
+ Assert.assertEquals(vpcName, response.getVpcName());
+ Assert.assertEquals(vpcUuid, response.getVpcId());
+ Assert.assertEquals(subnet, response.getParentSubnet());
+ Assert.assertEquals(zoneSubnetUuid, response.getParentId());
+ Assert.assertEquals(zoneUuid, response.getZoneId());
+ Assert.assertEquals(zoneName, response.getZoneName());
+ Assert.assertEquals("ipv4subnetforguestnetwork", response.getObjectName());
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr1() {
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getNetworkId()).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMap.getVpcId()).thenReturn(null);
+ when(ipv4GuestSubnetNetworkMap.getParentId()).thenReturn(zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+ when(subnetVO.getDomainId()).thenReturn(domainId);
+ when(subnetVO.getAccountId()).thenReturn(accountId);
+
+ routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(subnet, domainId, accountId, zoneId);
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr2() {
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(null);
+
+ routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(subnet, domainId, accountId, zoneId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).persist(any(Ipv4GuestSubnetNetworkMapVO.class));
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidr3() {
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(null);
+ when(routedIpv4Manager.getParentOfNetworkCidr(zoneId, subnet)).thenReturn(subnetVO);
+ when(subnetVO.getDomainId()).thenReturn(domainId);
+ when(subnetVO.getAccountId()).thenReturn(accountId);
+
+ routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(subnet, domainId, accountId, zoneId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).persist(any(Ipv4GuestSubnetNetworkMapVO.class));
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrSize1() {
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize, domainId, accountId, zoneId);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrSize2() {
+ DataCenterIpv4GuestSubnetVO subnet1 = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId)).thenReturn(Arrays.asList(subnet1));
+ DataCenterIpv4GuestSubnetVO subnet2 = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndDomainId(zoneId, domainId)).thenReturn(Arrays.asList(subnet2));
+ DataCenterIpv4GuestSubnetVO subnet3 = Mockito.mock(DataCenterIpv4GuestSubnetVO.class);
+ when(dataCenterIpv4GuestSubnetDao.listNonDedicatedByDataCenterId(zoneId)).thenReturn(Arrays.asList(subnet3));
+
+ doReturn(null).doReturn(null).doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(eq(cidrSize), any());
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize, domainId, accountId, zoneId);
+
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ verify(routedIpv4Manager, times(3)).getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(eq(cidrSize), any());
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrAndParentSubnet1() {
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize, subnetVO);
+ Assert.assertNull(result);
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrAndParentSubnet2() {
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+ when(ipv4GuestSubnetNetworkMapDao.findFirstAvailable(zoneSubnetId, cidrSize)).thenReturn(ipv4GuestSubnetNetworkMap);
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize, subnetVO);
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ }
+
+ @Test
+ public void testGetOrCreateIpv4SubnetForGuestNetworkOrVpcInternalByCidrAndParentSubnet3() {
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+ when(ipv4GuestSubnetNetworkMapDao.findFirstAvailable(zoneSubnetId, cidrSize)).thenReturn(null);
+ doReturn(ipv4GuestSubnetNetworkMap).when(routedIpv4Manager).createIpv4SubnetFromParentSubnet(subnetVO, cidrSize);
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.getOrCreateIpv4SubnetForGuestNetworkOrVpcInternal(cidrSize, subnetVO);
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ }
+
+ @Test
+ public void testGetParentOfNetworkCidr() {
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+ when(subnetVO.getSubnet()).thenReturn(subnet);
+ when(dataCenterIpv4GuestSubnetDao.listByDataCenterId(zoneId)).thenReturn(Arrays.asList(subnetVO));
+ when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap));
+ when(ipv4GuestSubnetNetworkMap.getSubnet()).thenReturn(subnetForNetwork);
+
+ try {
+ routedIpv4Manager.getParentOfNetworkCidr(zoneId, newSubnetForNetworkTooSmall);
+ Assert.fail("Getting parent of network cidr should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("Existing subnet %s has overlap with: %s", subnetForNetwork, newSubnetForNetworkTooSmall), ex.getMessage());
+ }
+
+ try {
+ routedIpv4Manager.getParentOfNetworkCidr(zoneId, newSubnetForNetworkTooBig);
+ Assert.fail("Getting parent of network cidr should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("Existing zone subnet %s has overlap with: %s", subnet, newSubnetForNetworkTooBig), ex.getMessage());
+ }
+
+ DataCenterIpv4GuestSubnet result = routedIpv4Manager.getParentOfNetworkCidr(zoneId, newSubnetForNetwork);
+ Assert.assertEquals(subnetVO, result);
+ }
+
+ @Test
+ public void testCreateIpv4SubnetFromParentSubnetByCidr() {
+ when(subnetVO.getSubnet()).thenReturn(subnet);
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+
+ try {
+ routedIpv4Manager.createIpv4SubnetFromParentSubnet(subnetVO, newSubnetForNetworkTooBig);
+ Assert.fail("Creating ipv4 subnet should fail.");
+ } catch (CloudRuntimeException ex) {
+ Assert.assertEquals(String.format("networkCidr %s is not within parent cidr: %s", newSubnetForNetworkTooBig, subnet), ex.getMessage());
+ }
+
+ when(ipv4GuestSubnetNetworkMap.getSubnet()).thenReturn(subnetForNetwork);
+ when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap));
+ when(ipv4GuestSubnetNetworkMapDao.persist(any())).thenReturn(ipv4GuestSubnetNetworkMap);
+
+ Ipv4GuestSubnetNetworkMap result = routedIpv4Manager.createIpv4SubnetFromParentSubnet(subnetVO, newSubnetForNetwork);
+ Assert.assertEquals(ipv4GuestSubnetNetworkMap, result);
+ }
+
+ @Test
+ public void testCreateIpv4SubnetFromParentSubnetByCidrSize() {
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+ when(dataCenterIpv4GuestSubnetDao.findById(zoneSubnetId)).thenReturn(subnetVO);
+
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap1 = new Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.0/28", null, Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap2 = new Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.64/28", null, Ipv4GuestSubnetNetworkMap.State.Free);
+ when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap1, ipv4GuestSubnetNetworkMap2));
+ when(subnetVO.getSubnet()).thenReturn("172.16.1.0/24");
+
+ String networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 28);
+ Assert.assertEquals("172.16.1.16/28", networkCidr);
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 27);
+ Assert.assertEquals("172.16.1.32/27", networkCidr);
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 26);
+ Assert.assertEquals("172.16.1.128/26", networkCidr);
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 25);
+ Assert.assertEquals("172.16.1.128/25", networkCidr);
+
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap3 = new Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.16/28", null, Ipv4GuestSubnetNetworkMap.State.Free);
+ Ipv4GuestSubnetNetworkMapVO ipv4GuestSubnetNetworkMap4 = new Ipv4GuestSubnetNetworkMapVO(zoneSubnetId, "172.16.1.128/28", null, Ipv4GuestSubnetNetworkMap.State.Free);
+ when(ipv4GuestSubnetNetworkMapDao.listByParent(zoneSubnetId)).thenReturn(Arrays.asList(ipv4GuestSubnetNetworkMap1, ipv4GuestSubnetNetworkMap2,
+ ipv4GuestSubnetNetworkMap3, ipv4GuestSubnetNetworkMap4));
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 28);
+ Assert.assertEquals("172.16.1.80/28", networkCidr);
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 27);
+ Assert.assertEquals("172.16.1.32/27", networkCidr);
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 26);
+ Assert.assertEquals("172.16.1.192/26", networkCidr);
+ try {
+ networkCidr = routedIpv4Manager.createIpv4SubnetStringFromParentSubnet(subnetVO, 25);
+ Assert.fail("Creating ipv4 subnet should fail.");
+ } catch (CloudRuntimeException ex) {
+ Assert.assertEquals("Failed to automatically allocate a subnet with specified cidrsize", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testAssignIpv4SubnetToNetwork() {
+ when(network.getId()).thenReturn(networkId);
+ when(network.getCidr()).thenReturn(subnet);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
+
+ routedIpv4Manager.assignIpv4SubnetToNetwork(network);
+
+ verify(ipv4GuestSubnetNetworkMapDao).update(eq(ipv4GuestSubnetNetworkMapId), any());
+ }
+
+ @Test
+ public void testAssignIpv4SubnetToVpc() {
+ when(vpc.getId()).thenReturn(vpcId);
+ when(vpc.getCidr()).thenReturn(subnet);
+ when(ipv4GuestSubnetNetworkMapDao.findBySubnet(subnet)).thenReturn(ipv4GuestSubnetNetworkMap);
+ when(ipv4GuestSubnetNetworkMap.getId()).thenReturn(ipv4GuestSubnetNetworkMapId);
+
+ routedIpv4Manager.assignIpv4SubnetToVpc(vpc);
+
+ verify(ipv4GuestSubnetNetworkMapDao).update(eq(ipv4GuestSubnetNetworkMapId), any());
+ }
+
+ @Test
+ public void testCreateRoutingFirewallRule() throws NetworkRuleConflictException {
+ CreateRoutingFirewallRuleCmd cmd = new CreateRoutingFirewallRuleCmd();
+ ReflectionTestUtils.setField(cmd, "protocol", "tcp");
+ List<String> sourceCidrList = Arrays.asList("192.168.0.0/24", "10.0.0.0/8");
+ ReflectionTestUtils.setField(cmd, "sourceCidrList", sourceCidrList);
+ List<String> destinationCidrlist = Arrays.asList("192.168.0.0/24", "10.0.0.0/8");
+ ReflectionTestUtils.setField(cmd, "destinationCidrlist", destinationCidrlist);
+ ReflectionTestUtils.setField(cmd, "publicStartPort", 1111);
+ ReflectionTestUtils.setField(cmd, "publicEndPort", 2222);
+ ReflectionTestUtils.setField(cmd, "networkId", networkId);
+
+ when(networkModel.getNetwork(networkId)).thenReturn(network);
+ when(network.getId()).thenReturn(networkId);
+ when(network.getDomainId()).thenReturn(domainId);
+ when(network.getAccountId()).thenReturn(accountId);
+ VirtualRouterElement virtualRouterElement = new VirtualRouterElement();
+ when(networkModel.getNetworkServiceCapabilities(networkId, Network.Service.Firewall)).thenReturn(virtualRouterElement.getCapabilities().get(Network.Service.Firewall));
+ when(firewallDao.persist(any())).thenReturn(rule);
+ when(firewallDao.setStateToAdd(any())).thenReturn(true);
+
+ // create Ingress rule
+ ReflectionTestUtils.setField(cmd, "trafficType", "ingress");
+ FirewallRule result = routedIpv4Manager.createRoutingFirewallRule(cmd);
+ Assert.assertNotNull(result);
+ Assert.assertEquals(rule, result);
+
+ // create Egress rule
+ ReflectionTestUtils.setField(cmd, "trafficType", "egress");
+ result = routedIpv4Manager.createRoutingFirewallRule(cmd);
+ Assert.assertNotNull(result);
+ Assert.assertEquals(rule, result);
+ }
+
+ @Test
+ public void testUpdateRoutingFirewallRule1() {
+ UpdateRoutingFirewallRuleCmd cmd = new UpdateRoutingFirewallRuleCmd();
+ ReflectionTestUtils.setField(cmd, "id", ruleId);
+
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getId()).thenReturn(ruleId);
+ when(rule.getTrafficType()).thenReturn(FirewallRule.TrafficType.Ingress);
+
+ routedIpv4Manager.updateRoutingFirewallRule(cmd);
+
+ verify(firewallManager).updateIngressFirewallRule(ruleId, null, true);
+ }
+
+ @Test
+ public void testUpdateRoutingFirewallRule2() {
+ UpdateRoutingFirewallRuleCmd cmd = new UpdateRoutingFirewallRuleCmd();
+ ReflectionTestUtils.setField(cmd, "id", ruleId);
+
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getId()).thenReturn(ruleId);
+ when(rule.getTrafficType()).thenReturn(FirewallRule.TrafficType.Egress);
+
+ routedIpv4Manager.updateRoutingFirewallRule(cmd);
+
+ verify(firewallManager).updateEgressFirewallRule(ruleId, null, true);
+ }
+
+ @Test
+ public void testRevokeRoutingFirewallRule1() {
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getId()).thenReturn(ruleId);
+ when(rule.getTrafficType()).thenReturn(FirewallRule.TrafficType.Ingress);
+
+ routedIpv4Manager.revokeRoutingFirewallRule(ruleId);
+
+ verify(firewallManager).revokeIngressFirewallRule(ruleId, true);
+ }
+
+ @Test
+ public void testRevokeRoutingFirewallRule2() {
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getId()).thenReturn(ruleId);
+ when(rule.getTrafficType()).thenReturn(FirewallRule.TrafficType.Egress);
+
+ routedIpv4Manager.revokeRoutingFirewallRule(ruleId);
+
+ verify(firewallManager).revokeEgressFirewallRule(ruleId, true);
+ }
+
+ @Test
+ public void testApplyRoutingFirewallRule1() {
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getPurpose()).thenReturn(FirewallRule.Purpose.Firewall);
+ when(rule.getNetworkId()).thenReturn(networkId);
+
+ FirewallRuleVO rule1 = Mockito.mock(FirewallRuleVO.class);
+ when(firewallDao.listByNetworkPurposeTrafficType(networkId, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Egress)).thenReturn(Arrays.asList(rule1));
+ FirewallRuleVO rule2 = Mockito.mock(FirewallRuleVO.class);
+ when(firewallDao.listByNetworkPurposeTrafficType(networkId, FirewallRule.Purpose.Firewall, FirewallRule.TrafficType.Ingress)).thenReturn(Arrays.asList(rule2));
+ when(firewallManager.applyFirewallRules(any(), eq(false), any())).thenReturn(true);
+
+ boolean result = routedIpv4Manager.applyRoutingFirewallRule(ruleId);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testApplyRoutingFirewallRule2() {
+ when(firewallDao.findById(ruleId)).thenReturn(rule);
+ when(rule.getPurpose()).thenReturn(FirewallRule.Purpose.LoadBalancing);
+
+ boolean result = routedIpv4Manager.applyRoutingFirewallRule(ruleId);
+ Assert.assertFalse(result);
+ }
+
+ @Test
+ public void testCreateBgpPeer() {
+ CreateBgpPeerCmd cmd = new CreateBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd, "zoneId", zoneId);
+ ReflectionTestUtils.setField(cmd, "ip4Address", ip4Address);
+ ReflectionTestUtils.setField(cmd, "ip6Address", ip6Address);
+ ReflectionTestUtils.setField(cmd, "asNumber", asNumber);
+ ReflectionTestUtils.setField(cmd, "password", password);
+
+ when(bgpPeerDao.findByZoneAndAsNumberAndAddress(zoneId, asNumber, ip4Address, null)).thenReturn(null);
+ when(bgpPeerDao.findByZoneAndAsNumberAndAddress(zoneId, asNumber, null, ip6Address)).thenReturn(null);
+
+ routedIpv4Manager.createBgpPeer(cmd);
+
+ verify(bgpPeerDao).persist(any(BgpPeerVO.class), any(Map.class));
+ }
+
+ @Test
+ public void testCreateBgpPeerResponse() {
+ BgpPeerVO bgpPeer = Mockito.mock(BgpPeerVO.class);
+ when(bgpPeer.getDataCenterId()).thenReturn(zoneId);
+ when(bgpPeer.getDomainId()).thenReturn(domainId);
+ when(bgpPeer.getAccountId()).thenReturn(accountId);
+ when(bgpPeer.getCreated()).thenReturn(created);
+ when(bgpPeer.getAsNumber()).thenReturn(asNumber);
+ when(bgpPeer.getUuid()).thenReturn(bgpPeerUuid);
+ when(bgpPeer.getIp4Address()).thenReturn(ip4Address);
+ when(bgpPeer.getIp6Address()).thenReturn(ip6Address);
+
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findZoneById(zoneId)).thenReturn(zone);
+ when(zone.getName()).thenReturn(zoneName);
+ when(zone.getUuid()).thenReturn(zoneUuid);
+
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findDomainById(domainId)).thenReturn(domain);
+ when(domain.getName()).thenReturn(domainName);
+ when(domain.getUuid()).thenReturn(domainUuid);
+
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findAccountById(accountId)).thenReturn(account);
+ when(account.getType()).thenReturn(Account.Type.PROJECT);
+ when(account.getId()).thenReturn(accountId);
+
+ apiDBUtilsMocked.when(() -> ApiDBUtils.findProjectByProjectAccountId(accountId)).thenReturn(project);
+ when(project.getName()).thenReturn(projectName);
+ when(project.getUuid()).thenReturn(projectUuid);
+
+ BgpPeerResponse response = routedIpv4Manager.createBgpPeerResponse(bgpPeer);
+
+ Assert.assertEquals(created, response.getCreated());
+ Assert.assertEquals(asNumber, response.getAsNumber());
+ Assert.assertEquals(ip4Address, response.getIp4Address());
+ Assert.assertEquals(ip6Address, response.getIp6Address());
+ Assert.assertEquals(bgpPeerUuid, response.getId());
+ Assert.assertEquals(zoneUuid, response.getZoneId());
+ Assert.assertEquals(zoneName, response.getZoneName());
+ Assert.assertEquals(domainUuid, response.getDomainId());
+ Assert.assertEquals(domainName, response.getDomainName());
+ Assert.assertEquals(projectName, response.getProjectName());
+ Assert.assertEquals(projectUuid, response.getProjectId());
+ Assert.assertNull(response.getAccountName());
+
+ Assert.assertEquals("bgppeer", response.getObjectName());
+
+ }
+
+ @Test
+ public void testDeleteBgpPeer1() {
+ DeleteBgpPeerCmd cmd = new DeleteBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd, "id", bgpPeerId);
+
+ BgpPeerNetworkMapVO bgpPeerNetworkMapVO = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMapDao.listByBgpPeerId(bgpPeerId)).thenReturn(Arrays.asList(bgpPeerNetworkMapVO));
+
+ try {
+ routedIpv4Manager.deleteBgpPeer(cmd);
+ Assert.fail("Deleting BGP peer should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("The BGP peer is being used by 1 guest networks.", ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testDeleteBgpPeer2() {
+ DeleteBgpPeerCmd cmd = new DeleteBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd, "id", bgpPeerId);
+
+ routedIpv4Manager.deleteBgpPeer(cmd);
+
+ verify(bgpPeerDao).remove(bgpPeerId);
+ }
+
+ @Test
+ public void testUpdateBgpPeer() {
+ UpdateBgpPeerCmd cmd = new UpdateBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd, "id", bgpPeerId);
+ ReflectionTestUtils.setField(cmd, "asNumber", asNumber+1);
+ ReflectionTestUtils.setField(cmd, "ip4Address", ip4Address + "1");
+ ReflectionTestUtils.setField(cmd, "ip6Address", ip6Address + "1");
+
+ when(bgpPeerDao.findById(bgpPeerId)).thenReturn(bgpPeer);
+ when(bgpPeer.getDataCenterId()).thenReturn(zoneId);
+
+ routedIpv4Manager.updateBgpPeer(cmd);
+
+ verify(bgpPeerDao).update(bgpPeerId, bgpPeer);
+ verify(bgpPeerDao).findByZoneAndAsNumberAndAddress(zoneId, asNumber+1, ip4Address + "1", null);
+ verify(bgpPeerDao).findByZoneAndAsNumberAndAddress(zoneId, asNumber+1, null, ip6Address + "1");
+ }
+
+ @Test
+ public void testDedicateBgpPeer() {
+ DedicateBgpPeerCmd cmd = new DedicateBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd,"id", bgpPeerId);
+ ReflectionTestUtils.setField(cmd,"domainId", domainId);
+ ReflectionTestUtils.setField(cmd,"accountName", accountName);
+ ReflectionTestUtils.setField(cmd,"projectId", null);
+
+ when(bgpPeerDao.findById(bgpPeerId)).thenReturn(bgpPeer);
+ when(accountManager.finalyzeAccountId(accountName, domainId, null, false)).thenReturn(accountId);
+ when(accountManager.getAccount(accountId)).thenReturn(account);
+ when(account.getDomainId()).thenReturn(domainId);
+
+ routedIpv4Manager.dedicateBgpPeer(cmd);
+
+ verify(bgpPeerDao).update(bgpPeerId, bgpPeer);
+ verify(bgpPeerNetworkMapDao).listUsedNetworksByOtherDomains(bgpPeerId, domainId);
+ verify(bgpPeerNetworkMapDao).listUsedVpcsByOtherDomains(bgpPeerId, domainId);
+ verify(bgpPeerNetworkMapDao).listUsedNetworksByOtherAccounts(bgpPeerId, accountId);
+ verify(bgpPeerNetworkMapDao).listUsedVpcsByOtherAccounts(bgpPeerId, accountId);
+ }
+
+ @Test
+ public void testReleaseDedicatedBgpPeer() {
+ ReleaseDedicatedBgpPeerCmd cmd = new ReleaseDedicatedBgpPeerCmd();
+ ReflectionTestUtils.setField(cmd,"id", bgpPeerId);
+ when(bgpPeerDao.findById(bgpPeerId)).thenReturn(bgpPeer);
+
+ routedIpv4Manager.releaseDedicatedBgpPeer(cmd);
+
+ verify(bgpPeer).setDomainId(null);
+ verify(bgpPeer).setAccountId(null);
+ verify(bgpPeerDao).update(bgpPeerId, bgpPeer);
+ }
+
+ @Test
+ public void testChangeBgpPeersForNetwork() {
+ ChangeBgpPeersForNetworkCmd cmd = new ChangeBgpPeersForNetworkCmd();
+ ReflectionTestUtils.setField(cmd,"networkId", networkId);
+ List<Long> bgpPeerIds = Arrays.asList(bgpPeerId);
+ ReflectionTestUtils.setField(cmd,"bgpPeerIds", bgpPeerIds);
+
+ when(networkDao.findById(networkId)).thenReturn(network);
+
+ try {
+ when(network.getVpcId()).thenReturn(vpcId);
+ routedIpv4Manager.changeBgpPeersForNetwork(cmd);
+ Assert.fail("Changing BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("The BGP peers of VPC tiers will inherit from the VPC, do not add separately.", ex.getMessage());
+ }
+
+ when(network.getVpcId()).thenReturn(null);
+ when(network.getAccountId()).thenReturn(accountId);
+ when(accountManager.getAccount(accountId)).thenReturn(account);
+ when(network.getNetworkOfferingId()).thenReturn(networkOfferingId);
+ when(networkOfferingDao.findById(networkOfferingId)).thenReturn(networkOffering);
+ when(network.getDataCenterId()).thenReturn(zoneId);
+
+ try {
+ when(networkOffering.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
+ when(networkOffering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
+ routedIpv4Manager.changeBgpPeersForNetwork(cmd);
+ Assert.fail("Changing BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("The network does not support Dynamic routing", ex.getMessage());
+ }
+
+ when(networkOffering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Dynamic);
+
+ doNothing().when(routedIpv4Manager).validateBgpPeers(account, zoneId, bgpPeerIds);
+ doReturn(network).when(routedIpv4Manager).changeBgpPeersForNetworkInternal(network, bgpPeerIds);
+
+ routedIpv4Manager.changeBgpPeersForNetwork(cmd);
+
+ verify(routedIpv4Manager).validateBgpPeers(account, zoneId, bgpPeerIds);
+ verify(routedIpv4Manager).changeBgpPeersForNetworkInternal(network, bgpPeerIds);
+ }
+
+ @Test
+ public void testChangeBgpPeersForNetworkInternal() throws ResourceUnavailableException {
+ Long bgpPeerId1 = 11L; // to be kept
+ Long bgpPeerId2 = 12L; // to be removed
+ Long bgpPeerId3 = 13L; // to be added
+ Long bgpPeerNetworkMapId2 = 14L; // to be removed
+
+ when(network.getId()).thenReturn(networkId);
+ when(networkDao.findById(networkId)).thenReturn(network);
+
+ BgpPeerNetworkMapVO bgpPeerNetworkMap1 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap1.getBgpPeerId()).thenReturn(bgpPeerId1);
+ when(bgpPeerNetworkMap1.getState()).thenReturn(BgpPeer.State.Active);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap2 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap2.getBgpPeerId()).thenReturn(bgpPeerId2);
+ when(bgpPeerNetworkMap2.getState()).thenReturn(BgpPeer.State.Revoke);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap3 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap3.getState()).thenReturn(BgpPeer.State.Add);
+
+ when(bgpPeerNetworkMap2.getId()).thenReturn(bgpPeerNetworkMapId2);
+
+ when(bgpPeerNetworkMapDao.listByNetworkId(networkId)).thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2))
+ .thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2, bgpPeerNetworkMap3));
+ when(bgpService.applyBgpPeers(network, false)).thenReturn(true);
+
+ Network result = routedIpv4Manager.changeBgpPeersForNetworkInternal(network, Arrays.asList(bgpPeerId1, bgpPeerId3));
+ Assert.assertEquals(network, result);
+
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Revoke);
+ verify(bgpPeerNetworkMapDao).persist(any());
+ verify(bgpPeerNetworkMap3).setState(BgpPeer.State.Active);
+ verify(bgpPeerNetworkMapDao).remove(bgpPeerNetworkMapId2);
+ }
+
+ @Test
+ public void testChangeBgpPeersForNetworkInternalFailure() throws ResourceUnavailableException {
+ Long bgpPeerId1 = 11L; // to be kept
+ Long bgpPeerId2 = 12L; // to be removed, but finally not
+ Long bgpPeerId3 = 13L; // to be added, but finally not
+ Long bgpPeerNetworkMapId3 = 15L; // to be added, but finally not
+
+ when(network.getId()).thenReturn(networkId);
+
+ BgpPeerNetworkMapVO bgpPeerNetworkMap1 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap1.getBgpPeerId()).thenReturn(bgpPeerId1);
+ when(bgpPeerNetworkMap1.getState()).thenReturn(BgpPeer.State.Active);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap2 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap2.getBgpPeerId()).thenReturn(bgpPeerId2);
+ when(bgpPeerNetworkMap2.getState()).thenReturn(BgpPeer.State.Revoke);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap3 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap3.getState()).thenReturn(BgpPeer.State.Add);
+
+ when(bgpPeerNetworkMap3.getId()).thenReturn(bgpPeerNetworkMapId3);
+
+ when(bgpPeerNetworkMapDao.listByNetworkId(networkId)).thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2))
+ .thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2, bgpPeerNetworkMap3));
+ when(bgpService.applyBgpPeers(network, false)).thenReturn(false);
+
+ Network result = routedIpv4Manager.changeBgpPeersForNetworkInternal(network, Arrays.asList(bgpPeerId1, bgpPeerId3));
+ Assert.assertNull(result);
+
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Revoke);
+ verify(bgpPeerNetworkMapDao).persist(any());
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Add);
+ verify(bgpPeerNetworkMapDao).remove(bgpPeerNetworkMapId3);
+ }
+
+ @Test
+ public void testValidateBgpPeers() {
+ List<Long> bgpPeerIds = Arrays.asList(bgpPeerId);
+ try {
+ routedIpv4Manager.validateBgpPeers(account, zoneId, bgpPeerIds);
+ Assert.fail("Validating BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("Invalid BGP peer ID: %s", bgpPeerId), ex.getMessage());
+ }
+
+ when(account.getDomainId()).thenReturn(domainId);
+ when(account.getAccountId()).thenReturn(accountId);
+ when(bgpPeerDao.findById(bgpPeerId)).thenReturn(bgpPeer);
+ when(bgpPeer.getUuid()).thenReturn(bgpPeerUuid);
+ try {
+ when(bgpPeer.getDataCenterId()).thenReturn(zoneId + 1);
+ routedIpv4Manager.validateBgpPeers(account, zoneId, bgpPeerIds);
+ Assert.fail("Validating BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("BGP peer (ID: %s) belongs to a different zone", bgpPeerUuid), ex.getMessage());
+ }
+
+ when(bgpPeer.getDataCenterId()).thenReturn(zoneId);
+ try {
+ when(bgpPeer.getDomainId()).thenReturn(domainId + 1);
+ routedIpv4Manager.validateBgpPeers(account, zoneId, bgpPeerIds);
+ Assert.fail("Validating BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("BGP peer (ID: %s) belongs to a different domain", bgpPeerUuid), ex.getMessage());
+ }
+
+ when(bgpPeer.getDomainId()).thenReturn(domainId);
+ try {
+ when(bgpPeer.getAccountId()).thenReturn(accountId + 1);
+ routedIpv4Manager.validateBgpPeers(account, zoneId, bgpPeerIds);
+ Assert.fail("Validating BGP peers for guest network should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals(String.format("BGP peer (ID: %s) belongs to a different account", bgpPeerUuid), ex.getMessage());
+ }
+
+ when(bgpPeer.getAccountId()).thenReturn(accountId);
+ routedIpv4Manager.validateBgpPeers(account, zoneId, bgpPeerIds);
+ }
+
+ @Test
+ public void testChangeBgpPeersForVpc() {
+ ChangeBgpPeersForVpcCmd cmd = new ChangeBgpPeersForVpcCmd();
+ ReflectionTestUtils.setField(cmd,"vpcId", vpcId);
+ List<Long> bgpPeerIds = Arrays.asList(bgpPeerId);
+ ReflectionTestUtils.setField(cmd,"bgpPeerIds", bgpPeerIds);
+
+ when(vpcDao.findById(vpcId)).thenReturn(vpc);
+ when(vpc.getAccountId()).thenReturn(accountId);
+ when(accountManager.getAccount(accountId)).thenReturn(account);
+ when(vpc.getVpcOfferingId()).thenReturn(vpcOfferingId);
+ when(vpcOfferingDao.findById(vpcOfferingId)).thenReturn(vpcOffering);
+ when(vpc.getZoneId()).thenReturn(zoneId);
+
+ try {
+ when(vpcOffering.getNetworkMode()).thenReturn(NetworkOffering.NetworkMode.ROUTED);
+ when(vpcOffering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Static);
+ routedIpv4Manager.changeBgpPeersForVpc(cmd);
+ Assert.fail("Changing BGP peers for VPC should fail.");
+ } catch (InvalidParameterValueException ex) {
+ Assert.assertEquals("The VPC does not support Dynamic routing", ex.getMessage());
+ }
+
+ when(vpcOffering.getRoutingMode()).thenReturn(NetworkOffering.RoutingMode.Dynamic);
+
+ doNothing().when(routedIpv4Manager).validateBgpPeers(account, zoneId, bgpPeerIds);
+ doReturn(vpc).when(routedIpv4Manager).changeBgpPeersForVpcInternal(vpc, bgpPeerIds);
+
+ routedIpv4Manager.changeBgpPeersForVpc(cmd);
+
+ verify(routedIpv4Manager).validateBgpPeers(account, zoneId, bgpPeerIds);
+ verify(routedIpv4Manager).changeBgpPeersForVpcInternal(vpc, bgpPeerIds);
+ }
+
+ @Test
+ public void testChangeBgpPeersForVpcInternal() throws ResourceUnavailableException {
+ Long bgpPeerId1 = 11L; // to be kept
+ Long bgpPeerId2 = 12L; // to be removed
+ Long bgpPeerId3 = 13L; // to be added
+ Long bgpPeerNetworkMapId2 = 14L; // to be removed
+
+ when(vpc.getId()).thenReturn(vpcId);
+ when(vpcDao.findById(vpcId)).thenReturn(vpc);
+
+ BgpPeerNetworkMapVO bgpPeerNetworkMap1 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap1.getBgpPeerId()).thenReturn(bgpPeerId1);
+ when(bgpPeerNetworkMap1.getState()).thenReturn(BgpPeer.State.Active);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap2 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap2.getBgpPeerId()).thenReturn(bgpPeerId2);
+ when(bgpPeerNetworkMap2.getState()).thenReturn(BgpPeer.State.Revoke);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap3 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap3.getState()).thenReturn(BgpPeer.State.Add);
+
+ when(bgpPeerNetworkMap2.getId()).thenReturn(bgpPeerNetworkMapId2);
+
+ when(bgpPeerNetworkMapDao.listByVpcId(vpcId)).thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2))
+ .thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2, bgpPeerNetworkMap3));
+ when(bgpService.applyBgpPeers(vpc, false)).thenReturn(true);
+
+ Vpc result = routedIpv4Manager.changeBgpPeersForVpcInternal(vpc, Arrays.asList(bgpPeerId1, bgpPeerId3));
+ Assert.assertEquals(vpc, result);
+
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Revoke);
+ verify(bgpPeerNetworkMapDao).persist(any());
+ verify(bgpPeerNetworkMap3).setState(BgpPeer.State.Active);
+ verify(bgpPeerNetworkMapDao).remove(bgpPeerNetworkMapId2);
+ }
+
+ @Test
+ public void testChangeBgpPeersForVpcInternalFailure() throws ResourceUnavailableException {
+ Long bgpPeerId1 = 11L; // to be kept
+ Long bgpPeerId2 = 12L; // to be removed, but finally not
+ Long bgpPeerId3 = 13L; // to be added, but finally not
+ Long bgpPeerNetworkMapId3 = 15L; // to be added, but finally not
+
+ when(vpc.getId()).thenReturn(vpcId);
+
+ BgpPeerNetworkMapVO bgpPeerNetworkMap1 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap1.getBgpPeerId()).thenReturn(bgpPeerId1);
+ when(bgpPeerNetworkMap1.getState()).thenReturn(BgpPeer.State.Active);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap2 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap2.getBgpPeerId()).thenReturn(bgpPeerId2);
+ when(bgpPeerNetworkMap2.getState()).thenReturn(BgpPeer.State.Revoke);
+ BgpPeerNetworkMapVO bgpPeerNetworkMap3 = Mockito.mock(BgpPeerNetworkMapVO.class);
+ when(bgpPeerNetworkMap3.getState()).thenReturn(BgpPeer.State.Add);
+
+ when(bgpPeerNetworkMap3.getId()).thenReturn(bgpPeerNetworkMapId3);
+
+ when(bgpPeerNetworkMapDao.listByVpcId(vpcId)).thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2))
+ .thenReturn(Arrays.asList(bgpPeerNetworkMap1, bgpPeerNetworkMap2, bgpPeerNetworkMap3));
+ when(bgpService.applyBgpPeers(vpc, false)).thenReturn(false);
+
+ Vpc result = routedIpv4Manager.changeBgpPeersForVpcInternal(vpc, Arrays.asList(bgpPeerId1, bgpPeerId3));
+ Assert.assertNull(result);
+
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Revoke);
+ verify(bgpPeerNetworkMapDao).persist(any());
+ verify(bgpPeerNetworkMap2).setState(BgpPeer.State.Add);
+ verify(bgpPeerNetworkMapDao).remove(bgpPeerNetworkMapId3);
+ }
+
+ @Test
+ public void testRemoveIpv4SubnetsForZoneByAccountId() {
+ when(dataCenterIpv4GuestSubnetDao.listByAccountId(accountId)).thenReturn(Arrays.asList(subnetVO));
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+
+ routedIpv4Manager.removeIpv4SubnetsForZoneByAccountId(accountId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).deleteByParentId(zoneSubnetId);
+ verify(dataCenterIpv4GuestSubnetDao).remove(zoneSubnetId);
+ }
+
+ @Test
+ public void testRemoveIpv4SubnetsForZoneByDomainId() {
+ when(dataCenterIpv4GuestSubnetDao.listByDomainId(domainId)).thenReturn(Arrays.asList(subnetVO));
+ when(subnetVO.getId()).thenReturn(zoneSubnetId);
+
+ routedIpv4Manager.removeIpv4SubnetsForZoneByDomainId(domainId);
+
+ verify(ipv4GuestSubnetNetworkMapDao).deleteByParentId(zoneSubnetId);
+ verify(dataCenterIpv4GuestSubnetDao).remove(zoneSubnetId);
+ }
+}
diff --git a/ui/src/config/section/infra/zones.js b/ui/src/config/section/infra/zones.js
index 25535979e4d..b4a34372e10 100644
--- a/ui/src/config/section/infra/zones.js
+++ b/ui/src/config/section/infra/zones.js
@@ -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'))),
diff --git a/ui/src/config/section/network.js b/ui/src/config/section/network.js
index 79eae34f537..3bb2c75eabf 100644
--- a/ui/src/config/section/network.js
+++ b/ui/src/config/section/network.js
@@ -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: [
{
diff --git a/ui/src/views/network/CreateIpv4SubnetForNetwork.vue b/ui/src/views/network/CreateIpv4SubnetForNetwork.vue
index 44af8246066..af1ef8c0e25 100644
--- a/ui/src/views/network/CreateIpv4SubnetForNetwork.vue
+++ b/ui/src/views/network/CreateIpv4SubnetForNetwork.vue
@@ -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(() => {
diff --git a/ui/src/views/network/CreateIsolatedNetworkForm.vue b/ui/src/views/network/CreateIsolatedNetworkForm.vue
index b60223219e7..2c3fa17fa35 100644
--- a/ui/src/views/network/CreateIsolatedNetworkForm.vue
+++ b/ui/src/views/network/CreateIsolatedNetworkForm.vue
@@ -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)
diff --git a/ui/src/views/network/CreateVpc.vue b/ui/src/views/network/CreateVpc.vue
index b0a56ca724a..6fb9a712262 100644
--- a/ui/src/views/network/CreateVpc.vue
+++ b/ui/src/views/network/CreateVpc.vue
@@ -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(() => {
diff --git a/ui/src/views/offering/AddNetworkOffering.vue b/ui/src/views/offering/AddNetworkOffering.vue
index 66d7a4a675e..f637823812e 100644
--- a/ui/src/views/offering/AddNetworkOffering.vue
+++ b/ui/src/views/offering/AddNetworkOffering.vue
@@ -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
diff --git a/ui/src/views/offering/AddVpcOffering.vue b/ui/src/views/offering/AddVpcOffering.vue
index c914467a088..450ee117715 100644
--- a/ui/src/views/offering/AddVpcOffering.vue
+++ b/ui/src/views/offering/AddVpcOffering.vue
@@ -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