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 getBgpPeersForNetwork(Network network); + + List 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(); } @@ -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 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 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 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 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 bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId()); - bgpPeers = bgpPeerIds.stream() - .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId)) - .collect(Collectors.toList()); - } + List 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 bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId()); - if (CollectionUtils.isEmpty(bgpPeers)) { - Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId()); - List bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, vpc.getZoneId()); - bgpPeers = bgpPeerIds.stream() - .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId)) - .collect(Collectors.toList()); - } + List 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 getBgpPeersForNetwork(Network network) { + List 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 bgpPeerIds = routedIpv4Manager.getBgpPeerIdsForAccount(owner, network.getDataCenterId()); + bgpPeers = bgpPeerIds.stream() + .map(bgpPeerId -> bgpPeerDao.findById(bgpPeerId)) + .collect(Collectors.toList()); + } + return bgpPeers; + } + + @Override + public List getBgpPeersForVpc(Vpc vpc) { + List bgpPeers = bgpPeerDao.listNonRevokeByVpcId(vpc.getId()); + if (CollectionUtils.isEmpty(bgpPeers)) { + Account owner = accountDao.findByIdIncludingRemoved(vpc.getAccountId()); + List 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 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 bgpPeers = bgpPeerDao.listNonRevokeByVpcId(guestNetwork.getVpcId()); + List bgpPeers = bgpService.getBgpPeersForVpc(vpc); _commandSetupHelper.createBgpPeersCommands(bgpPeers, router, cmds, guestNetwork); } } else { if (routedIpv4Manager.isDynamicRoutedNetwork(guestNetwork)) { - final List bgpPeers = bgpPeerDao.listNonRevokeByNetworkId(guestNetworkId); + List 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> getCommands() { final List> cmdList = new ArrayList>(); + 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 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 existingSubnets, String newSubnet, Long ignoreSubnetId) { + protected void checkConflicts(List 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 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 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 getZoneSubnetsForAccount(long domainId, long accountId, long zoneId) { // Get dedicated guest subnets for the account - List subnets = dataCenterIpv4GuestSubnetDao.listByDataCenterIdAndAccountId(zoneId, accountId); + List 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> 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 rules = firewallDao.listByNetworkPurposeTrafficType(rule.getNetworkId(), rule.getPurpose(), FirewallRule.TrafficType.Egress); + List 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 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 bgpPeerIds) { + protected Network changeBgpPeersForNetworkInternal(Network network, List bgpPeerIds) { final List 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 bgpPeerIds) { + protected Vpc changeBgpPeersForVpcInternal(Vpc vpc, List bgpPeerIds) { final List 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 sourceCidrList = Arrays.asList("192.168.0.0/24", "10.0.0.0/8"); + ReflectionTestUtils.setField(cmd, "sourceCidrList", sourceCidrList); + List 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 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 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 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