From 09bd84704050055fc635c10a6891ff8ecd65ac66 Mon Sep 17 00:00:00 2001 From: Antonio Fornie Date: Sun, 28 Sep 2014 03:38:06 -0500 Subject: [PATCH] Vpc redundancy enabled. Including Vpc & Vpc Offering creation. Marvin tests and UI. --- api/src/com/cloud/network/Network.java | 2 + api/src/com/cloud/network/NetworkProfile.java | 11 +- api/src/com/cloud/network/vpc/Vpc.java | 2 + .../com/cloud/network/vpc/VpcOffering.java | 4 + .../apache/cloudstack/api/ApiConstants.java | 1 + .../cloudstack/api/response/VpcResponse.java | 8 + .../orchestration/NetworkOrchestrator.java | 3 +- .../src/com/cloud/network/dao/NetworkVO.java | 20 +- .../com/cloud/network/vpc/VpcOfferingVO.java | 15 +- .../src/com/cloud/network/vpc/VpcVO.java | 21 +- .../cloud/upgrade/dao/Upgrade451to460.java | 62 ++++- .../guru/BigSwitchVnsGuestNetworkGuru.java | 2 +- .../contrail/management/ContrailGuru.java | 2 +- .../management/ManagementNetworkGuru.java | 2 +- .../network/guru/MidoNetGuestNetworkGuru.java | 2 +- .../guru/MidoNetPublicNetworkGuru.java | 4 +- .../guru/NiciraNvpGuestNetworkGuru.java | 2 +- .../guru/NuageVspGuestNetworkGuru.java | 4 +- .../OpendaylightGuestNetworkGuru.java | 2 +- .../network/guru/VxlanGuestNetworkGuru.java | 2 +- .../src/com/cloud/api/ApiResponseHelper.java | 1 + .../network/element/VirtualRouterElement.java | 18 +- .../element/VpcVirtualRouterElement.java | 3 +- .../network/guru/ControlNetworkGuru.java | 2 +- .../cloud/network/guru/DirectNetworkGuru.java | 3 +- .../guru/ExternalGuestNetworkGuru.java | 2 +- .../cloud/network/guru/GuestNetworkGuru.java | 4 +- .../network/guru/PodBasedNetworkGuru.java | 3 +- .../network/guru/PrivateNetworkGuru.java | 3 +- .../cloud/network/guru/PublicNetworkGuru.java | 2 +- .../network/guru/StorageNetworkGuru.java | 2 +- .../network/router/NetworkHelperImpl.java | 2 +- .../com/cloud/network/vpc/VpcManagerImpl.java | 260 ++++++++---------- .../cloud/server/ConfigurationServerImpl.java | 2 +- .../RouterDeploymentDefinition.java | 60 ++-- .../RouterDeploymentDefinitionBuilder.java | 37 +-- .../VpcRouterDeploymentDefinition.java | 49 ++-- .../network/CreatePrivateNetworkTest.java | 2 +- .../cloud/network/vpc/VpcManagerImplTest.java | 107 ++++++- server/test/com/cloud/vpc/VpcApiUnitTest.java | 2 +- .../com/cloud/vpc/dao/MockVpcDaoImpl.java | 4 +- .../lb/ApplicationLoadBalancerTest.java | 4 +- .../RouterDeploymentDefinitionTest.java | 58 ++-- .../VpcRouterDeploymentDefinitionTest.java | 49 +++- .../component/test_vpc_offerings.py | 80 ++++++ ui/scripts/configuration.js | 15 +- 46 files changed, 620 insertions(+), 325 deletions(-) diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index c5a9bf286df..e07cea627ff 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -326,6 +326,8 @@ public interface Network extends ControlledEntity, StateObject, I @Override State getState(); + boolean isRedundant(); + long getRelated(); URI getBroadcastUri(); diff --git a/api/src/com/cloud/network/NetworkProfile.java b/api/src/com/cloud/network/NetworkProfile.java index 1b806d56de9..ab033edaa53 100644 --- a/api/src/com/cloud/network/NetworkProfile.java +++ b/api/src/com/cloud/network/NetworkProfile.java @@ -16,12 +16,12 @@ // under the License. package com.cloud.network; -import java.net.URI; - import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.Networks.Mode; import com.cloud.network.Networks.TrafficType; +import java.net.URI; + public class NetworkProfile implements Network { private final long id; private final String uuid; @@ -32,6 +32,7 @@ public class NetworkProfile implements Network { private String dns2; private URI broadcastUri; private final State state; + private boolean isRedundant; private final String name; private final Mode mode; private final BroadcastDomainType broadcastDomainType; @@ -89,6 +90,7 @@ public class NetworkProfile implements Network { networkAclId = network.getNetworkACLId(); guruName = network.getGuruName(); strechedL2Subnet = network.isStrechedL2Network(); + isRedundant = network.isRedundant(); } public String getDns1() { @@ -146,6 +148,11 @@ public class NetworkProfile implements Network { return state; } + @Override + public boolean isRedundant() { + return this.isRedundant; + } + @Override public String getName() { return name; diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java index 23388787d23..dd607fe6caa 100644 --- a/api/src/com/cloud/network/vpc/Vpc.java +++ b/api/src/com/cloud/network/vpc/Vpc.java @@ -74,6 +74,8 @@ public interface Vpc extends ControlledEntity, Identity, InternalIdentity { boolean isDisplay(); + boolean isRedundant(); + /** * * @return true if VPC is configured to use distributed router to provides one-hop forwarding and hypervisor based ACL diff --git a/api/src/com/cloud/network/vpc/VpcOffering.java b/api/src/com/cloud/network/vpc/VpcOffering.java index 660c79dc1e4..fb4b151fb4c 100644 --- a/api/src/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/com/cloud/network/vpc/VpcOffering.java @@ -26,6 +26,7 @@ public interface VpcOffering extends InternalIdentity, Identity { public static final String defaultVPCOfferingName = "Default VPC offering"; public static final String defaultVPCNSOfferingName = "Default VPC offering with Netscaler"; + public static final String redundantVPCOfferingName = "Redundant VPC offering"; /** * @@ -64,4 +65,7 @@ public interface VpcOffering extends InternalIdentity, Identity { * @return true if VPC created with the offering can span multiple zones in the region */ boolean offersRegionLevelVPC(); + + boolean getRedundantRouter(); + } diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 72b5e64c1dd..0cae1d3b4ef 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -608,6 +608,7 @@ public class ApiConstants { public static final String REMAININGCAPACITY = "remainingcapacity"; public static final String MAXCAPACITY = "maxcapacity"; public static final String DISTRIBUTED_VPC_ROUTER = "distributedvpcrouter"; + public static final String REDUNDANT_VPC_ROUTER = "redundantvpcrouter"; public static final String READ_ONLY = "readonly"; public static final String SUPPORTS_REGION_LEVEL_VPC = "supportsregionLevelvpc"; public static final String SUPPORTS_STRECHED_L2_SUBNET = "supportsstrechedl2subnet"; diff --git a/api/src/org/apache/cloudstack/api/response/VpcResponse.java b/api/src/org/apache/cloudstack/api/response/VpcResponse.java index d1afdfb8169..7f9565affb1 100644 --- a/api/src/org/apache/cloudstack/api/response/VpcResponse.java +++ b/api/src/org/apache/cloudstack/api/response/VpcResponse.java @@ -119,6 +119,10 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons @Param(description = "true if VPC is region level", since = "4.4") private Boolean regionLevelVpc; + @SerializedName(ApiConstants.REDUNDANT_VPC_ROUTER) + @Param(description = "if this VPC has redundant router", since = "4.4") + private boolean redundantRouter; + public void setId(String id) { this.id = id; } @@ -215,4 +219,8 @@ public class VpcResponse extends BaseResponse implements ControlledEntityRespons public void setUsesDistributedRouter(Boolean usesDistributedRouter) { this.usesDistributedRouter = usesDistributedRouter; } + + public void setRedundantRouter(Boolean redundantRouter) { + this.redundantRouter = redundantRouter; + } } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java index ead46828c81..6277df1b1ef 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -670,7 +670,8 @@ public class NetworkOrchestrator extends ManagerBase implements NetworkOrchestra @Override public void doInTransactionWithoutResult(TransactionStatus status) { NetworkVO vo = new NetworkVO(id, network, offering.getId(), guru.getName(), owner.getDomainId(), owner.getId(), relatedFile, name, displayText, predefined - .getNetworkDomain(), offering.getGuestType(), plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(), vpcId); + .getNetworkDomain(), offering.getGuestType(), plan.getDataCenterId(), plan.getPhysicalNetworkId(), aclType, offering.getSpecifyIpRanges(), + vpcId, offering.getRedundantRouter()); vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled); vo.setStrechedL2Network(offering.getSupportsStrechedL2()); networks.add(_networksDao.persist(vo, vo.getGuestType() == Network.GuestType.Isolated, diff --git a/engine/schema/src/com/cloud/network/dao/NetworkVO.java b/engine/schema/src/com/cloud/network/dao/NetworkVO.java index b0332106aec..34d5aa7420e 100644 --- a/engine/schema/src/com/cloud/network/dao/NetworkVO.java +++ b/engine/schema/src/com/cloud/network/dao/NetworkVO.java @@ -103,6 +103,9 @@ public class NetworkVO implements Network { @Enumerated(value = EnumType.STRING) State state; + @Column(name = "redundant") + boolean isRedundant; + @Column(name = "dns1") String dns1; @@ -184,13 +187,14 @@ public class NetworkVO implements Network { * @param physicalNetworkId TODO */ public NetworkVO(TrafficType trafficType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, State state, long dataCenterId, - Long physicalNetworkId) { + Long physicalNetworkId, final boolean isRedundant) { this.trafficType = trafficType; this.mode = mode; this.broadcastDomainType = broadcastDomainType; this.networkOfferingId = networkOfferingId; this.dataCenterId = dataCenterId; this.physicalNetworkId = physicalNetworkId; + this.isRedundant = isRedundant; if (state == null) { this.state = State.Allocated; } else { @@ -201,7 +205,7 @@ public class NetworkVO implements Network { } public NetworkVO(long id, Network that, long offeringId, String guruName, long domainId, long accountId, long related, String name, String displayText, - String networkDomain, GuestType guestType, long dcId, Long physicalNetworkId, ACLType aclType, boolean specifyIpRanges, Long vpcId) { + String networkDomain, GuestType guestType, long dcId, Long physicalNetworkId, ACLType aclType, boolean specifyIpRanges, Long vpcId, final boolean isRedundant) { this(id, that.getTrafficType(), that.getMode(), @@ -218,7 +222,8 @@ public class NetworkVO implements Network { physicalNetworkId, aclType, specifyIpRanges, - vpcId); + vpcId, + isRedundant); gateway = that.getGateway(); cidr = that.getCidr(); networkCidr = that.getNetworkCidr(); @@ -253,8 +258,8 @@ public class NetworkVO implements Network { */ public NetworkVO(long id, TrafficType trafficType, Mode mode, BroadcastDomainType broadcastDomainType, long networkOfferingId, long domainId, long accountId, long related, String name, String displayText, String networkDomain, GuestType guestType, long dcId, Long physicalNetworkId, ACLType aclType, - boolean specifyIpRanges, Long vpcId) { - this(trafficType, mode, broadcastDomainType, networkOfferingId, State.Allocated, dcId, physicalNetworkId); + boolean specifyIpRanges, Long vpcId, final boolean isRedundant) { + this(trafficType, mode, broadcastDomainType, networkOfferingId, State.Allocated, dcId, physicalNetworkId, isRedundant); this.domainId = domainId; this.accountId = accountId; this.related = related; @@ -283,6 +288,11 @@ public class NetworkVO implements Network { return state; } + @Override + public boolean isRedundant() { + return this.isRedundant; + } + // don't use this directly when possible, use Network state machine instead public void setState(State state) { this.state = state; diff --git a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java index a7d61b36923..bd13a02d90a 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcOfferingVO.java @@ -73,6 +73,9 @@ public class VpcOfferingVO implements VpcOffering { @Column(name = "supports_region_level_vpc") boolean offersRegionLevelVPC = false; + @Column(name = "redundant_router_service") + boolean redundantRouter = false; + public VpcOfferingVO() { this.uuid = UUID.randomUUID().toString(); } @@ -86,12 +89,14 @@ public class VpcOfferingVO implements VpcOffering { this.state = State.Disabled; } - public VpcOfferingVO(String name, String displayText, boolean isDefault, Long serviceOfferingId, - boolean supportsDistributedRouter, boolean offersRegionLevelVPC) { + public VpcOfferingVO(final String name, final String displayText, final boolean isDefault, final Long serviceOfferingId, + final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC, + final boolean redundantRouter) { this(name, displayText, serviceOfferingId); this.isDefault = isDefault; this.supportsDistributedRouter = supportsDistributedRouter; this.offersRegionLevelVPC = offersRegionLevelVPC; + this.redundantRouter = redundantRouter; } @Override @@ -164,4 +169,10 @@ public class VpcOfferingVO implements VpcOffering { public boolean offersRegionLevelVPC() { return offersRegionLevelVPC; } + + @Override + public boolean getRedundantRouter() { + return this.redundantRouter; + } + } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/com/cloud/network/vpc/VpcVO.java index 8c124b29c15..b400d95380d 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcVO.java @@ -16,8 +16,7 @@ // under the License. package com.cloud.network.vpc; -import java.util.Date; -import java.util.UUID; +import com.cloud.utils.db.GenericDao; import javax.persistence.Column; import javax.persistence.Entity; @@ -25,8 +24,8 @@ import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.Id; import javax.persistence.Table; - -import com.cloud.utils.db.GenericDao; +import java.util.Date; +import java.util.UUID; @Entity @Table(name = "vpc") @@ -61,6 +60,9 @@ public class VpcVO implements Vpc { @Enumerated(value = EnumType.STRING) State state; + @Column(name = "redundant") + boolean isRedundant; + @Column(name = "vpc_offering_id") long vpcOfferingId; @@ -89,8 +91,9 @@ public class VpcVO implements Vpc { uuid = UUID.randomUUID().toString(); } - public VpcVO(long zoneId, String name, String displayText, long accountId, long domainId, long vpcOffId, String cidr, - String networkDomain, boolean useDistributedRouter, boolean regionLevelVpc) { + public VpcVO(final long zoneId, final String name, final String displayText, final long accountId, final long domainId, + final long vpcOffId, String cidr, final String networkDomain, final boolean useDistributedRouter, + final boolean regionLevelVpc, final boolean isRedundant) { this.zoneId = zoneId; this.name = name; this.displayText = displayText; @@ -103,6 +106,7 @@ public class VpcVO implements Vpc { vpcOfferingId = vpcOffId; this.usesDistributedRouter = useDistributedRouter; this.regionLevelVpc = regionLevelVpc; + this.isRedundant = isRedundant; } @Override @@ -210,6 +214,11 @@ public class VpcVO implements Vpc { return display; } + @Override + public boolean isRedundant() { + return this.isRedundant; + } + @Override public Class getEntityType() { return Vpc.class; diff --git a/engine/schema/src/com/cloud/upgrade/dao/Upgrade451to460.java b/engine/schema/src/com/cloud/upgrade/dao/Upgrade451to460.java index a3be9ec7c77..6c1f05e0b6c 100644 --- a/engine/schema/src/com/cloud/upgrade/dao/Upgrade451to460.java +++ b/engine/schema/src/com/cloud/upgrade/dao/Upgrade451to460.java @@ -48,7 +48,7 @@ public class Upgrade451to460 implements DbUpgrade { @Override public File[] getPrepareScripts() { - String script = Script.findScript("", "db/schema-451to460.sql"); + final String script = Script.findScript("", "db/schema-451to460.sql"); if (script == null) { throw new CloudRuntimeException("Unable to find db/schema-451to460.sql"); } @@ -57,49 +57,81 @@ public class Upgrade451to460 implements DbUpgrade { } @Override - public void performDataMigration(Connection conn) { + public void performDataMigration(final Connection conn) { updateVMInstanceUserId(conn); } - public void updateVMInstanceUserId(Connection conn) { + public void updateVMInstanceUserId(final Connection conn) { // For schemas before this, copy first user from an account_id which deployed already running VMs s_logger.debug("Updating vm_instance column user_id using first user in vm_instance's account_id"); - String vmInstanceSql = "SELECT id, account_id FROM `cloud`.`vm_instance`"; - String userSql = "SELECT id FROM `cloud`.`user` where account_id=?"; - String userIdUpdateSql = "update `cloud`.`vm_instance` set user_id=? where id=?"; + final String vmInstanceSql = "SELECT id, account_id FROM `cloud`.`vm_instance`"; + final String userSql = "SELECT id FROM `cloud`.`user` where account_id=?"; + final String userIdUpdateSql = "update `cloud`.`vm_instance` set user_id=? where id=?"; try(PreparedStatement selectStatement = conn.prepareStatement(vmInstanceSql)) { - ResultSet results = selectStatement.executeQuery(); + final ResultSet results = selectStatement.executeQuery(); while (results.next()) { - long vmId = results.getLong(1); - long accountId = results.getLong(2); + final long vmId = results.getLong(1); + final long accountId = results.getLong(2); try (PreparedStatement selectUserStatement = conn.prepareStatement(userSql)) { selectUserStatement.setLong(1, accountId); - ResultSet userResults = selectUserStatement.executeQuery(); + final ResultSet userResults = selectUserStatement.executeQuery(); if (userResults.next()) { - long userId = userResults.getLong(1); + final long userId = userResults.getLong(1); try (PreparedStatement updateStatement = conn.prepareStatement(userIdUpdateSql)) { updateStatement.setLong(1, userId); updateStatement.setLong(2, vmId); updateStatement.executeUpdate(); - } catch (SQLException e) { + } catch (final SQLException e) { throw new CloudRuntimeException("Unable to update user ID " + userId + " on vm_instance id=" + vmId, e); } } - } catch (SQLException e) { + } catch (final SQLException e) { throw new CloudRuntimeException("Unable to update user ID using accountId " + accountId + " on vm_instance id=" + vmId, e); } } - } catch (SQLException e) { + } catch (final SQLException e) { throw new CloudRuntimeException("Unable to update user Ids for previously deployed VMs", e); } s_logger.debug("Done updating user Ids for previously deployed VMs"); + addRedundancyForNwAndVpc(conn); } + private void addRedundancyForNwAndVpc(final Connection conn) { + ResultSet rs = null; + try (PreparedStatement addRedundantColToVpcOfferingPstmt = conn.prepareStatement( + "ALTER TABLE `cloud`.`vpc_offerings` ADD COLUMN `redundant_router_service` tinyint(1) DEFAULT 0"); + PreparedStatement addRedundantColToVpcPstmt = conn.prepareStatement( + "ALTER TABLE `cloud`.`vpc` ADD COLUMN `redundant` tinyint(1) DEFAULT 0"); + PreparedStatement addRedundantColToNwPstmt = conn.prepareStatement( + "ALTER TABLE `cloud`.`networks` ADD COLUMN `redundant` tinyint(1) DEFAULT 0"); + + // The redundancy of the networks must be based on the redundancy of their network offerings + PreparedStatement redundancyPerNwPstmt = conn.prepareStatement( + "select distinct nw.network_offering_id from networks nw join network_offerings off " + + "on nw.network_offering_id = off.id where off.redundant_router_service = 1"); + PreparedStatement updateNwRedundancyPstmt = conn.prepareStatement( + "update networks set redundant = 1 where network_offering_id = ?"); + ) { + addRedundantColToVpcPstmt.executeUpdate(); + addRedundantColToVpcOfferingPstmt.executeUpdate(); + addRedundantColToNwPstmt.executeUpdate(); + + rs = redundancyPerNwPstmt.executeQuery(); + while(rs.next()){ + final long nwOfferingId = rs.getLong("nw.network_offering_id"); + updateNwRedundancyPstmt.setLong(1, nwOfferingId); + updateNwRedundancyPstmt.executeUpdate(); + } + } catch (final SQLException e) { + e.printStackTrace(); + throw new CloudRuntimeException("Adding redundancy to vpc, networks and vpc_offerings failed", e); + } + } @Override public File[] getCleanupScripts() { - String script = Script.findScript("", "db/schema-451to460-cleanup.sql"); + final String script = Script.findScript("", "db/schema-451to460-cleanup.sql"); if (script == null) { throw new CloudRuntimeException("Unable to find db/schema-451to460-cleanup.sql"); } diff --git a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java index 9805144ef92..cff758544f6 100644 --- a/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java +++ b/plugins/network-elements/bigswitch-vns/src/com/cloud/network/guru/BigSwitchVnsGuestNetworkGuru.java @@ -138,7 +138,7 @@ public class BigSwitchVnsGuestNetworkGuru extends GuestNetworkGuru { NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ContrailGuru.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ContrailGuru.java index 391a9b3dbed..427c2795305 100644 --- a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ContrailGuru.java +++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ContrailGuru.java @@ -132,7 +132,7 @@ public class ContrailGuru extends AdapterBase implements NetworkGuru { } NetworkVO network = new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Lswitch, offering.getId(), State.Allocated, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); if (userSpecified.getCidr() != null) { network.setCidr(userSpecified.getCidr()); network.setGateway(userSpecified.getGateway()); diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ManagementNetworkGuru.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ManagementNetworkGuru.java index cfc6fb62a11..71d2901a1e3 100644 --- a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ManagementNetworkGuru.java +++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ManagementNetworkGuru.java @@ -120,7 +120,7 @@ public class ManagementNetworkGuru extends ContrailGuru { } NetworkVO network = new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Lswitch, offering.getId(), Network.State.Allocated, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); if (_mgmtCidr != null) { network.setCidr(_mgmtCidr); network.setGateway(_mgmtGateway); diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java index e24fa5c3ae8..aaf2fca51ba 100644 --- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java +++ b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetGuestNetworkGuru.java @@ -104,7 +104,7 @@ public class MidoNetGuestNetworkGuru extends GuestNetworkGuru { NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); diff --git a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java index 6af97c8674b..ee8fa27609d 100644 --- a/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java +++ b/plugins/network-elements/midonet/src/com/cloud/network/guru/MidoNetPublicNetworkGuru.java @@ -80,7 +80,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { if (offering.getTrafficType() == Networks.TrafficType.Public) { NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), Networks.Mode.Static, Networks.BroadcastDomainType.Mido, offering.getId(), Network.State.Allocated, - plan.getDataCenterId(), plan.getPhysicalNetworkId()); + plan.getDataCenterId(), plan.getPhysicalNetworkId(), offering.getRedundantRouter()); return ntwk; } else { return null; @@ -185,7 +185,7 @@ public class MidoNetPublicNetworkGuru extends PublicNetworkGuru { NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), Network.State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); diff --git a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java index 2845e9b8afa..e68f740cdcf 100644 --- a/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java +++ b/plugins/network-elements/nicira-nvp/src/com/cloud/network/guru/NiciraNvpGuestNetworkGuru.java @@ -158,7 +158,7 @@ public class NiciraNvpGuestNetworkGuru extends GuestNetworkGuru { NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); diff --git a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java index d9882eaa7b3..6dc1a003cfa 100644 --- a/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java +++ b/plugins/network-elements/nuage-vsp/src/com/cloud/network/guru/NuageVspGuestNetworkGuru.java @@ -140,7 +140,7 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { physicalNetworkId = _networkModel.findPhysicalNetworkId(dcId, offering.getTags(), offering.getTrafficType()); } NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); } @@ -413,4 +413,4 @@ public class NuageVspGuestNetworkGuru extends GuestNetworkGuru { } return nuageVspHost; } -} \ No newline at end of file +} diff --git a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java index 5dc0f449642..cbaa4d024b3 100644 --- a/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java +++ b/plugins/network-elements/opendaylight/src/main/java/org/apache/cloudstack/network/opendaylight/OpendaylightGuestNetworkGuru.java @@ -143,7 +143,7 @@ public class OpendaylightGuestNetworkGuru extends GuestNetworkGuru { } NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); if (network.getGateway() != null) { implemented.setGateway(network.getGateway()); diff --git a/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java index 0700ef8f3cf..4138b228e10 100644 --- a/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java +++ b/plugins/network-elements/vxlan/src/com/cloud/network/guru/VxlanGuestNetworkGuru.java @@ -121,7 +121,7 @@ public class VxlanGuestNetworkGuru extends GuestNetworkGuru { NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); allocateVnet(network, implemented, dcId, physicalNetworkId, context.getReservationId()); diff --git a/server/src/com/cloud/api/ApiResponseHelper.java b/server/src/com/cloud/api/ApiResponseHelper.java index 275a2b862fd..65d9a21f3de 100644 --- a/server/src/com/cloud/api/ApiResponseHelper.java +++ b/server/src/com/cloud/api/ApiResponseHelper.java @@ -2703,6 +2703,7 @@ public class ApiResponseHelper implements ResponseGenerator { response.setNetworkDomain(vpc.getNetworkDomain()); response.setForDisplay(vpc.isDisplay()); response.setUsesDistributedRouter(vpc.usesDistributedRouter()); + response.setRedundantRouter(vpc.isRedundant()); response.setRegionLevelVpc(vpc.isRegionLevelVpc()); Map> serviceProviderMap = ApiDBUtils.listVpcOffServices(vpc.getVpcOfferingId()); diff --git a/server/src/com/cloud/network/element/VirtualRouterElement.java b/server/src/com/cloud/network/element/VirtualRouterElement.java index 5d7f5256e40..2c28f8749de 100644 --- a/server/src/com/cloud/network/element/VirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VirtualRouterElement.java @@ -204,8 +204,13 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); - RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create().setGuestNetwork(network).setDeployDestination(dest) - .setAccountOwner(_accountMgr.getAccount(network.getAccountId())).setParams(params).setRedundant(offering.getRedundantRouter()).build(); + RouterDeploymentDefinition routerDeploymentDefinition = + routerDeploymentDefinitionBuilder.create() + .setGuestNetwork(network) + .setDeployDestination(dest) + .setAccountOwner(_accountMgr.getAccount(network.getAccountId())) + .setParams(params) + .build(); List routers = routerDeploymentDefinition.deployVirtualRouter(); @@ -239,8 +244,13 @@ public class VirtualRouterElement extends AdapterBase implements VirtualRouterEl return false; } - RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create().setGuestNetwork(network).setDeployDestination(dest) - .setAccountOwner(_accountMgr.getAccount(network.getAccountId())).setParams(vm.getParameters()).setRedundant(offering.getRedundantRouter()).build(); + RouterDeploymentDefinition routerDeploymentDefinition = + routerDeploymentDefinitionBuilder.create() + .setGuestNetwork(network) + .setDeployDestination(dest) + .setAccountOwner(_accountMgr.getAccount(network.getAccountId())) + .setParams(vm.getParameters()) + .build(); List routers = routerDeploymentDefinition.deployVirtualRouter(); diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 4a29fd1c4c2..63864c169fc 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -326,7 +326,8 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc Map sourceNatCapabilities = new HashMap(); sourceNatCapabilities.putAll(capabilities.get(Service.SourceNat)); - sourceNatCapabilities.put(Capability.RedundantRouter, "false"); + // TODO This kind of logic is already placed in the DB + sourceNatCapabilities.put(Capability.RedundantRouter, "true"); capabilities.put(Service.SourceNat, sourceNatCapabilities); Map vpnCapabilities = new HashMap(); diff --git a/server/src/com/cloud/network/guru/ControlNetworkGuru.java b/server/src/com/cloud/network/guru/ControlNetworkGuru.java index dd7c92d685f..355842ce8a2 100644 --- a/server/src/com/cloud/network/guru/ControlNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ControlNetworkGuru.java @@ -100,7 +100,7 @@ public class ControlNetworkGuru extends PodBasedNetworkGuru implements NetworkGu NetworkVO config = new NetworkVO(offering.getTrafficType(), Mode.Static, BroadcastDomainType.LinkLocal, offering.getId(), Network.State.Setup, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); config.setCidr(_cidr); config.setGateway(_gateway); diff --git a/server/src/com/cloud/network/guru/DirectNetworkGuru.java b/server/src/com/cloud/network/guru/DirectNetworkGuru.java index 95afc5f39d6..f3805534529 100644 --- a/server/src/com/cloud/network/guru/DirectNetworkGuru.java +++ b/server/src/com/cloud/network/guru/DirectNetworkGuru.java @@ -141,7 +141,8 @@ public class DirectNetworkGuru extends AdapterBase implements NetworkGuru { } NetworkVO config = - new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), state, plan.getDataCenterId(), plan.getPhysicalNetworkId()); + new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), state, plan.getDataCenterId(), + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { diff --git a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java index 3524b770803..d01a65bfcc5 100644 --- a/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/ExternalGuestNetworkGuru.java @@ -138,7 +138,7 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru { DataCenter zone = dest.getDataCenter(); NetworkVO implemented = new NetworkVO(config.getTrafficType(), config.getMode(), config.getBroadcastDomainType(), config.getNetworkOfferingId(), State.Allocated, - config.getDataCenterId(), config.getPhysicalNetworkId()); + config.getDataCenterId(), config.getPhysicalNetworkId(), offering.getRedundantRouter()); // Get a vlan tag int vlanTag; diff --git a/server/src/com/cloud/network/guru/GuestNetworkGuru.java b/server/src/com/cloud/network/guru/GuestNetworkGuru.java index 138afd5c176..17b313c029a 100644 --- a/server/src/com/cloud/network/guru/GuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/GuestNetworkGuru.java @@ -187,7 +187,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur NetworkVO network = new NetworkVO(offering.getTrafficType(), Mode.Dhcp, BroadcastDomainType.Vlan, offering.getId(), State.Allocated, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { throw new InvalidParameterValueException("cidr and gateway must be specified together."); @@ -311,7 +311,7 @@ public abstract class GuestNetworkGuru extends AdapterBase implements NetworkGur NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated, - network.getDataCenterId(), physicalNetworkId); + network.getDataCenterId(), physicalNetworkId, offering.getRedundantRouter()); allocateVnet(network, implemented, dcId, physicalNetworkId, context.getReservationId()); diff --git a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java index b99fc761021..49480db6b71 100644 --- a/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PodBasedNetworkGuru.java @@ -83,7 +83,8 @@ public class PodBasedNetworkGuru extends AdapterBase implements NetworkGuru { } NetworkVO config = - new NetworkVO(type, Mode.Static, BroadcastDomainType.Native, offering.getId(), Network.State.Setup, plan.getDataCenterId(), plan.getPhysicalNetworkId()); + new NetworkVO(type, Mode.Static, BroadcastDomainType.Native, offering.getId(), Network.State.Setup, plan.getDataCenterId(), + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); return config; } diff --git a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java index aefd0002783..e9bde69dd5d 100644 --- a/server/src/com/cloud/network/guru/PrivateNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PrivateNetworkGuru.java @@ -112,7 +112,8 @@ public class PrivateNetworkGuru extends AdapterBase implements NetworkGuru { broadcastType = BroadcastDomainType.Vlan; } NetworkVO network = - new NetworkVO(offering.getTrafficType(), Mode.Static, broadcastType, offering.getId(), State.Allocated, plan.getDataCenterId(), plan.getPhysicalNetworkId()); + new NetworkVO(offering.getTrafficType(), Mode.Static, broadcastType, offering.getId(), State.Allocated, plan.getDataCenterId(), + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); if (userSpecified != null) { if ((userSpecified.getCidr() == null && userSpecified.getGateway() != null) || (userSpecified.getCidr() != null && userSpecified.getGateway() == null)) { throw new InvalidParameterValueException("cidr and gateway must be specified together."); diff --git a/server/src/com/cloud/network/guru/PublicNetworkGuru.java b/server/src/com/cloud/network/guru/PublicNetworkGuru.java index 19c2ce24cf2..b1c226bb9d9 100644 --- a/server/src/com/cloud/network/guru/PublicNetworkGuru.java +++ b/server/src/com/cloud/network/guru/PublicNetworkGuru.java @@ -104,7 +104,7 @@ public class PublicNetworkGuru extends AdapterBase implements NetworkGuru { if (offering.getTrafficType() == TrafficType.Public) { NetworkVO ntwk = new NetworkVO(offering.getTrafficType(), Mode.Static, network.getBroadcastDomainType(), offering.getId(), State.Setup, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); return ntwk; } else { return null; diff --git a/server/src/com/cloud/network/guru/StorageNetworkGuru.java b/server/src/com/cloud/network/guru/StorageNetworkGuru.java index 716d5a0f891..9df7a1b56f1 100644 --- a/server/src/com/cloud/network/guru/StorageNetworkGuru.java +++ b/server/src/com/cloud/network/guru/StorageNetworkGuru.java @@ -90,7 +90,7 @@ public class StorageNetworkGuru extends PodBasedNetworkGuru implements NetworkGu NetworkVO config = new NetworkVO(offering.getTrafficType(), Mode.Static, BroadcastDomainType.Native, offering.getId(), Network.State.Setup, plan.getDataCenterId(), - plan.getPhysicalNetworkId()); + plan.getPhysicalNetworkId(), offering.getRedundantRouter()); return config; } diff --git a/server/src/com/cloud/network/router/NetworkHelperImpl.java b/server/src/com/cloud/network/router/NetworkHelperImpl.java index 852a22328a7..5267a9a7596 100644 --- a/server/src/com/cloud/network/router/NetworkHelperImpl.java +++ b/server/src/com/cloud/network/router/NetworkHelperImpl.java @@ -477,7 +477,7 @@ public class NetworkHelperImpl implements NetworkHelper { public DomainRouterVO deployRouter(final RouterDeploymentDefinition routerDeploymentDefinition, final boolean startRouter) throws InsufficientAddressCapacityException, InsufficientServerCapacityException, InsufficientCapacityException, StorageUnavailableException, ResourceUnavailableException { - final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getOfferingId()); + final ServiceOfferingVO routerOffering = _serviceOfferingDao.findById(routerDeploymentDefinition.getServiceOfferingId()); final Account owner = routerDeploymentDefinition.getOwner(); // Router is the network element, we don't know the hypervisor type yet. diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 99f3aa1bd5c..08276d77ffa 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -74,6 +74,7 @@ import com.cloud.network.Network; import com.cloud.network.Network.GuestType; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.Network.Capability; import com.cloud.network.NetworkModel; import com.cloud.network.NetworkService; import com.cloud.network.Networks.BroadcastDomainType; @@ -142,6 +143,13 @@ import com.cloud.vm.dao.DomainRouterDao; @Local(value = {VpcManager.class, VpcService.class, VpcProvisioningService.class}) public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvisioningService, VpcService { private static final Logger s_logger = Logger.getLogger(VpcManagerImpl.class); + + public static final String SERVICE = "service"; + public static final String CAPABILITYTYPE = "capabilitytype"; + public static final String CAPABILITYVALUE = "capabilityvalue"; + public static final String TRUE_VALUE = "true"; + public static final String FALSE_VALUE = "false"; + @Inject EntityManager _entityMgr; @Inject @@ -254,7 +262,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } } createVpcOffering(VpcOffering.defaultVPCOfferingName, VpcOffering.defaultVPCOfferingName, - svcProviderMap, true, State.Enabled, null, false, false); + svcProviderMap, true, State.Enabled, null, false, false, false); } //configure default vpc offering with Netscaler as LB Provider @@ -274,11 +282,30 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } } createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, - svcProviderMap, false, State.Enabled, null, false, false); + svcProviderMap, false, State.Enabled, null, false, false, false); } - } + if (_vpcOffDao.findByUniqueName(VpcOffering.redundantVPCOfferingName) == null) { + s_logger.debug("Creating Redundant VPC offering " + VpcOffering.redundantVPCOfferingName); + + Map> svcProviderMap = new HashMap>(); + Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (Service svc : getSupportedServices()) { + if (svc == Service.Lb) { + Set lbProviders = new HashSet(); + lbProviders.add(Provider.VPCVirtualRouter); + lbProviders.add(Provider.InternalLbVm); + svcProviderMap.put(svc, lbProviders); + } else { + svcProviderMap.put(svc, defaultProviders); + } + } + createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, + svcProviderMap, true, State.Enabled, null, false, false, true); + } + } }); Map configs = _configDao.getConfiguration(params); @@ -329,6 +356,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis Map> serviceProviders, Map serviceCapabilitystList, Long serviceOfferingId) { + Map> svcProviderMap = new HashMap>(); Set defaultProviders = new HashSet(); defaultProviders.add(Provider.VPCVirtualRouter); @@ -401,12 +429,13 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } } - validateConnectivtyServiceCapablitlies(svcProviderMap.get(Service.Connectivity), serviceCapabilitystList); + validateConnectivtyServiceCapabilities(svcProviderMap.get(Service.Connectivity), serviceCapabilitystList); boolean supportsDistributedRouter = isVpcOfferingSupportsDistributedRouter(serviceCapabilitystList); boolean offersRegionLevelVPC = isVpcOfferingForRegionLevelVpc(serviceCapabilitystList); + boolean redundantRouter = this.isVpcOfferingRedundantRouter(serviceCapabilitystList); VpcOffering offering = createVpcOffering(name, displayText, svcProviderMap, false, null, - serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC); + serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC, redundantRouter); CallContext.current().setEventDetails(" Id: " + offering.getId() + " Name: " + name); return offering; @@ -416,14 +445,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis protected VpcOffering createVpcOffering(final String name, final String displayText, final Map> svcProviderMap, final boolean isDefault, final State state, final Long serviceOfferingId, - final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC) { + final boolean supportsDistributedRouter, final boolean offersRegionLevelVPC, + final boolean redundantRouter) { return Transaction.execute(new TransactionCallback() { @Override public VpcOffering doInTransaction(TransactionStatus status) { // create vpc offering object VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, - supportsDistributedRouter, offersRegionLevelVPC); + supportsDistributedRouter, offersRegionLevelVPC, redundantRouter); if (state != null) { offering.setState(state); @@ -451,152 +481,100 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis }); } - private void validateConnectivtyServiceCapablitlies(Set providers, Map serviceCapabilitystList) { - - if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { - Collection serviceCapabilityCollection = serviceCapabilitystList.values(); - Iterator iter = serviceCapabilityCollection.iterator(); - Map capabilityMap = null; - boolean distributedRouterCapabilitySpecified = false; - boolean regionLevelVpcCapabilitySpecified = false; - - while (iter.hasNext()) { - HashMap svcCapabilityMap = (HashMap)iter.next(); - Network.Capability capability = null; - String svc = svcCapabilityMap.get("service"); - String capabilityName = svcCapabilityMap.get("capabilitytype"); - String capabilityValue = svcCapabilityMap.get("capabilityvalue"); - if (capabilityName != null) { - capability = Network.Capability.getCapability(capabilityName); - } - - if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) { - throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); - } - - if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { - throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only 'Connectivity'" + - " service capabilities can be specified"); - } - - if (!capabilityName.equalsIgnoreCase("DistributedRouter") && !capabilityName.equalsIgnoreCase("RegionLevelVpc")) { - throw new InvalidParameterValueException("Invalid Capability:" + capabilityName + " specified." + - " Only 'DistributedRouter'/'RegionLevelVpc' capability can be specified."); - } - - if (capabilityName.equalsIgnoreCase("DistributedRouter")) { - distributedRouterCapabilitySpecified = true; - } - - if (capabilityName.equalsIgnoreCase("RegionLevelVpc")) { - regionLevelVpcCapabilitySpecified = true; - } - - if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { - throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); - } - } - - if (providers != null && !providers.isEmpty()) { - for (Provider provider: providers) { - NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); - Map> capabilities = element.getCapabilities(); - if (capabilities != null && !capabilities.isEmpty()) { - Map connectivityCapabilities = capabilities.get(Service.Connectivity); - if (regionLevelVpcCapabilitySpecified) { - if (connectivityCapabilities == null || (connectivityCapabilities != null && - !connectivityCapabilities.keySet().contains(Network.Capability.RegionLevelVpc))) { - throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " - + Network.Capability.RegionLevelVpc.getName() + " capability."); - } - } - if (distributedRouterCapabilitySpecified) { - if (connectivityCapabilities == null || (connectivityCapabilities != null && - !connectivityCapabilities.keySet().contains(Network.Capability.DistributedRouter))) { - throw new InvalidParameterValueException("Provider: " + provider.getName() + " does not support " - + Network.Capability.DistributedRouter.getName() + " capability."); - } - } + protected void checkCapabilityPerServiceProvider(final Set providers, final Capability capability, + final Service service) { + // TODO Shouldn't it fail it there are no providers? + if (providers != null) { + for (Provider provider: providers) { + NetworkElement element = _ntwkModel.getElementImplementingProvider(provider.getName()); + Map> capabilities = element.getCapabilities(); + if (capabilities != null && !capabilities.isEmpty()) { + Map connectivityCapabilities = capabilities.get(service); + if (connectivityCapabilities == null || (connectivityCapabilities != null && + !connectivityCapabilities.keySet().contains(capability))) { + throw new InvalidParameterValueException(String.format( + "Provider %s does not support %s capability.", + provider.getName(), capability.getName())); } } } } } - private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) { - boolean offersRegionLevelVPC = false; + private void validateConnectivtyServiceCapabilities(Set providers, Map serviceCapabilitystList) { if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { Collection serviceCapabilityCollection = serviceCapabilitystList.values(); Iterator iter = serviceCapabilityCollection.iterator(); - Map capabilityMap = null; + List specifiedCapabilities = new ArrayList<>(); while (iter.hasNext()) { HashMap svcCapabilityMap = (HashMap)iter.next(); - Network.Capability capability = null; - String svc = svcCapabilityMap.get("service"); - String capabilityName = svcCapabilityMap.get("capabilitytype"); - String capabilityValue = svcCapabilityMap.get("capabilityvalue"); + Capability capability = null; + String svc = svcCapabilityMap.get(SERVICE); + String capabilityName = svcCapabilityMap.get(CAPABILITYTYPE); + String capabilityValue = svcCapabilityMap.get(CAPABILITYVALUE); if (capabilityName != null) { - capability = Network.Capability.getCapability(capabilityName); + capability = Capability.getCapability(capabilityName); } - if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) { + if ((capability == null) || (capabilityValue == null)) { throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); } + Service usedService = Service.getService(svc); - if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { - throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); - } + this.checkCapabilityPerServiceProvider(providers, capability, usedService); - if (!capabilityName.equalsIgnoreCase("RegionLevelVpc")) { - continue; - } - - if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { + if (!capabilityValue.equalsIgnoreCase(TRUE_VALUE) && !capabilityValue.equalsIgnoreCase(FALSE_VALUE)) { throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); } - offersRegionLevelVPC = capabilityValue.equalsIgnoreCase("true"); } } - return offersRegionLevelVPC; + } + + private boolean findCapabilityForService(Map serviceCapabilitystList, Capability capability, Service service) { + boolean foundCapability = false; + if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { + Iterator iter = serviceCapabilitystList.values().iterator(); + while (iter.hasNext()) { + HashMap currentCapabilityMap = (HashMap)iter.next(); + String currentCapabilityService = currentCapabilityMap.get(SERVICE); + String currentCapabilityName = currentCapabilityMap.get(CAPABILITYTYPE); + String currentCapabilityValue = currentCapabilityMap.get(CAPABILITYVALUE); + + if ((currentCapabilityName == null) || (currentCapabilityService == null) || (currentCapabilityValue == null)) { + throw new InvalidParameterValueException(String.format("Invalid capability with name %s, value %s and service %s", + currentCapabilityName, currentCapabilityValue, currentCapabilityService)); + } + + if (currentCapabilityName.equalsIgnoreCase(capability.getName())) { + foundCapability = currentCapabilityValue.equalsIgnoreCase(TRUE_VALUE); + + if (!currentCapabilityService.equalsIgnoreCase(service.getName())) { + throw new InvalidParameterValueException(String.format( + "Invalid Service: %s specified. Capability %s can be specified only for service %s", + currentCapabilityService, service.getName(), currentCapabilityName)); + } + + break; + } + } + } + return foundCapability; + } + + private boolean isVpcOfferingForRegionLevelVpc(Map serviceCapabilitystList) { + return this.findCapabilityForService(serviceCapabilitystList, Capability.RegionLevelVpc, + Service.Connectivity); } private boolean isVpcOfferingSupportsDistributedRouter(Map serviceCapabilitystList) { - boolean supportsDistributedRouter = false; - if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { - Collection serviceCapabilityCollection = serviceCapabilitystList.values(); - Iterator iter = serviceCapabilityCollection.iterator(); - Map capabilityMap = null; + return this.findCapabilityForService(serviceCapabilitystList, Capability.DistributedRouter, + Service.Connectivity); + } - while (iter.hasNext()) { - HashMap svcCapabilityMap = (HashMap)iter.next(); - Network.Capability capability = null; - String svc = svcCapabilityMap.get("service"); - String capabilityName = svcCapabilityMap.get("capabilitytype"); - String capabilityValue = svcCapabilityMap.get("capabilityvalue"); - if (capabilityName != null) { - capability = Network.Capability.getCapability(capabilityName); - } - - if ((capability == null) || (capabilityName == null) || (capabilityValue == null)) { - throw new InvalidParameterValueException("Invalid capability:" + capabilityName + " capability value:" + capabilityValue); - } - - if (!svc.equalsIgnoreCase(Service.Connectivity.getName())) { - throw new InvalidParameterValueException("Invalid Service:" + svc + " specified. Only for 'Connectivity' service capabilities can be specified"); - } - - if (!capabilityName.equalsIgnoreCase("DistributedRouter")) { - continue; - } - - if (!capabilityValue.equalsIgnoreCase("true") && capabilityValue.equalsIgnoreCase("false")) { - throw new InvalidParameterValueException("Invalid Capability value:" + capabilityValue + " specified."); - } - supportsDistributedRouter = capabilityValue.equalsIgnoreCase("true"); - } - } - return supportsDistributedRouter; + private boolean isVpcOfferingRedundantRouter(Map serviceCapabilitystList) { + return this.findCapabilityForService(serviceCapabilitystList, Capability.RedundantRouter, + Service.SourceNat); } @Override @@ -832,14 +810,15 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } boolean useDistributedRouter = vpcOff.supportsDistributedRouter(); - return createVpc(zoneId, vpcOffId, owner, vpcName, displayText, cidr, networkDomain, displayVpc, - useDistributedRouter, isRegionLevelVpcOff); + final VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, owner.getId(), owner.getDomainId(), vpcOffId, + cidr, networkDomain, useDistributedRouter, isRegionLevelVpcOff, vpcOff.getRedundantRouter()); + + return createVpc(displayVpc, vpc); } @DB - protected Vpc createVpc(final long zoneId, final long vpcOffId, final Account vpcOwner, final String vpcName, final String displayText, final String cidr, - final String networkDomain, final Boolean displayVpc, final boolean useDistributedRouter, final boolean regionLevelVpc) { - + protected Vpc createVpc(final Boolean displayVpc, final VpcVO vpc) { + final String cidr = vpc.getCidr(); //Validate CIDR if (!NetUtils.isValidCIDR(cidr)) { throw new InvalidParameterValueException("Invalid CIDR specified " + cidr); @@ -851,7 +830,7 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } // validate network domain - if (!NetUtils.verifyDomainName(networkDomain)) { + if (!NetUtils.verifyDomainName(vpc.getNetworkDomain())) { throw new InvalidParameterValueException("Invalid network domain. Total length shouldn't exceed 190 chars. Each domain " + "label must be between 1 and 63 characters long, can contain ASCII letters 'a' through 'z', " + "the digits '0' through '9', " + "and the hyphen ('-'); can't start or end with \"-\""); @@ -860,24 +839,21 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis return Transaction.execute(new TransactionCallback() { @Override public VpcVO doInTransaction(TransactionStatus status) { - VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, vpcOwner.getId(), vpcOwner.getDomainId(), vpcOffId, - cidr, networkDomain, useDistributedRouter, regionLevelVpc); - if (displayVpc != null) { vpc.setDisplay(displayVpc); } - vpc = _vpcDao.persist(vpc, finalizeServicesAndProvidersForVpc(zoneId, vpcOffId)); - _resourceLimitMgr.incrementResourceCount(vpcOwner.getId(), ResourceType.vpc); - s_logger.debug("Created VPC " + vpc); + VpcVO persistedVpc = _vpcDao.persist(vpc, finalizeServicesAndProvidersForVpc(vpc.getZoneId(), vpc.getVpcOfferingId())); + _resourceLimitMgr.incrementResourceCount(vpc.getAccountId(), ResourceType.vpc); + s_logger.debug("Created VPC " + persistedVpc); - return vpc; - } + return persistedVpc; + } }); } private Map> finalizeServicesAndProvidersForVpc(long zoneId, long offeringId) { - Map> svcProviders = new HashMap>(); + Map> svcProviders = new HashMap<>(); List servicesMap = _vpcOffSvcMapDao.listByVpcOffId(offeringId); for (VpcOfferingServiceMapVO serviceMap : servicesMap) { @@ -1342,9 +1318,11 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis } //3) No redundant router support + /* TODO This should have never been hardcoded like this in the first place if (guestNtwkOff.getRedundantRouter()) { throw new InvalidParameterValueException("No redunant router support when network belnogs to VPC"); } + */ //4) Conserve mode should be off if (guestNtwkOff.isConserveMode()) { diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index a3bd14ad9b0..58e0692b187 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -1341,7 +1341,7 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio if (broadcastDomainType != null) { NetworkVO network = new NetworkVO(id, trafficType, mode, broadcastDomainType, networkOfferingId, domainId, accountId, related, null, null, networkDomain, - Network.GuestType.Shared, zoneId, null, null, specifyIpRanges, null); + Network.GuestType.Shared, zoneId, null, null, specifyIpRanges, null, offering.getRedundantRouter()); network.setGuruName(guruNames.get(network.getTrafficType())); network.setDns1(zone.getDns1()); network.setDns2(zone.getDns2()); diff --git a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java index 89dde3e7fd2..0dc3097338e 100644 --- a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinition.java @@ -16,13 +16,6 @@ // under the License. package org.cloud.network.router.deployment; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.apache.log4j.Logger; - import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.HostPodVO; import com.cloud.dc.Pod; @@ -67,6 +60,12 @@ import com.cloud.vm.VirtualMachineProfile.Param; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class RouterDeploymentDefinition { private static final Logger logger = Logger.getLogger(RouterDeploymentDefinition.class); @@ -92,25 +91,24 @@ public class RouterDeploymentDefinition { protected DeployDestination dest; protected Account owner; protected Map params; - protected boolean isRedundant; protected DeploymentPlan plan; protected List routers = new ArrayList<>(); - protected Long offeringId; + protected Long serviceOfferingId; protected Long tableLockId; protected boolean isPublicNetwork; protected PublicIp sourceNatIp; - protected RouterDeploymentDefinition(final Network guestNetwork, final DeployDestination dest, final Account owner, final Map params, final boolean isRedundant) { + protected RouterDeploymentDefinition(final Network guestNetwork, final DeployDestination dest, + final Account owner, final Map params) { this.guestNetwork = guestNetwork; this.dest = dest; this.owner = owner; this.params = params; - this.isRedundant = isRedundant; } - public Long getOfferingId() { - return offeringId; + public Long getServiceOfferingId() { + return this.serviceOfferingId; } public Vpc getVpc() { @@ -134,7 +132,7 @@ public class RouterDeploymentDefinition { } public boolean isRedundant() { - return isRedundant; + return this.guestNetwork.isRedundant(); } public DeploymentPlan getPlan() { @@ -287,7 +285,7 @@ public class RouterDeploymentDefinition { // If old network is redundant but new is single router, then // routers.size() = 2 but routerCount = 1 int routersExpected = 1; - if (isRedundant) { + if (this.isRedundant()) { routersExpected = 2; } return routersExpected < routers.size() ? 0 : routersExpected - routers.size(); @@ -312,7 +310,7 @@ public class RouterDeploymentDefinition { isPublicNetwork = networkModel.isProviderSupportServiceInNetwork(guestNetwork.getId(), Service.SourceNat, Provider.VirtualRouter); boolean canProceed = true; - if (isRedundant && !isPublicNetwork) { + if (this.isRedundant() && !this.isPublicNetwork) { // TODO Shouldn't be this throw an exception instead of log error and empty list of routers logger.error("Didn't support redundant virtual router without public network!"); routers = new ArrayList(); @@ -331,17 +329,17 @@ public class RouterDeploymentDefinition { * @throws InsufficientCapacityException * @throws ResourceUnavailableException */ - protected void executeDeployment() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - // Check current redundant routers, if possible(all routers are - // stopped), reset the priority - planDeploymentRouters(); - setupPriorityOfRedundantRouter(); + protected void executeDeployment() + throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - if (getNumberOfRoutersToDeploy() > 0 && prepareDeployment()) { - findVirtualProvider(); - findOfferingId(); - findSourceNatIP(); - deployAllVirtualRouters(); + //Check current redundant routers, if possible(all routers are stopped), reset the priority + this.setupPriorityOfRedundantRouter(); + + if (this.getNumberOfRoutersToDeploy() > 0 && this.prepareDeployment()) { + this.findVirtualProvider(); + this.findServiceOfferingId(); + this.findSourceNatIP(); + this.deployAllVirtualRouters(); } } @@ -352,10 +350,10 @@ public class RouterDeploymentDefinition { } } - protected void findOfferingId() { + protected void findServiceOfferingId() { Long networkOfferingId = networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()).getServiceOfferingId(); if (networkOfferingId != null) { - offeringId = networkOfferingId; + this.serviceOfferingId = networkOfferingId; } } @@ -445,8 +443,8 @@ public class RouterDeploymentDefinition { * reset all routers priorities */ protected void setupPriorityOfRedundantRouter() { - if (isRedundant && routersNeedReset()) { - for (final DomainRouterVO router : routers) { + if (this.isRedundant() && this.routersNeedReset()) { + for (final DomainRouterVO router : this.routers) { // getUpdatedPriority() would update the value later router.setPriority(0); router.setIsPriorityBumpUp(false); @@ -454,4 +452,4 @@ public class RouterDeploymentDefinition { } } } -} \ No newline at end of file +} diff --git a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java index b78535efe95..84bbd8b19f2 100644 --- a/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java +++ b/server/src/org/cloud/network/router/deployment/RouterDeploymentDefinitionBuilder.java @@ -16,16 +16,6 @@ // under the License. package org.cloud.network.router.deployment; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import javax.inject.Inject; - -import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; - import com.cloud.dc.dao.HostPodDao; import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DeployDestination; @@ -52,6 +42,14 @@ import com.cloud.vm.VirtualMachineProfile.Param; import com.cloud.vm.dao.DomainRouterDao; import com.cloud.vm.dao.NicDao; import com.cloud.vm.dao.VMInstanceDao; +import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import javax.inject.Inject; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class RouterDeploymentDefinitionBuilder { @@ -128,7 +126,7 @@ public class RouterDeploymentDefinitionBuilder { routerDeploymentDefinition.nicDao = nicDao; routerDeploymentDefinition.ipv6Dao = ipv6Dao; routerDeploymentDefinition.ipAddressDao = ipAddressDao; - routerDeploymentDefinition.offeringId = offeringId; + routerDeploymentDefinition.serviceOfferingId = offeringId; routerDeploymentDefinition.nwHelper = nwHelper; @@ -160,30 +158,19 @@ public class RouterDeploymentDefinitionBuilder { protected DeployDestination dest; protected Account owner; protected Map params; - protected boolean isRedundant; protected List routers = new ArrayList<>(); protected IntermediateStateBuilder(final RouterDeploymentDefinitionBuilder builder) { this.builder = builder; } - public IntermediateStateBuilder makeRedundant() { - isRedundant = true; - return this; - } - - public IntermediateStateBuilder setRedundant(final boolean isRedundant) { - this.isRedundant = isRedundant; - return this; - } - public IntermediateStateBuilder setVpc(final Vpc vpc) { this.vpc = vpc; return this; } public IntermediateStateBuilder setGuestNetwork(final Network nw) { - guestNetwork = nw; + this.guestNetwork = nw; return this; } @@ -205,9 +192,9 @@ public class RouterDeploymentDefinitionBuilder { public RouterDeploymentDefinition build() { RouterDeploymentDefinition routerDeploymentDefinition = null; if (vpc != null) { - routerDeploymentDefinition = new VpcRouterDeploymentDefinition(vpc, dest, owner, params, isRedundant); + routerDeploymentDefinition = new VpcRouterDeploymentDefinition(vpc, dest, owner, params); } else { - routerDeploymentDefinition = new RouterDeploymentDefinition(guestNetwork, dest, owner, params, isRedundant); + routerDeploymentDefinition = new RouterDeploymentDefinition(guestNetwork, dest, owner, params); } return builder.injectDependencies(routerDeploymentDefinition); diff --git a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java index f8fb26e21f1..a9784049070 100644 --- a/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java +++ b/server/src/org/cloud/network/router/deployment/VpcRouterDeploymentDefinition.java @@ -16,12 +16,6 @@ // under the License. package org.cloud.network.router.deployment; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; - import com.cloud.dc.dao.VlanDao; import com.cloud.deploy.DataCenterDeployment; import com.cloud.deploy.DeployDestination; @@ -41,6 +35,11 @@ import com.cloud.user.Account; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.VirtualMachineProfile.Param; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { private static final Logger logger = Logger.getLogger(VpcRouterDeploymentDefinition.class); @@ -53,9 +52,10 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { protected Vpc vpc; - protected VpcRouterDeploymentDefinition(final Vpc vpc, final DeployDestination dest, final Account owner, final Map params, final boolean isRedundant) { + protected VpcRouterDeploymentDefinition(final Vpc vpc, final DeployDestination dest, final Account owner, + final Map params) { - super(null, dest, owner, params, isRedundant); + super(null, dest, owner, params); this.vpc = vpc; } @@ -108,9 +108,9 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { @Override protected int getNumberOfRoutersToDeploy() { - // TODO Should we make our changes here in order to enable Redundant - // Router for VPC? - return routers.isEmpty() ? 1 : 0; + // Enable redundant Vpc, with the same behavior a Non Vpc Router + // TODO Remove this method unless we need to actually add some behavior + return super.getNumberOfRoutersToDeploy(); } /** @@ -125,9 +125,9 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { @Override protected void setupPriorityOfRedundantRouter() { - // Nothing to do for now - // TODO Shouldn't we add this behavior once Redundant Router works for - // Vpc too + // Implement Redundant Vpc + // TODO Remove this method unless we need to actually add some behavior + super.setupPriorityOfRedundantRouter(); } @Override @@ -152,10 +152,10 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { } @Override - protected void findOfferingId() { + protected void findServiceOfferingId() { Long vpcOfferingId = vpcOffDao.findById(vpc.getVpcOfferingId()).getServiceOfferingId(); if (vpcOfferingId != null) { - offeringId = vpcOfferingId; + serviceOfferingId = vpcOfferingId; } } @@ -163,10 +163,16 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { protected void deployAllVirtualRouters() throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { - DomainRouterVO router = nwHelper.deployRouter(this, true); + // Implement Redundant Vpc + int routersToDeploy = this.getNumberOfRoutersToDeploy(); + for(int i = 0; i < routersToDeploy; i++) { + // Don't start the router as we are holding the network lock that needs to be released at the end of router allocation + DomainRouterVO router = this.nwHelper.deployRouter(this, false); - if (router != null) { - routers.add(router); + if (router != null) { + // TODO this.routerDao.addRouterToGuestNetwork(router, this.guestNetwork); + this.routers.add(router); + } } } @@ -179,4 +185,9 @@ public class VpcRouterDeploymentDefinition extends RouterDeploymentDefinition { protected void generateDeploymentPlan() { plan = new DataCenterDeployment(dest.getDataCenter().getId()); } + + @Override + public boolean isRedundant() { + return this.vpc.isRedundant(); + } } diff --git a/server/test/com/cloud/network/CreatePrivateNetworkTest.java b/server/test/com/cloud/network/CreatePrivateNetworkTest.java index b124b20dadc..2e6cfa14369 100644 --- a/server/test/com/cloud/network/CreatePrivateNetworkTest.java +++ b/server/test/com/cloud/network/CreatePrivateNetworkTest.java @@ -119,7 +119,7 @@ public class CreatePrivateNetworkTest { Network net = new NetworkVO(1L, TrafficType.Guest, Mode.None, BroadcastDomainType.Vlan, 1L, 1L, 1L, 1L, "bla", "fake", "eet.net", GuestType.Isolated, 1L, 1L, - ACLType.Account, false, 1L); + ACLType.Account, false, 1L, false); when( networkService._networkMgr.createGuestNetwork(eq(ntwkOff.getId()), eq("bla"), eq("fake"), eq("10.1.1.1"), eq("10.1.1.0/24"), anyString(), anyString(), eq(account), anyLong(), eq(physicalNetwork), eq(physicalNetwork.getDataCenterId()), eq(ACLType.Account), anyBoolean(), eq(1L), anyString(), anyString(), diff --git a/server/test/com/cloud/network/vpc/VpcManagerImplTest.java b/server/test/com/cloud/network/vpc/VpcManagerImplTest.java index 3918a374034..fb0776f551a 100644 --- a/server/test/com/cloud/network/vpc/VpcManagerImplTest.java +++ b/server/test/com/cloud/network/vpc/VpcManagerImplTest.java @@ -20,22 +20,31 @@ package com.cloud.network.vpc; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.when; +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.network.NetworkModel; +import com.cloud.network.element.NetworkElement; + +import com.cloud.network.Network; +import com.cloud.network.Network.Capability; import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import org.junit.Before; import org.junit.Test; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao; +import org.powermock.reflect.Whitebox; + +import static org.mockito.Mockito.mock; +import static org.powermock.api.mockito.PowerMockito.when; public class VpcManagerImplTest { @@ -50,11 +59,12 @@ public class VpcManagerImplTest { manager = new VpcManagerImpl(); manager._vpcOffSvcMapDao = vpcOffSvcMapDao; } + @Test public void getVpcOffSvcProvidersMapForEmptyServiceTest() { long vpcOffId = 1L; List list = new ArrayList(); - list.add(Mockito.mock(VpcOfferingServiceMapVO.class)); + list.add(mock(VpcOfferingServiceMapVO.class)); when(manager._vpcOffSvcMapDao.listByVpcOffId(vpcOffId)).thenReturn(list); Map> map = manager.getVpcOffSvcProvidersMap(vpcOffId); @@ -63,4 +73,93 @@ public class VpcManagerImplTest { assertEquals(map.size(),1); } + protected Map createFakeCapabilityInputMap() { + Map map = new HashMap(); + map.put(VpcManagerImpl.CAPABILITYVALUE, VpcManagerImpl.TRUE_VALUE); + map.put(VpcManagerImpl.CAPABILITYTYPE, Network.Capability.SupportedProtocols.getName()); + map.put(VpcManagerImpl.SERVICE, ""); + return map; + } + + @Test + public void testIsVpcOfferingForRegionLevelVpc() throws Exception { + // Prepare + Map> serviceCapabilitystList = new HashMap<>(); + // First add some other capabilities to be ignored + serviceCapabilitystList.put("", createFakeCapabilityInputMap()); + + Map servicePair = new HashMap<>(); + servicePair.put(VpcManagerImpl.SERVICE, Service.Connectivity.getName()); + servicePair.put(VpcManagerImpl.CAPABILITYTYPE, Network.Capability.RegionLevelVpc.getName()); + servicePair.put(VpcManagerImpl.CAPABILITYVALUE, VpcManagerImpl.TRUE_VALUE); + serviceCapabilitystList.put("", servicePair); + + + // Execute + boolean result = Whitebox.invokeMethod(this.manager, "isVpcOfferingForRegionLevelVpc", + serviceCapabilitystList); //, Network.Capability.RedundantRouter.getName(), Service.SourceNat); + + // Assert + assertEquals("VpcOffering should be created for Region Level Vpc", true, result); + } + + @Test + public void testIsVpcOfferingForRegionLevelVpcFalse() throws Exception { + // Prepare + Map> serviceCapabilitystList = new HashMap<>(); + // First add some other capabilities to be ignored + serviceCapabilitystList.put("", createFakeCapabilityInputMap()); + serviceCapabilitystList.put("", createFakeCapabilityInputMap()); + + // Execute + boolean result = Whitebox.invokeMethod(this.manager, "isVpcOfferingForRegionLevelVpc", + serviceCapabilitystList); + + // Assert + assertEquals("VpcOffering should be created NOT for Region Level Vpc", false, result); + } + + @Test(expected = InvalidParameterValueException.class) + public void testCheckCapabilityPerServiceProviderFail() { + // Prepare + final Map capabilities = new HashMap<>(); + capabilities.put(Capability.RegionLevelVpc, ""); + capabilities.put(Capability.DistributedRouter, ""); + Set providers = this.prepareVpcManagerForCheckingCapabilityPerService(Service.Connectivity, capabilities); + + // Execute + this.manager.checkCapabilityPerServiceProvider(providers, Capability.RedundantRouter, Service.SourceNat); + } + + @Test + public void testCheckCapabilityPerServiceProvider() { + // Prepare + final Map capabilities = new HashMap<>(); + capabilities.put(Capability.RegionLevelVpc, ""); + capabilities.put(Capability.DistributedRouter, ""); + Set providers = this.prepareVpcManagerForCheckingCapabilityPerService(Service.Connectivity, capabilities); + + // Execute + this.manager.checkCapabilityPerServiceProvider(providers, Capability.DistributedRouter, Service.Connectivity); + this.manager.checkCapabilityPerServiceProvider(providers, Capability.RegionLevelVpc, Service.Connectivity); + } + + protected Set prepareVpcManagerForCheckingCapabilityPerService(Service service, Map capabilities) { + final Set providers = new HashSet<>(); + providers.add(Provider.VPCVirtualRouter); + final Network.Capability capability = Capability.DistributedRouter; + final boolean regionLevel = true; + final boolean distributedRouter = true; + final NetworkElement nwElement1 = mock(NetworkElement.class); + this.manager._ntwkModel = mock(NetworkModel.class); + when(this.manager._ntwkModel.getElementImplementingProvider(Provider.VPCVirtualRouter.getName())) + .thenReturn(nwElement1); + final Map> capabilitiesService1 = new HashMap<>(); + when(nwElement1.getCapabilities()).thenReturn(capabilitiesService1); + capabilities.put(Capability.RegionLevelVpc, ""); + capabilities.put(Capability.DistributedRouter, ""); + capabilitiesService1.put(service, capabilities); + + return providers; + } } diff --git a/server/test/com/cloud/vpc/VpcApiUnitTest.java b/server/test/com/cloud/vpc/VpcApiUnitTest.java index dee9afe3b57..f4056358d4e 100644 --- a/server/test/com/cloud/vpc/VpcApiUnitTest.java +++ b/server/test/com/cloud/vpc/VpcApiUnitTest.java @@ -85,7 +85,7 @@ public class VpcApiUnitTest extends TestCase { public void validateNtwkOffForVpc() { //validate network offering //1) correct network offering - VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); + VpcVO vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false, false); boolean result = false; try { _vpcService.validateNtwkOffForNtwkInVpc(2L, 1, "0.0.0.0", "111-", vo, "10.1.1.1", new AccountVO(), null); diff --git a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java index 7492598e901..a436a92a382 100644 --- a/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java +++ b/server/test/com/cloud/vpc/dao/MockVpcDaoImpl.java @@ -98,9 +98,9 @@ public class MockVpcDaoImpl extends GenericDaoBase implements VpcDa public VpcVO findById(Long id) { VpcVO vo = null; if (id.longValue() == 1) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false, false); } else if (id.longValue() == 2) { - vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false); + vo = new VpcVO(1, "new vpc", "new vpc", 1, 1, 1, "0.0.0.0/0", "vpc domain", false, false, false); vo.setState(State.Inactive); } diff --git a/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java b/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java index 33de3cd71e3..939293ed15b 100644 --- a/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java +++ b/server/test/org/apache/cloudstack/network/lb/ApplicationLoadBalancerTest.java @@ -130,11 +130,11 @@ public class ApplicationLoadBalancerTest extends TestCase { Mockito.when(_lbService.deleteLoadBalancerRule(nonExistingLbId, true)).thenReturn(false); //mockito for .createApplicationLoadBalancer tests - NetworkVO guestNetwork = new NetworkVO(TrafficType.Guest, null, null, 1, null, 1, 1L); + NetworkVO guestNetwork = new NetworkVO(TrafficType.Guest, null, null, 1, null, 1, 1L, false); setId(guestNetwork, validGuestNetworkId); guestNetwork.setCidr("10.1.1.1/24"); - NetworkVO publicNetwork = new NetworkVO(TrafficType.Public, null, null, 1, null, 1, 1L); + NetworkVO publicNetwork = new NetworkVO(TrafficType.Public, null, null, 1, null, 1, 1L, false); Mockito.when(_ntwkModel.getNetwork(validGuestNetworkId)).thenReturn(guestNetwork); Mockito.when(_ntwkModel.getNetwork(invalidGuestNetworkId)).thenReturn(null); diff --git a/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java b/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java index c12ffb89cb7..97355a7a399 100644 --- a/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java +++ b/server/test/org/cloud/network/router/deployment/RouterDeploymentDefinitionTest.java @@ -105,18 +105,14 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe @Test public void testRedundancyProperty() { // Set and confirm is redundant - RouterDeploymentDefinition deployment1 = this.builder.create() + when(this.mockNw.isRedundant()).thenReturn(true); + RouterDeploymentDefinition deployment = this.builder.create() .setGuestNetwork(this.mockNw) .setDeployDestination(this.mockDestination) - .makeRedundant() .build(); - assertTrue("The builder ignored \".makeRedundant()\"", deployment1.isRedundant()); - RouterDeploymentDefinition deployment2 = this.builder.create() - .setGuestNetwork(this.mockNw) - .setDeployDestination(this.mockDestination) - .setRedundant(true) - .build(); - assertTrue("The builder ignored \".setRedundant(true)\"", deployment2.isRedundant()); + assertTrue("The builder ignored redundancy from its inner network", deployment.isRedundant()); + when(this.mockNw.isRedundant()).thenReturn(false); + assertFalse("The builder ignored redundancy from its inner network", deployment.isRedundant()); } @Test @@ -124,20 +120,16 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe // Vpc type assertFalse(this.deployment.isVpcRouter()); // Offering null - this.deployment.offeringId = null; - assertNull(this.deployment.getOfferingId()); - this.deployment.offeringId = OFFERING_ID; - assertEquals(OFFERING_ID, this.deployment.getOfferingId().longValue()); + this.deployment.serviceOfferingId = null; + assertNull(this.deployment.getServiceOfferingId()); + this.deployment.serviceOfferingId = OFFERING_ID; + assertEquals(OFFERING_ID, this.deployment.getServiceOfferingId().longValue()); assertNotNull(this.deployment.getRouters()); assertNotNull(this.deployment.getGuestNetwork()); assertNotNull(this.deployment.getDest()); assertNotNull(this.deployment.getOwner()); this.deployment.plan = mock(DeploymentPlan.class); assertNotNull(this.deployment.getPlan()); - // Redundant : by default is not - assertFalse(this.deployment.isRedundant()); - this.deployment.isRedundant = true; - assertTrue(this.deployment.isRedundant()); assertFalse(this.deployment.isPublicNetwork()); this.deployment.isPublicNetwork = true; assertTrue(this.deployment.isPublicNetwork()); @@ -550,7 +542,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe when(routerVO2.getIsRedundantRouter()).thenReturn(false); when(routerVO2.getState()).thenReturn(VirtualMachine.State.Stopped); // If this deployment is not redundant nothing will be executed - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); // Execute this.deployment.setupPriorityOfRedundantRouter(); @@ -577,7 +569,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe when(routerVO2.getIsRedundantRouter()).thenReturn(true); when(routerVO2.getState()).thenReturn(VirtualMachine.State.Running); // If this deployment is not redundant nothing will be executed - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); // Execute this.deployment.setupPriorityOfRedundantRouter(); @@ -606,7 +598,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe when(routerVO2.getIsRedundantRouter()).thenReturn(true); when(routerVO2.getState()).thenReturn(VirtualMachine.State.Stopped); // If this deployment is not redundant nothing will be executed - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); // Execute this.deployment.setupPriorityOfRedundantRouter(); @@ -655,17 +647,17 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe 1, this.deployment.getNumberOfRoutersToDeploy()); // Execute and assert, just the same but for redundant deployment - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, 2, this.deployment.getNumberOfRoutersToDeploy()); // Just the same, instead of an empty list, a 1 items list this.deployment.routers.add(mock(DomainRouterVO.class)); - this.deployment.isRedundant = false; + when(this.mockNw.isRedundant()).thenReturn(false); assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, 0, this.deployment.getNumberOfRoutersToDeploy()); - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); assertEquals(NUMBER_OF_ROUTERS_TO_DEPLOY_IS_NOT_THE_EXPECTED, 1, this.deployment.getNumberOfRoutersToDeploy()); } @@ -759,33 +751,33 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe @Test public void testFindOfferingIdReceivingNewOne() { // Prepare - this.deployment.offeringId = 1L; + this.deployment.serviceOfferingId = 1L; when(this.mockNw.getNetworkOfferingId()).thenReturn(OFFERING_ID); when(this.mockNetworkOfferingDao.findById(OFFERING_ID)).thenReturn(this.mockNwOfferingVO); when(this.mockNwOfferingVO.getServiceOfferingId()).thenReturn(OFFERING_ID); // Execute - this.deployment.findOfferingId(); + this.deployment.findServiceOfferingId(); // Assert assertEquals("Given that no Offering was found, the previous Offering Id should be kept", - OFFERING_ID, this.deployment.offeringId.longValue()); + OFFERING_ID, this.deployment.serviceOfferingId.longValue()); } @Test public void testFindOfferingIdReceivingKeepingPrevious() { // Prepare - this.deployment.offeringId = 1L; + this.deployment.serviceOfferingId = 1L; when(this.mockNw.getNetworkOfferingId()).thenReturn(OFFERING_ID); when(this.mockNetworkOfferingDao.findById(OFFERING_ID)).thenReturn(this.mockNwOfferingVO); when(this.mockNwOfferingVO.getServiceOfferingId()).thenReturn(null); // Execute - this.deployment.findOfferingId(); + this.deployment.findServiceOfferingId(); // Assert assertEquals("Found Offering Id didn't replace previous one", - 1L, this.deployment.offeringId.longValue()); + 1L, this.deployment.serviceOfferingId.longValue()); } @Test @@ -794,7 +786,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe // Prepare this.deployment.routers = new ArrayList<>(); - this.deployment.isRedundant = true; + when(this.mockNw.isRedundant()).thenReturn(true); //this.deployment.routers.add(routerVO1); RouterDeploymentDefinition deploymentUT = spy(this.deployment); doReturn(2).when(deploymentUT).getNumberOfRoutersToDeploy(); @@ -858,7 +850,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe protected void driveTestPrepareDeployment(final boolean isRedundant, final boolean isPublicNw) { // Prepare - this.deployment.isRedundant = isRedundant; + when(this.mockNw.isRedundant()).thenReturn(isRedundant); when(this.mockNetworkModel.isProviderSupportServiceInNetwork( NW_ID_1, Service.SourceNat, Provider.VirtualRouter)).thenReturn(isPublicNw); // Execute @@ -898,7 +890,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe doReturn(noOfRoutersToDeploy).when(deploymentUT).getNumberOfRoutersToDeploy(); doReturn(passPreparation).when(deploymentUT).prepareDeployment(); doNothing().when(deploymentUT).findVirtualProvider(); - doNothing().when(deploymentUT).findOfferingId(); + doNothing().when(deploymentUT).findServiceOfferingId(); doNothing().when(deploymentUT).findSourceNatIP(); doNothing().when(deploymentUT).deployAllVirtualRouters(); @@ -916,7 +908,7 @@ public class RouterDeploymentDefinitionTest extends RouterDeploymentDefinitionTe } } verify(deploymentUT, times(proceedToDeployment)).findVirtualProvider(); - verify(deploymentUT, times(proceedToDeployment)).findOfferingId(); + verify(deploymentUT, times(proceedToDeployment)).findServiceOfferingId(); verify(deploymentUT, times(proceedToDeployment)).findSourceNatIP(); verify(deploymentUT, times(proceedToDeployment)).deployAllVirtualRouters(); } diff --git a/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java b/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java index 4e4b7778367..a63a395ab19 100644 --- a/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java +++ b/server/test/org/cloud/network/router/deployment/VpcRouterDeploymentDefinitionTest.java @@ -20,12 +20,14 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.assertFalse; import static org.mockito.Matchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.cloud.network.vpc.VpcOfferingVO; import java.util.List; import org.junit.Before; @@ -54,7 +56,7 @@ public class VpcRouterDeploymentDefinitionTest extends RouterDeploymentDefinitio private static final String FOR_VPC_ONLY_THE_GIVEN_DESTINATION_SHOULD_BE_USED = "For Vpc only the given destination should be used"; private static final long VPC_ID = 201L; - private static final long ZONE_ID = 211L; + public static final long VPC_OFFERING_ID = 210L; @Mock protected VpcDao mockVpcDao; @@ -79,6 +81,7 @@ public class VpcRouterDeploymentDefinitionTest extends RouterDeploymentDefinitio super.initMocks(); when(mockVpc.getId()).thenReturn(VPC_ID); when(mockVpc.getZoneId()).thenReturn(VPC_ID); + when(mockVpc.getVpcOfferingId()).thenReturn(VPC_OFFERING_ID); } @Before @@ -175,13 +178,34 @@ public class VpcRouterDeploymentDefinitionTest extends RouterDeploymentDefinitio } @Test - public void testCheckPreconditions() { - // TODO Implement this test + public void testFindOfferingIdLeavingPrevious() { + // Prepare + Long initialOfferingId = deployment.serviceOfferingId; + VpcOfferingVO vpcOffering = mock(VpcOfferingVO.class); + when(mockVpcOffDao.findById(VPC_OFFERING_ID)).thenReturn(vpcOffering); + when(vpcOffering.getServiceOfferingId()).thenReturn(null); + + // Execute + deployment.findServiceOfferingId(); + + // Assert + assertEquals("Offering Id shouldn't have been updated", + initialOfferingId, deployment.serviceOfferingId); } @Test - public void testExecuteDeployment() { - // TODO Implement this test + public void testFindOfferingIdSettingNewOne() { + // Prepare + VpcOfferingVO vpcOffering = mock(VpcOfferingVO.class); + when(mockVpcOffDao.findById(VPC_OFFERING_ID)).thenReturn(vpcOffering); + when(vpcOffering.getServiceOfferingId()).thenReturn(VPC_OFFERING_ID); + + // Test + deployment.findServiceOfferingId(); + + // Assert + assertEquals("Offering Id should have been updated", + VPC_OFFERING_ID, deployment.serviceOfferingId.longValue()); } @Test @@ -227,4 +251,17 @@ public class VpcRouterDeploymentDefinitionTest extends RouterDeploymentDefinitio // Assert assertEquals("SourceNatIp returned by the VpcManager was not correctly set", publicIp, deployment.sourceNatIp); } -} \ No newline at end of file + + @Test + public void testRedundancyProperty() { + // Set and confirm is redundant + when(this.mockVpc.isRedundant()).thenReturn(true); + RouterDeploymentDefinition deployment = this.builder.create() + .setVpc(this.mockVpc) + .setDeployDestination(this.mockDestination) + .build(); + assertTrue("The builder ignored redundancy from its inner network", deployment.isRedundant()); + when(this.mockVpc.isRedundant()).thenReturn(false); + assertFalse("The builder ignored redundancy from its inner network", deployment.isRedundant()); + } +} diff --git a/test/integration/component/test_vpc_offerings.py b/test/integration/component/test_vpc_offerings.py index e62aeb5db10..6ae8277755a 100644 --- a/test/integration/component/test_vpc_offerings.py +++ b/test/integration/component/test_vpc_offerings.py @@ -77,11 +77,37 @@ class Services: "displaytext": 'VPC off', "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', }, + "redundant_vpc_offering": { + "name": 'Redundant VPC off', + "displaytext": 'Redundant VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + "serviceCapabilityList": { + "SourceNat": { + "RedundantRouter": 'true' + } + }, + }, "vpc": { "name": "TestVPC", "displaytext": "TestVPC", "cidr": '10.0.0.1/24' }, + "redundant_vpc": { + "name": "TestRedundantVPC", + "displaytext": "TestRedundantVPC", + "cidr": '10.0.0.1/24' + }, "network": { "name": "Test Network", "displaytext": "Test Network", @@ -171,6 +197,7 @@ class TestVPCOffering(cloudstackTestCase): return def setUp(self): + self.debug("test_vpc_offering#setUp") self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() self.account = Account.create( @@ -184,6 +211,7 @@ class TestVPCOffering(cloudstackTestCase): return def tearDown(self): + self.debug("test_vpc_offering#tearDown") try: cleanup_resources(self.apiclient, self.cleanup) except Exception as e: @@ -1103,3 +1131,55 @@ class TestVPCOffering(cloudstackTestCase): "List VPC offering should return only offerings that are disabled" ) return + + @attr(tags=["advanced", "redundancy"], required_hardware="false") + def test_09_create_redundant_vpc_offering(self): + + self.debug("Creating Redundant VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["redundant_vpc_offering"] + ) + self.cleanup.append(vpc_off) + + self.debug("Check if the Redundant VPC offering is created successfully?") + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the created Redundant VPC offering") + vpc_off.update(self.apiclient, state='Enabled') + + + self.debug("Creating a Redundant VPC network in the account: %s" % + self.account.name) + vpc = VPC.create( + self.apiclient, + self.services["redundant_vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.name, + domainid=self.account.domainid + ) + self.debug("Validating Redundant VPC Nw creation") + self.validate_vpc_network(vpc) + + vpcs = VPC.list( + self.apiclient, + id=vpc.id + ) + + found = False + redundant = False + for iVpc in vpcs: + if iVpc.id == vpc.id: + found = True + if iVpc.redundantvpcrouter: + redundant = True + break + + self.assertEqual( + redundant, + True, + "Didn't create any Redundant Vpc" + ) + + return diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 3997e53d2e9..e78dd232260 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -3711,6 +3711,13 @@ isHidden: true, dependsOn: 'service.Connectivity.isEnabled', isBoolean: true + }, + + "service.SourceNat.redundantRouterCapabilityCheckbox": { + label: 'label.redundant.router.capability', + isHidden: true, + dependsOn: 'service.SourceNat.isEnabled', + isBoolean: true } },//end of fields }, //end of createForm @@ -3720,10 +3727,8 @@ var inputData = {}; var serviceProviderMap = {}; var serviceCapabilityIndex = 0; - $.each(formData, function(key, value) { var serviceData = key.split('.'); - if (serviceData.length > 1) { if (serviceData[0] == 'service' && serviceData[2] == 'isEnabled' && @@ -3742,7 +3747,13 @@ inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilitytype'] = 'DistributedRouter'; inputData['servicecapabilitylist[' + serviceCapabilityIndex + '].capabilityvalue'] = true; serviceCapabilityIndex++; + } else if ((key == 'service.SourceNat.redundantRouterCapabilityCheckbox') && ("SourceNat" in serviceProviderMap)) { + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].service'] = 'SourceNat'; + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].capabilitytype'] = "RedundantRouter"; + inputData['serviceCapabilityList[' + serviceCapabilityIndex + '].capabilityvalue'] = true; + serviceCapabilityIndex++; } + } else if (value != '') { // Normal data inputData[key] = value; }