From 1d2fd100079184f74649c39be807f5170021cc44 Mon Sep 17 00:00:00 2001 From: Abhinandan Prateek Date: Thu, 24 Dec 2015 17:23:27 +0530 Subject: [PATCH] OSPF: Adding dynamically routing capability to VPC by configuring quagga on VR . Added zone level quagga/ospf config API and UI as addtional tab on zone . Added service offering with ospf . Added service offering for the tier guest network for VPC . Modified system vm template so that quagga is pre-installed . Added various configuration files that are required by Quagga . Added marvin tests for new APIs and unit test . Send quagga config from the server if VPC and tier are dynamically routed . Configure quagga when a VM of the tier is created/destroyed . Added necessary scritps on the vpc router to enable and configure quagga and iptable rules . Multiple Cidr management and netmask based cidr allocation . Added unit tests for cidr management . New dialog for create dynamic VPC and netmask as a field . Marvin tests to test dynmaic vpc service offering . Marvin tests to test dynamic network offering . Converting String based CIDR representation to InetAddress and mask based CIDR object representation that is implemented for ipv4 and with ipv6 placeholder. --- api/src/com/cloud/dc/DataCenter.java | 2 + api/src/com/cloud/network/Network.java | 8 +- .../PhysicalNetworkServiceProvider.java | 2 + .../com/cloud/network/vpc/OSPFZoneConfig.java | 329 +++++++++++ api/src/com/cloud/network/vpc/Vpc.java | 1 + .../com/cloud/network/vpc/VpcOffering.java | 2 + .../network/vpc/VpcProvisioningService.java | 17 +- api/src/com/cloud/network/vpc/VpcService.java | 28 +- .../com/cloud/offering/NetworkOffering.java | 1 + .../apache/cloudstack/api/ApiConstants.java | 1 + .../command/admin/vpc/VPCOSPFConfigCmd.java | 80 +++ .../admin/vpc/VPCOSPFConfigUpdateCmd.java | 207 +++++++ .../user/network/CreateNetworkCmd.java | 44 +- .../api/command/user/vpc/CreateVPCCmd.java | 68 ++- .../api/response/VPCOSPFConfigResponse.java | 187 +++++++ .../apache/cloudstack/usage/UsageTypes.java | 2 + .../admin/vpc/VPCOSPFConfigCmdTest.java | 72 +++ .../classes/resources/messages.properties | 26 + client/tomcatconf/commands.properties.in | 4 + .../api/routing/QuaggaConfigCommand.java | 86 +++ .../resource/virtualnetwork/VRScripts.java | 1 + .../VirtualRoutingResource.java | 2 - .../facade/AbstractConfigItemFacade.java | 11 +- .../facade/QuaggaConfigItem.java | 93 ++++ .../virtualnetwork/model/ConfigBase.java | 1 + .../virtualnetwork/model/QuaggaRule.java | 87 +++ .../src/com/cloud/network/vpc/VpcManager.java | 15 +- .../entity/api/db/EngineDataCenterVO.java | 6 + .../orchestration/NetworkOrchestrator.java | 255 +++++---- .../schema/src/com/cloud/dc/DataCenterVO.java | 13 + .../src/com/cloud/dc/dao/DataCenterDao.java | 4 + .../com/cloud/dc/dao/DataCenterDaoImpl.java | 14 + ...PhysicalNetworkServiceProviderDaoImpl.java | 2 + .../dao/PhysicalNetworkServiceProviderVO.java | 39 +- .../src/com/cloud/network/vpc/VpcVO.java | 27 +- .../vpc/dao/VpcOfferingServiceMapDao.java | 2 +- .../network/vpc/dao/VpcServiceMapDaoImpl.java | 26 +- .../cloud/offerings/NetworkOfferingVO.java | 52 +- .../dao/NetworkOfferingServiceMapDaoImpl.java | 1 - .../quota/constant/QuotaConfig.java | 2 +- .../cloudstack/quota/constant/QuotaTypes.java | 1 + .../response/QuotaResponseBuilderImpl.java | 8 +- .../resource/CitrixResourceBase.java | 9 + pom.xml | 2 + .../cloud/network/IpAddressManagerImpl.java | 1 + .../com/cloud/network/NetworkServiceImpl.java | 514 +++++++++--------- .../element/VpcVirtualRouterElement.java | 46 +- .../network/router/CommandSetupHelper.java | 71 ++- .../VirtualNetworkApplianceManagerImpl.java | 3 + ...VpcVirtualNetworkApplianceManagerImpl.java | 78 ++- .../com/cloud/network/rules/QuaggaRules.java | 49 ++ .../com/cloud/network/vpc/VpcManagerImpl.java | 271 ++++++--- .../cloud/server/ConfigurationServerImpl.java | 178 +++--- .../cloud/server/ManagementServerImpl.java | 4 + .../topology/AdvancedNetworkVisitor.java | 22 +- .../network/topology/BasicNetworkVisitor.java | 12 +- .../topology/NetworkTopologyVisitor.java | 3 + .../cloud/network/vpc/VpcManagerImplTest.java | 50 +- setup/db/db/schema-471to480.sql | 1 + setup/db/db/schema-481to490.sql | 3 + .../patches/debian/config/etc/quagga/daemons | 32 ++ .../debian/config/etc/quagga/debian.conf | 24 + .../debian/config/opt/cloud/bin/configure.py | 13 + .../config/opt/cloud/bin/cs/CsHelper.py | 2 +- .../config/opt/cloud/bin/cs/CsQuagga.py | 85 +++ .../debian/config/opt/cloud/bin/cs_quagga.py | 27 + .../debian/config/opt/cloud/bin/merge.py | 6 + test/integration/component/test_ospf.py | 477 ++++++++++++++++ .../smoke/test_ospf_zone_config.py | 165 ++++++ tools/apidoc/gen_toc.py | 15 +- tools/appliance/Gemfile | 2 + tools/appliance/README.md | 2 +- .../install_systemvm_packages.sh | 2 +- ui/dictionary.jsp | 17 + ui/scripts/configuration.js | 8 +- ui/scripts/docs.js | 4 + ui/scripts/network.js | 16 +- ui/scripts/sharedFunctions.js | 173 ++++++ ui/scripts/system.js | 94 ++++ .../main/java/com/cloud/utils/Nullable.java | 25 + .../java/com/cloud/utils/net/NetUtils.java | 195 ++++++- .../utils/net/cidr/BadCIDRException.java | 33 ++ .../java/com/cloud/utils/net/cidr/CIDR.java | 98 ++++ .../java/com/cloud/utils/net/cidr/CIDR4.java | 172 ++++++ .../java/com/cloud/utils/net/cidr/CIDR6.java | 95 ++++ .../com/cloud/utils/net/cidr/CIDRFactory.java | 79 +++ .../com/cloud/utils/net/NetUtilsTest.java | 125 ++++- 87 files changed, 4318 insertions(+), 814 deletions(-) create mode 100644 api/src/com/cloud/network/vpc/OSPFZoneConfig.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmd.java create mode 100644 api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigUpdateCmd.java create mode 100644 api/src/org/apache/cloudstack/api/response/VPCOSPFConfigResponse.java create mode 100644 api/test/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmdTest.java create mode 100644 core/src/com/cloud/agent/api/routing/QuaggaConfigCommand.java create mode 100644 core/src/com/cloud/agent/resource/virtualnetwork/facade/QuaggaConfigItem.java create mode 100644 core/src/com/cloud/agent/resource/virtualnetwork/model/QuaggaRule.java create mode 100644 server/src/com/cloud/network/rules/QuaggaRules.java create mode 100644 systemvm/patches/debian/config/etc/quagga/daemons create mode 100644 systemvm/patches/debian/config/etc/quagga/debian.conf create mode 100755 systemvm/patches/debian/config/opt/cloud/bin/cs/CsQuagga.py create mode 100755 systemvm/patches/debian/config/opt/cloud/bin/cs_quagga.py create mode 100644 test/integration/component/test_ospf.py create mode 100644 test/integration/smoke/test_ospf_zone_config.py create mode 100644 utils/src/main/java/com/cloud/utils/Nullable.java create mode 100644 utils/src/main/java/com/cloud/utils/net/cidr/BadCIDRException.java create mode 100644 utils/src/main/java/com/cloud/utils/net/cidr/CIDR.java create mode 100644 utils/src/main/java/com/cloud/utils/net/cidr/CIDR4.java create mode 100644 utils/src/main/java/com/cloud/utils/net/cidr/CIDR6.java create mode 100644 utils/src/main/java/com/cloud/utils/net/cidr/CIDRFactory.java diff --git a/api/src/com/cloud/dc/DataCenter.java b/api/src/com/cloud/dc/DataCenter.java index 5b3d3c01f300..80751d163b38 100644 --- a/api/src/com/cloud/dc/DataCenter.java +++ b/api/src/com/cloud/dc/DataCenter.java @@ -81,4 +81,6 @@ public enum NetworkType { String getZoneToken(); boolean isLocalStorageEnabled(); + + boolean isDynamicRoutingEnabled(); } diff --git a/api/src/com/cloud/network/Network.java b/api/src/com/cloud/network/Network.java index 7cc5441603ae..c03951dcd676 100644 --- a/api/src/com/cloud/network/Network.java +++ b/api/src/com/cloud/network/Network.java @@ -59,6 +59,7 @@ public static class Service { public static final Service SecurityGroup = new Service("SecurityGroup"); public static final Service NetworkACL = new Service("NetworkACL", Capability.SupportedProtocols); public static final Service Connectivity = new Service("Connectivity", Capability.DistributedRouter, Capability.RegionLevelVpc, Capability.StretchedL2Subnet); + public static final Service VPCDynamicRouting = new Service("VPCDynamicRouting"); private final String name; private final Capability[] caps; @@ -213,6 +214,7 @@ public static class Capability { public static final Capability DistributedRouter = new Capability("DistributedRouter"); public static final Capability StretchedL2Subnet = new Capability("StretchedL2Subnet"); public static final Capability RegionLevelVpc = new Capability("RegionLevelVpc"); + public static final Capability VPCDynamicRouting = new Capability("VPCDynamicRouting"); private final String name; @@ -241,9 +243,9 @@ enum Event { public enum State { - Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"), Implementing( - "Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"), Shutdown( - "Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed"); + Allocated("Indicates the network configuration is in allocated but not setup"), Setup("Indicates the network configuration is setup"), + Implementing("Indicates the network configuration is being implemented"), Implemented("Indicates the network configuration is in use"), + Shutdown("Indicates the network configuration is being destroyed"), Destroy("Indicates that the network is destroyed"); protected static final StateMachine2 s_fsm = new StateMachine2(); diff --git a/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java b/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java index d3c8193242e8..666abc09c858 100644 --- a/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java +++ b/api/src/com/cloud/network/PhysicalNetworkServiceProvider.java @@ -67,4 +67,6 @@ public enum State { String getUuid(); boolean isNetworkAclServiceProvided(); + + boolean isDynamicRoutingProvided(); } diff --git a/api/src/com/cloud/network/vpc/OSPFZoneConfig.java b/api/src/com/cloud/network/vpc/OSPFZoneConfig.java new file mode 100644 index 000000000000..fad6306f497b --- /dev/null +++ b/api/src/com/cloud/network/vpc/OSPFZoneConfig.java @@ -0,0 +1,329 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.network.vpc; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; + +import com.cloud.exception.InvalidParameterValueException; +import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; + +public class OSPFZoneConfig { + + private long zoneId; + private Protocol protocol; + private String ospfArea; + private Short helloInterval; + private Short deadInterval; + private Short retransmitInterval; + private Short transitDelay; + private Authentication authentication; + private String password; + private CIDR[] superCIDRList; + private Boolean enabled; + + public static final String s_protocol = "protocol"; + public static final String s_area = "area"; + public static final String s_helloInterval = "hellointerval"; + public static final String s_deadInterval = "deadinterval"; + public static final String s_retransmitInterval = "retransmitinterval"; + public static final String s_transitDelay = "transitdelay"; + public static final String s_authentication = "authentication"; + public static final String s_superCIDR = "supercidr"; + public static final String s_password = "password"; + public static final String s_enabled = "enabled"; + + public Protocol getProtocol() { + return protocol; + } + + public void setProtocol(Protocol protocol) { + this.protocol = protocol; + } + + public String getOspfArea() { + return ospfArea; + } + + public void setOspfArea(String ospfArea) { + this.ospfArea = ospfArea; + } + + public Short getHelloInterval() { + return helloInterval; + } + + public void setHelloInterval(Short helloInterval) { + this.helloInterval = helloInterval; + } + + public Short getDeadInterval() { + return deadInterval; + } + + public void setDeadInterval(Short deadInterval) { + this.deadInterval = deadInterval; + } + + public Short getRetransmitInterval() { + return retransmitInterval; + } + + public void setRetransmitInterval(Short retransmitInterval) { + this.retransmitInterval = retransmitInterval; + } + + public Short getTransitDelay() { + return transitDelay; + } + + public void setTransitDelay(Short transitDelay) { + this.transitDelay = transitDelay; + } + + public Authentication getAuthentication() { + return authentication; + } + + public void setAuthentication(Authentication authentication) { + this.authentication = authentication; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public CIDR[] getSuperCIDR() { + return superCIDRList; + } + + public void setSuperCIDR(CIDR[] superCIDR) { + this.superCIDRList = superCIDR; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public enum Params { + PROTOCOL, AREA, HELLO_INTERVAL, DEAD_INTERVAL, RETRANSMIT_INTERVAL, TRANSIT_DELAY, AUTHENTICATION, SUPER_CIDR, PASSWORD, ENABLED + } + + public enum Protocol { + OSPF + } + + public enum Authentication { + MD5, PLAIN_TEXT + } + + public OSPFZoneConfig() { + } + + public void setDefaultValues(final Map details) throws BadCIDRException { + this.protocol = details.get(Params.PROTOCOL.name()) == null ? Protocol.OSPF : Protocol.valueOf(details.get(Params.PROTOCOL.name())); + this.ospfArea = details.get(Params.AREA.name()) == null ? "0" : details.get(Params.AREA.name()); + this.helloInterval = Short.valueOf(details.get(Params.HELLO_INTERVAL.name()) == null ? "10" : details.get(Params.HELLO_INTERVAL.name())); + this.deadInterval = Short.valueOf(details.get(Params.DEAD_INTERVAL.name()) == null ? "40" : details.get(Params.DEAD_INTERVAL.name())); + this.retransmitInterval = Short.valueOf(details.get(Params.RETRANSMIT_INTERVAL.name()) == null ? "5" : details.get(Params.RETRANSMIT_INTERVAL.name())); + this.transitDelay = Short.valueOf(details.get(Params.TRANSIT_DELAY.name()) == null ? "1" : details.get(Params.TRANSIT_DELAY.name())); + this.authentication = details.get(Params.AUTHENTICATION.name()) == null ? Authentication.MD5 : Authentication.valueOf(details.get(Params.AUTHENTICATION.name())); + this.password = details.get(Params.PASSWORD.name()) == null ? "" : details.get(Params.PASSWORD.name()); + this.superCIDRList = details.get(Params.SUPER_CIDR.name()) == null ? new CIDR[0] : NetUtils.convertToCIDR(details.get(Params.SUPER_CIDR.name()).split(",")); + this.enabled = details.get(Params.ENABLED.name()) == null ? Boolean.FALSE : Boolean.valueOf(details.get(Params.ENABLED.name())); + } + + public void setValues(final String protocol, final String ospfArea, final Short helloInterval, final Short deadInterval, final Short retransmitInterval, + final Short transitDelay, final String authentication, final String quaggaPassword, final String superCIDRList, final Boolean enabled) throws BadCIDRException { + if (protocol != null) { + if ((Protocol.OSPF.name().equals(protocol))) { + this.protocol = Protocol.valueOf(protocol); + } else { + throw new InvalidParameterValueException("The quagga protocal can have values of OSPF only " + protocol); + } + } + if (ospfArea != null) { + this.ospfArea = ospfArea; + } + if (helloInterval != null) { + this.helloInterval = helloInterval; + } + if (deadInterval != null) { + this.deadInterval = deadInterval; + } + if (retransmitInterval != null) { + this.retransmitInterval = retransmitInterval; + } + if (transitDelay != null) { + this.transitDelay = transitDelay; + } + if (authentication != null) { + if (Authentication.MD5.name().equals(authentication) || Authentication.PLAIN_TEXT.name().equals(authentication)) { + this.authentication = Authentication.valueOf(authentication); + } else { + throw new InvalidParameterValueException("The quagga authentication can have values of MD5 or PLAIN_TEXT and not " + protocol); + } + } + if (quaggaPassword != null) { + this.password = quaggaPassword; + } + if (superCIDRList != null) { + String[] cidr_list = superCIDRList.split(","); + for (String cidr : cidr_list) { + if (!NetUtils.isValidCIDR(cidr)) { + throw new InvalidParameterValueException("The super CIDR is not a valid cidr " + cidr); + } + } + CIDR[] v_cidr = NetUtils.convertToCIDR(cidr_list); + if (!NetUtils.cidrListConsistency(v_cidr)) { + throw new InvalidParameterValueException("The cidr list is not consistent " + Arrays.toString(cidr_list)); + } + this.superCIDRList = v_cidr; + } + if (enabled != null) { + this.enabled = enabled; + } + } + + public void setValues(Map details) throws BadCIDRException { + Protocol protocol = Protocol.valueOf(details.get(Params.PROTOCOL.name())); + String ospfArea = details.get(Params.AREA.name()); + Short helloInterval = Short.valueOf(details.get(Params.HELLO_INTERVAL.name())); + Short deadInterval = Short.valueOf(details.get(Params.DEAD_INTERVAL.name())); + Short retransmitInterval = Short.valueOf(details.get(Params.RETRANSMIT_INTERVAL.name())); + Short transitDelay = Short.valueOf(details.get(Params.TRANSIT_DELAY.name())); + Authentication authentication = Authentication.valueOf(details.get(Params.AUTHENTICATION.name())); + String quaggaPassword = details.get(Params.PASSWORD.name()); + String superCIDRList = details.get(Params.SUPER_CIDR.name()); + Boolean enabled = Boolean.valueOf(details.get(Params.ENABLED.name())); + + if (protocol != null) { + if (Protocol.OSPF == protocol) { + this.protocol = protocol; + } else { + throw new InvalidParameterValueException("The quagga protocal can have values of OSPF " + protocol); + } + } + if (ospfArea != null) { + this.ospfArea = ospfArea; + } + if (helloInterval != null) { + this.helloInterval = helloInterval; + } + if (deadInterval != null) { + this.deadInterval = deadInterval; + } + if (retransmitInterval != null) { + this.retransmitInterval = retransmitInterval; + } + if (transitDelay != null) { + this.transitDelay = transitDelay; + } + if (authentication != null) { + if (Authentication.MD5 == authentication || Authentication.PLAIN_TEXT == authentication) { + this.authentication = authentication; + } else { + throw new InvalidParameterValueException("The quagga authentication can have values of MD5 or PLAIN_TEXT and not " + authentication); + } + } + if (quaggaPassword != null) { + this.password = quaggaPassword; + } + if (superCIDRList != null) { + String[] cidr_list = superCIDRList.split(","); + for (String cidr : cidr_list) { + if (!NetUtils.isValidCIDR(cidr)) { + throw new InvalidParameterValueException("The super CIDR is not a valid cidr " + cidr); + } + } + CIDR[] v_cidr = NetUtils.convertToCIDR(cidr_list); + if (!NetUtils.cidrListConsistency(v_cidr)) { + throw new InvalidParameterValueException("The cidr list is not consistent " + Arrays.toString(cidr_list)); + } + this.superCIDRList = v_cidr; + } + if (enabled != null) { + this.enabled = enabled; + } + } + + public Map getValues() throws BadCIDRException { + Map details = new HashMap(); + if (protocol != null) { + if ((Protocol.OSPF.name().equals(protocol))) { + details.put(Params.PROTOCOL.name(), protocol.name()); + } else { + details.put(Params.PROTOCOL.name(), Protocol.OSPF.name()); + } + } + if (ospfArea != null) { + details.put(Params.AREA.name(), ospfArea); + } + if (helloInterval != null) { + details.put(Params.HELLO_INTERVAL.name(), helloInterval.toString()); + } + if (deadInterval != null) { + details.put(Params.DEAD_INTERVAL.name(), deadInterval.toString()); + } + if (retransmitInterval != null) { + details.put(Params.RETRANSMIT_INTERVAL.name(), retransmitInterval.toString()); + } + if (transitDelay != null) { + details.put(Params.TRANSIT_DELAY.name(), transitDelay.toString()); + } + if (authentication != null) { + if (Authentication.MD5.name().equals(authentication) || Authentication.PLAIN_TEXT.name().equals(authentication)) { + details.put(Params.AUTHENTICATION.name(), authentication.name()); + } else { + details.put(Params.AUTHENTICATION.name(), Authentication.MD5.name()); + } + } + if (password != null) { + details.put(Params.PASSWORD.name(), password); + } + if (!ArrayUtils.isEmpty(superCIDRList)) { + if (!NetUtils.cidrListConsistency(superCIDRList)) { + throw new InvalidParameterValueException("The cidr list is not consistent " + Arrays.toString(superCIDRList)); + } + details.put(Params.SUPER_CIDR.name(), StringUtils.join(superCIDRList, ',')); + + } else { + details.put(Params.SUPER_CIDR.name(), "200.100.0.0/20"); + } + if (enabled != null) { + details.put(Params.ENABLED.name(), enabled.toString()); + } + + return details; + } + +} diff --git a/api/src/com/cloud/network/vpc/Vpc.java b/api/src/com/cloud/network/vpc/Vpc.java index dd607fe6caa9..2aeace546837 100644 --- a/api/src/com/cloud/network/vpc/Vpc.java +++ b/api/src/com/cloud/network/vpc/Vpc.java @@ -87,4 +87,5 @@ public enum State { * @return true if VPC spans multiple zones in the region */ boolean isRegionLevelVpc(); + } diff --git a/api/src/com/cloud/network/vpc/VpcOffering.java b/api/src/com/cloud/network/vpc/VpcOffering.java index fb4b151fb4ca..9e53aa6a3f0d 100644 --- a/api/src/com/cloud/network/vpc/VpcOffering.java +++ b/api/src/com/cloud/network/vpc/VpcOffering.java @@ -20,6 +20,7 @@ import org.apache.cloudstack.api.InternalIdentity; public interface VpcOffering extends InternalIdentity, Identity { + public enum State { Disabled, Enabled } @@ -27,6 +28,7 @@ public enum State { 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"; + public static final String routedVPCOfferingName = "Default Dynamically Routed VPC offering"; /** * diff --git a/api/src/com/cloud/network/vpc/VpcProvisioningService.java b/api/src/com/cloud/network/vpc/VpcProvisioningService.java index cce285030b98..5b2da219e876 100644 --- a/api/src/com/cloud/network/vpc/VpcProvisioningService.java +++ b/api/src/com/cloud/network/vpc/VpcProvisioningService.java @@ -16,23 +16,21 @@ // under the License. package com.cloud.network.vpc; - import java.util.List; import java.util.Map; import com.cloud.utils.Pair; +import com.cloud.utils.net.cidr.BadCIDRException; public interface VpcProvisioningService { public VpcOffering getVpcOffering(long vpcOfferingId); - public VpcOffering createVpcOffering(String name, String displayText, List supportedServices, - Map> serviceProviders, - Map serviceCapabilitystList, - Long serviceOfferingId); + public VpcOffering createVpcOffering(String name, String displayText, List supportedServices, Map> serviceProviders, Map serviceCapabilitystList, + Long serviceOfferingId); - Pair,Integer> listVpcOfferings(Long id, String name, String displayText, List supportedServicesStr, Boolean isDefault, String keyword, - String state, Long startIndex, Long pageSizeVal); + Pair, Integer> listVpcOfferings(Long id, String name, String displayText, List supportedServicesStr, Boolean isDefault, String keyword, + String state, Long startIndex, Long pageSizeVal); /** * @param offId @@ -49,4 +47,9 @@ Pair,Integer> listVpcOfferings(Long id, String name, */ public VpcOffering updateVpcOffering(long vpcOffId, String vpcOfferingName, String displayText, String state); + Map updateQuaggaConfig(Long id, String protocol, String ospfArea, Short helloInterval, Short deadInterval, Short retransmitInterval, Short transitDelay, + String authentication, String password, String superCIDR, Boolean enabled) throws BadCIDRException; + + Map quaggaConfig(Long id); + } diff --git a/api/src/com/cloud/network/vpc/VpcService.java b/api/src/com/cloud/network/vpc/VpcService.java index 241e27b1552e..68fdfacb5c0b 100644 --- a/api/src/com/cloud/network/vpc/VpcService.java +++ b/api/src/com/cloud/network/vpc/VpcService.java @@ -30,6 +30,7 @@ import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.IpAddress; import com.cloud.utils.Pair; +import com.cloud.utils.net.cidr.BadCIDRException; public interface VpcService { @@ -50,6 +51,25 @@ public interface VpcService { public Vpc createVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String cidr, String networkDomain, Boolean displayVpc) throws ResourceAllocationException; + /** + * Persists VPC record in the database + * + * @param zoneId + * @param vpcOffId + * @param vpcOwnerId + * @param vpcName + * @param displayText + * @param cidr + * @param networkDomain TODO + * @param displayVpc TODO + * @return + * @throws ResourceAllocationException TODO + * @throws UnknownHostException + * @throws BadCIDRException + */ + public Vpc createDynamicVpc(long zoneId, long vpcOffId, long vpcOwnerId, String vpcName, String displayText, String netmask, String networkDomain, Boolean displayVpc) + throws ResourceAllocationException, BadCIDRException; + /** * Deletes a VPC * @@ -247,8 +267,8 @@ public PrivateGateway createVpcPrivateGateway(long vpcId, Long physicalNetworkId * @throws InsufficientAddressCapacityException * @throws ConcurrentOperationException */ - IpAddress associateIPToVpc(long ipId, long vpcId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, - ConcurrentOperationException; + IpAddress associateIPToVpc(long ipId, long vpcId) + throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException; /** * @param routeId @@ -256,4 +276,8 @@ IpAddress associateIPToVpc(long ipId, long vpcId) throws ResourceAllocationExcep */ public boolean applyStaticRoute(long routeId) throws ResourceUnavailableException; + boolean isVpcOfferingDynamicallyRouted(long dcId, long vpcOffId); + + boolean isVpcOfferingDynamicallyRouted(long vpcOffId); + } diff --git a/api/src/com/cloud/offering/NetworkOffering.java b/api/src/com/cloud/offering/NetworkOffering.java index f1ef69c2f68e..4386375512de 100644 --- a/api/src/com/cloud/offering/NetworkOffering.java +++ b/api/src/com/cloud/offering/NetworkOffering.java @@ -55,6 +55,7 @@ public enum Detail { public final static String DefaultIsolatedNetworkOffering = "DefaultIsolatedNetworkOffering"; public final static String DefaultSharedEIPandELBNetworkOffering = "DefaultSharedNetscalerEIPandELBNetworkOffering"; public final static String DefaultIsolatedNetworkOfferingForVpcNetworks = "DefaultIsolatedNetworkOfferingForVpcNetworks"; + public final static String DefaultIsolatedDynamicRoutedNetworkOfferingForVpcNetworks = "DefaultIsolatedDynamicRoutedNetworkOfferingForVpcNetworks"; public final static String DefaultIsolatedNetworkOfferingForVpcNetworksNoLB = "DefaultIsolatedNetworkOfferingForVpcNetworksNoLB"; public final static String DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB = "DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB"; diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index ef4ff9a0fe9f..79b8aab92cb6 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -622,6 +622,7 @@ public class ApiConstants { 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 DYNAMICALLY_ROUTED_VPC_ROUTER = "dynamicallyroutedvpcrouter"; 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/command/admin/vpc/VPCOSPFConfigCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmd.java new file mode 100644 index 000000000000..074909d099a6 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmd.java @@ -0,0 +1,80 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.vpc; + +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VPCOSPFConfigResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.network.vpc.VpcProvisioningService; +import com.cloud.user.Account; +import com.cloud.utils.net.cidr.BadCIDRException; + +@APICommand(name = "vpcOSPFConfig", description = "Return zone level ospf configuration", responseObject = VPCOSPFConfigResponse.class, since = "4.9.0", requestHasSensitiveInfo = true, responseHasSensitiveInfo = false) +public class VPCOSPFConfigCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(VPCOSPFConfigCmd.class); + private static final String s_name = "vpcospfconfigresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "the ID of the Zone") + private Long zoneid; + + @Inject + public VpcProvisioningService _vpcProvSvc; + + public Long getId() { + return zoneid; + } + + @Override + public void execute() { + Map details = _vpcProvSvc.quaggaConfig(getId()); + try { + VPCOSPFConfigResponse response = new VPCOSPFConfigResponse(getId(), details); + response.setResponseName(getCommandName()); + response.setObjectName("ospfconfig"); + setResponseObject(response); + } catch (BadCIDRException ex) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to return a valid response due to problems with CIDR"); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + +} diff --git a/api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigUpdateCmd.java b/api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigUpdateCmd.java new file mode 100644 index 000000000000..0fa7291438f1 --- /dev/null +++ b/api/src/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigUpdateCmd.java @@ -0,0 +1,207 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.vpc; + +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.APICommand; +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; +import org.apache.cloudstack.api.response.VPCOSPFConfigResponse; +import org.apache.cloudstack.api.response.ZoneResponse; +import org.apache.log4j.Logger; + +import com.cloud.network.vpc.OSPFZoneConfig; +import com.cloud.network.vpc.VpcProvisioningService; +import com.cloud.user.Account; +import com.cloud.utils.net.cidr.BadCIDRException; + +@APICommand(name = "vpcOSPFConfigUpdate", description = "Captures config informaton for ospf zone level params", responseObject = VPCOSPFConfigResponse.class, since = "4.9.0", requestHasSensitiveInfo = true) +public class VPCOSPFConfigUpdateCmd extends BaseCmd { + public static final Logger s_logger = Logger.getLogger(VPCOSPFConfigUpdateCmd.class); + private static final String s_name = "vpcospfconfigresponse"; + + ///////////////////////////////////////////////////// + //////////////// API parameters ///////////////////// + ///////////////////////////////////////////////////// + + @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "the ID of the Zone") + private Long zoneid; + + @Parameter(name = OSPFZoneConfig.s_protocol, type = CommandType.STRING, required = false, description = "the password used to secure inter ospf communication(default ospf)") + private String protocol; + + @Parameter(name = OSPFZoneConfig.s_area, type = CommandType.STRING, required = false, description = "Specify the OSPF Area ID") + private String area; + + @Parameter(name = OSPFZoneConfig.s_helloInterval, type = CommandType.SHORT, required = false, description = "Set number of seconds for HelloInterval timer value.(default 10)") + private Short helloInterval; + + @Parameter(name = OSPFZoneConfig.s_deadInterval, type = CommandType.SHORT, required = false, description = "Set number of seconds for RouterDeadInterval timer value used for Wait Timer and Inactivity Timer.(default 40)") + private Short deadInterval; + + @Parameter(name = OSPFZoneConfig.s_retransmitInterval, type = CommandType.SHORT, required = false, description = "Set number of seconds for RxmtInterval timer value.(default 5)") + private Short retransmitInterval; + + @Parameter(name = OSPFZoneConfig.s_transitDelay, type = CommandType.SHORT, required = false, description = "Set number of seconds for InfTransDelay value.(default 1)") + private Short transitDelay; + + @Parameter(name = OSPFZoneConfig.s_authentication, type = CommandType.STRING, required = false, description = "Md5 or PlainText (default MD5)") + private String authentication; + + @Parameter(name = OSPFZoneConfig.s_password, type = CommandType.STRING, required = false, description = "The password used to secure inter quagga communication") + private String password; + + @Parameter(name = OSPFZoneConfig.s_superCIDR, type = CommandType.STRING, required = false, description = "The super zone level CIDR for ospf enabled VPCs") + private String superCIDR; + + @Parameter(name = OSPFZoneConfig.s_enabled, type = CommandType.BOOLEAN, required = false, description = "The flag to enable or disable ospf for this zone") + private Boolean enabled; + + @Inject + public VpcProvisioningService _vpcProvSvc; + + public Long getZoneid() { + return zoneid; + } + + public void setZoneid(Long zoneid) { + this.zoneid = zoneid; + } + + public Long getId() { + return zoneid; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getArea() { + return area; + } + + public void setArea(String area) { + this.area = area; + } + + public Short getHelloInterval() { + return helloInterval; + } + + public void setHelloInterval(Short helloInterval) { + this.helloInterval = helloInterval; + } + + public Short getDeadInterval() { + return deadInterval; + } + + public void setDeadInterval(Short deadInterval) { + this.deadInterval = deadInterval; + } + + public Short getRetransmitInterval() { + return retransmitInterval; + } + + public void setRetransmitInterval(Short retransmitInterval) { + this.retransmitInterval = retransmitInterval; + } + + public Short getTransitDelay() { + return transitDelay; + } + + public void setTransitDelay(Short transitDelay) { + this.transitDelay = transitDelay; + } + + public String getAuthentication() { + return authentication; + } + + public void setAuthentication(String authentication) { + this.authentication = authentication; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getSuperCIDR() { + return superCIDR; + } + + public void setSuperCIDR(String superCIDR) { + this.superCIDR = superCIDR; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + @Override + public void execute() { + try { + Map details = _vpcProvSvc.updateQuaggaConfig(getId(), getProtocol(), getArea(), getHelloInterval(), getDeadInterval(), getRetransmitInterval(), + getTransitDelay(), getAuthentication(), getPassword(), getSuperCIDR(), getEnabled()); + VPCOSPFConfigResponse response = new VPCOSPFConfigResponse(getId(), details); + response.setResponseName(getCommandName()); + response.setObjectName("ospfconfig"); + setResponseObject(response); + } catch (BadCIDRException ex) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to return a valid response due to problems with CIDR"); + } + } + + @Override + public String getCommandName() { + return s_name; + } + + @Override + public long getEntityOwnerId() { + return Account.ACCOUNT_ID_SYSTEM; + } + + @Override + public String toString() { + return "VPCOSPFConfigUpdateCmd [zoneid=" + zoneid + ", protocol=" + protocol + ", area=" + area + ", helloInterval=" + helloInterval + ", deadInterval=" + deadInterval + + ", retransmitInterval=" + retransmitInterval + ", transitDelay=" + transitDelay + ", authentication=" + authentication + ", password=" + password + ", superCIDR=" + + superCIDR + ", enabled=" + enabled + "]"; + } + +} diff --git a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java index 173126148082..b92fb3ca4ee7 100644 --- a/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/network/CreateNetworkCmd.java @@ -45,8 +45,8 @@ import com.cloud.network.Network.GuestType; import com.cloud.offering.NetworkOffering; -@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = {Network.class}, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "createNetwork", description = "Creates a network", responseObject = NetworkResponse.class, responseView = ResponseView.Restricted, entityType = { + Network.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateNetworkCmd extends BaseCmd { public static final Logger s_logger = Logger.getLogger(CreateNetworkCmd.class.getName()); @@ -62,35 +62,28 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, required = true, description = "the display text of the network") private String displayText; - @Parameter(name = ApiConstants.NETWORK_OFFERING_ID, - type = CommandType.UUID, - entityType = NetworkOfferingResponse.class, - required = true, - description = "the network offering ID") + @Parameter(name = ApiConstants.NETWORK_OFFERING_ID, type = CommandType.UUID, entityType = NetworkOfferingResponse.class, required = true, description = "the network offering ID") private Long networkOfferingId; @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "the zone ID for the network") private Long zoneId; - @Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, - type = CommandType.UUID, - entityType = PhysicalNetworkResponse.class, - description = "the physical network ID the network belongs to") + @Parameter(name = ApiConstants.PHYSICAL_NETWORK_ID, type = CommandType.UUID, entityType = PhysicalNetworkResponse.class, description = "the physical network ID the network belongs to") private Long physicalNetworkId; @Parameter(name = ApiConstants.GATEWAY, type = CommandType.STRING, description = "the gateway of the network. Required " - + "for shared networks and isolated networks when it belongs to VPC") + + "for shared networks and isolated networks when it belongs to VPC") private String gateway; @Parameter(name = ApiConstants.NETMASK, type = CommandType.STRING, description = "the netmask of the network. Required " - + "for shared networks and isolated networks when it belongs to VPC") + + "for shared networks and isolated networks when it belongs to VPC") private String netmask; @Parameter(name = ApiConstants.START_IP, type = CommandType.STRING, description = "the beginning IP address in the network IP range") private String startIp; @Parameter(name = ApiConstants.END_IP, type = CommandType.STRING, description = "the ending IP address in the network IP" - + " range. If not specified, will be defaulted to startIP") + + " range. If not specified, will be defaulted to startIP") private String endIp; @Parameter(name = ApiConstants.ISOLATED_PVLAN, type = CommandType.STRING, description = "the isolated private VLAN for this network") @@ -100,8 +93,8 @@ public class CreateNetworkCmd extends BaseCmd { private String networkDomain; @Parameter(name = ApiConstants.ACL_TYPE, type = CommandType.STRING, description = "Access control type; supported values" - + " are account and domain. In 3.0 all shared networks should have aclType=Domain, and all isolated networks" - + " - Account. Account means that only the account owner can use the network, domain - all accounts in the domain can use the network") + + " are account and domain. In 3.0 all shared networks should have aclType=Domain, and all isolated networks" + + " - Account. Account means that only the account owner can use the network, domain - all accounts in the domain can use the network") private String aclType; @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "account that will own the network") @@ -113,10 +106,8 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "domain ID of the account owning a network") private Long domainId; - @Parameter(name = ApiConstants.SUBDOMAIN_ACCESS, - type = CommandType.BOOLEAN, - description = "Defines whether to allow" - + " subdomains to use networks dedicated to their parent domain(s). Should be used with aclType=Domain, defaulted to allow.subdomain.network.access global config if not specified") + @Parameter(name = ApiConstants.SUBDOMAIN_ACCESS, type = CommandType.BOOLEAN, description = "Defines whether to allow" + + " subdomains to use networks dedicated to their parent domain(s). Should be used with aclType=Domain, defaulted to allow.subdomain.network.access global config if not specified") private Boolean subdomainAccess; @Parameter(name = ApiConstants.VPC_ID, type = CommandType.UUID, entityType = VpcResponse.class, description = "the VPC network belongs to") @@ -134,9 +125,8 @@ public class CreateNetworkCmd extends BaseCmd { @Parameter(name = ApiConstants.IP6_CIDR, type = CommandType.STRING, description = "the CIDR of IPv6 network, must be at least /64") private String ip6Cidr; - @Parameter(name = ApiConstants.DISPLAY_NETWORK, - type = CommandType.BOOLEAN, - description = "an optional field, whether to the display the network to the end user or not.", authorized = {RoleType.Admin}) + @Parameter(name = ApiConstants.DISPLAY_NETWORK, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the network to the end user or not.", authorized = { + RoleType.Admin}) private Boolean displayNetwork; @Parameter(name = ApiConstants.ACL_ID, type = CommandType.UUID, entityType = NetworkACLResponse.class, description = "Network ACL ID associated for the network") @@ -211,10 +201,11 @@ public Boolean getDisplayNetwork() { @Override public boolean isDisplay() { - if(displayNetwork == null) + if (displayNetwork == null) { return true; - else + } else { return displayNetwork; + } } public Long getZoneId() { @@ -299,8 +290,7 @@ public long getEntityOwnerId() { @Override // an exception thrown by createNetwork() will be caught by the dispatcher. - public - void execute() throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException { + public void execute() throws InsufficientCapacityException, ConcurrentOperationException, ResourceAllocationException { Network result = _networkService.createGuestNetwork(this); if (result != null) { NetworkResponse response = _responseGenerator.createNetworkResponse(ResponseView.Restricted, result); diff --git a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java index e5e50178d9b8..c316071ea65a 100644 --- a/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java +++ b/api/src/org/apache/cloudstack/api/command/user/vpc/CreateVPCCmd.java @@ -18,6 +18,7 @@ import org.apache.log4j.Logger; + import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; @@ -39,9 +40,10 @@ import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.ResourceUnavailableException; import com.cloud.network.vpc.Vpc; +import com.cloud.utils.net.cidr.BadCIDRException; -@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = {Vpc.class}, - requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) +@APICommand(name = "createVPC", description = "Creates a VPC", responseObject = VpcResponse.class, responseView = ResponseView.Restricted, entityType = { + Vpc.class}, requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class CreateVPCCmd extends BaseAsyncCreateCmd { public static final Logger s_logger = Logger.getLogger(CreateVPCCmd.class.getName()); private static final String s_name = "createvpcresponse"; @@ -50,48 +52,48 @@ public class CreateVPCCmd extends BaseAsyncCreateCmd { // ////////////// API parameters ///////////////////// // /////////////////////////////////////////////////// - @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the account associated with the VPC. " + - "Must be used with the domainId parameter.") + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, description = "the account associated with the VPC. " + "Must be used with the domainId parameter.") private String accountName; - @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, - description = "the domain ID associated with the VPC. " + - "If used with the account parameter returns the VPC associated with the account for the specified domain.") + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, entityType = DomainResponse.class, description = "the domain ID associated with the VPC. " + + "If used with the account parameter returns the VPC associated with the account for the specified domain.") private Long domainId; - @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, - description = "create VPC for the project") + @Parameter(name = ApiConstants.PROJECT_ID, type = CommandType.UUID, entityType = ProjectResponse.class, description = "create VPC for the project") private Long projectId; - @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, - required = true, description = "the ID of the availability zone") + @Parameter(name = ApiConstants.ZONE_ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "the ID of the availability zone") private Long zoneId; @Parameter(name = ApiConstants.NAME, type = CommandType.STRING, required = true, description = "the name of the VPC") private String vpcName; - @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, required = true, description = "the display text of " + - "the VPC") + @Parameter(name = ApiConstants.DISPLAY_TEXT, type = CommandType.STRING, required = true, description = "the display text of " + "the VPC") private String displayText; - @Parameter(name = ApiConstants.CIDR, type = CommandType.STRING, required = true, description = "the cidr of the VPC. All VPC " + - "guest networks' cidrs should be within this CIDR") + @Parameter(name = ApiConstants.CIDR, type = CommandType.STRING, description = "the cidr of the VPC. All VPC " + "guest networks' cidrs should be within this CIDR") private String cidr; - @Parameter(name = ApiConstants.VPC_OFF_ID, type = CommandType.UUID, entityType = VpcOfferingResponse.class, - required = true, description = "the ID of the VPC offering") + @Parameter(name = ApiConstants.GATEWAY, type = CommandType.STRING, description = "the gateway of the network. Required " + + "for shared networks and isolated networks when it belongs to VPC") + private String gateway; + + @Parameter(name = ApiConstants.NETMASK, type = CommandType.STRING, description = "the netmask of the network. Required " + + "for shared networks and isolated networks when it belongs to VPC") + private String netmask; + + @Parameter(name = ApiConstants.VPC_OFF_ID, type = CommandType.UUID, entityType = VpcOfferingResponse.class, required = true, description = "the ID of the VPC offering") private Long vpcOffering; - @Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, - description = "VPC network domain. All networks inside the VPC will belong to this domain") + @Parameter(name = ApiConstants.NETWORK_DOMAIN, type = CommandType.STRING, description = "VPC network domain. All networks inside the VPC will belong to this domain") private String networkDomain; - @Parameter(name = ApiConstants.START, type = CommandType.BOOLEAN, - description = "If set to false, the VPC won't start (VPC VR will not get allocated) until its first network gets implemented. " + - "True by default.", since = "4.3") + @Parameter(name = ApiConstants.START, type = CommandType.BOOLEAN, description = "If set to false, the VPC won't start (VPC VR will not get allocated) until its first network gets implemented. " + + "True by default.", since = "4.3") private Boolean start; - @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the vpc to the end user or not", since = "4.4", authorized = {RoleType.Admin}) + @Parameter(name = ApiConstants.FOR_DISPLAY, type = CommandType.BOOLEAN, description = "an optional field, whether to the display the vpc to the end user or not", since = "4.4", authorized = { + RoleType.Admin}) private Boolean display; // /////////////////////////////////////////////////// @@ -118,6 +120,10 @@ public String getCidr() { return cidr; } + public String getNetmask() { + return netmask; + } + public String getDisplayText() { return displayText; } @@ -143,7 +149,17 @@ public Boolean getDisplayVpc() { @Override public void create() throws ResourceAllocationException { - Vpc vpc = _vpcService.createVpc(getZoneId(), getVpcOffering(), getEntityOwnerId(), getVpcName(), getDisplayText(), getCidr(), getNetworkDomain(), getDisplayVpc()); + Vpc vpc; + if (_vpcService.isVpcOfferingDynamicallyRouted(getZoneId(), getVpcOffering())) { + try { + vpc = _vpcService.createDynamicVpc(getZoneId(), getVpcOffering(), getEntityOwnerId(), getVpcName(), getDisplayText(), getNetmask(), getNetworkDomain(), + getDisplayVpc()); + } catch (BadCIDRException e) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create a VPC due to invalid CIDR"); + } + } else { + vpc = _vpcService.createVpc(getZoneId(), getVpcOffering(), getEntityOwnerId(), getVpcName(), getDisplayText(), getCidr(), getNetworkDomain(), getDisplayVpc()); + } if (vpc != null) { setEntityId(vpc.getId()); setEntityUuid(vpc.getUuid()); @@ -160,7 +176,7 @@ public void execute() { _vpcService.startVpc(getEntityId(), true); } else { s_logger.debug("Not starting VPC as " + ApiConstants.START + "=false was passed to the API"); - } + } vpc = _entityMgr.findById(Vpc.class, getEntityId()); } catch (ResourceUnavailableException ex) { s_logger.warn("Exception: ", ex); @@ -190,7 +206,7 @@ public String getEventType() { @Override public String getEventDescription() { - return "creating VPC. Id: " + getEntityId(); + return "creating VPC. Id: " + getEntityId(); } @Override diff --git a/api/src/org/apache/cloudstack/api/response/VPCOSPFConfigResponse.java b/api/src/org/apache/cloudstack/api/response/VPCOSPFConfigResponse.java new file mode 100644 index 000000000000..eb9f78ea6c7e --- /dev/null +++ b/api/src/org/apache/cloudstack/api/response/VPCOSPFConfigResponse.java @@ -0,0 +1,187 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.response; + +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.BaseResponse; +import org.apache.commons.lang.StringUtils; + +import com.cloud.network.vpc.OSPFZoneConfig; +import com.cloud.network.vpc.VpcProvisioningService; +import com.cloud.serializer.Param; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.google.gson.annotations.SerializedName; + +public class VPCOSPFConfigResponse extends BaseResponse { + + @SerializedName("zoneid") + @Param(description = "the ID of the Zone") + private Long zoneid; + + @SerializedName("protocol") + @Param(description = "the ospf protocol to use") + private String protocol; + + @SerializedName("area") + @Param(description = "the name of ospf area") + private String area; + + @SerializedName("helloInterval") + @Param(description = "number of seconds for HelloInterval timer value") + private Short helloInterval; + + @SerializedName("deadInterval") + @Param(description = "number of seconds for RouterDeadInterval timer value used for Wait Timer and Inactivity Timer.") + private Short deadInterval; + + @SerializedName("retransmitInterval") + @Param(description = "number of seconds for RxmtInterval timer value.") + private Short retransmitInterval; + + @SerializedName("transitDelay") + @Param(description = "number of seconds for InfTransDelay value. ") + private Short transitDelay; + + @SerializedName("authentication") + @Param(description = "the authentciation type MD5 or PlainText") + private String authentication; + + @SerializedName("password") + @Param(description = "the password used to secure inter quagga communication") + private String password; + + @SerializedName("superCIDR") + @Param(description = "the super zone level CIDR for ospf enabled VPCs") + private String superCIDR; + + @SerializedName("enabled") + @Param(description = "flag to enable or disable quagga for this zone") + private Boolean enabled; + + @Inject + public VpcProvisioningService _vpcProvSvc; + + public Long getZoneid() { + return zoneid; + } + + public void setZoneid(Long zoneid) { + this.zoneid = zoneid; + } + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String quaggaProtocol) { + this.protocol = quaggaProtocol; + } + + public String getArea() { + return area; + } + + public void setArea(String ospfArea) { + this.area = ospfArea; + } + + public Short getHelloInterval() { + return helloInterval; + } + + public void setHelloInterval(Short quaggaHelloInterval) { + this.helloInterval = quaggaHelloInterval; + } + + public Short getDeadInterval() { + return deadInterval; + } + + public void setDeadInterval(Short quaggaDeadInterval) { + this.deadInterval = quaggaDeadInterval; + } + + public Short getRetransmitInterval() { + return retransmitInterval; + } + + public void setRetransmitInterval(Short quaggaRetransmitInterval) { + this.retransmitInterval = quaggaRetransmitInterval; + } + + public Short getTransitDelay() { + return transitDelay; + } + + public void setTransitDelay(Short quaggaTransitDelay) { + this.transitDelay = quaggaTransitDelay; + } + + public String getAuthentication() { + return authentication; + } + + public void setAuthentication(String quaggaAuthentication) { + this.authentication = quaggaAuthentication; + } + + public String getPassword() { + return password; + } + + public void setPassword(String quaggaPassword) { + this.password = quaggaPassword; + } + + public String getSuperCIDR() { + return superCIDR; + } + + public void setSuperCIDR(String ospfSuperCIDR) { + this.superCIDR = ospfSuperCIDR; + } + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean quaggaEnabled) { + this.enabled = quaggaEnabled; + } + + public VPCOSPFConfigResponse(Long zoneid, Map details) throws BadCIDRException { + super(); + this.zoneid = zoneid; + OSPFZoneConfig qzc = new OSPFZoneConfig(); + qzc.setDefaultValues(details); + this.protocol = qzc.getProtocol().name(); + this.area = qzc.getOspfArea(); + this.helloInterval = qzc.getHelloInterval(); + this.deadInterval = qzc.getDeadInterval(); + this.retransmitInterval = qzc.getRetransmitInterval(); + this.transitDelay = qzc.getTransitDelay(); + this.authentication = qzc.getAuthentication().name(); + this.password = qzc.getPassword(); + this.superCIDR = StringUtils.join(qzc.getSuperCIDR(), ','); + this.enabled = qzc.getEnabled(); + } + +} diff --git a/api/src/org/apache/cloudstack/usage/UsageTypes.java b/api/src/org/apache/cloudstack/usage/UsageTypes.java index d9cfc132e15d..e66e29b7fd06 100644 --- a/api/src/org/apache/cloudstack/usage/UsageTypes.java +++ b/api/src/org/apache/cloudstack/usage/UsageTypes.java @@ -42,6 +42,7 @@ public class UsageTypes { public static final int VM_DISK_BYTES_READ = 23; public static final int VM_DISK_BYTES_WRITE = 24; public static final int VM_SNAPSHOT = 25; + public static final int DYNAMIC_ROUTING_POLICY = 16; public static List listUsageTypes() { List responseList = new ArrayList(); @@ -56,6 +57,7 @@ public static List listUsageTypes() { responseList.add(new UsageTypeResponse(SNAPSHOT, "Snapshot Usage")); responseList.add(new UsageTypeResponse(SECURITY_GROUP, "Security Group Usage")); responseList.add(new UsageTypeResponse(LOAD_BALANCER_POLICY, "Load Balancer Usage")); + responseList.add(new UsageTypeResponse(DYNAMIC_ROUTING_POLICY, "Dynmaic Routing Usage")); responseList.add(new UsageTypeResponse(PORT_FORWARDING_RULE, "Port Forwarding Usage")); responseList.add(new UsageTypeResponse(NETWORK_OFFERING, "Network Offering Usage")); responseList.add(new UsageTypeResponse(VPN_USERS, "VPN users usage")); diff --git a/api/test/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmdTest.java b/api/test/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmdTest.java new file mode 100644 index 000000000000..12a7e89a1890 --- /dev/null +++ b/api/test/org/apache/cloudstack/api/command/admin/vpc/VPCOSPFConfigCmdTest.java @@ -0,0 +1,72 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.cloudstack.api.command.admin.vpc; + +import java.lang.reflect.Field; + +import org.apache.cloudstack.api.ApiConstants; +import org.apache.cloudstack.context.CallContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +import com.cloud.network.vpc.VpcProvisioningService; +import com.cloud.utils.net.cidr.BadCIDRException; + +import junit.framework.TestCase; + +@RunWith(MockitoJUnitRunner.class) +public class VPCOSPFConfigCmdTest extends TestCase { + + @Mock + public VpcProvisioningService vpcProvSvc; + + @InjectMocks + VPCOSPFConfigUpdateCmd vpcOSPFConfig = new VPCOSPFConfigUpdateCmd(); + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + Field f = VPCOSPFConfigUpdateCmd.class.getDeclaredField("_vpcProvSvc"); + f.setAccessible(true); + f.set(vpcOSPFConfig, vpcProvSvc); + } + + @After + public void tearDown() throws Exception { + CallContext.unregister(); + } + + @Test + public void testInvocation() throws IllegalArgumentException, IllegalAccessException, BadCIDRException { + ReflectionTestUtils.setField(vpcOSPFConfig, ApiConstants.ZONE_ID, 1L); + ReflectionTestUtils.setField(vpcOSPFConfig, "password", "sfkjsdkk123"); + ReflectionTestUtils.setField(vpcOSPFConfig, "superCIDR", "192.168.100.0/20"); + + vpcOSPFConfig.execute(); + Mockito.verify(vpcProvSvc, Mockito.times(1)).updateQuaggaConfig(1L, null, null, null, null, null, null, null, "sfkjsdkk123", "192.168.100.0/20", null); + } + +} diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties index fbdedda5c2db..cda52139901c 100644 --- a/client/WEB-INF/classes/resources/messages.properties +++ b/client/WEB-INF/classes/resources/messages.properties @@ -2260,3 +2260,29 @@ message.configure.firewall.rules.allow.traffic=Configure the rules to allow Traf message.configure.firewall.rules.block.traffic=Configure the rules to block Traffic message.ldap.group.import=All The users from the given group name will be imported label.vpn.force.encapsulation=Force UDP Encapsulation of ESP Packets +label.vpc.dynamicallyrouted=Dynamically Routed +label.vpc.dynamicallyrouted.configitemname=Config Item +label.vpc.dynamicallyrouted.configitemvalue=Value +label.vpc.dynamicallyrouted.enabled=Dynamic Routing Enabled +label.vpc.dynamicallyrouted.protocol=Dynamic Routing Protocol +label.vpc.dynamicallyrouted.ospfarea=OSPF Area Id +label.vpc.dynamicallyrouted.hellointerval=Hello Interval +label.vpc.dynamicallyrouted.deadinterval=Dead Interval +label.vpc.dynamicallyrouted.retransmitinterval=Retransmit Interval +label.vpc.dynamicallyrouted.transitdelay=Transit Delay +label.vpc.dynamicallyrouted.authentication=Authentication +label.vpc.dynamicallyrouted.password=Password +label.vpc.dynamicallyrouted.supercidr=Zone Super CIDR +label.vpc.dynamicrouting.service=VPCDynamicRouting +label.vpc.dynamicrouting.add=Add Routed VPC +label.vpc.dynamicrouting.ipv4.netmask=IPv4 Netmask + + + + + + + + + + diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index 32f33c98805b..ab3c9e31e110 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -485,6 +485,10 @@ updateVPCOffering=1 deleteVPCOffering=1 listVPCOfferings=15 +#### VPC OSPF config commands +vpcOSPFConfig=15 +vpcOSPFConfigUpdate=1 + #### Private gateway commands createPrivateGateway=1 listPrivateGateways=15 diff --git a/core/src/com/cloud/agent/api/routing/QuaggaConfigCommand.java b/core/src/com/cloud/agent/api/routing/QuaggaConfigCommand.java new file mode 100644 index 000000000000..6130b59e97bf --- /dev/null +++ b/core/src/com/cloud/agent/api/routing/QuaggaConfigCommand.java @@ -0,0 +1,86 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.agent.api.routing; + +import com.cloud.network.vpc.OSPFZoneConfig; +import com.cloud.utils.net.cidr.CIDR; + +public class QuaggaConfigCommand extends NetworkElementCommand { + + private String routerPublicIp; + private String routerName; + private String vpnCidr; + private CIDR[] tierCidrs; + private OSPFZoneConfig zoneConfig; + + public QuaggaConfigCommand(final String routerPublicIp, final String routerName, final String vpnCidr, final CIDR[] tierCidrs, final OSPFZoneConfig qzc) { + this.routerPublicIp = routerPublicIp; + this.routerName = routerName; + this.vpnCidr = vpnCidr; + this.tierCidrs = tierCidrs; + this.zoneConfig = qzc; + } + + public OSPFZoneConfig getZoneConfig() { + return zoneConfig; + } + + public void setZoneConfig(OSPFZoneConfig zoneConfig) { + this.zoneConfig = zoneConfig; + } + + public String getRouterPublicIp() { + return routerPublicIp; + } + + public void setRouterPublicIp(String routerPublicIp) { + this.routerPublicIp = routerPublicIp; + } + + public String getRouterName() { + return routerName; + } + + public void setRouterName(String routerName) { + this.routerName = routerName; + } + + public String getVpnCidr() { + return vpnCidr; + } + + public void setVpnCidr(String vpnCidr) { + this.vpnCidr = vpnCidr; + } + + public CIDR[] getTierCidrs() { + return tierCidrs; + } + + public void setTierCidrs(CIDR[] tierCidrs) { + this.tierCidrs = tierCidrs; + } + + @Override + public boolean executeInSequence() { + return true; + } + +} diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VRScripts.java b/core/src/com/cloud/agent/resource/virtualnetwork/VRScripts.java index a2515056be1d..008ece483461 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VRScripts.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VRScripts.java @@ -38,6 +38,7 @@ public class VRScripts { public static final String DHCP_CONFIG = "dhcp.json"; public static final String IP_ALIAS_CONFIG = "ip_aliases.json"; public static final String LOAD_BALANCER_CONFIG = "load_balancer.json"; + public static final String QUAGGA_CONFIG = "quagga.json"; public final static String CONFIG_CACHE_LOCATION = "/var/cache/cloud/"; public final static int DEFAULT_EXECUTEINVR_TIMEOUT = 120; //Seconds diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java index f3edc6967594..59aa98bd7e07 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/VirtualRoutingResource.java @@ -169,8 +169,6 @@ private ExecutionResult applyConfigToVR(String routerAccessIp, ConfigItem c, int private Answer applyConfig(NetworkElementCommand cmd, List cfg) { - - if (cfg.isEmpty()) { return new Answer(cmd, true, "Nothing to do"); } diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java b/core/src/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java index f017384b63c3..deea673978be 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/facade/AbstractConfigItemFacade.java @@ -23,6 +23,8 @@ import java.util.LinkedList; import java.util.List; +import org.apache.log4j.Logger; + import com.cloud.agent.api.BumpUpPriorityCommand; import com.cloud.agent.api.SetupGuestNetworkCommand; import com.cloud.agent.api.routing.CreateIpAliasCommand; @@ -33,6 +35,7 @@ import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.LoadBalancerConfigCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.QuaggaConfigCommand; import com.cloud.agent.api.routing.RemoteAccessVpnCfgCommand; import com.cloud.agent.api.routing.SavePasswordCommand; import com.cloud.agent.api.routing.SetFirewallRulesCommand; @@ -57,16 +60,14 @@ import com.google.gson.GsonBuilder; public abstract class AbstractConfigItemFacade { + private static final Logger s_logger = Logger.getLogger(AbstractConfigItemFacade.class); private final static Gson gson; private static Hashtable, AbstractConfigItemFacade> flyweight = new Hashtable, AbstractConfigItemFacade>(); static { - gson = new GsonBuilder() - .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) - .disableHtmlEscaping() - .create(); + gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).disableHtmlEscaping().create(); flyweight.put(SetPortForwardingRulesVpcCommand.class, new SetPortForwardingRulesVpcConfigItem()); flyweight.put(SetPortForwardingRulesCommand.class, new SetPortForwardingRulesConfigItem()); @@ -90,6 +91,7 @@ public abstract class AbstractConfigItemFacade { flyweight.put(SetSourceNatCommand.class, new SetSourceNatConfigItem()); flyweight.put(IpAssocCommand.class, new IpAssociationConfigItem()); flyweight.put(IpAssocVpcCommand.class, new IpAssociationConfigItem()); + flyweight.put(QuaggaConfigCommand.class, new QuaggaConfigItem()); } protected String destinationFile; @@ -98,7 +100,6 @@ public static AbstractConfigItemFacade getInstance(final Class generateConfig(final NetworkElementCommand cmd) { + final QuaggaConfigCommand command = (QuaggaConfigCommand)cmd; + + final String vrIp = command.getRouterPublicIp(); + final String vrName = command.getRouterName(); + final CIDR[] cidrs = command.getTierCidrs(); + final OSPFZoneConfig qzc = command.getZoneConfig(); + + StringBuilder zebra = new StringBuilder(); + zebra.append("hostname " + vrName).append(","); + zebra.append("interface eth1").append(","); + zebra.append(" description link to area 0").append(","); + zebra.append(" ip address " + vrIp + "/24").append(","); + zebra.append(" link-detect").append(","); + zebra.append("log file /var/log/quagga/zebra.log").append(","); + + StringBuilder ospfd = new StringBuilder(); + ospfd.append("hostname " + vrName).append(","); + ospfd.append("interface eth1").append(","); + ospfd.append(" ip ospf hello-interval ").append(qzc.getHelloInterval()).append(","); + ospfd.append(" ip ospf dead-interval ").append(qzc.getDeadInterval()).append(","); + ospfd.append(" ip ospf retransmit-interval ").append(qzc.getRetransmitInterval()).append(","); + ospfd.append(" ip ospf transmit-delay ").append(qzc.getTransitDelay()).append(","); + if (qzc.getAuthentication().equals(OSPFZoneConfig.Authentication.MD5) && qzc.getPassword().length() > 3){ + ospfd.append(" ip ospf authentication message-digest").append(","); + ospfd.append(" ip ospf message-digest-key 1 md5 ").append(qzc.getPassword()).append(","); + } + ospfd.append("router ospf").append(","); + ospfd.append(" ospf router-id " + vrIp).append(","); + ospfd.append(" redistribute connected").append(","); + ospfd.append(" no passive-interface eth1").append(","); + ospfd.append(" network " + vrIp + "/24 area ").append(qzc.getOspfArea()).append(","); + if (qzc.getAuthentication().equals(OSPFZoneConfig.Authentication.MD5) && qzc.getPassword().length() > 3){ + ospfd.append(" area ").append(qzc.getOspfArea()).append(" authentication message-digest").append(","); + } + if (cidrs != null) { + for (CIDR cidr : cidrs) { + ospfd.append(" network " + cidr + " area ").append(qzc.getOspfArea()).append(","); + } + } + ospfd.append("log file /var/log/quagga/ospfd.log").append(","); + + final String tmpCfgFilePath = "/etc/quagga/"; + final String tmpCfgFileName = "ospfd.conf.new." + String.valueOf(System.currentTimeMillis()); + + final QuaggaRule quaggaRule = new QuaggaRule(zebra.toString(), ospfd.toString(), tmpCfgFilePath, tmpCfgFileName, vrIp); + + return generateConfigItems(quaggaRule); + } + + @Override + protected List generateConfigItems(final ConfigBase configuration) { + destinationFile = VRScripts.QUAGGA_CONFIG; + + return super.generateConfigItems(configuration); + } + +} diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java b/core/src/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java index edc721178cbe..95f8caf8dddb 100644 --- a/core/src/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java +++ b/core/src/com/cloud/agent/resource/virtualnetwork/model/ConfigBase.java @@ -38,6 +38,7 @@ public abstract class ConfigBase { public static final String MONITORSERVICE = "monitorservice"; public static final String DHCP_CONFIG = "dhcpconfig"; public static final String LOAD_BALANCER = "loadbalancer"; + public static final String QUAGGA = "quagga"; private String type = UNKNOWN; diff --git a/core/src/com/cloud/agent/resource/virtualnetwork/model/QuaggaRule.java b/core/src/com/cloud/agent/resource/virtualnetwork/model/QuaggaRule.java new file mode 100644 index 000000000000..1d9f5d4b4f78 --- /dev/null +++ b/core/src/com/cloud/agent/resource/virtualnetwork/model/QuaggaRule.java @@ -0,0 +1,87 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.agent.resource.virtualnetwork.model; + +public class QuaggaRule extends ConfigBase { + private String zebraConfig; + private String ospfConfig; + private String tmpCfgFilePath; + private String tmpCfgFileName; + private String routerIp; + + public QuaggaRule() { + super(QuaggaRule.QUAGGA); + } + + public QuaggaRule(final String zebraConfig, final String ospfConfig, final String tmpCfgFilePath, final String tmpCfgFileName, final String routerIp) { + super(QuaggaRule.QUAGGA); + this.zebraConfig = zebraConfig; + this.ospfConfig = ospfConfig; + this.tmpCfgFilePath = tmpCfgFilePath; + this.tmpCfgFileName = tmpCfgFileName; + this.routerIp = routerIp; + } + + public String getZebraConfig() { + return zebraConfig; + } + + public void setZebraConfig(String zebraConfig) { + this.zebraConfig = zebraConfig; + } + + public String getOspfConfig() { + return ospfConfig; + } + + public void setOspfConfig(String ospfConfig) { + this.ospfConfig = ospfConfig; + } + + public String getTmpCfgFilePath() { + return tmpCfgFilePath; + } + + public void setTmpCfgFilePath(String tmpCfgFilePath) { + this.tmpCfgFilePath = tmpCfgFilePath; + } + + public String getTmpCfgFileName() { + return tmpCfgFileName; + } + + public void setTmpCfgFileName(String tmpCfgFileName) { + this.tmpCfgFileName = tmpCfgFileName; + } + + public String getRouterIp() { + return routerIp; + } + + public void setRouterIp(String routerIp) { + this.routerIp = routerIp; + } + + @Override + public String toString() { + return "QuaggaRule [zebraConfig=" + (zebraConfig) + ", ospfConfig=" + (ospfConfig) + ", tmpCfgFilePath=" + tmpCfgFilePath + + ", tmpCfgFileName=" + tmpCfgFileName + ", routerIp=" + routerIp + "]"; + } +} diff --git a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java index 8539871e48bd..b94d998b2a1d 100644 --- a/engine/components-api/src/com/cloud/network/vpc/VpcManager.java +++ b/engine/components-api/src/com/cloud/network/vpc/VpcManager.java @@ -36,6 +36,8 @@ import com.cloud.network.addr.PublicIp; import com.cloud.offering.NetworkOffering; import com.cloud.user.Account; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; public interface VpcManager { /** @@ -106,12 +108,10 @@ public interface VpcManager { * @throws InsufficientCapacityException * @throws ResourceAllocationException */ - Network - createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, - Long domainId, PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, Long aclId, Account caller, - Boolean displayNetworkEnabled) + Network createVpcGuestNetwork(long ntwkOffId, String name, String displayText, String gateway, String cidr, String vlanId, String networkDomain, Account owner, Long domainId, + PhysicalNetwork pNtwk, long zoneId, ACLType aclType, Boolean subdomainAccess, long vpcId, Long aclId, Account caller, Boolean displayNetworkEnabled) - throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; + throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException; /** * Assigns source nat public IP address to VPC @@ -161,8 +161,9 @@ public interface VpcManager { * @param gateway * @param networkOwner TODO */ - void - validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId); + void validateNtwkOffForNtwkInVpc(Long networkId, long newNtwkOffId, String newCidr, String newNetworkDomain, Vpc vpc, String gateway, Account networkOwner, Long aclId); List getVpcPrivateGateways(long vpcId); + + CIDR[] getZoneSuperCidrList(long zoneId) throws BadCIDRException; } diff --git a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java index ca9ad50b3c1c..31a4ec6fe3b1 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/datacenter/entity/api/db/EngineDataCenterVO.java @@ -38,6 +38,7 @@ import org.apache.cloudstack.engine.datacenter.entity.api.DataCenterResourceEntity.State.Event; import com.cloud.network.Network.Provider; +import com.cloud.network.vpc.OSPFZoneConfig; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; @@ -501,4 +502,9 @@ public String getIp6Dns2() { public void setIp6Dns2(String ip6Dns2) { this.ip6Dns2 = ip6Dns2; } + + @Override + public boolean isDynamicRoutingEnabled() { + return Boolean.valueOf(getDetail(OSPFZoneConfig.Params.ENABLED.name())); + } } 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 e4272720bc86..2ea15067b667 100644 --- a/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java +++ b/engine/orchestration/src/org/apache/cloudstack/engine/orchestration/NetworkOrchestrator.java @@ -16,7 +16,6 @@ // under the License. package org.apache.cloudstack.engine.orchestration; - import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -156,6 +155,7 @@ import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.VpcManager; import com.cloud.network.vpc.dao.PrivateIpDao; +import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao; import com.cloud.network.vpn.RemoteAccessVpnService; import com.cloud.offering.NetworkOffering; import com.cloud.offering.NetworkOffering.Availability; @@ -189,6 +189,9 @@ import com.cloud.utils.fsm.NoTransitionException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; +import com.cloud.utils.net.cidr.CIDRFactory; import com.cloud.vm.Nic; import com.cloud.vm.Nic.ReservationStrategy; import com.cloud.vm.NicIpAlias; @@ -337,6 +340,8 @@ public void setDhcpProviders(final List dhcpProviders) { @Inject VpcManager _vpcMgr; @Inject + VpcOfferingServiceMapDao _vpcOffServiceDao; + @Inject PrivateIpDao _privateIpDao; @Inject NetworkACLManager _networkACLMgr; @@ -469,7 +474,16 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { _networkOfferingDao.update(offering.getId(), offering); } - //#6 - default vpc offering with no LB service + //#6 - default vpc offering with Dynamic Routing and LB service + if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedDynamicRoutedNetworkOfferingForVpcNetworks) == null) { + defaultVPCOffProviders.put(Service.VPCDynamicRouting, defaultProviders); + offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedDynamicRoutedNetworkOfferingForVpcNetworks, + "Offering for Isolated VPC networks with Source Nat and Dynamic Routing service enabled", TrafficType.Guest, null, false, Availability.Optional, null, + defaultVPCOffProviders, true, Network.GuestType.Isolated, false, null, false, null, false, false, null, false, null, true); + offering.setState(NetworkOffering.State.Enabled); + _networkOfferingDao.update(offering.getId(), offering); + } + //#7 - default vpc offering with no LB service if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB) == null) { //remove LB service defaultVPCOffProviders.remove(Service.Lb); @@ -480,7 +494,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { _networkOfferingDao.update(offering.getId(), offering); } - //#7 - isolated offering with source nat disabled + //#8 - isolated offering with source nat disabled if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOffering) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOffering, "Offering for Isolated networks with no Source Nat service", TrafficType.Guest, null, true, Availability.Optional, null, defaultIsolatedNetworkOfferingProviders, true, Network.GuestType.Isolated, false, null, @@ -504,6 +518,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { internalLbOffProviders.put(Service.Gateway, defaultVpcProvider); internalLbOffProviders.put(Service.Lb, defaultInternalLbProvider); internalLbOffProviders.put(Service.SourceNat, defaultVpcProvider); + internalLbOffProviders.put(Service.VPCDynamicRouting, defaultProviders); if (_networkOfferingDao.findByUniqueName(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB) == null) { offering = _configMgr.createNetworkOffering(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB, @@ -604,8 +619,8 @@ protected NetworkOrchestrator() { } @Override - public List setupNetwork(final Account owner, final NetworkOffering offering, final DeploymentPlan plan, final String name, final String displayText, final boolean isDefault) - throws ConcurrentOperationException { + public List setupNetwork(final Account owner, final NetworkOffering offering, final DeploymentPlan plan, final String name, final String displayText, + final boolean isDefault) throws ConcurrentOperationException { return setupNetwork(owner, offering, null, plan, name, displayText, false, null, null, null, null, true); } @@ -621,11 +636,11 @@ public List setupNetwork(final Account owner, final NetworkOf } try { - if (predefined == null - || offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null && !(predefined - .getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch || predefined - .getBroadcastDomainType() == BroadcastDomainType.Vxlan)) { + if (predefined == null || offering.getTrafficType() != TrafficType.Guest && predefined.getCidr() == null && predefined.getBroadcastUri() == null + && !(predefined.getBroadcastDomainType() == BroadcastDomainType.Vlan || predefined.getBroadcastDomainType() == BroadcastDomainType.Lswitch + || predefined.getBroadcastDomainType() == BroadcastDomainType.Vxlan)) { final List configs = _networksDao.listBy(owner.getId(), offering.getId(), plan.getDataCenterId()); + if (configs.size() > 0) { if (s_logger.isDebugEnabled()) { s_logger.debug("Found existing network configuration for offering " + offering + ": " + configs.get(0)); @@ -671,8 +686,9 @@ public List setupNetwork(final Account owner, final NetworkOf Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(final TransactionStatus status) { - final 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(), + final 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, offering.getRedundantRouter()); vo.setDisplayNetwork(isDisplayNetworkEnabled == null ? true : isDisplayNetworkEnabled); vo.setStrechedL2Network(offering.getSupportsStrechedL2()); @@ -680,8 +696,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { finalizeServicesAndProvidersForNetwork(offering, plan.getPhysicalNetworkId())); networks.add(networkPersisted); - if (predefined instanceof NetworkVO && guru instanceof NetworkGuruAdditionalFunctions){ - final NetworkGuruAdditionalFunctions functions = (NetworkGuruAdditionalFunctions) guru; + if (predefined instanceof NetworkVO && guru instanceof NetworkGuruAdditionalFunctions) { + final NetworkGuruAdditionalFunctions functions = (NetworkGuruAdditionalFunctions)guru; functions.finalizeNetworkDesign(networkPersisted.getId(), ((NetworkVO)predefined).getVlanIdAsUUID()); } @@ -708,8 +724,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { @Override @DB - public void allocate(final VirtualMachineProfile vm, final LinkedHashMap> networks) throws InsufficientCapacityException, - ConcurrentOperationException { + public void allocate(final VirtualMachineProfile vm, final LinkedHashMap> networks) + throws InsufficientCapacityException, ConcurrentOperationException { Transaction.execute(new TransactionCallbackWithExceptionNoReturn() { @Override @@ -943,8 +959,9 @@ boolean isNetworkImplemented(final NetworkVO network) { return false; } - Pair implementNetwork(final long networkId, final DeployDestination dest, final ReservationContext context, final boolean isRouter) throws ConcurrentOperationException, - ResourceUnavailableException, InsufficientCapacityException { + Pair implementNetwork(final long networkId, final DeployDestination dest, final ReservationContext context, final boolean isRouter) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + Pair implemented = null; if (!isRouter) { implemented = implementNetwork(networkId, dest, context); @@ -963,8 +980,8 @@ Pair implementNetwork(final long networkId, final Deploy @Override @DB - public Pair implementNetwork(final long networkId, final DeployDestination dest, final ReservationContext context) throws ConcurrentOperationException, - ResourceUnavailableException, InsufficientCapacityException { + public Pair implementNetwork(final long networkId, final DeployDestination dest, final ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { final Pair implemented = new Pair(null, null); NetworkVO network = _networksDao.findById(networkId); @@ -1114,7 +1131,8 @@ public void implementNetworkElementsAndResources(final DeployDestination dest, f } if (!element.implement(network, offering, dest, context)) { - final CloudRuntimeException ex = new CloudRuntimeException("Failed to implement provider " + element.getProvider().getName() + " for network with specified id"); + final CloudRuntimeException ex = new CloudRuntimeException( + "Failed to implement provider " + element.getProvider().getName() + " for network with specified id"); ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -1133,8 +1151,8 @@ public void implementNetworkElementsAndResources(final DeployDestination dest, f if (!reprogramNetworkRules(network.getId(), CallContext.current().getCallingAccount(), network)) { s_logger.warn("Failed to re-program the network as a part of network " + network + " implement"); // see DataCenterVO.java - final ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", DataCenter.class, - network.getDataCenterId()); + final ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", + DataCenter.class, network.getDataCenterId()); ex.addProxyObject(_entityMgr.findById(DataCenter.class, network.getDataCenterId()).getUuid()); throw ex; } @@ -1143,8 +1161,9 @@ public void implementNetworkElementsAndResources(final DeployDestination dest, f if (!((AggregatedCommandExecutor)element).completeAggregatedExecution(network, dest)) { s_logger.warn("Failed to re-program the network as a part of network " + network + " implement due to aggregated commands execution failure!"); // see DataCenterVO.java - final ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", DataCenter.class, - network.getDataCenterId()); + final ResourceUnavailableException ex = new ResourceUnavailableException("Unable to apply network rules as a part of network " + network + " implement", + DataCenter.class, network.getDataCenterId()); + ex.addProxyObject(_entityMgr.findById(DataCenter.class, network.getDataCenterId()).getUuid()); throw ex; } @@ -1169,6 +1188,7 @@ protected boolean reprogramNetworkRules(final long networkId, final Account call final DataCenter zone = _dcDao.findById(network.getDataCenterId()); if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) && (network.getGuestType() == Network.GuestType.Isolated || network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced)) { + // add default egress rule to accept the traffic _firewallMgr.applyDefaultEgressFirewallRule(network.getId(), offering.getEgressDefaultPolicy(), true); } @@ -1177,7 +1197,6 @@ protected boolean reprogramNetworkRules(final long networkId, final Account call success = false; } - // associate all ip addresses if (!_ipAddrMgr.applyIpAssociations(network, false)) { s_logger.warn("Failed to apply ip addresses as a part of network id" + networkId + " restart"); @@ -1242,8 +1261,8 @@ protected boolean reprogramNetworkRules(final long networkId, final Account call return success; } - protected boolean prepareElement(final NetworkElement element, final Network network, final NicProfile profile, final VirtualMachineProfile vmProfile, final DeployDestination dest, - final ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { + protected boolean prepareElement(final NetworkElement element, final Network network, final NicProfile profile, final VirtualMachineProfile vmProfile, + final DeployDestination dest, final ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { element.prepare(network, profile, vmProfile, dest, context); if (vmProfile.getType() == Type.User && element.getProvider() != null) { if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) @@ -1256,14 +1275,15 @@ protected boolean prepareElement(final NetworkElement element, final Network net return false; } } - if(!sp.addDhcpEntry(network, profile, vmProfile, dest, context)) { + if (!sp.addDhcpEntry(network, profile, vmProfile, dest, context)) { return false; } } if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.UserData) && _networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.UserData, element.getProvider()) && element instanceof UserDataServiceProvider) { final UserDataServiceProvider sp = (UserDataServiceProvider)element; - if(!sp.addPasswordAndUserdata(network, profile, vmProfile, dest, context)){ + if (!sp.addPasswordAndUserdata(network, profile, vmProfile, dest, context)) { + return false; } } @@ -1292,8 +1312,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { } @Override - public void prepare(final VirtualMachineProfile vmProfile, final DeployDestination dest, final ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException, - ResourceUnavailableException { + public void prepare(final VirtualMachineProfile vmProfile, final DeployDestination dest, final ReservationContext context) + throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException { final List nics = _nicDao.listByVmId(vmProfile.getId()); // we have to implement default nics first - to ensure that default network elements start up first in multiple @@ -1395,7 +1415,8 @@ public NicProfile prepareNic(final VirtualMachineProfile vmProfile, final Deploy @Override public void prepareNicForMigration(final VirtualMachineProfile vm, final DeployDestination dest) { - if(vm.getType().equals(VirtualMachine.Type.DomainRouter) && (vm.getHypervisorType().equals(HypervisorType.KVM) || vm.getHypervisorType().equals(HypervisorType.VMware))) { + if (vm.getType().equals(VirtualMachine.Type.DomainRouter) && (vm.getHypervisorType().equals(HypervisorType.KVM) || vm.getHypervisorType().equals(HypervisorType.VMware))) { + //Include nics hot plugged and not stored in DB prepareAllNicsForMigration(vm, dest); return; @@ -1407,8 +1428,8 @@ public void prepareNicForMigration(final VirtualMachineProfile vm, final DeployD final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); - final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), - _networkModel.getNetworkTag(vm.getHypervisorType(), network)); + final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, + _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network)); if (guru instanceof NetworkMigrationResponder) { if (!((NetworkMigrationResponder)guru).prepareMigration(profile, network, vm, dest, context)) { s_logger.error("NetworkGuru " + guru + " prepareForMigration failed."); // XXX: Transaction error @@ -1445,7 +1466,8 @@ public void prepareAllNicsForMigration(final VirtualMachineProfile vm, final Dep Long guestNetworkId = null; for (final NicVO nic : nics) { final NetworkVO network = _networksDao.findById(nic.getNetworkId()); - if(network.getTrafficType().equals(TrafficType.Guest) && network.getGuestType().equals(GuestType.Isolated)){ + if (network.getTrafficType().equals(TrafficType.Guest) && network.getGuestType().equals(GuestType.Isolated)) { + guestNetworkId = network.getId(); } final Integer networkRate = _networkModel.getNetworkRate(network.getId(), vm.getId()); @@ -1453,20 +1475,22 @@ public void prepareAllNicsForMigration(final VirtualMachineProfile vm, final Dep final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), networkRate, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vm.getHypervisorType(), network)); - if(guru instanceof NetworkMigrationResponder){ - if(!((NetworkMigrationResponder) guru).prepareMigration(profile, network, vm, dest, context)){ - s_logger.error("NetworkGuru "+guru+" prepareForMigration failed."); // XXX: Transaction error + if (guru instanceof NetworkMigrationResponder) { + if (!((NetworkMigrationResponder)guru).prepareMigration(profile, network, vm, dest, context)) { + s_logger.error("NetworkGuru " + guru + " prepareForMigration failed."); // XXX: Transaction error + } } final List providersToImplement = getNetworkProviders(network.getId()); for (final NetworkElement element : networkElements) { if (providersToImplement.contains(element.getProvider())) { if (!_networkModel.isProviderEnabledInPhysicalNetwork(_networkModel.getPhysicalNetworkId(network), element.getProvider().getName())) { - throw new CloudRuntimeException("Service provider " + element.getProvider().getName() + " either doesn't exist or is not enabled in physical network id: " + network.getPhysicalNetworkId()); + throw new CloudRuntimeException("Service provider " + element.getProvider().getName() + " either doesn't exist or is not enabled in physical network id: " + + network.getPhysicalNetworkId()); } - if(element instanceof NetworkMigrationResponder){ - if(!((NetworkMigrationResponder) element).prepareMigration(profile, network, vm, dest, context)){ - s_logger.error("NetworkElement "+element+" prepareForMigration failed."); // XXX: Transaction error + if (element instanceof NetworkMigrationResponder) { + if (!((NetworkMigrationResponder)element).prepareMigration(profile, network, vm, dest, context)) { + s_logger.error("NetworkElement " + element + " prepareForMigration failed."); // XXX: Transaction error } } } @@ -1476,22 +1500,22 @@ public void prepareAllNicsForMigration(final VirtualMachineProfile vm, final Dep } final List addedURIs = new ArrayList(); - if(guestNetworkId != null){ + if (guestNetworkId != null) { final List publicIps = _ipAddressDao.listByAssociatedNetwork(guestNetworkId, null); - for (final IPAddressVO userIp : publicIps){ + for (final IPAddressVO userIp : publicIps) { final PublicIp publicIp = PublicIp.createFromAddrAndVlan(userIp, _vlanDao.findById(userIp.getVlanId())); final URI broadcastUri = BroadcastDomainType.Vlan.toUri(publicIp.getVlanTag()); final long ntwkId = publicIp.getNetworkId(); - final Nic nic = _nicDao.findByNetworkIdInstanceIdAndBroadcastUri(ntwkId, vm.getId(), - broadcastUri.toString()); - if(nic == null && !addedURIs.contains(broadcastUri.toString())){ + final Nic nic = _nicDao.findByNetworkIdInstanceIdAndBroadcastUri(ntwkId, vm.getId(), broadcastUri.toString()); + if (nic == null && !addedURIs.contains(broadcastUri.toString())) { //Nic details are not available in DB //Create nic profile for migration - s_logger.debug("Creating nic profile for migration. BroadcastUri: "+broadcastUri.toString()+" NetworkId: "+ntwkId+" Vm: "+vm.getId()); + s_logger.debug("Creating nic profile for migration. BroadcastUri: " + broadcastUri.toString() + " NetworkId: " + ntwkId + " Vm: " + vm.getId()); final NetworkVO network = _networksDao.findById(ntwkId); _networkModel.getNetworkRate(network.getId(), vm.getId()); final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); final NicProfile profile = new NicProfile(); + profile.setDeviceId(255); //dummyId profile.setIPv4Address(userIp.getAddress().toString()); profile.setIPv4Netmask(publicIp.getNetmask()); @@ -1607,14 +1631,14 @@ public Pair doInTransaction(final TransactionStatus status) final Nic.State originalState = nic.getState(); final NetworkVO network = _networksDao.findById(nic.getNetworkId()); - if (originalState == Nic.State.Reserved || originalState == Nic.State.Reserving) { if (nic.getReservationStrategy() == Nic.ReservationStrategy.Start) { final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); nic.setState(Nic.State.Releasing); _nicDao.update(nic.getId(), nic); - final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, _networkModel - .isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network)); + final NicProfile profile = new NicProfile(nic, network, nic.getBroadcastUri(), nic.getIsolationUri(), null, + _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag(vmProfile.getHypervisorType(), network)); + if (guru.release(profile, vmProfile, nic.getReservationId())) { applyProfileToNicForRelease(nic, profile); nic.setState(Nic.State.Allocated); @@ -1637,12 +1661,12 @@ public Pair doInTransaction(final TransactionStatus status) }); // cleanup the entry in vm_network_map - if(vmProfile.getType().equals(VirtualMachine.Type.User)) { + if (vmProfile.getType().equals(VirtualMachine.Type.User)) { final NicVO nic = _nicDao.findById(nicId); - if(nic != null) { + if (nic != null) { final NetworkVO vmNetwork = _networksDao.findById(nic.getNetworkId()); final VMNetworkMapVO vno = _vmNetworkMapDao.findByVmAndNetworkId(vmProfile.getVirtualMachine().getId(), vmNetwork.getId()); - if(vno != null) { + if (vno != null) { _vmNetworkMapDao.remove(vno.getId()); } } @@ -1697,8 +1721,8 @@ protected void removeNic(final VirtualMachineProfile vm, final NicVO nic) { nic.setState(Nic.State.Deallocating); _nicDao.update(nic.getId(), nic); final NetworkVO network = _networksDao.findById(nic.getNetworkId()); - final NicProfile profile = new NicProfile(nic, network, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(network), _networkModel.getNetworkTag( - vm.getHypervisorType(), network)); + final NicProfile profile = new NicProfile(nic, network, null, null, null, _networkModel.isSecurityGroupSupportedInNetwork(network), + _networkModel.getNetworkTag(vm.getHypervisorType(), network)); /* * We need to release the nics with a Create ReservationStrategy here @@ -1722,15 +1746,12 @@ protected void removeNic(final VirtualMachineProfile vm, final NicVO nic) { } } - if (vm.getType() == Type.User - && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) - && network.getTrafficType() == TrafficType.Guest - && network.getGuestType() == GuestType.Shared - && isLastNicInSubnet(nic)) { + if (vm.getType() == Type.User && _networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) && network.getTrafficType() == TrafficType.Guest + && network.getGuestType() == GuestType.Shared && isLastNicInSubnet(nic)) { // remove the dhcpservice ip if this is the last nic in subnet. final DhcpServiceProvider dhcpServiceProvider = getDhcpServiceProvider(network); - if (dhcpServiceProvider != null - && isDhcpAccrossMultipleSubnetsSupported(dhcpServiceProvider)) { + if (dhcpServiceProvider != null && isDhcpAccrossMultipleSubnetsSupported(dhcpServiceProvider)) { + removeDhcpServiceInSubnet(nic); } } @@ -1822,7 +1843,8 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam // Validate network offering if (ntwkOff.getState() != NetworkOffering.State.Enabled) { // see NetworkOfferingVO - final InvalidParameterValueException ex = new InvalidParameterValueException("Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled); + final InvalidParameterValueException ex = new InvalidParameterValueException( + "Can't use specified network offering id as its stat is not " + NetworkOffering.State.Enabled); ex.addProxyObject(ntwkOff.getUuid(), "networkOfferingId"); throw ex; } @@ -1923,10 +1945,10 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam if (vlanSpecified) { //don't allow to specify vlan tag used by physical network for dynamic vlan allocation if (_dcDao.findVnet(zoneId, pNtwk.getId(), vlanId).size() > 0) { - throw new InvalidParameterValueException("The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone " - + zone.getName()); + throw new InvalidParameterValueException( + "The VLAN tag " + vlanId + " is already being used for dynamic vlan allocation for the guest network in zone " + zone.getName()); } - if (! UuidUtils.validateUUID(vlanId)){ + if (!UuidUtils.validateUUID(vlanId)) { final String uri = BroadcastDomainType.fromString(vlanId).toString(); // For Isolated networks, don't allow to create network with vlan that already exists in the zone if (ntwkOff.getGuestType() == GuestType.Isolated) { @@ -1952,9 +1974,10 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam final int vnetsAllocatedToAccount = _datacenterVnetDao.countVnetsAllocatedToAccount(zoneId, owner.getAccountId()); final int vnetsDedicatedToAccount = _datacenterVnetDao.countVnetsDedicatedToAccount(zoneId, owner.getAccountId()); if (vnetsAllocatedToAccount < vnetsDedicatedToAccount) { - throw new InvalidParameterValueException("Specified vlan " + vlanId + " doesn't belong" + " to the vlan range dedicated to the owner " - + owner.getAccountName()); + throw new InvalidParameterValueException( + "Specified vlan " + vlanId + " doesn't belong" + " to the vlan range dedicated to the owner " + owner.getAccountName()); } + } } } @@ -1962,9 +1985,10 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam } else { // don't allow to creating shared network with given Vlan ID, if there already exists a isolated network or // shared network with same Vlan ID in the zone - if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0 ) { + if (_networksDao.countByZoneUriAndGuestType(zoneId, uri, GuestType.Isolated) > 0) { throw new InvalidParameterValueException("There is a isolated/shared network with vlan id: " + vlanId + " already exists " + "in zone " + zoneId); } + } } @@ -1972,8 +1996,8 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam // If networkDomain is not specified, take it from the global configuration if (_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Dns)) { - final Map dnsCapabilities = _networkModel.getNetworkOfferingServiceCapabilities(_entityMgr.findById(NetworkOffering.class, networkOfferingId), - Service.Dns); + final Map dnsCapabilities = _networkModel + .getNetworkOfferingServiceCapabilities(_entityMgr.findById(NetworkOffering.class, networkOfferingId), Service.Dns); final String isUpdateDnsSupported = dnsCapabilities.get(Capability.AllowDnsSuffixModification); if (isUpdateDnsSupported == null || !Boolean.valueOf(isUpdateDnsSupported)) { if (networkDomain != null) { @@ -2008,10 +2032,9 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam // In Advance zone Cidr for Shared networks and Isolated networks w/o source nat service can't be NULL - 2.2.x // limitation, remove after we introduce support for multiple ip ranges // with different Cidrs for the same Shared network - final boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced - && ntwkOff.getTrafficType() == TrafficType.Guest - && (ntwkOff.getGuestType() == GuestType.Shared || ntwkOff.getGuestType() == GuestType.Isolated && !_networkModel.areServicesSupportedByNetworkOffering( - ntwkOff.getId(), Service.SourceNat)); + final boolean cidrRequired = zone.getNetworkType() == NetworkType.Advanced && ntwkOff.getTrafficType() == TrafficType.Guest && (ntwkOff.getGuestType() == GuestType.Shared + || ntwkOff.getGuestType() == GuestType.Isolated && !_networkModel.areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)); + if (cidr == null && ip6Cidr == null && cidrRequired) { throw new InvalidParameterValueException("StartIp/endIp/gateway/netmask are required when create network of" + " type " + Network.GuestType.Shared + " and network of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() + " disabled"); @@ -2024,8 +2047,25 @@ public Network createGuestNetwork(final long networkOfferingId, final String nam // Check if cidr is RFC1918 compliant if the network is Guest Isolated for IPv4 if (cidr != null && ntwkOff.getGuestType() == Network.GuestType.Isolated && ntwkOff.getTrafficType() == TrafficType.Guest) { - if (!NetUtils.validateGuestCidr(cidr)) { - throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not RFC1918 compliant"); + //check if the vpc supports dynamic routing, this network may not participate in dynamic routing but still the cidr has to be ospf compliant + final Vpc vpc = _vpcMgr.getActiveVpc(vpcId); + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpc.getVpcOfferingId(), Service.VPCDynamicRouting)) { + _dcDao.loadDetails(zone); + try { + final CIDR[] superCidr = _vpcMgr.getZoneSuperCidrList(zoneId); + final CIDR ncidr = CIDRFactory.getCIDR(cidr); + if (!NetUtils.validateGuestCidrForOSPF(ncidr, superCidr)) { + throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not compliant for this dynamically routed network."); + } + } + catch (BadCIDRException ex){ + throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not compliant for this dynamically routed network."); + } + } + else { + if (!NetUtils.validateGuestCidr(cidr)) { + throw new InvalidParameterValueException("Virtual Guest Cidr " + cidr + " is not RFC1918 compliant"); + } } } @@ -2056,11 +2096,10 @@ public Network doInTransaction(final TransactionStatus status) { if (vlanIdFinal != null) { if (isolatedPvlan == null) { URI uri = null; - if (UuidUtils.validateUUID(vlanIdFinal)){ + if (UuidUtils.validateUUID(vlanIdFinal)) { //Logical router's UUID provided as VLAN_ID userNetwork.setVlanIdAsUUID(vlanIdFinal); //Set transient field - } - else { + } else { uri = BroadcastDomainType.fromString(vlanIdFinal); } userNetwork.setBroadcastUri(uri); @@ -2226,7 +2265,7 @@ public boolean shutdownNetworkElementsAndResources(final ReservationContext cont boolean cleanupResult = true; boolean cleanupNeeded = false; try { - for (final Provider provider: providersToShutdown) { + for (final Provider provider : providersToShutdown) { if (provider.cleanupNeededOnShutdown()) { cleanupNeeded = true; break; @@ -2523,8 +2562,8 @@ public void reallyRun() { } @Override - public boolean startNetwork(final long networkId, final DeployDestination dest, final ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { + public boolean startNetwork(final long networkId, final DeployDestination dest, final ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { // Check if network exists final NetworkVO network = _networksDao.findById(networkId); @@ -2537,7 +2576,8 @@ public boolean startNetwork(final long networkId, final DeployDestination dest, // implement the network s_logger.debug("Starting network " + network + "..."); final Pair implementedNetwork = implementNetwork(networkId, dest, context); - if (implementedNetwork== null || implementedNetwork.first() == null) { + if (implementedNetwork == null || implementedNetwork.first() == null) { + s_logger.warn("Failed to start the network " + network); return false; } else { @@ -2546,8 +2586,8 @@ public boolean startNetwork(final long networkId, final DeployDestination dest, } @Override - public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { + public boolean restartNetwork(final Long networkId, final Account callerAccount, final User callerUser, final boolean cleanup) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { final NetworkVO network = _networksDao.findById(networkId); @@ -2638,7 +2678,7 @@ public DhcpServiceProvider getDhcpServiceProvider(final Network network) { } final NetworkElement element = _networkModel.getElementImplementingProvider(DhcpProvider); - if ( element instanceof DhcpServiceProvider ) { + if (element instanceof DhcpServiceProvider) { return (DhcpServiceProvider)element; } else { return null; @@ -2657,12 +2697,12 @@ && isSharedNetworkOfferingWithServices(network.getNetworkOfferingId())) { protected boolean isSharedNetworkOfferingWithServices(final long networkOfferingId) { final NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); - if (networkOffering.getGuestType() == Network.GuestType.Shared - && (_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) - || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) - || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) - || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || _networkModel.areServicesSupportedByNetworkOffering( - networkOfferingId, Service.Lb))) { + if (networkOffering.getGuestType() == Network.GuestType.Shared && (_networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) + || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) + || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) + || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) + || _networkModel.areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) { + return true; } return false; @@ -2683,14 +2723,14 @@ public List listVmNics(final long vmId, final Long nicId, final L s_logger.info("Listing NSX logical switch and logical switch por for each nic"); final NetworkVO network = _networksDao.findById(nic.getNetworkId()); final NetworkGuru guru = AdapterBase.getAdapterByName(networkGurus, network.getGuruName()); - final NetworkGuruAdditionalFunctions guruFunctions = (NetworkGuruAdditionalFunctions) guru; + final NetworkGuruAdditionalFunctions guruFunctions = (NetworkGuruAdditionalFunctions)guru; final Map nsxParams = guruFunctions.listAdditionalNicParams(nic.getUuid()); - if (nsxParams != null){ + if (nsxParams != null) { final String lswitchUuuid = nsxParams.containsKey(NetworkGuruAdditionalFunctions.NSX_LSWITCH_UUID) - ? (String) nsxParams.get(NetworkGuruAdditionalFunctions.NSX_LSWITCH_UUID) : null; + ? (String)nsxParams.get(NetworkGuruAdditionalFunctions.NSX_LSWITCH_UUID) : null; final String lswitchPortUuuid = nsxParams.containsKey(NetworkGuruAdditionalFunctions.NSX_LSWITCHPORT_UUID) - ? (String) nsxParams.get(NetworkGuruAdditionalFunctions.NSX_LSWITCHPORT_UUID) : null; + ? (String)nsxParams.get(NetworkGuruAdditionalFunctions.NSX_LSWITCHPORT_UUID) : null; nic.setNsxLogicalSwitchUuid(lswitchUuuid); nic.setNsxLogicalSwitchPortUuid(lswitchPortUuuid); } @@ -2913,8 +2953,9 @@ private boolean shutdownNetworkResources(final long networkId, final Account cal try { // delete default egress rule final DataCenter zone = _dcDao.findById(network.getDataCenterId()); - if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) - && (network.getGuestType() == Network.GuestType.Isolated || network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced)) { + if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Firewall) && (network.getGuestType() == Network.GuestType.Isolated + || network.getGuestType() == Network.GuestType.Shared && zone.getNetworkType() == NetworkType.Advanced)) { + // add default egress rule to accept the traffic _firewallMgr.applyDefaultEgressFirewallRule(network.getId(), _networkModel.getNetworkEgressDefaultPolicy(networkId), false); } @@ -3068,7 +3109,7 @@ public void processConnect(final Host host, final StartupCommand cmd, final bool } if (!answer.getResult()) { - s_logger.warn("Unable to setup agent " + hostId + " due to " + answer.getDetails() ); + s_logger.warn("Unable to setup agent " + hostId + " due to " + answer.getDetails()); final String msg = "Incorrect Network setup on agent, Reinitialize agent after network names are setup, details : " + answer.getDetails(); _alertMgr.sendAlert(AlertManager.AlertType.ALERT_TYPE_HOST, dcId, host.getPodId(), msg, msg); throw new ConnectionException(true, msg); @@ -3128,8 +3169,8 @@ public Map finalizeServicesAndProvidersForNetwork(final NetworkO // check that provider is supported if (checkPhysicalNetwork) { if (!_pNSPDao.isServiceProviderEnabled(physicalNetworkId, provider, service)) { - throw new UnsupportedServiceException("Provider " + provider + " is either not enabled or doesn't " + "support service " + service + " in physical network id=" - + physicalNetworkId); + throw new UnsupportedServiceException( + "Provider " + provider + " is either not enabled or doesn't " + "support service " + service + " in physical network id=" + physicalNetworkId); } } @@ -3184,9 +3225,9 @@ protected NicProfile getNicProfileForVm(final Network network, final NicProfile } @Override - public NicProfile createNicForVm(final Network network, final NicProfile requested, final ReservationContext context, final VirtualMachineProfile vmProfile, final boolean prepare) - throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException, InsufficientCapacityException, - ResourceUnavailableException { + public NicProfile createNicForVm(final Network network, final NicProfile requested, final ReservationContext context, final VirtualMachineProfile vmProfile, + final boolean prepare) throws InsufficientVirtualNetworkCapacityException, InsufficientAddressCapacityException, ConcurrentOperationException, + InsufficientCapacityException, ResourceUnavailableException { final VirtualMachine vm = vmProfile.getVirtualMachine(); final DataCenter dc = _entityMgr.findById(DataCenter.class, network.getDataCenterId()); @@ -3206,7 +3247,7 @@ public NicProfile createNicForVm(final Network network, final NicProfile request } //Update vm_network_map table - if(vmProfile.getType() == VirtualMachine.Type.User) { + if (vmProfile.getType() == VirtualMachine.Type.User) { final VMNetworkMapVO vno = new VMNetworkMapVO(vm.getId(), network.getId()); _vmNetworkMapDao.persist(vno); } diff --git a/engine/schema/src/com/cloud/dc/DataCenterVO.java b/engine/schema/src/com/cloud/dc/DataCenterVO.java index 42ea34a4704e..49bd1913bf04 100644 --- a/engine/schema/src/com/cloud/dc/DataCenterVO.java +++ b/engine/schema/src/com/cloud/dc/DataCenterVO.java @@ -32,6 +32,7 @@ import javax.persistence.Transient; import com.cloud.network.Network.Provider; +import com.cloud.network.vpc.OSPFZoneConfig; import com.cloud.org.Grouping; import com.cloud.utils.NumbersUtil; import com.cloud.utils.db.GenericDao; @@ -364,6 +365,18 @@ public void setLocalStorageEnabled(boolean enabled) { this.localStorageEnabled = enabled; } + @Override + public boolean isDynamicRoutingEnabled() { + String dynr = getDetail(OSPFZoneConfig.Params.ENABLED.name()); + if (dynr != null ){ + return Boolean.valueOf(dynr); + } + else { + return false; + } + } + + @Override public Map getDetails() { return details; diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java index 4fc055e6ac8c..c4648dda8996 100644 --- a/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java +++ b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java @@ -96,4 +96,8 @@ public interface DataCenterDao extends GenericDao { List findByKeyword(String keyword); List listAllZones(); + + boolean isDynamicallyRouted(long dcId); + + String getDetail(long dcId, String name); } diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java index 847a24730fc3..dd974a611454 100644 --- a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java +++ b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java @@ -438,4 +438,18 @@ public List listAllZones() { return dcs; } + + @Override + public boolean isDynamicallyRouted(final long dcId) { + DataCenterVO zone = this.findById(dcId); + loadDetails(zone); + return zone.isDynamicRoutingEnabled(); + } + + @Override + public String getDetail(final long dcId, final String name) { + DataCenterVO zone = this.findById(dcId); + loadDetails(zone); + return zone.getDetail(name); + } } diff --git a/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderDaoImpl.java b/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderDaoImpl.java index 75c70d14e3a5..93829528d30f 100644 --- a/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderDaoImpl.java +++ b/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderDaoImpl.java @@ -116,6 +116,8 @@ public boolean isServiceProviderEnabled(long physicalNetworkId, String providerT sc.setParameters("userDataService", true); } else if (serviceType.equalsIgnoreCase(Service.Vpn.getName())) { sc.setParameters("vpnService", true); + } else if (serviceType.equalsIgnoreCase(Service.VPCDynamicRouting.getName())) { + sc.setParameters("vpcDynamicRouting", true); } PhysicalNetworkServiceProviderVO map = findOneBy(sc); diff --git a/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java b/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java index 415b513b405a..e8b09478f90f 100644 --- a/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java +++ b/engine/schema/src/com/cloud/network/dao/PhysicalNetworkServiceProviderVO.java @@ -39,6 +39,7 @@ @Entity @Table(name = "physical_network_service_providers") public class PhysicalNetworkServiceProviderVO implements PhysicalNetworkServiceProvider, InternalIdentity { + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") @@ -96,6 +97,9 @@ public class PhysicalNetworkServiceProviderVO implements PhysicalNetworkServiceP @Column(name = "networkacl_service_provided") boolean networkAclServiceProvided; + @Column(name = "dynamic_routing_provided") + boolean dynamicRoutingProvided; + @Column(name = GenericDao.REMOVED_COLUMN) Date removed; @@ -240,6 +244,24 @@ public void setSecuritygroupServiceProvided(boolean securitygroupServiceProvided this.securitygroupServiceProvided = securitygroupServiceProvided; } + @Override + public boolean isNetworkAclServiceProvided() { + return networkAclServiceProvided; + } + + public void setDynamicRoutingProvided(boolean dynamicRoutingProvided) { + this.dynamicRoutingProvided = dynamicRoutingProvided; + } + + @Override + public boolean isDynamicRoutingProvided() { + return dynamicRoutingProvided; + } + + public void setNetworkAclServiceProvided(boolean networkAclServiceProvided) { + this.networkAclServiceProvided = networkAclServiceProvided; + } + @Override public String getUuid() { return this.uuid; @@ -270,6 +292,7 @@ public void setEnabledServices(List services) { this.setUserdataServiceProvided(services.contains(Service.UserData)); this.setSecuritygroupServiceProvided(services.contains(Service.SecurityGroup)); this.setNetworkAclServiceProvided(services.contains(Service.NetworkACL)); + this.setDynamicRoutingProvided(services.contains(Service.VPCDynamicRouting)); } @Override @@ -308,15 +331,21 @@ public List getEnabledServices() { if (this.isSecuritygroupServiceProvided()) { services.add(Service.SecurityGroup); } + if (this.isDynamicRoutingProvided()) { + services.add(Service.VPCDynamicRouting); + } return services; } @Override - public boolean isNetworkAclServiceProvided() { - return networkAclServiceProvided; + public String toString() { + return "PhysicalNetworkServiceProviderVO [id=" + id + ", physicalNetworkId=" + physicalNetworkId + ", destPhysicalNetworkId=" + destPhysicalNetworkId + ", providerName=" + + providerName + ", state=" + state + ", vpnServiceProvided=" + vpnServiceProvided + ", dhcpServiceProvided=" + dhcpServiceProvided + ", dnsServiceProvided=" + + dnsServiceProvided + ", gatewayServiceProvided=" + gatewayServiceProvided + ", firewallServiceProvided=" + firewallServiceProvided + ", sourcenatServiceProvided=" + + sourcenatServiceProvided + ", lbServiceProvided=" + lbServiceProvided + ", staticnatServiceProvided=" + staticnatServiceProvided + + ", portForwardingServiceProvided=" + portForwardingServiceProvided + ", userdataServiceProvided=" + userdataServiceProvided + ", securitygroupServiceProvided=" + + securitygroupServiceProvided + ", networkAclServiceProvided=" + networkAclServiceProvided + ", dynamicRoutingProvided=" + dynamicRoutingProvided + ", removed=" + + removed + "]"; } - public void setNetworkAclServiceProvided(boolean networkAclServiceProvided) { - this.networkAclServiceProvided = networkAclServiceProvided; - } } diff --git a/engine/schema/src/com/cloud/network/vpc/VpcVO.java b/engine/schema/src/com/cloud/network/vpc/VpcVO.java index b78f22f9f55b..79006d9b3a4f 100644 --- a/engine/schema/src/com/cloud/network/vpc/VpcVO.java +++ b/engine/schema/src/com/cloud/network/vpc/VpcVO.java @@ -82,7 +82,7 @@ public class VpcVO implements Vpc { @Column(name = "display", updatable = true, nullable = false) protected boolean display = true; - @Column(name="uses_distributed_router") + @Column(name = "uses_distributed_router") boolean usesDistributedRouter = false; @Column(name = "region_level_vpc") @@ -92,22 +92,21 @@ public VpcVO() { uuid = UUID.randomUUID().toString(); } - public VpcVO(final long zoneId, final String name, final String displayText, final long accountId, final long domainId, - final long vpcOffId, final String cidr, final String networkDomain, final boolean useDistributedRouter, - final boolean regionLevelVpc, final boolean isRedundant) { + public VpcVO(final long zoneId, final String name, final String displayText, final long accountId, final long domainId, final long vpcOffId, final String cidr, + final String networkDomain, final boolean useDistributedRouter, final boolean regionLevelVpc, final boolean isRedundant) { this.zoneId = zoneId; this.name = name; this.displayText = displayText; this.accountId = accountId; this.domainId = domainId; this.cidr = cidr; - uuid = UUID.randomUUID().toString(); - state = State.Enabled; + this.uuid = UUID.randomUUID().toString(); + this.state = State.Enabled; this.networkDomain = networkDomain; - vpcOfferingId = vpcOffId; - usesDistributedRouter = useDistributedRouter; + this.vpcOfferingId = vpcOffId; + this.usesDistributedRouter = useDistributedRouter; this.regionLevelVpc = regionLevelVpc; - redundant = isRedundant; + this.redundant = isRedundant; } @Override @@ -209,7 +208,6 @@ public boolean isRegionLevelVpc() { return regionLevelVpc; } - public void setDisplay(final boolean display) { this.display = display; } @@ -219,15 +217,15 @@ public boolean isDisplay() { return display; } + public void setRedundant(final boolean isRedundant) { + redundant = isRedundant; + } + @Override public boolean isRedundant() { return redundant; } - public void setRedundant(final boolean isRedundant) { - redundant = isRedundant; - } - @Override public Class getEntityType() { return Vpc.class; @@ -237,4 +235,5 @@ public Class getEntityType() { public boolean usesDistributedRouter() { return usesDistributedRouter; } + } diff --git a/engine/schema/src/com/cloud/network/vpc/dao/VpcOfferingServiceMapDao.java b/engine/schema/src/com/cloud/network/vpc/dao/VpcOfferingServiceMapDao.java index 56de31819d28..523f451677a0 100644 --- a/engine/schema/src/com/cloud/network/vpc/dao/VpcOfferingServiceMapDao.java +++ b/engine/schema/src/com/cloud/network/vpc/dao/VpcOfferingServiceMapDao.java @@ -31,7 +31,7 @@ public interface VpcOfferingServiceMapDao extends GenericDao listServicesForVpcOffering(long vpcOfferingId); diff --git a/engine/schema/src/com/cloud/network/vpc/dao/VpcServiceMapDaoImpl.java b/engine/schema/src/com/cloud/network/vpc/dao/VpcServiceMapDaoImpl.java index 753c45fcc789..56dccd7d50f5 100644 --- a/engine/schema/src/com/cloud/network/vpc/dao/VpcServiceMapDaoImpl.java +++ b/engine/schema/src/com/cloud/network/vpc/dao/VpcServiceMapDaoImpl.java @@ -62,7 +62,31 @@ protected VpcServiceMapDaoImpl() { @Override public boolean areServicesSupportedInVpc(long vpcId, Service... services) { - // TODO Auto-generated method stub + SearchCriteria sc = MultipleServicesSearch.create(); + sc.setParameters("vpcId", vpcId); + + if (services != null) { + String[] servicesStr = new String[services.length]; + + int i = 0; + for (Service service : services) { + servicesStr[i] = service.getName(); + i++; + } + + sc.setParameters("service", (Object[])servicesStr); + } + + List vpcServices = listBy(sc); + + if (services != null) { + if (vpcServices.size() == services.length) { + return true; + } + } else if (!vpcServices.isEmpty()) { + return true; + } + return false; } diff --git a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java index c3d849d134c8..2f39d5b522e6 100644 --- a/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java +++ b/engine/schema/src/com/cloud/offerings/NetworkOfferingVO.java @@ -139,7 +139,7 @@ public class NetworkOfferingVO implements NetworkOffering { @Column(name = "keep_alive_enabled") boolean keepAliveEnabled = false; - @Column(name="supports_streched_l2") + @Column(name = "supports_streched_l2") boolean supportsStrechedL2 = false; @Override @@ -301,9 +301,9 @@ public boolean getEgressDefaultPolicy() { return egressdefaultpolicy; } - public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, - Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, - boolean specifyIpRanges, boolean isPersistent, boolean internalLb, boolean publicLb) { + public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, + boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean specifyIpRanges, boolean isPersistent, + boolean internalLb, boolean publicLb) { this.name = name; this.displayText = displayText; this.rateMbps = rateMbps; @@ -331,26 +331,12 @@ public NetworkOfferingVO(String name, String displayText, TrafficType trafficTyp this.internalLb = internalLb; } - public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, - Integer multicastRateMbps, boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, - boolean sharedSourceNat, boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent, - boolean associatePublicIP, boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) { - this(name, - displayText, - trafficType, - systemOnly, - specifyVlan, - rateMbps, - multicastRateMbps, - isDefault, - availability, - tags, - guestType, - conserveMode, - specifyIpRanges, - isPersistent, - internalLb, - publicLb); + public NetworkOfferingVO(String name, String displayText, TrafficType trafficType, boolean systemOnly, boolean specifyVlan, Integer rateMbps, Integer multicastRateMbps, + boolean isDefault, Availability availability, String tags, Network.GuestType guestType, boolean conserveMode, boolean dedicatedLb, boolean sharedSourceNat, + boolean redundantRouter, boolean elasticIp, boolean elasticLb, boolean specifyIpRanges, boolean inline, boolean isPersistent, boolean associatePublicIP, + boolean publicLb, boolean internalLb, boolean egressdefaultpolicy, boolean supportsStrechedL2) { + this(name, displayText, trafficType, systemOnly, specifyVlan, rateMbps, multicastRateMbps, isDefault, availability, tags, guestType, conserveMode, specifyIpRanges, + isPersistent, internalLb, publicLb); this.dedicatedLB = dedicatedLb; this.sharedSourceNat = sharedSourceNat; this.redundantRouter = redundantRouter; @@ -379,22 +365,8 @@ public NetworkOfferingVO(String name, TrafficType trafficType, boolean specifyIp } public NetworkOfferingVO(String name, Network.GuestType guestType) { - this(name, - "System Offering for " + name, - TrafficType.Guest, - true, - true, - 0, - 0, - true, - Availability.Optional, - null, - Network.GuestType.Isolated, - true, - false, - false, - false, - false); + this(name, "System Offering for " + name, TrafficType.Guest, true, true, 0, 0, true, Availability.Optional, null, Network.GuestType.Isolated, true, false, false, false, + false); this.state = State.Enabled; } diff --git a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java index b667e58b5558..1513d47ec4c3 100644 --- a/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java +++ b/engine/schema/src/com/cloud/offerings/dao/NetworkOfferingServiceMapDaoImpl.java @@ -52,7 +52,6 @@ protected NetworkOfferingServiceMapDaoImpl() { MultipleServicesSearch = createSearchBuilder(); MultipleServicesSearch.and("networkOfferingId", MultipleServicesSearch.entity().getNetworkOfferingId(), SearchCriteria.Op.EQ); MultipleServicesSearch.and("service", MultipleServicesSearch.entity().getService(), SearchCriteria.Op.IN); - MultipleServicesSearch.and("provider", MultipleServicesSearch.entity().getProvider(), SearchCriteria.Op.EQ); MultipleServicesSearch.done(); ProvidersSearch = createSearchBuilder(String.class); diff --git a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaConfig.java b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaConfig.java index 73c9a80e3c91..4491dee7a2f9 100644 --- a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaConfig.java +++ b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaConfig.java @@ -24,7 +24,7 @@ public interface QuotaConfig { public static final ConfigKey QuotaPluginEnabled = new ConfigKey("Advanced", Boolean.class, "quota.enable.service", "false", "Indicates whether Quota plugin is enabled or not", true); - public static final ConfigKey QuotaEnableEnforcement = new ConfigKey("Advanced", String.class, "quota.enable.enforcement", "false", + public static final ConfigKey QuotaEnableEnforcement = new ConfigKey("Advanced", Boolean.class, "quota.enable.enforcement", "false", "Enable the usage quota enforcement, i.e. on true when exceeding quota the respective account will be locked.", true); public static final ConfigKey QuotaCurrencySymbol = new ConfigKey("Advanced", String.class, "quota.currency.symbol", "$", diff --git a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java index 36910f47741e..1b9b72409ca3 100644 --- a/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java +++ b/framework/quota/src/org/apache/cloudstack/quota/constant/QuotaTypes.java @@ -47,6 +47,7 @@ public class QuotaTypes extends UsageTypes { quotaTypeList.put(SNAPSHOT, new QuotaTypes(SNAPSHOT, "SNAPSHOT", "GB-Month", "Snapshot Usage")); quotaTypeList.put(SECURITY_GROUP, new QuotaTypes(SECURITY_GROUP, "SECURITY_GROUP", "Policy-Month", "Security Group Usage")); quotaTypeList.put(LOAD_BALANCER_POLICY, new QuotaTypes(LOAD_BALANCER_POLICY, "LOAD_BALANCER_POLICY", "Policy-Month", "Load Balancer Usage")); + quotaTypeList.put(DYNAMIC_ROUTING_POLICY, new QuotaTypes(DYNAMIC_ROUTING_POLICY, "DYNAMIC_ROUTING_POLICY", "Policy-Month", "Dynamic Routing Usage")); quotaTypeList.put(PORT_FORWARDING_RULE, new QuotaTypes(PORT_FORWARDING_RULE, "PORT_FORWARDING_RULE", "Policy-Month", "Port Forwarding Usage")); quotaTypeList.put(NETWORK_OFFERING, new QuotaTypes(NETWORK_OFFERING, "NETWORK_OFFERING", "Policy-Month", "Network Offering Usage")); quotaTypeList.put(VPN_USERS, new QuotaTypes(VPN_USERS, "VPN_USERS", "Policy-Month", "VPN users usage")); diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java index 162d2a98de46..78e2549d4b1d 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java @@ -138,7 +138,8 @@ public List createQuotaSummaryResponse(Boolean listAll) { } else { for (final QuotaAccountVO quotaAccount : _quotaAccountDao.listAllQuotaAccount()) { AccountVO account = _accountDao.findById(quotaAccount.getId()); - if (account == null) continue; + if (account == null) + continue; QuotaSummaryResponse qr = getQuotaSummaryResponse(account); result.add(qr); } @@ -389,7 +390,6 @@ public QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Doubl Date despositedOn = _quotaService.computeAdjustedTime(new Date()); QuotaBalanceVO qb = _quotaBalanceDao.findLaterBalanceEntry(accountId, domainId, despositedOn); - if (qb != null) { throw new InvalidParameterValueException("Incorrect deposit date: " + despositedOn + " there are balance entries after this date"); } @@ -399,10 +399,12 @@ public QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Doubl QuotaCreditsVO result = _quotaCreditsDao.saveCredits(credits); final AccountVO account = _accountDao.findById(accountId); + if (account == null) { throw new InvalidParameterValueException("Account does not exist with account id " + accountId); } - final boolean lockAccountEnforcement = "true".equalsIgnoreCase(QuotaConfig.QuotaEnableEnforcement.value()); + final boolean lockAccountEnforcement = QuotaConfig.QuotaEnableEnforcement.value(); + final BigDecimal currentAccountBalance = _quotaBalanceDao.lastQuotaBalance(accountId, domainId, startOfNextDay(new Date(despositedOn.getTime()))); if (s_logger.isDebugEnabled()) { s_logger.debug("AddQuotaCredits: Depositing " + amount + " on adjusted date " + despositedOn + ", current balance " + currentAccountBalance); diff --git a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java index 155c84bbadf7..beebf7dcf182 100644 --- a/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xenserver/src/com/cloud/hypervisor/xenserver/resource/CitrixResourceBase.java @@ -86,6 +86,7 @@ import com.cloud.agent.api.routing.IpAssocCommand; import com.cloud.agent.api.routing.IpAssocVpcCommand; import com.cloud.agent.api.routing.NetworkElementCommand; +import com.cloud.agent.api.routing.QuaggaConfigCommand; import com.cloud.agent.api.routing.SetNetworkACLCommand; import com.cloud.agent.api.routing.SetSourceNatCommand; import com.cloud.agent.api.to.DataStoreTO; @@ -3908,6 +3909,8 @@ public ExecutionResult prepareCommand(final NetworkElementCommand cmd) { return prepareNetworkElementCommand((SetSourceNatCommand) cmd); } else if (cmd instanceof SetNetworkACLCommand) { return prepareNetworkElementCommand((SetNetworkACLCommand) cmd); + } else if (cmd instanceof SetNetworkACLCommand) { + return prepareNetworkElementCommand((QuaggaConfigCommand) cmd); } return new ExecutionResult(true, null); } @@ -4115,6 +4118,12 @@ protected ExecutionResult prepareNetworkElementCommand(final IpAssocCommand cmd) return new ExecutionResult(true, null); } + protected ExecutionResult prepareNetworkElementCommand(final QuaggaConfigCommand cmd) { + final Connection conn = getConnection(); + final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); + return new ExecutionResult(true, null); + } + protected ExecutionResult prepareNetworkElementCommand(final IpAssocVpcCommand cmd) { final Connection conn = getConnection(); final String routerName = cmd.getAccessDetail(NetworkElementCommand.ROUTER_NAME); diff --git a/pom.xml b/pom.xml index c18c377cf226..f4379567c18d 100644 --- a/pom.xml +++ b/pom.xml @@ -867,6 +867,8 @@ systemvm/patches/debian/vpn/etc/xl2tpd/xl2tpd.conf systemvm/patches/debian/vpn/etc/ipsec.secrets systemvm/patches/debian/config/etc/haproxy/haproxy.cfg + systemvm/patches/debian/config/etc/quagga/daemons + systemvm/patches/debian/config/etc/quagga/debian.conf systemvm/patches/debian/config/etc/cloud-nic.rules systemvm/patches/debian/config/etc/modprobe.d/aesni_intel systemvm/patches/debian/config/etc/rc.local diff --git a/server/src/com/cloud/network/IpAddressManagerImpl.java b/server/src/com/cloud/network/IpAddressManagerImpl.java index e65adb60f7d5..0e1b922b5d2b 100644 --- a/server/src/com/cloud/network/IpAddressManagerImpl.java +++ b/server/src/com/cloud/network/IpAddressManagerImpl.java @@ -339,6 +339,7 @@ public boolean configure(String name, Map params) { defaultVPCOffProviders.put(Service.StaticNat, defaultProviders); defaultVPCOffProviders.put(Service.PortForwarding, defaultProviders); defaultVPCOffProviders.put(Service.Vpn, defaultProviders); + defaultVPCOffProviders.put(Service.VPCDynamicRouting, defaultProviders); //#8 - network offering with internal lb service Map> internalLbOffProviders = new HashMap>(); diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java b/server/src/com/cloud/network/NetworkServiceImpl.java index b6dac872f30a..ee20d2128515 100644 --- a/server/src/com/cloud/network/NetworkServiceImpl.java +++ b/server/src/com/cloud/network/NetworkServiceImpl.java @@ -196,7 +196,7 @@ /** * NetworkServiceImpl implements NetworkService. */ -public class NetworkServiceImpl extends ManagerBase implements NetworkService { +public class NetworkServiceImpl extends ManagerBase implements NetworkService { private static final Logger s_logger = Logger.getLogger(NetworkServiceImpl.class); private static final long MIN_VLAN_ID = 0L; @@ -441,8 +441,8 @@ protected boolean canIpUsedForNonConserveService(PublicIp ip, Service service) { throw new InvalidParameterException("There are multiple services used ip " + ip.getAddress() + "."); } if (service != null && !((Service)services.toArray()[0] == service || service.equals(Service.Firewall))) { - throw new InvalidParameterException("The IP " + ip.getAddress() + " is already used as " + ((Service)services.toArray()[0]).getName() + " rather than " - + service.getName()); + throw new InvalidParameterException( + "The IP " + ip.getAddress() + " is already used as " + ((Service)services.toArray()[0]).getName() + " rather than " + service.getName()); } return true; } @@ -531,8 +531,8 @@ public List getIsolatedNetworksWithSourceNATOwnedByAccountInZ @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "allocating Ip", create = true) - public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp) throws ResourceAllocationException, InsufficientAddressCapacityException, - ConcurrentOperationException { + public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolean displayIp) + throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); @@ -571,8 +571,8 @@ public IpAddress allocateIP(Account ipOwner, long zoneId, Long networkId, Boolea @Override @ActionEvent(eventType = EventTypes.EVENT_PORTABLE_IP_ASSIGN, eventDescription = "allocating portable public Ip", create = true) - public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) throws ResourceAllocationException, - InsufficientAddressCapacityException, ConcurrentOperationException { + public IpAddress allocatePortableIP(Account ipOwner, int regionId, Long zoneId, Long networkId, Long vpcId) + throws ResourceAllocationException, InsufficientAddressCapacityException, ConcurrentOperationException { Account caller = CallContext.current().getCallingAccount(); long callerUserId = CallContext.current().getCallingUserId(); DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); @@ -625,7 +625,7 @@ public boolean releasePortableIpAddress(long ipAddressId) { try { return releaseIpAddressInternal(ipAddressId); } catch (Exception e) { - return false; + return false; } } @@ -657,8 +657,7 @@ protected NetworkServiceImpl() { } @Override - @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_CONFIGURE, eventDescription = "Configuring secondary ip " + - "rules", async = true) + @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_CONFIGURE, eventDescription = "Configuring secondary ip " + "rules", async = true) public boolean configureNicSecondaryIp(NicSecondaryIp secIp, boolean isZoneSgEnabled) { boolean success = false; @@ -705,12 +704,11 @@ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requeste int maxAllowedIpsPerNic = NumbersUtil.parseInt(_configDao.getValue(Config.MaxNumberOfSecondaryIPsPerNIC.key()), 10); Long nicWiseIpCount = _nicSecondaryIpDao.countByNicId(nicId); - if(nicWiseIpCount.intValue() >= maxAllowedIpsPerNic) { - s_logger.error("Maximum Number of Ips \"vm.network.nic.max.secondary.ipaddresses = \"" + maxAllowedIpsPerNic + " per Nic has been crossed for the nic " + nicId + "."); + if (nicWiseIpCount.intValue() >= maxAllowedIpsPerNic) { + s_logger.error("Maximum Number of Ips \"vm.network.nic.max.secondary.ipaddresses = \"" + maxAllowedIpsPerNic + " per Nic has been crossed for the nic " + nicId + "."); throw new InsufficientAddressCapacityException("Maximum Number of Ips per Nic has been crossed.", Nic.class, nicId); } - s_logger.debug("Calling the ip allocation ..."); String ipaddr = null; //Isolated network can exist in Basic zone only, so no need to verify the zone type @@ -726,11 +724,11 @@ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requeste DataCenter dc = _dcDao.findById(network.getDataCenterId()); if (dc.getNetworkType() == NetworkType.Basic) { - VMInstanceVO vmi = (VMInstanceVO)vm; + VMInstanceVO vmi = (VMInstanceVO)vm; podId = vmi.getPodIdToDeployIn(); - if (podId == null) { + if (podId == null) { throw new InvalidParameterValueException("vm pod id is null in Basic zone; can't decide the range for ip allocation"); - } + } } try { @@ -753,23 +751,23 @@ public NicSecondaryIp allocateSecondaryGuestIP(final long nicId, String requeste long id = Transaction.execute(new TransactionCallback() { @Override public Long doInTransaction(TransactionStatus status) { - boolean nicSecondaryIpSet = nicVO.getSecondaryIp(); - if (!nicSecondaryIpSet) { - nicVO.setSecondaryIp(true); - // commit when previously set ?? - s_logger.debug("Setting nics table ..."); - _nicDao.update(nicId, nicVO); - } + boolean nicSecondaryIpSet = nicVO.getSecondaryIp(); + if (!nicSecondaryIpSet) { + nicVO.setSecondaryIp(true); + // commit when previously set ?? + s_logger.debug("Setting nics table ..."); + _nicDao.update(nicId, nicVO); + } - s_logger.debug("Setting nic_secondary_ip table ..."); + s_logger.debug("Setting nic_secondary_ip table ..."); Long vmId = nicVO.getInstanceId(); NicSecondaryIpVO secondaryIpVO = new NicSecondaryIpVO(nicId, addrFinal, vmId, ipOwner.getId(), ipOwner.getDomainId(), networkId); - _nicSecondaryIpDao.persist(secondaryIpVO); + _nicSecondaryIpDao.persist(secondaryIpVO); return secondaryIpVO.getId(); } }); - return getNicSecondaryIp(id); + return getNicSecondaryIp(id); } else { return null; } @@ -777,8 +775,7 @@ public Long doInTransaction(TransactionStatus status) { @Override @DB - @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_UNASSIGN, eventDescription = "Removing secondary ip " + - "from nic", async = true) + @ActionEvent(eventType = EventTypes.EVENT_NIC_SECONDARY_IP_UNASSIGN, eventDescription = "Removing secondary ip " + "from nic", async = true) public boolean releaseSecondaryIpFromNic(long ipAddressId) { Account caller = CallContext.current().getCallingAccount(); boolean success = false; @@ -824,7 +821,7 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { if (dc.getNetworkType() == NetworkType.Advanced && network.getGuestType() == Network.GuestType.Isolated) { //check PF or static NAT is configured on this ip address String secondaryIp = secIpVO.getIp4Address(); - List fwRulesList = _firewallDao.listByNetworkAndPurpose(network.getId(), Purpose.PortForwarding); + List fwRulesList = _firewallDao.listByNetworkAndPurpose(network.getId(), Purpose.PortForwarding); if (fwRulesList.size() != 0) { for (FirewallRuleVO rule : fwRulesList) { @@ -852,8 +849,8 @@ public boolean releaseSecondaryIpFromNic(long ipAddressId) { Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - _ipAddrMgr.markIpAsUnavailable(ip.getId()); - _ipAddressDao.unassignIpAddress(ip.getId()); + _ipAddrMgr.markIpAsUnavailable(ip.getId()); + _ipAddressDao.unassignIpAddress(ip.getId()); } }); } @@ -872,14 +869,14 @@ boolean removeNicSecondaryIP(final NicSecondaryIpVO ipVO, final boolean lastIp) Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - if (lastIp) { - nic.setSecondaryIp(false); - s_logger.debug("Setting nics secondary ip to false ..."); - _nicDao.update(nicId, nic); - } + if (lastIp) { + nic.setSecondaryIp(false); + s_logger.debug("Setting nics secondary ip to false ..."); + _nicDao.update(nicId, nic); + } - s_logger.debug("Revoving nic secondary ip entry ..."); - _nicSecondaryIpDao.remove(ipVO.getId()); + s_logger.debug("Revoving nic secondary ip entry ..."); + _nicSecondaryIpDao.remove(ipVO.getId()); } }); @@ -1130,8 +1127,8 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac if (domainId != null) { if (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Shared) { - throw new InvalidParameterValueException("Domain level networks are supported just for traffic type " + TrafficType.Guest + " and guest type " - + Network.GuestType.Shared); + throw new InvalidParameterValueException( + "Domain level networks are supported just for traffic type " + TrafficType.Guest + " and guest type " + Network.GuestType.Shared); } DomainVO domain = _domainDao.findById(domainId); @@ -1197,7 +1194,7 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } if (gateway != null && netmask != null) { - if(NetUtils.isNetworkorBroadcastIP(gateway,netmask)) { + if (NetUtils.isNetworkorBroadcastIP(gateway, netmask)) { if (s_logger.isDebugEnabled()) { s_logger.debug("The gateway IP provided is " + gateway + " and netmask is " + netmask + ". The IP is either broadcast or network IP."); } @@ -1236,9 +1233,8 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac } // Regular user can create Guest Isolated Source Nat enabled network only - if (_accountMgr.isNormalUser(caller.getId()) - && (ntwkOff.getTrafficType() != TrafficType.Guest || ntwkOff.getGuestType() != Network.GuestType.Isolated - && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) { + if (_accountMgr.isNormalUser(caller.getId()) && (ntwkOff.getTrafficType() != TrafficType.Guest + || ntwkOff.getGuestType() != Network.GuestType.Isolated && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) { throw new InvalidParameterValueException("Regular user can create a network only from the network" + " offering having traffic type " + TrafficType.Guest + " and network type " + Network.GuestType.Isolated + " with a service " + Service.SourceNat.getName() + " enabled"); } @@ -1285,10 +1281,8 @@ && areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat))) { // Vlan is created in 1 cases - works in Advance zone only: // 1) GuestType is Shared - boolean createVlan = (startIP != null && endIP != null && zone.getNetworkType() == NetworkType.Advanced - && ((ntwkOff.getGuestType() == Network.GuestType.Shared) - || (ntwkOff.getGuestType() == GuestType.Isolated && - !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)))); + boolean createVlan = (startIP != null && endIP != null && zone.getNetworkType() == NetworkType.Advanced && ((ntwkOff.getGuestType() == Network.GuestType.Shared) + || (ntwkOff.getGuestType() == GuestType.Isolated && !areServicesSupportedByNetworkOffering(ntwkOff.getId(), Service.SourceNat)))); if (!createVlan) { // Only support advance shared network in IPv6, which means createVlan is a must @@ -1519,7 +1513,7 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd if (domainId != null) { path = _domainDao.findById(domainId).getPath(); } else { - path = _domainDao.findById(caller.getDomainId()).getPath(); + path = _domainDao.findById(caller.getDomainId()).getPath(); } if (listAll && domainId == null) { @@ -1568,46 +1562,40 @@ public Pair, Integer> searchForNetworks(ListNetworksCmd sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId(), JoinBuilder.JoinType.INNER); } - SearchBuilder accountSearch = _accountDao.createSearchBuilder(); + SearchBuilder accountSearch = _accountDao.createSearchBuilder(); accountSearch.and("typeNEQ", accountSearch.entity().getType(), SearchCriteria.Op.NEQ); accountSearch.and("typeEQ", accountSearch.entity().getType(), SearchCriteria.Op.EQ); - sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER); + sb.join("accountSearch", accountSearch, sb.entity().getAccountId(), accountSearch.entity().getId(), JoinBuilder.JoinType.INNER); List networksToReturn = new ArrayList(); if (isSystem == null || !isSystem) { if (!permittedAccounts.isEmpty()) { //get account level networks - networksToReturn.addAll(listAccountSpecificNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts)); + networksToReturn.addAll(listAccountSpecificNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, + aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, permittedAccounts)); //get domain level networks if (domainId != null) { - networksToReturn.addAll(listDomainLevelNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false)); + networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, domainId, false)); } } else { //add account specific networks - networksToReturn.addAll(listAccountSpecificNetworksByDomainPath( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); + networksToReturn.addAll(listAccountSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); //add domain specific networks of domain + parent domains - networksToReturn.addAll(listDomainSpecificNetworksByDomainPath( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); + networksToReturn.addAll(listDomainSpecificNetworksByDomainPath(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, + physicalNetworkId, aclType, skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, path, isRecursive)); //add networks of subdomains if (domainId == null) { - networksToReturn.addAll(listDomainLevelNetworks( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, aclType, true, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true)); + networksToReturn.addAll(listDomainLevelNetworks(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, + aclType, true, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter, caller.getDomainId(), true)); } } } else { - networksToReturn = _networksDao.search( - buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, skipProjectNetworks, restartRequired, - specifyIpRanges, vpcId, tags, display), searchFilter); + networksToReturn = _networksDao.search(buildNetworkSearchCriteria(sb, keyword, id, isSystem, zoneId, guestIpType, trafficType, physicalNetworkId, null, + skipProjectNetworks, restartRequired, specifyIpRanges, vpcId, tags, display), searchFilter); } if (supportedServicesStr != null && !supportedServicesStr.isEmpty() && !networksToReturn.isEmpty()) { @@ -1719,7 +1707,7 @@ private SearchCriteria buildNetworkSearchCriteria(SearchBuilder entry: tags.entrySet()) { + for (Map.Entry entry : tags.entrySet()) { sc.setJoinParameters("tagSearch", "key" + String.valueOf(count), entry.getKey()); sc.setJoinParameters("tagSearch", "value" + String.valueOf(count), entry.getValue()); count++; @@ -1810,7 +1798,7 @@ private List listDomainSpecificNetworksByDomainPath(SearchCriteria(); } @@ -1878,8 +1866,8 @@ public boolean restartNetwork(RestartNetworkCmd cmd, boolean cleanup) throws Con // Don't allow to restart network if it's not in Implemented/Setup state if (!(network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup)) { - throw new InvalidParameterValueException("Network is not in the right state to be restarted. Correct states are: " + Network.State.Implemented + ", " - + Network.State.Setup); + throw new InvalidParameterValueException( + "Network is not in the right state to be restarted. Correct states are: " + Network.State.Implemented + ", " + Network.State.Setup); } if (network.getBroadcastDomainType() == BroadcastDomainType.Lswitch) { @@ -1939,8 +1927,8 @@ public Map getNetworkOfferingServiceCapabilities(NetworkOffe if (elementCapabilities == null || !elementCapabilities.containsKey(service)) { // TBD: We should be sending providerId and not the offering object itself. - throw new UnsupportedServiceException("Service " + service.getName() + " is not supported by the element=" + element.getName() + " implementing Provider=" - + provider); + throw new UnsupportedServiceException( + "Service " + service.getName() + " is not supported by the element=" + element.getName() + " implementing Provider=" + provider); } serviceCapabilities = elementCapabilities.get(service); } @@ -1965,10 +1953,9 @@ protected boolean providersConfiguredForExternalNetworking(Collection pr protected boolean isSharedNetworkOfferingWithServices(long networkOfferingId) { NetworkOfferingVO networkOffering = _networkOfferingDao.findById(networkOfferingId); - if ((networkOffering.getGuestType() == Network.GuestType.Shared) - && (areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) - || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) - || areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) { + if ((networkOffering.getGuestType() == Network.GuestType.Shared) && (areServicesSupportedByNetworkOffering(networkOfferingId, Service.SourceNat) + || areServicesSupportedByNetworkOffering(networkOfferingId, Service.StaticNat) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Firewall) + || areServicesSupportedByNetworkOffering(networkOfferingId, Service.PortForwarding) || areServicesSupportedByNetworkOffering(networkOfferingId, Service.Lb))) { return true; } return false; @@ -2071,8 +2058,8 @@ public Network updateGuestNetwork(final long networkId, String name, String disp // network offering should be in Enabled state if (networkOffering.getState() != NetworkOffering.State.Enabled) { - InvalidParameterValueException ex = new InvalidParameterValueException("Network offering with specified id is not in " + NetworkOffering.State.Enabled - + " state, can't upgrade to it"); + InvalidParameterValueException ex = new InvalidParameterValueException( + "Network offering with specified id is not in " + NetworkOffering.State.Enabled + " state, can't upgrade to it"); ex.addProxyObject(networkOffering.getUuid(), "networkOfferingId"); throw ex; } @@ -2100,8 +2087,8 @@ public Network updateGuestNetwork(final long networkId, String name, String disp } // check if the network is upgradable if (!canUpgrade(network, oldNetworkOfferingId, networkOfferingId)) { - throw new InvalidParameterValueException("Can't upgrade from network offering " + oldNtwkOff.getUuid() + " to " + networkOffering.getUuid() - + "; check logs for more information"); + throw new InvalidParameterValueException( + "Can't upgrade from network offering " + oldNtwkOff.getUuid() + " to " + networkOffering.getUuid() + "; check logs for more information"); } restartNetwork = true; networkOfferingChanged = true; @@ -2111,8 +2098,9 @@ public Network updateGuestNetwork(final long networkId, String name, String disp } } - final Map newSvcProviders = networkOfferingChanged ? _networkMgr.finalizeServicesAndProvidersForNetwork( - _entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()) : new HashMap(); + final Map newSvcProviders = networkOfferingChanged + ? _networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId()) + : new HashMap(); // don't allow to modify network domain if the service is not supported if (domainSuffix != null) { @@ -2147,7 +2135,7 @@ public Network updateGuestNetwork(final long networkId, String name, String disp if (guestVmCidr != null) { if (dc.getNetworkType() == NetworkType.Basic) { - throw new InvalidParameterValueException("Guest VM CIDR can't be specified for zone with " + NetworkType.Basic + " networking"); + throw new InvalidParameterValueException("Guest VM CIDR can't be specified for zone with " + NetworkType.Basic + " networking"); } if (network.getGuestType() != GuestType.Isolated) { throw new InvalidParameterValueException("Can only allow IP Reservation in networks with guest type " + GuestType.Isolated); @@ -2156,8 +2144,8 @@ public Network updateGuestNetwork(final long networkId, String name, String disp throw new InvalidParameterValueException("Cannot specify this nework offering change and guestVmCidr at same time. Specify only one."); } if (!(network.getState() == Network.State.Implemented)) { - throw new InvalidParameterValueException("The network must be in " + Network.State.Implemented + " state. IP Reservation cannot be applied in " - + network.getState() + " state"); + throw new InvalidParameterValueException( + "The network must be in " + Network.State.Implemented + " state. IP Reservation cannot be applied in " + network.getState() + " state"); } if (!NetUtils.isValidCIDR(guestVmCidr)) { throw new InvalidParameterValueException("Invalid format of Guest VM CIDR."); @@ -2170,76 +2158,77 @@ public Network updateGuestNetwork(final long networkId, String name, String disp // But in case networkCidr is a non null value (IP reservation already exists), it implies network cidr is networkCidr if (networkCidr != null) { if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, networkCidr)) { - throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " - + networkCidr); + throw new InvalidParameterValueException( + "Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + networkCidr); } } else { if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, network.getCidr())) { - throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " - + network.getCidr()); + throw new InvalidParameterValueException( + "Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + network.getCidr()); } } // This check makes sure there are no active IPs existing outside the guestVmCidr in the network - String[] guestVmCidrPair = guestVmCidr.split("\\/"); - Long size = Long.valueOf(guestVmCidrPair[1]); - List nicsPresent = _nicDao.listByNetworkId(networkId); + String[] guestVmCidrPair = guestVmCidr.split("\\/"); + Long size = Long.valueOf(guestVmCidrPair[1]); + List nicsPresent = _nicDao.listByNetworkId(networkId); - String cidrIpRange[] = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], size); + String cidrIpRange[] = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], size); s_logger.info("The start IP of the specified guest vm cidr is: " + cidrIpRange[0] + " and end IP is: " + cidrIpRange[1]); - long startIp = NetUtils.ip2Long(cidrIpRange[0]); - long endIp = NetUtils.ip2Long(cidrIpRange[1]); - long range = endIp - startIp + 1; - s_logger.info("The specified guest vm cidr has " + range + " IPs"); - - for (NicVO nic : nicsPresent) { - long nicIp = NetUtils.ip2Long(nic.getIPv4Address()); - //check if nic IP is outside the guest vm cidr - if (nicIp < startIp || nicIp > endIp) { + long startIp = NetUtils.ip2Long(cidrIpRange[0]); + long endIp = NetUtils.ip2Long(cidrIpRange[1]); + long range = endIp - startIp + 1; + s_logger.info("The specified guest vm cidr has " + range + " IPs"); + + for (NicVO nic : nicsPresent) { + long nicIp = NetUtils.ip2Long(nic.getIPv4Address()); + //check if nic IP is outside the guest vm cidr + if (nicIp < startIp || nicIp > endIp) { if (!(nic.getState() == Nic.State.Deallocating)) { - throw new InvalidParameterValueException("Active IPs like " + nic.getIPv4Address() + " exist outside the Guest VM CIDR. Cannot apply reservation "); - } - } + throw new InvalidParameterValueException("Active IPs like " + nic.getIPv4Address() + " exist outside the Guest VM CIDR. Cannot apply reservation "); } + } + } - // In some scenarios even though guesVmCidr and network CIDR do not appear similar but - // the IP ranges exactly matches, in these special cases make sure no Reservation gets applied - if (network.getNetworkCidr() == null) { - if (NetUtils.isSameIpRange(guestVmCidr, network.getCidr()) && !guestVmCidr.equals(network.getCidr())) { + // In some scenarios even though guesVmCidr and network CIDR do not appear similar but + // the IP ranges exactly matches, in these special cases make sure no Reservation gets applied + if (network.getNetworkCidr() == null) { + if (NetUtils.isSameIpRange(guestVmCidr, network.getCidr()) && !guestVmCidr.equals(network.getCidr())) { throw new InvalidParameterValueException("The Start IP and End IP of guestvmcidr: " + guestVmCidr + " and CIDR: " + network.getCidr() + " are same, " + "even though both the cidrs appear to be different. As a precaution no IP Reservation will be applied."); - } - } else { + } + } else { if (NetUtils.isSameIpRange(guestVmCidr, network.getNetworkCidr()) && !guestVmCidr.equals(network.getNetworkCidr())) { - throw new InvalidParameterValueException("The Start IP and End IP of guestvmcidr: " + guestVmCidr + " and Network CIDR: " + network.getNetworkCidr() - + " are same, " - + "even though both the cidrs appear to be different. As a precaution IP Reservation will not be affected. If you want to reset IP Reservation, " - + "specify guestVmCidr to be: " + network.getNetworkCidr()); - } + throw new InvalidParameterValueException( + "The Start IP and End IP of guestvmcidr: " + guestVmCidr + " and Network CIDR: " + network.getNetworkCidr() + " are same, " + + "even though both the cidrs appear to be different. As a precaution IP Reservation will not be affected. If you want to reset IP Reservation, " + + "specify guestVmCidr to be: " + network.getNetworkCidr()); } + } - // When reservation is applied for the first time, network_cidr will be null - // Populate it with the actual network cidr - if (network.getNetworkCidr() == null) { - network.setNetworkCidr(network.getCidr()); - } + // When reservation is applied for the first time, network_cidr will be null + // Populate it with the actual network cidr + if (network.getNetworkCidr() == null) { + network.setNetworkCidr(network.getCidr()); + } - // Condition for IP Reservation reset : guestVmCidr and network CIDR are same - if (network.getNetworkCidr().equals(guestVmCidr)) { - s_logger.warn("Guest VM CIDR and Network CIDR both are same, reservation will reset."); - network.setNetworkCidr(null); - } - // Finally update "cidr" with the guestVmCidr - // which becomes the effective address space for CloudStack guest VMs - network.setCidr(guestVmCidr); - _networksDao.update(networkId, network); - s_logger.info("IP Reservation has been applied. The new CIDR for Guests Vms is " + guestVmCidr); + // Condition for IP Reservation reset : guestVmCidr and network CIDR are same + if (network.getNetworkCidr().equals(guestVmCidr)) { + s_logger.warn("Guest VM CIDR and Network CIDR both are same, reservation will reset."); + network.setNetworkCidr(null); } + // Finally update "cidr" with the guestVmCidr + // which becomes the effective address space for CloudStack guest VMs + network.setCidr(guestVmCidr); + _networksDao.update(networkId, network); + s_logger.info("IP Reservation has been applied. The new CIDR for Guests Vms is " + guestVmCidr); + } ReservationContext context = new ReservationContextImpl(null, null, callerUser, callerAccount); // 1) Shutdown all the elements and cleanup all the rules. Don't allow to shutdown network in intermediate // states - Shutdown and Implementing - boolean validStateToShutdown = (network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup || network.getState() == Network.State.Allocated); + boolean validStateToShutdown = (network.getState() == Network.State.Implemented || network.getState() == Network.State.Setup + || network.getState() == Network.State.Allocated); if (restartNetwork) { if (validStateToShutdown) { if (!changeCidr) { @@ -2247,7 +2236,8 @@ public Network updateGuestNetwork(final long networkId, String name, String disp if (!_networkMgr.shutdownNetworkElementsAndResources(context, true, network)) { s_logger.warn("Failed to shutdown the network elements and resources as a part of network restart: " + network); - CloudRuntimeException ex = new CloudRuntimeException("Failed to shutdown the network elements and resources as a part of update to network of specified id"); + CloudRuntimeException ex = new CloudRuntimeException( + "Failed to shutdown the network elements and resources as a part of update to network of specified id"); ex.addProxyObject(network.getUuid(), "networkId"); throw ex; } @@ -2296,34 +2286,34 @@ public Network updateGuestNetwork(final long networkId, String name, String disp Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { - network.setNetworkOfferingId(networkOfferingId); - _networksDao.update(networkId, network, newSvcProviders); - // get all nics using this network - // log remove usage events for old offering - // log assign usage events for new offering - List nics = _nicDao.listByNetworkId(networkId); - for (NicVO nic : nics) { - long vmId = nic.getInstanceId(); - VMInstanceVO vm = _vmDao.findById(vmId); - if (vm == null) { - s_logger.error("Vm for nic " + nic.getId() + " not found with Vm Id:" + vmId); - continue; - } - long isDefault = (nic.isDefaultNic()) ? 1 : 0; - String nicIdString = Long.toString(nic.getId()); + network.setNetworkOfferingId(networkOfferingId); + _networksDao.update(networkId, network, newSvcProviders); + // get all nics using this network + // log remove usage events for old offering + // log assign usage events for new offering + List nics = _nicDao.listByNetworkId(networkId); + for (NicVO nic : nics) { + long vmId = nic.getInstanceId(); + VMInstanceVO vm = _vmDao.findById(vmId); + if (vm == null) { + s_logger.error("Vm for nic " + nic.getId() + " not found with Vm Id:" + vmId); + continue; + } + long isDefault = (nic.isDefaultNic()) ? 1 : 0; + String nicIdString = Long.toString(nic.getId()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_REMOVE, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, oldNetworkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); UsageEventUtils.publishUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, vm.getAccountId(), vm.getDataCenterId(), vm.getId(), nicIdString, networkOfferingId, null, isDefault, VirtualMachine.class.getName(), vm.getUuid(), vm.isDisplay()); - } + } } }); - } else { + } else { network.setNetworkOfferingId(networkOfferingId); _networksDao.update(networkId, network, _networkMgr.finalizeServicesAndProvidersForNetwork(_entityMgr.findById(NetworkOffering.class, networkOfferingId), network.getPhysicalNetworkId())); } - } else { + } else { _networksDao.update(networkId, network); } @@ -2398,7 +2388,8 @@ protected boolean canUpgrade(Network network, long oldNetworkOfferingId, long ne } // security group service should be the same - if (areServicesSupportedByNetworkOffering(oldNetworkOfferingId, Service.SecurityGroup) != areServicesSupportedByNetworkOffering(newNetworkOfferingId, Service.SecurityGroup)) { + if (areServicesSupportedByNetworkOffering(oldNetworkOfferingId, Service.SecurityGroup) != areServicesSupportedByNetworkOffering(newNetworkOfferingId, + Service.SecurityGroup)) { s_logger.debug("Offerings " + newNetworkOfferingId + " and " + oldNetworkOfferingId + " have different securityGroupProperty, can't upgrade"); return false; } @@ -2491,7 +2482,8 @@ public PhysicalNetwork createPhysicalNetwork(final Long zoneId, final String vne if (zoneType == NetworkType.Basic) { if (!_physicalNetworkDao.listByZone(zoneId).isEmpty()) { // TBD: Send uuid instead of zoneId; may have to hardcode tablename in call to addProxyObject(). - throw new CloudRuntimeException("Cannot add the physical network to basic zone id: " + zoneId + ", there is a physical network already existing in this basic Zone"); + throw new CloudRuntimeException( + "Cannot add the physical network to basic zone id: " + zoneId + ", there is a physical network already existing in this basic Zone"); } } if (tags != null && tags.size() > 1) { @@ -2505,8 +2497,8 @@ public PhysicalNetwork createPhysicalNetwork(final Long zoneId, final String vne if (vnetRange != null) { // Verify zone type if (zoneType == NetworkType.Basic || (zoneType == NetworkType.Advanced && zone.isSecurityGroupEnabled())) { - throw new InvalidParameterValueException("Can't add vnet range to the physical network in the zone that supports " + zoneType - + " network, Security Group enabled: " + zone.isSecurityGroupEnabled()); + throw new InvalidParameterValueException("Can't add vnet range to the physical network in the zone that supports " + zoneType + " network, Security Group enabled: " + + zone.isSecurityGroupEnabled()); } } @@ -2539,38 +2531,38 @@ public PhysicalNetwork createPhysicalNetwork(final Long zoneId, final String vne return Transaction.execute(new TransactionCallback() { @Override public PhysicalNetworkVO doInTransaction(TransactionStatus status) { - // Create the new physical network in the database - long id = _physicalNetworkDao.getNextInSequence(Long.class, "id"); + // Create the new physical network in the database + long id = _physicalNetworkDao.getNextInSequence(Long.class, "id"); PhysicalNetworkVO pNetwork = new PhysicalNetworkVO(id, zoneId, vnetRange, networkSpeed, domainId, broadcastDomainRangeFinal, name); - pNetwork.setTags(tags); - pNetwork.setIsolationMethods(isolationMethods); + pNetwork.setTags(tags); + pNetwork.setIsolationMethods(isolationMethods); - pNetwork = _physicalNetworkDao.persist(pNetwork); + pNetwork = _physicalNetworkDao.persist(pNetwork); - // Add vnet entries for the new zone if zone type is Advanced - if (vnetRange != null) { - addOrRemoveVnets(vnetRange.split(","), pNetwork); - } + // Add vnet entries for the new zone if zone type is Advanced + if (vnetRange != null) { + addOrRemoveVnets(vnetRange.split(","), pNetwork); + } - // add VirtualRouter as the default network service provider - addDefaultVirtualRouterToPhysicalNetwork(pNetwork.getId()); + // add VirtualRouter as the default network service provider + addDefaultVirtualRouterToPhysicalNetwork(pNetwork.getId()); if (pNetwork.getIsolationMethods().contains("GRE")) addDefaultOvsToPhysicalNetwork(pNetwork.getId()); - // add security group provider to the physical network - addDefaultSecurityGroupProviderToPhysicalNetwork(pNetwork.getId()); + // add security group provider to the physical network + addDefaultSecurityGroupProviderToPhysicalNetwork(pNetwork.getId()); - // add VPCVirtualRouter as the defualt network service provider - addDefaultVpcVirtualRouterToPhysicalNetwork(pNetwork.getId()); + // add VPCVirtualRouter as the defualt network service provider + addDefaultVpcVirtualRouterToPhysicalNetwork(pNetwork.getId()); - // add baremetal as the defualt network service provider - addDefaultBaremetalProvidersToPhysicalNetwork(pNetwork.getId()); + // add baremetal as the defualt network service provider + addDefaultBaremetalProvidersToPhysicalNetwork(pNetwork.getId()); - //Add Internal Load Balancer element as a default network service provider - addDefaultInternalLbProviderToPhysicalNetwork(pNetwork.getId()); + //Add Internal Load Balancer element as a default network service provider + addDefaultInternalLbProviderToPhysicalNetwork(pNetwork.getId()); - return pNetwork; + return pNetwork; } }); } catch (Exception ex) { @@ -2596,7 +2588,7 @@ public Pair, Integer> searchPhysicalNetworks(Lon sc.addAnd("name", SearchCriteria.Op.LIKE, "%" + name + "%"); } - Pair, Integer> result = _physicalNetworkDao.searchAndCount(sc, searchFilter); + Pair, Integer> result = _physicalNetworkDao.searchAndCount(sc, searchFilter); return new Pair, Integer>(result.first(), result.second()); } @@ -2663,7 +2655,7 @@ public PhysicalNetwork updatePhysicalNetwork(Long id, String networkSpeed, List< @DB public void addOrRemoveVnets(String[] listOfRanges, final PhysicalNetworkVO network) { - List addVnets = null; + List addVnets = null; List removeVnets = null; HashSet tempVnets = new HashSet(); HashSet vnetsInDb = new HashSet(); @@ -2713,16 +2705,16 @@ public void doInTransactionWithoutResult(TransactionStatus status) { if (addVnetsFinal != null) { s_logger.debug("Adding vnet range " + addVnetsFinal.toString() + " for the physicalNetwork id= " + network.getId() + " and zone id=" + network.getDataCenterId() + " as a part of updatePhysicalNetwork call"); - //add vnet takes a list of strings to be added. each string is a vnet. + //add vnet takes a list of strings to be added. each string is a vnet. _dcDao.addVnet(network.getDataCenterId(), network.getId(), addVnetsFinal); - } + } if (removeVnetsFinal != null) { s_logger.debug("removing vnet range " + removeVnetsFinal.toString() + " for the physicalNetwork id= " + network.getId() + " and zone id=" + network.getDataCenterId() + " as a part of updatePhysicalNetwork call"); - //deleteVnets takes a list of strings to be removed. each string is a vnet. + //deleteVnets takes a list of strings to be removed. each string is a vnet. _datacneterVnet.deleteVnets(TransactionLegacy.currentTxn(), network.getDataCenterId(), network.getId(), removeVnetsFinal); - } - _physicalNetworkDao.update(network.getId(), network); + } + _physicalNetworkDao.update(network.getId(), network); } }); @@ -2772,8 +2764,8 @@ private List> validateVlanRange(PhysicalNetworkVO network return vlanTokens; } if (VnetRange.length < 2) { - throw new InvalidParameterValueException("Please provide valid vnet range. vnet range should be a coma seperated list of vlan ranges. example 500-500,600-601" - + rangeMessage); + throw new InvalidParameterValueException( + "Please provide valid vnet range. vnet range should be a coma seperated list of vlan ranges. example 500-500,600-601" + rangeMessage); } if (VnetRange[0] == null || VnetRange[1] == null) { @@ -2785,8 +2777,8 @@ private List> validateVlanRange(PhysicalNetworkVO network EndVnet = Integer.parseInt(VnetRange[1]); } catch (NumberFormatException e) { s_logger.warn("Unable to parse vnet range:", e); - throw new InvalidParameterValueException("Please provide valid vnet range. The vnet range should be a coma seperated list example 2001-2012,3000-3005." - + rangeMessage); + throw new InvalidParameterValueException( + "Please provide valid vnet range. The vnet range should be a coma seperated list example 2001-2012,3000-3005." + rangeMessage); } if (StartVnet < minVnet || EndVnet > maxVnet) { throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); @@ -2801,7 +2793,7 @@ private List> validateVlanRange(PhysicalNetworkVO network } - public String generateVnetString(List vnetList) { + public String generateVnetString(List vnetList) { Collections.sort(vnetList, new Comparator() { @Override public int compare(String s1, String s2) { @@ -2877,7 +2869,7 @@ private List getVnetsToremove(PhysicalNetworkVO network, List() { @Override public Boolean doInTransaction(TransactionStatus status) { - // delete vlans for this zone - List vlans = _vlanDao.listVlansByPhysicalNetworkId(physicalNetworkId); - for (VlanVO vlan : vlans) { - _vlanDao.remove(vlan.getId()); - } + // delete vlans for this zone + List vlans = _vlanDao.listVlansByPhysicalNetworkId(physicalNetworkId); + for (VlanVO vlan : vlans) { + _vlanDao.remove(vlan.getId()); + } - // Delete networks - List networks = _networksDao.listByPhysicalNetwork(physicalNetworkId); - if (networks != null && !networks.isEmpty()) { - for (NetworkVO network : networks) { - _networksDao.remove(network.getId()); - } - } + // Delete networks + List networks = _networksDao.listByPhysicalNetwork(physicalNetworkId); + if (networks != null && !networks.isEmpty()) { + for (NetworkVO network : networks) { + _networksDao.remove(network.getId()); + } + } - // delete vnets - _dcDao.deleteVnet(physicalNetworkId); + // delete vnets + _dcDao.deleteVnet(physicalNetworkId); - // delete service providers - List providers = _pNSPDao.listBy(physicalNetworkId); + // delete service providers + List providers = _pNSPDao.listBy(physicalNetworkId); for (PhysicalNetworkServiceProviderVO provider : providers) { - try { - deleteNetworkServiceProvider(provider.getId()); + try { + deleteNetworkServiceProvider(provider.getId()); } catch (ResourceUnavailableException e) { s_logger.warn("Unable to complete destroy of the physical network provider: " + provider.getProviderName() + ", id: " + provider.getId(), e); - return false; - } catch (ConcurrentOperationException e) { + return false; + } catch (ConcurrentOperationException e) { s_logger.warn("Unable to complete destroy of the physical network provider: " + provider.getProviderName() + ", id: " + provider.getId(), e); - return false; - } - } + return false; + } + } - // delete traffic types - _pNTrafficTypeDao.deleteTrafficTypes(physicalNetworkId); + // delete traffic types + _pNTrafficTypeDao.deleteTrafficTypes(physicalNetworkId); return _physicalNetworkDao.remove(physicalNetworkId); } @@ -3075,9 +3067,9 @@ public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) { int existingStartVlan = existingRanges.get(i).first(); int existingEndVlan = existingRanges.get(i).second(); if (startVlan <= endVlan && startVlan >= existingStartVlan && endVlan <= existingEndVlan) { - exists = true; - break; - } + exists = true; + break; + } } if (!exists) { throw new InvalidParameterValueException("Unable to find guest vlan by range " + vlan); @@ -3089,7 +3081,7 @@ public GuestVlan dedicateGuestVlanRange(DedicateGuestVlanRangeCmd cmd) { List allocatedVlans = _datacneterVnet.listAllocatedVnetsInRange(physicalNetwork.getDataCenterId(), physicalNetwork.getId(), startVlan, endVlan); if (allocatedVlans != null && !allocatedVlans.isEmpty()) { for (DataCenterVnetVO allocatedVlan : allocatedVlans) { - if (allocatedVlan.getAccountId() != vlanOwner.getAccountId()) { + if (allocatedVlan.getAccountId() != vlanOwner.getAccountId()) { throw new InvalidParameterValueException("Guest vlan from this range " + allocatedVlan.getVnet() + " is allocated to a different account." + " Can only dedicate a range which has no allocated vlans or has vlans allocated to the same account "); } @@ -3154,7 +3146,7 @@ public int compare(AccountGuestVlanMapVO obj1, AccountGuestVlanMapVO obj2) { _accountGuestVlanMapDao.update(guestVlanMapId, accountGuestVlanMapVO); } else { accountGuestVlanMapVO = new AccountGuestVlanMapVO(vlanOwner.getAccountId(), physicalNetworkId); - accountGuestVlanMapVO.setGuestVlanRange(startVlan + "-" + endVlan); + accountGuestVlanMapVO.setGuestVlanRange(startVlan + "-" + endVlan); _accountGuestVlanMapDao.persist(accountGuestVlanMapVO); } // For every guest vlan set the corresponding account guest vlan map id @@ -3306,8 +3298,8 @@ public List listNetworkServices(String providerName) { @Override @DB @ActionEvent(eventType = EventTypes.EVENT_SERVICE_PROVIDER_CREATE, eventDescription = "Creating Physical Network ServiceProvider", create = true) - public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, List enabledServices) { - + public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physicalNetworkId, String providerName, Long destinationPhysicalNetworkId, + List enabledServices) { // verify input parameters PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); if (network == null) { @@ -3348,8 +3340,8 @@ public PhysicalNetworkServiceProvider addProviderToPhysicalNetwork(Long physical if (enabledServices != null) { if (!element.canEnableIndividualServices()) { if (enabledServices.size() != element.getCapabilities().keySet().size()) { - throw new InvalidParameterValueException("Cannot enable subset of Services, Please specify the complete list of Services for this Service Provider '" - + providerName + "'"); + throw new InvalidParameterValueException( + "Cannot enable subset of Services, Please specify the complete list of Services for this Service Provider '" + providerName + "'"); } } @@ -3417,7 +3409,7 @@ public Pair, Integer> listNetwork sc.addAnd("state", Op.EQ, state); } - Pair, Integer> result = _pNSPDao.searchAndCount(sc, searchFilter); + Pair, Integer> result = _pNSPDao.searchAndCount(sc, searchFilter); return new Pair, Integer>(result.first(), result.second()); } @@ -3448,8 +3440,8 @@ public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, Stri if (state != null) { if (s_logger.isDebugEnabled()) { - s_logger.debug("trying to update the state of the service provider id=" + id + " on physical network: " + provider.getPhysicalNetworkId() + " to state: " - + stateStr); + s_logger.debug( + "trying to update the state of the service provider id=" + id + " on physical network: " + provider.getPhysicalNetworkId() + " to state: " + stateStr); } switch (state) { case Enabled: @@ -3466,7 +3458,7 @@ public PhysicalNetworkServiceProvider updateNetworkServiceProvider(Long id, Stri update = true; break; case Shutdown: - throw new InvalidParameterValueException("Updating the provider state to 'Shutdown' is not supported"); + throw new InvalidParameterValueException("Updating the provider state to 'Shutdown' is not supported"); } } @@ -3591,8 +3583,8 @@ public long findPhysicalNetworkId(long zoneId, String tag, TrafficType trafficTy @Override @DB @ActionEvent(eventType = EventTypes.EVENT_TRAFFIC_TYPE_CREATE, eventDescription = "Creating Physical Network TrafficType", create = true) - public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalNetworkId, String trafficTypeStr, String isolationMethod, String xenLabel, String kvmLabel, String vmwareLabel, - String simulatorLabel, String vlan, String hypervLabel, String ovm3Label) { + public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalNetworkId, String trafficTypeStr, String isolationMethod, String xenLabel, String kvmLabel, + String vmwareLabel, String simulatorLabel, String vlan, String hypervLabel, String ovm3Label) { // verify input parameters PhysicalNetworkVO network = _physicalNetworkDao.findById(physicalNetworkId); @@ -3618,18 +3610,16 @@ public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalN if (TrafficType.isSystemNetwork(trafficType) || TrafficType.Public.equals(trafficType) || TrafficType.Storage.equals(trafficType)) { if (!_physicalNetworkDao.listByZoneAndTrafficType(network.getDataCenterId(), trafficType).isEmpty()) { - throw new CloudRuntimeException("Fail to add the traffic type to physical network because Zone already has a physical network with this traffic type: " - + trafficType); + throw new CloudRuntimeException( + "Fail to add the traffic type to physical network because Zone already has a physical network with this traffic type: " + trafficType); } } if (TrafficType.Storage.equals(trafficType)) { List ssvms = _stnwMgr.getSSVMWithNoStorageNetwork(network.getDataCenterId()); if (!ssvms.isEmpty()) { - StringBuilder sb = new StringBuilder( - "Cannot add " - + trafficType - + " traffic type as there are below secondary storage vm still running. Please stop them all and add Storage traffic type again, then destory them all to allow CloudStack recreate them with storage network(If you have added storage network ip range)"); + StringBuilder sb = new StringBuilder("Cannot add " + trafficType + + " traffic type as there are below secondary storage vm still running. Please stop them all and add Storage traffic type again, then destory them all to allow CloudStack recreate them with storage network(If you have added storage network ip range)"); sb.append("SSVMs:"); for (SecondaryStorageVmVO ssvm : ssvms) { sb.append(ssvm.getInstanceName()).append(":").append(ssvm.getState()); @@ -3649,19 +3639,19 @@ public PhysicalNetworkTrafficType addTrafficTypeToPhysicalNetwork(Long physicalN // For public traffic, get isolation method of physical network and update the public network accordingly // each broadcast type will individually need to be qualified for support of public traffic - if (TrafficType.Public.equals(trafficType)){ - List isolationMethods = network.getIsolationMethods(); - if ((isolationMethods.size() == 1 && isolationMethods.get(0).toLowerCase().equals("vxlan")) - || (isolationMethod != null && isolationMethods.contains(isolationMethod) && isolationMethod.toLowerCase().equals("vxlan"))) { - // find row in networks table that is defined as 'Public', created when zone was deployed - NetworkVO publicNetwork = _networksDao.listByZoneAndTrafficType(network.getDataCenterId(),TrafficType.Public).get(0); - if (publicNetwork != null) { - s_logger.debug("setting public network " + publicNetwork + " to broadcast type vxlan"); - publicNetwork.setBroadcastDomainType(BroadcastDomainType.Vxlan); - _networksDao.persist(publicNetwork); + if (TrafficType.Public.equals(trafficType)) { + List isolationMethods = network.getIsolationMethods(); + if ((isolationMethods.size() == 1 && isolationMethods.get(0).toLowerCase().equals("vxlan")) + || (isolationMethod != null && isolationMethods.contains(isolationMethod) && isolationMethod.toLowerCase().equals("vxlan"))) { + // find row in networks table that is defined as 'Public', created when zone was deployed + NetworkVO publicNetwork = _networksDao.listByZoneAndTrafficType(network.getDataCenterId(), TrafficType.Public).get(0); + if (publicNetwork != null) { + s_logger.debug("setting public network " + publicNetwork + " to broadcast type vxlan"); + publicNetwork.setBroadcastDomainType(BroadcastDomainType.Vxlan); + _networksDao.persist(publicNetwork); + } } } - } return pNetworktrafficType; } catch (Exception ex) { @@ -3765,8 +3755,8 @@ public boolean deletePhysicalNetworkTrafficType(Long id) { } else if (TrafficType.Storage.equals(trafficType.getTrafficType())) { PhysicalNetworkVO pn = _physicalNetworkDao.findById(trafficType.getPhysicalNetworkId()); if (_stnwMgr.isAnyStorageIpInUseInZone(pn.getDataCenterId())) { - throw new CloudRuntimeException("The Traffic Type is not deletable because there are still some storage network ip addresses in use:" - + trafficType.getTrafficType()); + throw new CloudRuntimeException( + "The Traffic Type is not deletable because there are still some storage network ip addresses in use:" + trafficType.getTrafficType()); } } return _pNTrafficTypeDao.remove(id); @@ -3794,8 +3784,8 @@ public NetworkVO getExclusiveGuestNetwork(long zoneId) { } if (networks.size() > 1) { - throw new InvalidParameterValueException("Found more than 1 network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared + " in zone " - + zoneId); + throw new InvalidParameterValueException( + "Found more than 1 network with trafficType " + TrafficType.Guest + " and guestType " + GuestType.Shared + " in zone " + zoneId); } @@ -3837,7 +3827,7 @@ protected PhysicalNetworkServiceProvider addDefaultVpcVirtualRouterToPhysicalNet PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.VPCVirtualRouter.getName(), null, null); - NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.VPCVirtualRouter.getName()); + NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.VPCVirtualRouter.getName()); if (networkElement == null) { throw new CloudRuntimeException("Unable to find the Network Element implementing the VPCVirtualRouter Provider"); } @@ -3852,7 +3842,7 @@ protected PhysicalNetworkServiceProvider addDefaultInternalLbProviderToPhysicalN PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId, Network.Provider.InternalLbVm.getName(), null, null); - NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.InternalLbVm.getName()); + NetworkElement networkElement = _networkModel.getElementImplementingProvider(Network.Provider.InternalLbVm.getName()); if (networkElement == null) { throw new CloudRuntimeException("Unable to find the Network Element implementing the " + Network.Provider.InternalLbVm.getName() + " Provider"); } @@ -3937,8 +3927,8 @@ public List> listTrafficTypeImplementor(ListTrafficTyp @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true) - public IpAddress associateIPToNetwork(long ipId, long networkId) throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException, - ConcurrentOperationException { + public IpAddress associateIPToNetwork(long ipId, long networkId) + throws InsufficientAddressCapacityException, ResourceAllocationException, ResourceUnavailableException, ConcurrentOperationException { Network network = _networksDao.findById(networkId); if (network == null) { @@ -3962,7 +3952,7 @@ public IpAddress associateIPToNetwork(long ipId, long networkId) throws Insuffic @DB public Network createPrivateNetwork(final String networkName, final String displayText, long physicalNetworkId, String broadcastUriString, final String startIp, String endIp, final String gateway, String netmask, final long networkOwnerId, final Long vpcId, final Boolean sourceNat, final Long networkOfferingId) - throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { + throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { final Account owner = _accountMgr.getAccount(networkOwnerId); @@ -4079,7 +4069,7 @@ private NetworkOfferingVO findSystemNetworkOffering(String offeringName) { @Override public Network getNetwork(String networkUuid) { - return _networksDao.findByUuid(networkUuid); + return _networksDao.findByUuid(networkUuid); } @Override @@ -4088,13 +4078,13 @@ public List listNics(ListNicsCmd cmd) { Long nicId = cmd.getNicId(); long vmId = cmd.getVmId(); Long networkId = cmd.getNetworkId(); - UserVmVO userVm = _userVmDao.findById(vmId); + UserVmVO userVm = _userVmDao.findById(vmId); if (userVm == null || (!userVm.isDisplayVm() && caller.getType() == Account.ACCOUNT_TYPE_NORMAL)) { - InvalidParameterValueException ex = new InvalidParameterValueException("Virtual mahine id does not exist"); + InvalidParameterValueException ex = new InvalidParameterValueException("Virtual mahine id does not exist"); ex.addProxyObject(Long.valueOf(vmId).toString(), "vmId"); - throw ex; - } + throw ex; + } _accountMgr.checkAccess(caller, null, true, userVm); return _networkMgr.listVmNics(vmId, nicId, networkId); diff --git a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java index 6ef2ed36faff..767b012c911e 100644 --- a/server/src/com/cloud/network/element/VpcVirtualRouterElement.java +++ b/server/src/com/cloud/network/element/VpcVirtualRouterElement.java @@ -114,7 +114,8 @@ public class VpcVirtualRouterElement extends VirtualRouterElement implements Vpc @Qualifier("vpcNetworkHelper") private VpcNetworkHelperImpl _vpcNetWprkHelper; - @Inject RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder; + @Inject + RouterDeploymentDefinitionBuilder routerDeploymentDefinitionBuilder; @Override protected boolean canHandle(final Network network, final Service service) { @@ -147,8 +148,8 @@ protected boolean canHandle(final Network network, final Service service) { } @Override - public boolean implementVpc(final Vpc vpc, final DeployDestination dest, final ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { + public boolean implementVpc(final Vpc vpc, final DeployDestination dest, final ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { final Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); @@ -194,13 +195,8 @@ public boolean implement(final Network network, final NetworkOffering offering, final Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); - final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create() - .setGuestNetwork(network) - .setVpc(vpc) - .setDeployDestination(dest) - .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())) - .setParams(params) - .build(); + final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create().setGuestNetwork(network).setVpc(vpc).setDeployDestination(dest) + .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())).setParams(params).build(); final List routers = routerDeploymentDefinition.deployVirtualRouter(); @@ -213,7 +209,7 @@ public boolean implement(final Network network, final NetworkOffering offering, return true; } - protected void configureGuestNetwork(final Network network, final List routers ) + protected void configureGuestNetwork(final Network network, final List routers) throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException { s_logger.info("Adding VPC routers to Guest Network: " + routers.size() + " to be added!"); @@ -253,13 +249,8 @@ public boolean prepare(final Network network, final NicProfile nic, final Virtua final Map params = new HashMap(1); params.put(VirtualMachineProfile.Param.ReProgramGuestNetworks, true); - final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create() - .setGuestNetwork(network) - .setVpc(vpc) - .setDeployDestination(dest) - .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())) - .setParams(params) - .build(); + final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create().setGuestNetwork(network).setVpc(vpc).setDeployDestination(dest) + .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())).setParams(params).build(); final List routers = routerDeploymentDefinition.deployVirtualRouter(); @@ -356,12 +347,8 @@ protected List getRouters(final Network network, final DeployDes return routers; } - final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create() - .setGuestNetwork(network) - .setVpc(vpc) - .setDeployDestination(dest) - .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())) - .build(); + final RouterDeploymentDefinition routerDeploymentDefinition = routerDeploymentDefinitionBuilder.create().setGuestNetwork(network).setVpc(vpc).setDeployDestination(dest) + .setAccountOwner(_accountMgr.getAccount(vpc.getAccountId())).build(); try { routers = routerDeploymentDefinition.deployVirtualRouter(); @@ -399,6 +386,11 @@ private static Map> setCapabilities() { networkACLCapabilities.put(Capability.SupportedProtocols, "tcp,udp,icmp"); capabilities.put(Service.NetworkACL, networkACLCapabilities); + // add dynamic routing capability + final Map dynamicRoutingCapabilities = new HashMap(); + dynamicRoutingCapabilities.put(Capability.SupportedProtocols, "ospf,bgp"); + capabilities.put(Service.VPCDynamicRouting, dynamicRoutingCapabilities); + return capabilities; } @@ -482,8 +474,8 @@ public boolean applyIps(final Network network, final List routers = _routerDao.listByNetworkAndRole(network.getId(), Role.VIRTUAL_ROUTER); if (routers == null || routers.isEmpty()) { - s_logger.debug(getName() + " element doesn't need to associate ip addresses on the backend; VPC virtual " + "router doesn't exist in the network " - + network.getId()); + s_logger.debug( + getName() + " element doesn't need to associate ip addresses on the backend; VPC virtual " + "router doesn't exist in the network " + network.getId()); return false; } @@ -653,7 +645,7 @@ public String[] applyVpnUsers(final RemoteAccessVpn vpn, final List users, final VirtualRouter router, final Commands cmds) { @@ -277,8 +280,8 @@ public void configDnsMasq(final VirtualRouter router, final Network network, fin for (final NicIpAliasVO ipAliasVO : ipAliasVOList) { final DhcpTO DhcpTO = new DhcpTO(ipAliasVO.getIp4Address(), ipAliasVO.getGateway(), ipAliasVO.getNetmask(), ipAliasVO.getStartIpOfSubnet()); if (s_logger.isTraceEnabled()) { - s_logger.trace("configDnsMasq : adding ip {" + DhcpTO.getGateway() + ", " + DhcpTO.getNetmask() + ", " + DhcpTO.getRouterIp() + ", " + DhcpTO.getStartIpOfSubnet() - + "}"); + s_logger.trace( + "configDnsMasq : adding ip {" + DhcpTO.getGateway() + ", " + DhcpTO.getNetmask() + ", " + DhcpTO.getRouterIp() + ", " + DhcpTO.getStartIpOfSubnet() + "}"); } ipList.add(DhcpTO); ipAliasVO.setVmId(router.getId()); @@ -324,8 +327,9 @@ public void createApplyLoadBalancingRulesCommands(final List final Network guestNetwork = _networkModel.getNetwork(guestNetworkId); final Nic nic = _nicDao.findByNtwkIdAndInstanceId(guestNetwork.getId(), router.getId()); - final NicProfile nicProfile = new NicProfile(nic, guestNetwork, nic.getBroadcastUri(), nic.getIsolationUri(), _networkModel.getNetworkRate(guestNetwork.getId(), - router.getId()), _networkModel.isSecurityGroupSupportedInNetwork(guestNetwork), _networkModel.getNetworkTag(router.getHypervisorType(), guestNetwork)); + final NicProfile nicProfile = new NicProfile(nic, guestNetwork, nic.getBroadcastUri(), nic.getIsolationUri(), + _networkModel.getNetworkRate(guestNetwork.getId(), router.getId()), _networkModel.isSecurityGroupSupportedInNetwork(guestNetwork), + _networkModel.getNetworkTag(router.getHypervisorType(), guestNetwork)); final NetworkOffering offering = _networkOfferingDao.findById(guestNetwork.getNetworkOfferingId()); String maxconn = null; if (offering.getConcurrentConnections() == null) { @@ -407,7 +411,7 @@ public void createApplyFirewallRulesCommands(final List } } for (final FirewallRule rule : rules) { - _rulesDao.loadSourceCidrs((FirewallRuleVO) rule); + _rulesDao.loadSourceCidrs((FirewallRuleVO)rule); final FirewallRule.TrafficType traffictype = rule.getTrafficType(); if (traffictype == FirewallRule.TrafficType.Ingress) { final IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); @@ -450,7 +454,7 @@ public void createFirewallRulesCommands(final List rules } } for (final FirewallRule rule : rules) { - _rulesDao.loadSourceCidrs((FirewallRuleVO) rule); + _rulesDao.loadSourceCidrs((FirewallRuleVO)rule); final FirewallRule.TrafficType traffictype = rule.getTrafficType(); if (traffictype == FirewallRule.TrafficType.Ingress) { final IpAddress sourceIp = _networkModel.getIp(rule.getSourceIpAddressId()); @@ -519,7 +523,7 @@ public void createNetworkACLsCommands(final List rules } public void createPasswordCommand(final VirtualRouter router, final VirtualMachineProfile profile, final NicVO nic, final Commands cmds) { - final String password = (String) profile.getParameter(VirtualMachineProfile.Param.VmPassword); + final String password = (String)profile.getParameter(VirtualMachineProfile.Param.VmPassword); final DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); // password should be set only on default network element @@ -691,8 +695,8 @@ public void createVpcAssociatePublicIPCommands(final VirtualRouter router, final final String macAddress = vlanMacAddress.get(BroadcastDomainType.getValue(BroadcastDomainType.fromString(ipAddr.getVlanTag()))); - final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, false, ipAddr.isSourceNat(), BroadcastDomainType.fromString(ipAddr.getVlanTag()).toString(), ipAddr.getGateway(), - ipAddr.getNetmask(), macAddress, networkRate, ipAddr.isOneToOneNat()); + final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, false, ipAddr.isSourceNat(), + BroadcastDomainType.fromString(ipAddr.getVlanTag()).toString(), ipAddr.getGateway(), ipAddr.getNetmask(), macAddress, networkRate, ipAddr.isOneToOneNat()); ip.setTrafficType(network.getTrafficType()); ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network)); @@ -724,7 +728,8 @@ public void createVpcAssociatePublicIPCommands(final VirtualRouter router, final } } - public void createRedundantAssociateIPCommands(final VirtualRouter router, final List ips, final Commands cmds, final String ipAssocCommand, final long vmId) { + public void createRedundantAssociateIPCommands(final VirtualRouter router, final List ips, final Commands cmds, final String ipAssocCommand, + final long vmId) { // Ensure that in multiple vlans case we first send all ip addresses of // vlan1, then all ip addresses of vlan2, etc.. @@ -801,8 +806,8 @@ public int compare(final PublicIpAddress o1, final PublicIpAddress o2) { } } - final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, - vifMacAddress, networkRate, ipAddr.isOneToOneNat()); + final IpAddressTO ip = new IpAddressTO(ipAddr.getAccountId(), ipAddr.getAddress().addr(), add, firstIP, sourceNat, vlanId, vlanGateway, vlanNetmask, vifMacAddress, + networkRate, ipAddr.isOneToOneNat()); ip.setTrafficType(network.getTrafficType()); ip.setNetworkName(_networkModel.getNetworkTag(router.getHypervisorType(), network)); @@ -862,7 +867,6 @@ public void createSite2SiteVpnCfgCommands(final Site2SiteVpnConnection conn, fin final Site2SiteVpnCfgCommand cmd = new Site2SiteVpnCfgCommand(isCreate, localPublicIp, localPublicGateway, localGuestCidr, peerGatewayIp, peerGuestCidrList, ikePolicy, espPolicy, ipsecPsk, ikeLifetime, espLifetime, dpd, conn.isPassive(), encap); cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); - cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); final DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); @@ -933,8 +937,8 @@ public SetupGuestNetworkCommand createSetupGuestNetworkCommand(final DomainRoute final NicProfile nicProfile = _networkModel.getNicProfile(router, nic.getNetworkId(), null); - final SetupGuestNetworkCommand setupCmd = new SetupGuestNetworkCommand(dhcpRange, networkDomain, router.getIsRedundantRouter(), defaultDns1, defaultDns2, add, _itMgr.toNicTO(nicProfile, - router.getHypervisorType())); + final SetupGuestNetworkCommand setupCmd = new SetupGuestNetworkCommand(dhcpRange, networkDomain, router.getIsRedundantRouter(), defaultDns1, defaultDns2, add, + _itMgr.toNicTO(nicProfile, router.getHypervisorType())); final String brd = NetUtils.long2Ip(NetUtils.ip2Long(guestNic.getIPv4Address()) | ~NetUtils.ip2Long(guestNic.getIPv4Netmask())); setupCmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); @@ -1048,4 +1052,33 @@ protected String getGuestDhcpRange(final NicProfile guestNic, final Network gues } return dhcpRange; } + + // this command goes as part of the VPC start command + public void createQuaggaConfigCommand(final VirtualRouter router, final Long vpcId, final Commands cmds) throws BadCIDRException { + final Vpc vpc = _vpcDao.findById(vpcId); + final DataCenterVO dc = _dcDao.findById(vpc.getZoneId()); + _dcDao.loadDetails(dc); + final OSPFZoneConfig qzc = new OSPFZoneConfig(); + qzc.setValues(dc.getDetails()); + // vpc is dynamic if control comes here + ArrayList tier_cidr = new ArrayList(); + // get all dynamic tiers cidr for this vpc + final List vpc_tiers = _networkDao.listByVpc(vpcId); + for (NetworkVO tier : vpc_tiers) { + // network tier supports dynamic routing + if (_networkModel.areServicesSupportedByNetworkOffering(tier.getNetworkOfferingId(), Service.VPCDynamicRouting)) { + tier_cidr.add(CIDRFactory.getCIDR(tier.getCidr())); + } + } + final String publicIp = router.getPublicIpAddress(); + //String routerIp, String routerName, String vpnCidr, String[] tierCidrs + final QuaggaConfigCommand cmd = new QuaggaConfigCommand(publicIp, router.getInstanceName(), vpc.getCidr(), tier_cidr.toArray(new CIDR[tier_cidr.size()]), qzc); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_IP, _routerControlHelper.getRouterControlIp(router.getId())); + cmd.setAccessDetail(NetworkElementCommand.ROUTER_NAME, router.getInstanceName()); + final DataCenterVO dcVo = _dcDao.findById(router.getDataCenterId()); + cmd.setAccessDetail(NetworkElementCommand.ZONE_NETWORK_TYPE, dcVo.getNetworkType().toString()); + + cmds.addCommand(cmd); + } + } diff --git a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java index ac8b86816a25..7fbb9e3f2e75 100644 --- a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java @@ -181,6 +181,7 @@ import com.cloud.network.rules.dao.PortForwardingRulesDao; import com.cloud.network.vpc.Vpc; import com.cloud.network.vpc.dao.VpcDao; +import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao; import com.cloud.network.vpn.Site2SiteVpnManager; import com.cloud.offering.NetworkOffering; import com.cloud.offering.ServiceOffering; @@ -300,6 +301,8 @@ public class VirtualNetworkApplianceManagerImpl extends ManagerBase implements V @Inject NetworkOfferingDao _networkOfferingDao = null; @Inject + VpcOfferingServiceMapDao _vpcOffServiceDao; + @Inject GuestOSDao _guestOSDao = null; @Inject NetworkOrchestrationService _networkMgr; diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 712c74723934..b9719cd615c6 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -80,6 +80,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.fsm.StateMachine2; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.cidr.BadCIDRException; import com.cloud.vm.DomainRouterVO; import com.cloud.vm.Nic; import com.cloud.vm.NicProfile; @@ -144,7 +145,7 @@ public boolean addVpcRouterToGuestNetwork(final VirtualRouter router, final Netw result = false; } // 3) apply networking rules - if (result && params.get(Param.ReProgramGuestNetworks) != null && (Boolean) params.get(Param.ReProgramGuestNetworks) == true) { + if (result && params.get(Param.ReProgramGuestNetworks) != null && (Boolean)params.get(Param.ReProgramGuestNetworks) == true) { sendNetworkRulesToRouter(router.getId(), network.getId()); } } catch (final Exception ex) { @@ -167,8 +168,8 @@ public boolean addVpcRouterToGuestNetwork(final VirtualRouter router, final Netw } @Override - public boolean removeVpcRouterFromGuestNetwork(final VirtualRouter router, final Network network) throws ConcurrentOperationException, - ResourceUnavailableException { + public boolean removeVpcRouterFromGuestNetwork(final VirtualRouter router, final Network network) + throws ConcurrentOperationException, ResourceUnavailableException { if (network.getTrafficType() != TrafficType.Guest) { s_logger.warn("Network " + network + " is not of type " + TrafficType.Guest); return false; @@ -198,14 +199,26 @@ public boolean removeVpcRouterFromGuestNetwork(final VirtualRouter router, final return result; } - protected boolean setupVpcGuestNetwork(final Network network, final VirtualRouter router, final boolean add, final NicProfile guestNic) throws ConcurrentOperationException, - ResourceUnavailableException { + protected boolean setupVpcGuestNetwork(final Network network, final VirtualRouter router, final boolean add, final NicProfile guestNic) + throws ConcurrentOperationException, ResourceUnavailableException { boolean result = true; if (router.getState() == State.Running) { - final SetupGuestNetworkCommand setupCmd = _commandSetupHelper.createSetupGuestNetworkCommand((DomainRouterVO) router, add, guestNic); - + final SetupGuestNetworkCommand setupCmd = _commandSetupHelper.createSetupGuestNetworkCommand((DomainRouterVO)router, add, guestNic); final Commands cmds = new Commands(Command.OnError.Stop); + final VpcVO vpc = _vpcDao.findById(router.getVpcId()); + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpc.getVpcOfferingId(), Service.VPCDynamicRouting) + && _networkModel.areServicesSupportedByNetworkOffering(network.getNetworkOfferingId(), Service.VPCDynamicRouting)) { + try { + _commandSetupHelper.createQuaggaConfigCommand(router, vpc.getId(), cmds); + } + catch (BadCIDRException ex){ + s_logger.warn("Unable to configure the VPC network for dynamic routing " + ex); + throw new ResourceUnavailableException("Unable to configure the VPC network for dynamic routing ," + " virtual router " + router + " is not in the right state", DataCenter.class, + router.getDataCenterId()); + } + } + cmds.addCommand("setupguestnetwork", setupCmd); _nwHelper.sendCommandsToRouter(router, cmds); @@ -289,7 +302,7 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine final List> guestNics = new ArrayList>(); final List> publicNics = new ArrayList>(); final Map vlanMacAddress = new HashMap(); - + long publicNtwkId = 0L; final List routerNics = _nicDao.listByVmId(profile.getId()); for (final Nic routerNic : routerNics) { final Network network = _networkModel.getNetwork(routerNic.getNetworkId()); @@ -297,6 +310,7 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine final Pair guestNic = new Pair(routerNic, network); guestNics.add(guestNic); } else if (network.getTrafficType() == TrafficType.Public) { + publicNtwkId = network.getId(); final Pair publicNic = new Pair(routerNic, network); publicNics.add(publicNic); final String vlanTag = BroadcastDomainType.getValue(routerNic.getBroadcastUri()); @@ -331,13 +345,14 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine domainRouterVO.getInstanceName(), domainRouterVO.getType()); cmds.addCommand(plugNicCmd); final VpcVO vpc = _vpcDao.findById(domainRouterVO.getVpcId()); - final NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(domainRouterVO.getPrivateIpAddress(), domainRouterVO.getInstanceName(), true, publicNic.getIPv4Address(), vpc.getCidr()); + final NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(domainRouterVO.getPrivateIpAddress(), domainRouterVO.getInstanceName(), true, + publicNic.getIPv4Address(), vpc.getCidr()); usageCmds.add(netUsageCmd); - UserStatisticsVO stats = _userStatsDao.findBy(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNtwk.getId(), publicNic.getIPv4Address(), domainRouterVO.getId(), - domainRouterVO.getType().toString()); + UserStatisticsVO stats = _userStatsDao.findBy(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNtwk.getId(), publicNic.getIPv4Address(), + domainRouterVO.getId(), domainRouterVO.getType().toString()); if (stats == null) { - stats = new UserStatisticsVO(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNic.getIPv4Address(), domainRouterVO.getId(), domainRouterVO.getType().toString(), - publicNtwk.getId()); + stats = new UserStatisticsVO(domainRouterVO.getAccountId(), domainRouterVO.getDataCenterId(), publicNic.getIPv4Address(), domainRouterVO.getId(), + domainRouterVO.getType().toString(), publicNtwk.getId()); _userStatsDao.persist(stats); } } @@ -351,7 +366,8 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine for (final Pair nicNtwk : guestNics) { final Nic guestNic = nicNtwk.first(); // plug guest nic - final PlugNicCommand plugNicCmd = new PlugNicCommand(_nwHelper.getNicTO(domainRouterVO, guestNic.getNetworkId(), null), domainRouterVO.getInstanceName(), domainRouterVO.getType()); + final PlugNicCommand plugNicCmd = new PlugNicCommand(_nwHelper.getNicTO(domainRouterVO, guestNic.getNetworkId(), null), domainRouterVO.getInstanceName(), + domainRouterVO.getType()); cmds.addCommand(plugNicCmd); if (!_networkModel.isPrivateGateway(guestNic.getNetworkId())) { // set guest network @@ -415,7 +431,7 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine // 6) REPROGRAM GUEST NETWORK boolean reprogramGuestNtwks = true; - if (profile.getParameter(Param.ReProgramGuestNetworks) != null && (Boolean) profile.getParameter(Param.ReProgramGuestNetworks) == false) { + if (profile.getParameter(Param.ReProgramGuestNetworks) != null && (Boolean)profile.getParameter(Param.ReProgramGuestNetworks) == false) { reprogramGuestNtwks = false; } @@ -430,8 +446,8 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine for (final Pair nicNtwk : guestNics) { final Nic guestNic = nicNtwk.first(); - final AggregationControlCommand startCmd = new AggregationControlCommand(Action.Start, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( - guestNic.getNetworkId(), domainRouterVO.getId())); + final AggregationControlCommand startCmd = new AggregationControlCommand(Action.Start, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), + _routerControlHelper.getRouterIpInNetwork(guestNic.getNetworkId(), domainRouterVO.getId())); cmds.addCommand(startCmd); if (reprogramGuestNtwks) { finalizeIpAssocForNetwork(cmds, domainRouterVO, provider, guestNic.getNetworkId(), vlanMacAddress); @@ -439,8 +455,8 @@ public boolean finalizeCommandsOnStart(final Commands cmds, final VirtualMachine } finalizeUserDataAndDhcpOnStart(cmds, domainRouterVO, provider, guestNic.getNetworkId()); - final AggregationControlCommand finishCmd = new AggregationControlCommand(Action.Finish, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), _routerControlHelper.getRouterIpInNetwork( - guestNic.getNetworkId(), domainRouterVO.getId())); + final AggregationControlCommand finishCmd = new AggregationControlCommand(Action.Finish, domainRouterVO.getInstanceName(), controlNic.getIPv4Address(), + _routerControlHelper.getRouterIpInNetwork(guestNic.getNetworkId(), domainRouterVO.getId())); cmds.addCommand(finishCmd); } @@ -455,16 +471,26 @@ protected void finalizeNetworkRulesForNetwork(final Commands cmds, final DomainR super.finalizeNetworkRulesForNetwork(cmds, domainRouterVO, provider, guestNetworkId); + final VpcVO vpc = _vpcDao.findById(domainRouterVO.getVpcId()); if (domainRouterVO.getVpcId() != null) { - if (domainRouterVO.getState() == State.Starting || domainRouterVO.getState() == State.Running) { if (_networkModel.isProviderSupportServiceInNetwork(guestNetworkId, Service.NetworkACL, Provider.VPCVirtualRouter)) { final List networkACLs = _networkACLMgr.listNetworkACLItems(guestNetworkId); if (networkACLs != null && !networkACLs.isEmpty()) { - s_logger.debug("Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + domainRouterVO + " start for guest network id=" + guestNetworkId); + s_logger.debug( + "Found " + networkACLs.size() + " network ACLs to apply as a part of VPC VR " + domainRouterVO + " start for guest network id=" + guestNetworkId); _commandSetupHelper.createNetworkACLsCommands(networkACLs, domainRouterVO, cmds, guestNetworkId, false); } } + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpc.getVpcOfferingId(), Service.VPCDynamicRouting) + && _networkModel.areServicesSupportedInNetwork(guestNetworkId, Service.VPCDynamicRouting)) { + try { + _commandSetupHelper.createQuaggaConfigCommand(domainRouterVO, vpc.getId(), cmds); + } catch (BadCIDRException ex) { + s_logger.debug(ex); + throw new CloudRuntimeException("The cidr for dynamic routing is bad " + ex); + } + } } } } @@ -523,8 +549,8 @@ protected boolean setupVpcPrivateNetwork(final VirtualRouter router, final boole } else { s_logger.warn("Unable to setup private gateway, virtual router " + router + " is not in the right state " + router.getState()); - throw new ResourceUnavailableException("Unable to setup Private gateway on the backend," + " virtual router " + router + " is not in the right state", - DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to setup Private gateway on the backend," + " virtual router " + router + " is not in the right state", DataCenter.class, + router.getDataCenterId()); } return true; } @@ -606,7 +632,8 @@ protected boolean applySite2SiteVpn(final boolean isCreate, final VirtualRouter return _nwHelper.sendCommandsToRouter(router, cmds); } - protected Pair, Map> getNicsToChangeOnRouter(final List publicIps, final VirtualRouter router) { + protected Pair, Map> getNicsToChangeOnRouter(final List publicIps, + final VirtualRouter router) { // 1) check which nics need to be plugged/unplugged and plug/unplug them final Map nicsToPlug = new HashMap(); @@ -738,7 +765,8 @@ public boolean stopRemoteAccessVpn(final RemoteAccessVpn vpn, final VirtualRoute } @Override - public boolean postStateTransitionEvent(final StateMachine2.Transition transition, final VirtualMachine vo, final boolean status, final Object opaque) { + public boolean postStateTransitionEvent(final StateMachine2.Transition transition, final VirtualMachine vo, final boolean status, + final Object opaque) { // Without this VirtualNetworkApplianceManagerImpl.postStateTransitionEvent() gets called twice as part of listeners - // once from VpcVirtualNetworkApplianceManagerImpl and once from VirtualNetworkApplianceManagerImpl itself return true; diff --git a/server/src/com/cloud/network/rules/QuaggaRules.java b/server/src/com/cloud/network/rules/QuaggaRules.java new file mode 100644 index 000000000000..78336f276335 --- /dev/null +++ b/server/src/com/cloud/network/rules/QuaggaRules.java @@ -0,0 +1,49 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package com.cloud.network.rules; + +import org.apache.cloudstack.network.topology.NetworkTopologyVisitor; + +import com.cloud.exception.ResourceUnavailableException; +import com.cloud.network.Network; +import com.cloud.network.router.VirtualRouter; + +public class QuaggaRules extends RuleApplier { + private Long vpcId; + + public Long getVpcId() { + return vpcId; + } + + public void setVpcId(Long vpcId) { + this.vpcId = vpcId; + } + + public QuaggaRules(Network network, Long vpcId) { + super(network); + this.vpcId = vpcId; + } + + @Override + public boolean accept(NetworkTopologyVisitor visitor, VirtualRouter router) throws ResourceUnavailableException { + _router = router; + + return visitor.visit(this); + } + +} diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java b/server/src/com/cloud/network/vpc/VpcManagerImpl.java index 18fbfe20226d..6ddcc4aba196 100644 --- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java +++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java @@ -92,6 +92,7 @@ import com.cloud.network.element.NetworkElement; import com.cloud.network.element.StaticNatServiceProvider; import com.cloud.network.element.VpcProvider; +import com.cloud.network.vpc.OSPFZoneConfig.Params; import com.cloud.network.vpc.VpcOffering.State; import com.cloud.network.vpc.dao.NetworkACLDao; import com.cloud.network.vpc.dao.PrivateIpDao; @@ -137,6 +138,9 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.exception.ExceptionUtil; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; +import com.cloud.utils.net.cidr.CIDRFactory; import com.cloud.vm.ReservationContext; import com.cloud.vm.ReservationContextImpl; import com.cloud.vm.dao.DomainRouterDao; @@ -226,9 +230,9 @@ public class VpcManagerImpl extends ManagerBase implements VpcManager, VpcProvis private final List supportedProviders = Arrays.asList(Provider.VPCVirtualRouter, Provider.NiciraNvp, Provider.InternalLbVm, Provider.Netscaler, Provider.JuniperContrailVpcRouter, Provider.Ovs, Provider.NuageVsp, Provider.BigSwitchBcf); - int _cleanupInterval; - int _maxNetworks; - SearchBuilder IpAddressSearch; + private int _cleanupInterval; + private int _maxNetworks; + private SearchBuilder IpAddressSearch; protected final List hTypes = new ArrayList(); @@ -286,6 +290,7 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { svcProviderMap.put(svc, defaultProviders); } } + createVpcOffering(VpcOffering.defaultVPCNSOfferingName, VpcOffering.defaultVPCNSOfferingName, svcProviderMap, false, State.Enabled, null, false, false, false); } @@ -308,6 +313,19 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { } createVpcOffering(VpcOffering.redundantVPCOfferingName, VpcOffering.redundantVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, true); } + + if (_vpcOffDao.findByUniqueName(VpcOffering.routedVPCOfferingName) == null) { + s_logger.debug("Creating default routed VPC offering " + VpcOffering.routedVPCOfferingName); + + final Map> svcProviderMap = new HashMap>(); + final Set defaultProviders = new HashSet(); + defaultProviders.add(Provider.VPCVirtualRouter); + for (final Service svc : getSupportedServices()) { + svcProviderMap.put(svc, defaultProviders); + } + svcProviderMap.put(Network.Service.VPCDynamicRouting, defaultProviders); + createVpcOffering(VpcOffering.routedVPCOfferingName, VpcOffering.routedVPCOfferingName, svcProviderMap, true, State.Enabled, null, false, false, false); + } } }); @@ -325,10 +343,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { IpAddressSearch.and("associatedWithNetworkId", IpAddressSearch.entity().getAssociatedWithNetworkId(), Op.EQ); final SearchBuilder virtualNetworkVlanSB = _vlanDao.createSearchBuilder(); virtualNetworkVlanSB.and("vlanType", virtualNetworkVlanSB.entity().getVlanType(), Op.EQ); - IpAddressSearch - .join("virtualNetworkVlanSB", virtualNetworkVlanSB, IpAddressSearch.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(), JoinBuilder.JoinType.INNER); + IpAddressSearch.join("virtualNetworkVlanSB", virtualNetworkVlanSB, IpAddressSearch.entity().getVlanId(), virtualNetworkVlanSB.entity().getId(), JoinBuilder.JoinType.INNER); IpAddressSearch.done(); - return true; } @@ -369,6 +385,7 @@ public VpcOffering createVpcOffering(final String name, final String displayText boolean sourceNatSvc = false; boolean firewallSvs = false; + boolean dynamicRouting = false; // populate the services first for (final String serviceName : supportedServices) { // validate if the service is supported @@ -386,7 +403,6 @@ public VpcOffering createVpcOffering(final String name, final String displayText if (service == Service.NetworkACL) { firewallSvs = true; } - if (service == Service.SourceNat) { sourceNatSvc = true; } @@ -438,20 +454,20 @@ public VpcOffering createVpcOffering(final String name, final String displayText } @DB - 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 redundantRouter) { + 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 redundantRouter) { return Transaction.execute(new TransactionCallback() { @Override public VpcOffering doInTransaction(final TransactionStatus status) { // create vpc offering object + VpcOfferingVO offering = new VpcOfferingVO(name, displayText, isDefault, serviceOfferingId, supportsDistributedRouter, offersRegionLevelVPC, redundantRouter); if (state != null) { offering.setState(state); } - s_logger.debug("Adding vpc offering " + offering); + s_logger.info("Adding vpc offering " + offering); offering = _vpcOffDao.persist(offering); // populate services and providers if (svcProviderMap != null) { @@ -496,7 +512,7 @@ private void validateConnectivtyServiceCapabilities(final Set provider final Iterator iter = serviceCapabilityCollection.iterator(); while (iter.hasNext()) { - final HashMap svcCapabilityMap = (HashMap) iter.next(); + final HashMap svcCapabilityMap = (HashMap)iter.next(); Capability capability = null; final String svc = svcCapabilityMap.get(SERVICE); final String capabilityName = svcCapabilityMap.get(CAPABILITYTYPE); @@ -524,14 +540,14 @@ private boolean findCapabilityForService(final Map serviceCapabilitystList, fina if (serviceCapabilitystList != null && !serviceCapabilitystList.isEmpty()) { final Iterator iter = serviceCapabilitystList.values().iterator(); while (iter.hasNext()) { - final HashMap currentCapabilityMap = (HashMap) iter.next(); + final HashMap currentCapabilityMap = (HashMap)iter.next(); final String currentCapabilityService = currentCapabilityMap.get(SERVICE); final String currentCapabilityName = currentCapabilityMap.get(CAPABILITYTYPE); final 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)); + throw new InvalidParameterValueException( + String.format("Invalid capability with name %s, value %s and service %s", currentCapabilityName, currentCapabilityValue, currentCapabilityService)); } if (currentCapabilityName.equalsIgnoreCase(capability.getName())) { @@ -559,6 +575,29 @@ private boolean isVpcOfferingSupportsDistributedRouter(final Map serviceCapabili private boolean isVpcOfferingRedundantRouter(final Map serviceCapabilitystList) { return findCapabilityForService(serviceCapabilitystList, Capability.RedundantRouter, Service.SourceNat); + + } + + private boolean isVpcOfferingDynamicRouter(final Map serviceCapabilitystList) { + return findCapabilityForService(serviceCapabilitystList, Capability.VPCDynamicRouting, Service.VPCDynamicRouting); + } + + @Override + public boolean isVpcOfferingDynamicallyRouted(final long dcId, final long vpcOffId) { + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpcOffId, Service.VPCDynamicRouting) && _dcDao.isDynamicallyRouted(dcId)) { + return true; + } else { + return false; + } + } + + @Override + public boolean isVpcOfferingDynamicallyRouted(final long vpcOffId) { + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpcOffId, Service.VPCDynamicRouting)) { + return true; + } else { + return false; + } } @Override @@ -688,8 +727,8 @@ public boolean deleteVpcOffering(final long offId) { // (the offering can be disabled though) final int vpcCount = _vpcDao.getVpcCountByOfferingId(offId); if (vpcCount > 0) { - throw new InvalidParameterValueException("Can't delete vpc offering " + offId + " as its used by " + vpcCount + " vpcs. " - + "To make the network offering unavaiable, disable it"); + throw new InvalidParameterValueException( + "Can't delete vpc offering " + offId + " as its used by " + vpcCount + " vpcs. " + "To make the network offering unavaiable, disable it"); } if (_vpcOffDao.remove(offId)) { @@ -699,6 +738,30 @@ public boolean deleteVpcOffering(final long offId) { } } + @Override + public Map updateQuaggaConfig(final Long zoneId, final String protocol, final String ospfArea, final Short helloInterval, final Short deadInterval, + final Short retransmitInterval, final Short transitDelay, final String authentication, final String quaggaPassword, final String superCIDR, final Boolean enabled) + throws BadCIDRException { + OSPFZoneConfig qzc = new OSPFZoneConfig(); + DataCenterVO dc = _dcDao.findById(zoneId); + _dcDao.loadDetails(dc); + Map details = dc.getDetails(); + qzc.setDefaultValues(details); + qzc.setValues(protocol, ospfArea, helloInterval, deadInterval, retransmitInterval, transitDelay, authentication, quaggaPassword, superCIDR, enabled); + details = qzc.getValues(); + dc.setDetails(details); + _dcDao.saveDetails(dc); + s_logger.info("Quagga config saved to datacenter " + zoneId); + return details; + } + + @Override + public Map quaggaConfig(final Long zoneId) { + DataCenterVO dc = _dcDao.findById(zoneId); + _dcDao.loadDetails(dc); + return dc.getDetails(); + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_OFFERING_UPDATE, eventDescription = "updating vpc offering") public VpcOffering updateVpcOffering(final long vpcOffId, final String vpcOfferingName, final String displayText, final String state) { @@ -741,6 +804,67 @@ public VpcOffering updateVpcOffering(final long vpcOffId, final String vpcOfferi } } + @Override + public CIDR[] getZoneSuperCidrList(final long zoneId) throws BadCIDRException { + final String superCIDRList = _dcDao.getDetail(zoneId, Params.SUPER_CIDR.name()); + if (superCIDRList != null) { + String[] str_cidr_list = superCIDRList.split(","); + CIDR[] cidr_list = NetUtils.convertToCIDR(str_cidr_list); + if (!NetUtils.cidrListConsistency(cidr_list)) { + throw new InvalidParameterValueException("The cidr list is not consistent " + Arrays.toString(cidr_list)); + } + return cidr_list; + } else { + throw new InvalidParameterValueException("Zone super cidr is null check cloud.data_center_details for zone id=" + zoneId); + } + } + + private List getAllVpcCidrs() throws BadCIDRException { + // get all the used cidrs + List usedSubnets = new ArrayList(); + for (Vpc vpc : _vpcDao.listAll()) { + if (_vpcSrvcDao.areServicesSupportedInVpc(vpc.getId(), Service.VPCDynamicRouting)) { + usedSubnets.add(CIDRFactory.getCIDR(vpc.getCidr())); + } + } + return usedSubnets; + } + + @Override + @ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", create = true) + public synchronized Vpc createDynamicVpc(final long zoneId, final long vpcOffId, final long vpcOwnerId, final String vpcName, final String displayText, final String netmask, + String networkDomain, final Boolean displayVpc) throws ResourceAllocationException, BadCIDRException { + if (netmask != null) { + if (!NetUtils.isValidNetmask(netmask)) { + throw new InvalidParameterValueException("Invalid netmask " + netmask); + } + final CIDR[] superCidr = getZoneSuperCidrList(zoneId); + final List usedSubnets = getAllVpcCidrs(); + //find cidr that does not overlap with the used cidrs + List allSubnets = NetUtils.getAllSubnets(superCidr, netmask); + //check for overlap with usedSubnets + CIDR unused_cidr = null; + for (CIDR subnet : allSubnets) { + if (NetUtils.isCidrOverlap(subnet, usedSubnets)) { + continue; + } else { + unused_cidr = subnet; + break; + } + } + + if (unused_cidr == null) { + throw new InvalidParameterValueException("There are no available cidrs in the zone with super Cidr = " + superCidr); + } else { + return createVpc(zoneId, vpcOffId, vpcOwnerId, vpcName, displayText, unused_cidr.toString(), networkDomain, displayVpc); + } + + } else { + throw new InvalidParameterValueException("For dynamically routed VPC you need to provide netmask."); + } + + } + @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_CREATE, eventDescription = "creating vpc", create = true) public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwnerId, final String vpcName, final String displayText, final String cidr, String networkDomain, @@ -772,7 +896,7 @@ public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwner } // Validate zone - final DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); + final DataCenterVO zone = _dcDao.findById(zoneId); if (zone == null) { throw new InvalidParameterValueException("Can't find zone by id specified"); } @@ -795,6 +919,18 @@ public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwner } } + //validate dynamic routing + //check dynamic routing + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpcOff.getId(), Service.VPCDynamicRouting)) { + _dcDao.loadDetails(zone); + if (!zone.isDynamicRoutingEnabled()) { + final InvalidParameterValueException ex = new InvalidParameterValueException( + "Dynamic routing can not be used as it is not enabled for this zone " + zone.getName()); + ex.addProxyObject(String.valueOf(vpcOffId), "VPC"); + throw ex; + } + } + final boolean useDistributedRouter = vpcOff.supportsDistributedRouter(); final VpcVO vpc = new VpcVO(zoneId, vpcName, displayText, owner.getId(), owner.getDomainId(), vpcOffId, cidr, networkDomain, useDistributedRouter, isRegionLevelVpcOff, vpcOff.getRedundantRouter()); @@ -804,15 +940,22 @@ public Vpc createVpc(final long zoneId, final long vpcOffId, final long vpcOwner @DB 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); - } - // cidr has to be RFC 1918 complient - if (!NetUtils.validateGuestCidr(cidr)) { - throw new InvalidParameterValueException("Guest Cidr " + cidr + " is not RFC1918 compliant"); + try { + final CIDR cidr = CIDRFactory.getCIDR(vpc.getCidr()); + + final CIDR[] superCidr = getZoneSuperCidrList(vpc.zoneId); + + if (_vpcOffServiceDao.areServicesSupportedByNetworkOffering(vpc.getVpcOfferingId(), Service.VPCDynamicRouting)) { + if (!NetUtils.validateGuestCidrForOSPF(cidr, superCidr)) { + throw new InvalidParameterValueException("Guest Cidr " + cidr + " is not within Zone superCIDR " + Arrays.toString(superCidr)); + } + } else if (!NetUtils.validateGuestCidr(cidr)) { + //cidr has to be RFC 1918 complient + throw new InvalidParameterValueException("Guest Cidr " + cidr + " is not RFC1918 compliant"); + } + } catch (BadCIDRException ex) { + throw new InvalidParameterValueException("The VPC guest Cidr is not well formatted"); } // validate network domain @@ -1182,9 +1325,9 @@ public boolean startVpc(final long vpcId, final boolean destroyOnFailure) throws return result; } - protected boolean startVpc(final Vpc vpc, final DeployDestination dest, final ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { - // deploy provider + protected boolean startVpc(final Vpc vpc, final DeployDestination dest, final ReservationContext context) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { + //deploy provider boolean success = true; final List providersToImplement = getVpcProviders(vpc.getId()); for (final VpcProvider element : getVpcElements()) { @@ -1237,8 +1380,8 @@ public boolean shutdownVpc(final long vpcId) throws ConcurrentOperationException @DB @Override - public void validateNtwkOffForNtwkInVpc(final Long networkId, final long newNtwkOffId, final String newCidr, final String newNetworkDomain, final Vpc vpc, - final String gateway, final Account networkOwner, final Long aclId) { + public void validateNtwkOffForNtwkInVpc(final Long networkId, final long newNtwkOffId, final String newCidr, final String newNetworkDomain, final Vpc vpc, final String gateway, + final Account networkOwner, final Long aclId) { final NetworkOffering guestNtwkOff = _entityMgr.findById(NetworkOffering.class, newNtwkOffId); @@ -1277,8 +1420,7 @@ public void validateNtwkOffForNtwkInVpc(final Long networkId, final long newNtwk continue; } else { final NetworkOffering otherOff = _entityMgr.findById(NetworkOffering.class, network.getNetworkOfferingId()); - // throw only if networks have different offerings with - // public lb support + //throw only if networks have different offerings with public lb support if (_ntwkModel.areServicesSupportedInNetwork(network.getId(), Service.Lb) && otherOff.getPublicLb() && guestNtwkOff.getId() != otherOff.getId()) { throw new InvalidParameterValueException("Public LB service is already supported " + "by network " + network + " in VPC " + vpc); } @@ -1308,8 +1450,8 @@ public void validateNtwkOffForVpc(final NetworkOffering guestNtwkOff, final List // added to vpc if (!(guestNtwkOff.getGuestType() == GuestType.Isolated && supportedSvcs.contains(Service.SourceNat))) { - throw new InvalidParameterValueException("Only network offerings of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() - + " are valid for vpc "); + throw new InvalidParameterValueException( + "Only network offerings of type " + GuestType.Isolated + " with service " + Service.SourceNat.getName() + " are valid for vpc "); } // 3) No redundant router support @@ -1395,8 +1537,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { public List getVpcElements() { if (vpcElements == null) { vpcElements = new ArrayList(); - vpcElements.add((VpcProvider) _ntwkModel.getElementImplementingProvider(Provider.VPCVirtualRouter.getName())); - vpcElements.add((VpcProvider) _ntwkModel.getElementImplementingProvider(Provider.JuniperContrailVpcRouter.getName())); + vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Provider.VPCVirtualRouter.getName())); + vpcElements.add((VpcProvider)_ntwkModel.getElementImplementingProvider(Provider.JuniperContrailVpcRouter.getName())); } if (vpcElements == null) { @@ -1481,7 +1623,7 @@ public boolean cleanupVpcResources(final long vpcId, final Account caller, final searchCriteria.setParameters("vpcId", vpcId, 0); final Filter filter = new Filter(NetworkACLVO.class, "id", false, null, null); - final Pair, Integer> aclsCountPair = _networkAclDao.searchAndCount(searchCriteria, filter); + final Pair, Integer> aclsCountPair = _networkAclDao.searchAndCount(searchCriteria, filter); final List acls = aclsCountPair.first(); for (final NetworkACLVO networkAcl : acls) { @@ -1494,8 +1636,8 @@ public boolean cleanupVpcResources(final long vpcId, final Account caller, final @Override @ActionEvent(eventType = EventTypes.EVENT_VPC_RESTART, eventDescription = "restarting vpc") - public boolean restartVpc(final long vpcId, final boolean cleanUp, final boolean makeRedundant) throws ConcurrentOperationException, ResourceUnavailableException, - InsufficientCapacityException { + public boolean restartVpc(final long vpcId, final boolean cleanUp, final boolean makeRedundant) + throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException { final Account caller = CallContext.current().getCallingAccount(); @@ -1591,8 +1733,8 @@ protected PrivateGateway getPrivateGatewayProfile(final VpcGateway gateway) { @DB @ActionEvent(eventType = EventTypes.EVENT_PRIVATE_GATEWAY_CREATE, eventDescription = "creating VPC private gateway", create = true) public PrivateGateway createVpcPrivateGateway(final long vpcId, Long physicalNetworkId, final String broadcastUri, final String ipAddress, final String gateway, - final String netmask, final long gatewayOwnerId, final Long networkOfferingId, final Boolean isSourceNat, final Long aclId) throws ResourceAllocationException, - ConcurrentOperationException, InsufficientCapacityException { + final String netmask, final long gatewayOwnerId, final Long networkOfferingId, final Boolean isSourceNat, final Long aclId) + throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { // Validate parameters final Vpc vpc = getActiveVpc(vpcId); @@ -1624,8 +1766,8 @@ public PrivateGateway createVpcPrivateGateway(final long vpcId, Long physicalNet try { gatewayVO = Transaction.execute(new TransactionCallbackWithException() { @Override - public VpcGatewayVO doInTransaction(final TransactionStatus status) throws ResourceAllocationException, ConcurrentOperationException, - InsufficientCapacityException { + public VpcGatewayVO doInTransaction(final TransactionStatus status) + throws ResourceAllocationException, ConcurrentOperationException, InsufficientCapacityException { s_logger.debug("Creating Private gateway for VPC " + vpc); // 1) create private network unless it is existing and // lswitch'd @@ -1641,16 +1783,15 @@ public VpcGatewayVO doInTransaction(final TransactionStatus status) throws Resou final String networkName = "vpc-" + vpc.getName() + "-privateNetwork"; privateNtwk = _ntwkSvc.createPrivateNetwork(networkName, networkName, physicalNetworkIdFinal, broadcastUri, ipAddress, null, gateway, netmask, gatewayOwnerId, vpcId, isSourceNat, networkOfferingId); - } else { // create the nic/ip as createPrivateNetwork - // doesn''t do that work for us now + } else { // create the nic/ip as createPrivateNetwork doesn''t do that work for us now s_logger.info("found and using existing network for vpc " + vpc + ": " + broadcastUri); final DataCenterVO dc = _dcDao.lockRow(physNetFinal.getDataCenterId(), true); // add entry to private_ip_address table PrivateIpVO privateIp = _privateIpDao.findByIpAndSourceNetworkId(privateNtwk.getId(), ipAddress); if (privateIp != null) { - throw new InvalidParameterValueException("Private ip address " + ipAddress + " already used for private gateway" + " in zone " - + _entityMgr.findById(DataCenter.class, dcId).getName()); + throw new InvalidParameterValueException( + "Private ip address " + ipAddress + " already used for private gateway" + " in zone " + _entityMgr.findById(DataCenter.class, dcId).getName()); } final Long mac = dc.getMacAddress(); @@ -1677,21 +1818,19 @@ public VpcGatewayVO doInTransaction(final TransactionStatus status) throws Resou networkAclId = aclId; } - { // experimental block, this is a hack - // set vpc id in network to null - // might be needed for all types of broadcast domains - // the ugly hack is that vpc gateway nets are created as - // guest network - // while they are not. - // A more permanent solution would be to define a type of - // 'gatewaynetwork' - // so that handling code is not mixed between the two + { // experimental block, this is a hack + // set vpc id in network to null + // might be needed for all types of broadcast domains + // the ugly hack is that vpc gateway nets are created as guest network + // while they are not. + // A more permanent solution would be to define a type of 'gatewaynetwork' + // so that handling code is not mixed between the two final NetworkVO gatewaynet = _ntwkDao.findById(privateNtwk.getId()); gatewaynet.setVpcId(null); _ntwkDao.persist(gatewaynet); } - // 2) create gateway entry + //2) create gateway entry final VpcGatewayVO gatewayVO = new VpcGatewayVO(ipAddress, VpcGateway.Type.Private, vpcId, privateNtwk.getDataCenterId(), privateNtwk.getId(), broadcastUri, gateway, netmask, vpc.getAccountId(), vpc.getDomainId(), isSourceNat, networkAclId); _vpcGatewayDao.persist(gatewayVO); @@ -1777,8 +1916,8 @@ public void doInTransactionWithoutResult(final TransactionStatus status) { // routes associated with it final long routeCount = _staticRouteDao.countRoutesByGateway(gatewayVO.getId()); if (routeCount > 0) { - throw new CloudRuntimeException("Can't delete private gateway " + gatewayVO + " as it has " + routeCount - + " static routes applied. Remove the routes first"); + throw new CloudRuntimeException( + "Can't delete private gateway " + gatewayVO + " as it has " + routeCount + " static routes applied. Remove the routes first"); } gatewayVO.setState(VpcGateway.State.Deleting); @@ -2239,8 +2378,8 @@ protected void runInContext() { @DB @Override @ActionEvent(eventType = EventTypes.EVENT_NET_IP_ASSIGN, eventDescription = "associating Ip", async = true) - public IpAddress associateIPToVpc(final long ipId, final long vpcId) throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, - ConcurrentOperationException { + public IpAddress associateIPToVpc(final long ipId, final long vpcId) + throws ResourceAllocationException, ResourceUnavailableException, InsufficientAddressCapacityException, ConcurrentOperationException { final Account caller = CallContext.current().getCallingAccount(); Account owner = null; @@ -2330,8 +2469,8 @@ public boolean isIpAllocatedToVpc(final IpAddress ip) { @Override public Network createVpcGuestNetwork(final long ntwkOffId, final String name, final String displayText, final String gateway, final String cidr, final String vlanId, String networkDomain, final Account owner, final Long domainId, final PhysicalNetwork pNtwk, final long zoneId, final ACLType aclType, final Boolean subdomainAccess, - final long vpcId, final Long aclId, final Account caller, final Boolean isDisplayNetworkEnabled) throws ConcurrentOperationException, InsufficientCapacityException, - ResourceAllocationException { + final long vpcId, final Long aclId, final Account caller, final Boolean isDisplayNetworkEnabled) + throws ConcurrentOperationException, InsufficientCapacityException, ResourceAllocationException { final Vpc vpc = getActiveVpc(vpcId); @@ -2353,13 +2492,13 @@ public Network createVpcGuestNetwork(final long ntwkOffId, final String name, fi // 1) Validate if network can be created for VPC validateNtwkOffForNtwkInVpc(null, ntwkOffId, cidr, networkDomain, vpc, gateway, owner, aclId); - // 2) Create network + //2) Create network final Network guestNetwork = _ntwkMgr.createGuestNetwork(ntwkOffId, name, displayText, gateway, cidr, vlanId, networkDomain, owner, domainId, pNtwk, zoneId, aclType, subdomainAccess, vpcId, null, null, isDisplayNetworkEnabled, null); if (guestNetwork != null) { guestNetwork.setNetworkACLId(aclId); - _ntwkDao.update(guestNetwork.getId(), (NetworkVO) guestNetwork); + _ntwkDao.update(guestNetwork.getId(), (NetworkVO)guestNetwork); } return guestNetwork; } diff --git a/server/src/com/cloud/server/ConfigurationServerImpl.java b/server/src/com/cloud/server/ConfigurationServerImpl.java index 16e4ff059022..b2b11d7d56ec 100644 --- a/server/src/com/cloud/server/ConfigurationServerImpl.java +++ b/server/src/com/cloud/server/ConfigurationServerImpl.java @@ -158,7 +158,6 @@ public class ConfigurationServerImpl extends ManagerBase implements Configuratio @Inject protected ManagementService _mgrService; - public ConfigurationServerImpl() { setRunLevel(ComponentLifecycle.RUN_LEVEL_FRAMEWORK_BOOTSTRAP); } @@ -430,9 +429,9 @@ private String getEnvironmentProperty(String name) { return null; } else { final Properties props = new Properties(); - try(final FileInputStream finputstream = new FileInputStream(propsFile);) { + try (final FileInputStream finputstream = new FileInputStream(propsFile);) { props.load(finputstream); - }catch (IOException e) { + } catch (IOException e) { s_logger.error("getEnvironmentProperty:Exception:" + e.getMessage()); } return props.getProperty("mount.parent"); @@ -476,8 +475,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { String lastname = "cloud"; // create an account for the admin user first - insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username - + "', '1', '1', 1)"; + insertSql = "INSERT INTO `cloud`.`account` (id, uuid, account_name, type, domain_id, account.default) VALUES (" + id + ", UUID(), '" + username + "', '1', '1', 1)"; try { PreparedStatement stmt = txn.prepareAutoCloseStatement(insertSql); stmt.executeUpdate(); @@ -620,18 +618,14 @@ protected void updateSSLKeystore() { s_logger.info("Generated SSL keystore."); } String base64Keystore = getBase64Keystore(keystorePath); - ConfigurationVO configVO = - new ConfigurationVO("Hidden", "DEFAULT", "management-server", "ssl.keystore", base64Keystore, - "SSL Keystore for the management servers"); + ConfigurationVO configVO = new ConfigurationVO("Hidden", "DEFAULT", "management-server", "ssl.keystore", base64Keystore, "SSL Keystore for the management servers"); _configDao.persist(configVO); s_logger.info("Stored SSL keystore to database."); } else { // !keystoreFile.exists() and dbExisted // Export keystore to local file byte[] storeBytes = Base64.decodeBase64(dbString); String tmpKeystorePath = "/tmp/tmpkey"; - try ( - FileOutputStream fo = new FileOutputStream(tmpKeystorePath); - ) { + try (FileOutputStream fo = new FileOutputStream(tmpKeystorePath);) { fo.write(storeBytes); Script script = new Script(true, "cp", 5000, null); script.add("-f"); @@ -672,7 +666,7 @@ protected void updateSystemvmPassword() { try { String rpassword = _mgrService.generateRandomPassword(); String wSql = "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " - + "VALUES ('Secure','DEFAULT', 'management-server','system.vm.password', ?,'randmon password generated each management server starts for system vm')"; + + "VALUES ('Secure','DEFAULT', 'management-server','system.vm.password', ?,'randmon password generated each management server starts for system vm')"; PreparedStatement stmt = txn.prepareAutoCloseStatement(wSql); stmt.setString(1, DBEncryptionUtil.encrypt(rpassword)); stmt.executeUpdate(); @@ -727,7 +721,7 @@ public void updateKeyPairs() { } // FIXME: take a global database lock here for safety. boolean onWindows = isOnWindows(); - if(!onWindows) { + if (!onWindows) { Script.runSimpleBashScript("if [ -f " + privkeyfile + " ]; then rm -f " + privkeyfile + "; fi; ssh-keygen -t rsa -N '' -f " + privkeyfile + " -q"); } @@ -752,14 +746,10 @@ public void updateKeyPairs() { } String publicKey = new String(arr2).trim(); - final String insertSql1 = - "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + - "VALUES ('Hidden','DEFAULT', 'management-server','ssh.privatekey', '" + DBEncryptionUtil.encrypt(privateKey) + - "','Private key for the entire CloudStack')"; - final String insertSql2 = - "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + - "VALUES ('Hidden','DEFAULT', 'management-server','ssh.publickey', '" + DBEncryptionUtil.encrypt(publicKey) + - "','Public key for the entire CloudStack')"; + final String insertSql1 = "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + + "VALUES ('Hidden','DEFAULT', 'management-server','ssh.privatekey', '" + DBEncryptionUtil.encrypt(privateKey) + "','Private key for the entire CloudStack')"; + final String insertSql2 = "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + + "VALUES ('Hidden','DEFAULT', 'management-server','ssh.publickey', '" + DBEncryptionUtil.encrypt(publicKey) + "','Public key for the entire CloudStack')"; Transaction.execute(new TransactionCallbackNoReturn() { @Override @@ -830,7 +820,7 @@ private void writeKeyToDisk(String key, String keyPath) { } if (keyfile.exists()) { - try (FileOutputStream kStream = new FileOutputStream(keyfile);){ + try (FileOutputStream kStream = new FileOutputStream(keyfile);) { if (kStream != null) { kStream.write(key.getBytes()); } @@ -877,16 +867,16 @@ protected void injectSshKeysIntoSystemVmIsoPatch(String publicKeyPath, String pr throw new CloudRuntimeException("Unable to find systemvm iso vms/systemvm.iso"); } Script command = null; - if(isOnWindows()) { + if (isOnWindows()) { command = new Script("python", s_logger); } else { command = new Script("/bin/bash", s_logger); } if (isOnWindows()) { - scriptPath = scriptPath.replaceAll("\\\\" ,"/" ); - systemVmIsoPath = systemVmIsoPath.replaceAll("\\\\" ,"/" ); - publicKeyPath = publicKeyPath.replaceAll("\\\\" ,"/" ); - privKeyPath = privKeyPath.replaceAll("\\\\" ,"/" ); + scriptPath = scriptPath.replaceAll("\\\\", "/"); + systemVmIsoPath = systemVmIsoPath.replaceAll("\\\\", "/"); + publicKeyPath = publicKeyPath.replaceAll("\\\\", "/"); + privKeyPath = privKeyPath.replaceAll("\\\\", "/"); } command.add(scriptPath); command.add(publicKeyPath); @@ -904,7 +894,7 @@ protected void injectSshKeysIntoSystemVmIsoPatch(String publicKeyPath, String pr protected String getInjectScript() { String injectScript = null; boolean onWindows = isOnWindows(); - if(onWindows) { + if (onWindows) { injectScript = "scripts/vm/systemvm/injectkeys.py"; } else { injectScript = "scripts/vm/systemvm/injectkeys.sh"; @@ -927,10 +917,9 @@ protected void generateSecStorageVmCopyPassword() { s_logger.info("Need to store secondary storage vm copy password in the database"); String password = PasswordGenerator.generateRandomPassword(12); - final String insertSql1 = - "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + - "VALUES ('Hidden','DEFAULT', 'management-server','secstorage.copy.password', '" + DBEncryptionUtil.encrypt(password) + - "','Password used to authenticate zone-to-zone template copy requests')"; + final String insertSql1 = "INSERT INTO `cloud`.`configuration` (category, instance, component, name, value, description) " + + "VALUES ('Hidden','DEFAULT', 'management-server','secstorage.copy.password', '" + DBEncryptionUtil.encrypt(password) + + "','Password used to authenticate zone-to-zone template copy requests')"; Transaction.execute(new TransactionCallbackNoReturn() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { @@ -962,7 +951,7 @@ private void updateSSOKey() { private void updateSecondaryStorageVMSharedKey() { try { ConfigurationVO configInDB = _configDao.findByName(Config.SSVMPSK.key()); - if(configInDB == null) { + if (configInDB == null) { ConfigurationVO configVO = new ConfigurationVO(Config.SSVMPSK.getCategory(), "DEFAULT", Config.SSVMPSK.getComponent(), Config.SSVMPSK.key(), getPrivateKey(), Config.SSVMPSK.getDescription()); s_logger.info("generating a new SSVM PSK. This goes to SSVM on Start"); @@ -986,10 +975,8 @@ private String getPrivateKey() throws NoSuchAlgorithmException { } - @DB - protected HostPodVO createPod(long userId, String podName, final long zoneId, String gateway, String cidr, final String startIp, String endIp) - throws InternalErrorException { + protected HostPodVO createPod(long userId, String podName, final long zoneId, String gateway, String cidr, final String startIp, String endIp) throws InternalErrorException { String[] cidrPair = cidr.split("\\/"); String cidrAddress = cidrPair[0]; int cidrSize = Integer.parseInt(cidrPair[1]); @@ -1047,8 +1034,8 @@ public void doInTransactionWithoutResult(TransactionStatus status) throws Intern return pod; } - private DiskOfferingVO createdefaultDiskOffering(Long domainId, String name, String description, ProvisioningType provisioningType, - int numGibibytes, String tags, boolean isCustomized, boolean isSystemUse) { + private DiskOfferingVO createdefaultDiskOffering(Long domainId, String name, String description, ProvisioningType provisioningType, int numGibibytes, String tags, + boolean isCustomized, boolean isSystemUse) { long diskSize = numGibibytes; diskSize = diskSize * 1024 * 1024 * 1024; tags = cleanupTags(tags); @@ -1060,11 +1047,11 @@ private DiskOfferingVO createdefaultDiskOffering(Long domainId, String name, Str return newDiskOffering; } - private ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, - ProvisioningType provisioningType, boolean localStorageRequired, boolean offerHA, String tags) { + private ServiceOfferingVO createServiceOffering(long userId, String name, int cpu, int ramSize, int speed, String displayText, ProvisioningType provisioningType, + boolean localStorageRequired, boolean offerHA, String tags) { tags = cleanupTags(tags); - ServiceOfferingVO offering = - new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, offerHA, displayText, provisioningType, localStorageRequired, false, tags, false, null, false); + ServiceOfferingVO offering = new ServiceOfferingVO(name, cpu, ramSize, speed, null, null, offerHA, displayText, provisioningType, localStorageRequired, false, tags, false, + null, false); offering.setUniqueName("Cloud.Com-" + name); offering = _serviceOfferingDao.persistSystemServiceOffering(offering); return offering; @@ -1138,88 +1125,83 @@ protected void createDefaultNetworkOfferings() { @Override public void doInTransactionWithoutResult(TransactionStatus status) { // Offering #1 - NetworkOfferingVO defaultSharedSGNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, "Offering for Shared Security group enabled networks", - TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, Network.GuestType.Shared, true, true, false, false, false); + NetworkOfferingVO defaultSharedSGNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultSharedNetworkOfferingWithSGService, + "Offering for Shared Security group enabled networks", TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, + Network.GuestType.Shared, true, true, false, false, false); defaultSharedSGNetworkOffering.setState(NetworkOffering.State.Enabled); defaultSharedSGNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultSharedSGNetworkOffering); for (Service service : defaultSharedSGNetworkOfferingProviders.keySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultSharedSGNetworkOffering.getId(), service, defaultSharedSGNetworkOfferingProviders.get(service)); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultSharedSGNetworkOffering.getId(), service, + defaultSharedSGNetworkOfferingProviders.get(service)); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #2 - NetworkOfferingVO defaultSharedNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultSharedNetworkOffering, "Offering for Shared networks", TrafficType.Guest, false, true, null, null, true, - Availability.Optional, null, Network.GuestType.Shared, true, true, false, false, false); + NetworkOfferingVO defaultSharedNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultSharedNetworkOffering, "Offering for Shared networks", + TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, Network.GuestType.Shared, true, true, false, false, false); defaultSharedNetworkOffering.setState(NetworkOffering.State.Enabled); defaultSharedNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultSharedNetworkOffering); for (Service service : defaultSharedNetworkOfferingProviders.keySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultSharedNetworkOffering.getId(), service, defaultSharedNetworkOfferingProviders.get(service)); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultSharedNetworkOffering.getId(), service, + defaultSharedNetworkOfferingProviders.get(service)); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #3 - NetworkOfferingVO defaultIsolatedSourceNatEnabledNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService, - "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Required, null, - Network.GuestType.Isolated, true, false, false, false, true); + NetworkOfferingVO defaultIsolatedSourceNatEnabledNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingWithSourceNatService, + "Offering for Isolated networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Required, null, + Network.GuestType.Isolated, true, false, false, false, true); defaultIsolatedSourceNatEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); defaultIsolatedSourceNatEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedSourceNatEnabledNetworkOffering); for (Service service : defaultIsolatedSourceNatEnabledNetworkOfferingProviders.keySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultIsolatedSourceNatEnabledNetworkOffering.getId(), service, - defaultIsolatedSourceNatEnabledNetworkOfferingProviders.get(service)); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultIsolatedSourceNatEnabledNetworkOffering.getId(), service, + defaultIsolatedSourceNatEnabledNetworkOfferingProviders.get(service)); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #4 - NetworkOfferingVO defaultIsolatedEnabledNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOffering, "Offering for Isolated networks with no Source Nat service", TrafficType.Guest, - false, true, null, null, true, Availability.Optional, null, Network.GuestType.Isolated, true, true, false, false, false); + NetworkOfferingVO defaultIsolatedEnabledNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOffering, + "Offering for Isolated networks with no Source Nat service", TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, + Network.GuestType.Isolated, true, true, false, false, false); defaultIsolatedEnabledNetworkOffering.setState(NetworkOffering.State.Enabled); defaultIsolatedEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultIsolatedEnabledNetworkOffering); for (Service service : defaultIsolatedNetworkOfferingProviders.keySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultIsolatedEnabledNetworkOffering.getId(), service, defaultIsolatedNetworkOfferingProviders.get(service)); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultIsolatedEnabledNetworkOffering.getId(), service, + defaultIsolatedNetworkOfferingProviders.get(service)); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #5 - NetworkOfferingVO defaultNetscalerNetworkOffering = - new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, - "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, - Availability.Optional, null, Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false); + NetworkOfferingVO defaultNetscalerNetworkOffering = new NetworkOfferingVO(NetworkOffering.DefaultSharedEIPandELBNetworkOffering, + "Offering for Shared networks with Elastic IP and Elastic LB capabilities", TrafficType.Guest, false, true, null, null, true, Availability.Optional, null, + Network.GuestType.Shared, true, false, false, false, true, true, true, false, false, true, true, false, false, false); defaultNetscalerNetworkOffering.setState(NetworkOffering.State.Enabled); defaultNetscalerNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetscalerNetworkOffering); for (Service service : netscalerServiceProviders.keySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultNetscalerNetworkOffering.getId(), service, netscalerServiceProviders.get(service)); + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultNetscalerNetworkOffering.getId(), service, + netscalerServiceProviders.get(service)); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #6 - NetworkOfferingVO defaultNetworkOfferingForVpcNetworks = - new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks, - "Offering for Isolated Vpc networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Optional, - null, Network.GuestType.Isolated, false, false, false, false, true); + NetworkOfferingVO defaultNetworkOfferingForVpcNetworks = new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworks, + "Offering for Isolated Vpc networks with Source Nat service enabled", TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, + Network.GuestType.Isolated, false, false, false, false, true); defaultNetworkOfferingForVpcNetworks.setState(NetworkOffering.State.Enabled); defaultNetworkOfferingForVpcNetworks = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetworkOfferingForVpcNetworks); @@ -1236,18 +1218,34 @@ public void doInTransactionWithoutResult(TransactionStatus status) { defaultVpcNetworkOfferingProviders.put(Service.PortForwarding, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProviders.put(Service.Vpn, Provider.VPCVirtualRouter); - for (Map.Entry entry : defaultVpcNetworkOfferingProviders.entrySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultNetworkOfferingForVpcNetworks.getId(), entry.getKey(), entry.getValue()); + for (Map.Entry entry : defaultVpcNetworkOfferingProviders.entrySet()) { + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultNetworkOfferingForVpcNetworks.getId(), entry.getKey(), entry.getValue()); + _ntwkOfferingServiceMapDao.persist(offService); + s_logger.trace("Added service for the network offering: " + offService); + } + + // Offering #7 + NetworkOfferingVO defaultNetworkOfferingForDynamicRoutedVpcNetworks = new NetworkOfferingVO( + NetworkOffering.DefaultIsolatedDynamicRoutedNetworkOfferingForVpcNetworks, + "Offering for Isolated Vpc networks with Source Nat and Dynamic Routing service enabled", TrafficType.Guest, false, false, null, null, true, + Availability.Optional, null, Network.GuestType.Isolated, false, false, false, false, true); + + defaultNetworkOfferingForDynamicRoutedVpcNetworks.setState(NetworkOffering.State.Enabled); + defaultNetworkOfferingForDynamicRoutedVpcNetworks = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetworkOfferingForDynamicRoutedVpcNetworks); + + defaultVpcNetworkOfferingProviders.put(Service.VPCDynamicRouting, Provider.VPCVirtualRouter); + + for (Map.Entry entry : defaultVpcNetworkOfferingProviders.entrySet()) { + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultNetworkOfferingForDynamicRoutedVpcNetworks.getId(), entry.getKey(), + entry.getValue()); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } // Offering #7 - NetworkOfferingVO defaultNetworkOfferingForVpcNetworksNoLB = - new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB, - "Offering for Isolated Vpc networks with Source Nat service enabled and LB service Disabled", TrafficType.Guest, false, false, null, null, true, - Availability.Optional, null, Network.GuestType.Isolated, false, false, false, false, false); + NetworkOfferingVO defaultNetworkOfferingForVpcNetworksNoLB = new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksNoLB, + "Offering for Isolated Vpc networks with Source Nat service enabled and LB service Disabled", TrafficType.Guest, false, false, null, null, true, + Availability.Optional, null, Network.GuestType.Isolated, false, false, false, false, false); defaultNetworkOfferingForVpcNetworksNoLB.setState(NetworkOffering.State.Enabled); defaultNetworkOfferingForVpcNetworksNoLB = _networkOfferingDao.persistDefaultNetworkOffering(defaultNetworkOfferingForVpcNetworksNoLB); @@ -1263,18 +1261,16 @@ public void doInTransactionWithoutResult(TransactionStatus status) { defaultVpcNetworkOfferingProvidersNoLB.put(Service.PortForwarding, Provider.VPCVirtualRouter); defaultVpcNetworkOfferingProvidersNoLB.put(Service.Vpn, Provider.VPCVirtualRouter); - for (Map.Entry entry : defaultVpcNetworkOfferingProvidersNoLB.entrySet()) { - NetworkOfferingServiceMapVO offService = - new NetworkOfferingServiceMapVO(defaultNetworkOfferingForVpcNetworksNoLB.getId(), entry.getKey(), entry.getValue()); + for (Map.Entry entry : defaultVpcNetworkOfferingProvidersNoLB.entrySet()) { + NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultNetworkOfferingForVpcNetworksNoLB.getId(), entry.getKey(), entry.getValue()); _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } //offering #8 - network offering with internal lb service - NetworkOfferingVO internalLbOff = - new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB, - "Offering for Isolated Vpc networks with Internal LB support", TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, - Network.GuestType.Isolated, false, false, false, true, false); + NetworkOfferingVO internalLbOff = new NetworkOfferingVO(NetworkOffering.DefaultIsolatedNetworkOfferingForVpcNetworksWithInternalLB, + "Offering for Isolated Vpc networks with Internal LB support", TrafficType.Guest, false, false, null, null, true, Availability.Optional, null, + Network.GuestType.Isolated, false, false, false, true, false); internalLbOff.setState(NetworkOffering.State.Enabled); internalLbOff = _networkOfferingDao.persistDefaultNetworkOffering(internalLbOff); @@ -1293,6 +1289,7 @@ public void doInTransactionWithoutResult(TransactionStatus status) { _ntwkOfferingServiceMapDao.persist(offService); s_logger.trace("Added service for the network offering: " + offService); } + } }); } @@ -1348,9 +1345,8 @@ private void createDefaultNetworks() { } 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, offering.getRedundantRouter()); + NetworkVO network = new NetworkVO(id, trafficType, mode, broadcastDomainType, networkOfferingId, domainId, accountId, related, null, null, networkDomain, + 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/com/cloud/server/ManagementServerImpl.java b/server/src/com/cloud/server/ManagementServerImpl.java index e4ae8e166997..670a018fe094 100644 --- a/server/src/com/cloud/server/ManagementServerImpl.java +++ b/server/src/com/cloud/server/ManagementServerImpl.java @@ -258,6 +258,8 @@ import org.apache.cloudstack.api.command.admin.vpc.ListVPCsCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCCmdByAdmin; import org.apache.cloudstack.api.command.admin.vpc.UpdateVPCOfferingCmd; +import org.apache.cloudstack.api.command.admin.vpc.VPCOSPFConfigCmd; +import org.apache.cloudstack.api.command.admin.vpc.VPCOSPFConfigUpdateCmd; import org.apache.cloudstack.api.command.admin.zone.CreateZoneCmd; import org.apache.cloudstack.api.command.admin.zone.DeleteZoneCmd; import org.apache.cloudstack.api.command.admin.zone.ListZonesCmdByAdmin; @@ -2696,6 +2698,8 @@ public List> getCommands() { cmdList.add(DeletePrivateGatewayCmd.class); cmdList.add(DeleteVPCOfferingCmd.class); cmdList.add(UpdateVPCOfferingCmd.class); + cmdList.add(VPCOSPFConfigCmd.class); + cmdList.add(VPCOSPFConfigUpdateCmd.class); cmdList.add(CreateZoneCmd.class); cmdList.add(DeleteZoneCmd.class); cmdList.add(MarkDefaultZoneForAccountCmd.class); diff --git a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java index b5283dacfeba..cdbf1268dfe0 100644 --- a/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java +++ b/server/src/org/apache/cloudstack/network/topology/AdvancedNetworkVisitor.java @@ -39,6 +39,7 @@ import com.cloud.network.rules.NetworkAclsRules; import com.cloud.network.rules.NicPlugInOutRules; import com.cloud.network.rules.PrivateGatewayRules; +import com.cloud.network.rules.QuaggaRules; import com.cloud.network.rules.StaticRoutesRules; import com.cloud.network.rules.UserdataPwdRules; import com.cloud.network.rules.VpcIpAssociationRules; @@ -47,6 +48,7 @@ import com.cloud.network.vpc.PrivateIpVO; import com.cloud.network.vpc.StaticRouteProfile; import com.cloud.utils.net.NetUtils; +import com.cloud.utils.net.cidr.BadCIDRException; import com.cloud.vm.NicProfile; import com.cloud.vm.NicVO; import com.cloud.vm.UserVmVO; @@ -164,8 +166,8 @@ public boolean visit(final PrivateGatewayRules privateGW) throws ResourceUnavail } else { s_logger.warn("Unable to setup private gateway, virtual router " + router + " is not in the right state " + router.getState()); - throw new ResourceUnavailableException("Unable to setup Private gateway on the backend," + " virtual router " + router + " is not in the right state", - DataCenter.class, router.getDataCenterId()); + throw new ResourceUnavailableException("Unable to setup Private gateway on the backend," + " virtual router " + router + " is not in the right state", DataCenter.class, + router.getDataCenterId()); } return true; } @@ -212,4 +214,20 @@ public boolean visit(final AdvancedVpnRules vpnRules) throws ResourceUnavailable // results accordingly return _networkGeneralHelper.sendCommandsToRouter(router, cmds); } + + @Override + public boolean visit(final QuaggaRules quaggaRules) throws ResourceUnavailableException { + final VirtualRouter router = quaggaRules.getRouter(); + + final Commands cmds = new Commands(Command.OnError.Continue); + + try { + _commandSetupHelper.createQuaggaConfigCommand(router, quaggaRules.getVpcId(), cmds); + } catch (BadCIDRException ex) { + s_logger.warn("Failed to create Quagga config due to faulty cidr "); + return false; + } + + return _networkGeneralHelper.sendCommandsToRouter(router, cmds); + } } \ No newline at end of file diff --git a/server/src/org/apache/cloudstack/network/topology/BasicNetworkVisitor.java b/server/src/org/apache/cloudstack/network/topology/BasicNetworkVisitor.java index 53ddebbc3ded..a631c807bf59 100644 --- a/server/src/org/apache/cloudstack/network/topology/BasicNetworkVisitor.java +++ b/server/src/org/apache/cloudstack/network/topology/BasicNetworkVisitor.java @@ -54,6 +54,7 @@ import com.cloud.network.rules.PasswordToRouterRules; import com.cloud.network.rules.PortForwardingRule; import com.cloud.network.rules.PrivateGatewayRules; +import com.cloud.network.rules.QuaggaRules; import com.cloud.network.rules.SshKeyToRouterRules; import com.cloud.network.rules.StaticNat; import com.cloud.network.rules.StaticNatRule; @@ -106,7 +107,7 @@ public boolean visit(final StaticNatRules nat) throws ResourceUnavailableExcepti @Override public boolean visit(final LoadBalancingRules loadbalancing) throws ResourceUnavailableException { final Network network = loadbalancing.getNetwork(); - final DomainRouterVO router = (DomainRouterVO) loadbalancing.getRouter(); + final DomainRouterVO router = (DomainRouterVO)loadbalancing.getRouter(); final List rules = loadbalancing.getRules(); final Commands cmds = new Commands(Command.OnError.Continue); @@ -134,13 +135,13 @@ public boolean visit(final FirewallRules firewall) throws ResourceUnavailableExc } else if (purpose == Purpose.PortForwarding) { - _commandSetupHelper.createApplyPortForwardingRulesCommands((List) rules, router, cmds, network.getId()); + _commandSetupHelper.createApplyPortForwardingRulesCommands((List)rules, router, cmds, network.getId()); return _networkGeneralHelper.sendCommandsToRouter(router, cmds); } else if (purpose == Purpose.StaticNat) { - _commandSetupHelper.createApplyStaticNatRulesCommands((List) rules, router, cmds, network.getId()); + _commandSetupHelper.createApplyStaticNatRulesCommands((List)rules, router, cmds, network.getId()); return _networkGeneralHelper.sendCommandsToRouter(router, cmds); @@ -316,4 +317,9 @@ public boolean visit(final StaticRoutesRules staticRoutesRules) throws ResourceU public boolean visit(final AdvancedVpnRules vpnRules) throws ResourceUnavailableException { throw new CloudRuntimeException("AdvancedVpnRules not implemented in Basic Network Topology."); } + + @Override + public boolean visit(final QuaggaRules vpnRules) throws ResourceUnavailableException { + throw new CloudRuntimeException("AdvancedVpnRules not implemented in Basic Network Topology."); + } } \ No newline at end of file diff --git a/server/src/org/apache/cloudstack/network/topology/NetworkTopologyVisitor.java b/server/src/org/apache/cloudstack/network/topology/NetworkTopologyVisitor.java index 7c57d063b2cb..e0c39bf7e4a1 100644 --- a/server/src/org/apache/cloudstack/network/topology/NetworkTopologyVisitor.java +++ b/server/src/org/apache/cloudstack/network/topology/NetworkTopologyVisitor.java @@ -30,6 +30,7 @@ import com.cloud.network.rules.NicPlugInOutRules; import com.cloud.network.rules.PasswordToRouterRules; import com.cloud.network.rules.PrivateGatewayRules; +import com.cloud.network.rules.QuaggaRules; import com.cloud.network.rules.SshKeyToRouterRules; import com.cloud.network.rules.StaticNatRules; import com.cloud.network.rules.StaticRoutesRules; @@ -60,4 +61,6 @@ public abstract class NetworkTopologyVisitor { public abstract boolean visit(DhcpSubNetRules dhcpRules) throws ResourceUnavailableException; public abstract boolean visit(NicPlugInOutRules nicPlugInOutRules) throws ResourceUnavailableException; public abstract boolean visit(StaticRoutesRules staticRoutesRules) throws ResourceUnavailableException; + public abstract boolean visit(QuaggaRules quaggaRules) throws ResourceUnavailableException; + } \ No newline at end of file diff --git a/server/test/com/cloud/network/vpc/VpcManagerImplTest.java b/server/test/com/cloud/network/vpc/VpcManagerImplTest.java index fb0776f551af..09721ddaa953 100644 --- a/server/test/com/cloud/network/vpc/VpcManagerImplTest.java +++ b/server/test/com/cloud/network/vpc/VpcManagerImplTest.java @@ -18,21 +18,22 @@ */ package com.cloud.network.vpc; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.DataCenterDao; 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; @@ -41,8 +42,12 @@ import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; import com.cloud.network.vpc.dao.VpcOfferingServiceMapDao; +import com.cloud.utils.net.cidr.BadCIDRException; + import org.powermock.reflect.Whitebox; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.mock; import static org.powermock.api.mockito.PowerMockito.when; @@ -50,14 +55,18 @@ public class VpcManagerImplTest { @Mock VpcOfferingServiceMapDao vpcOffSvcMapDao; + VpcManagerImpl manager; + @Mock + DataCenterDao dcDao; + @Before - public void setup() - { + public void setup() { MockitoAnnotations.initMocks(this); manager = new VpcManagerImpl(); manager._vpcOffSvcMapDao = vpcOffSvcMapDao; + manager._dcDao = dcDao; } @Test @@ -70,7 +79,7 @@ public void getVpcOffSvcProvidersMapForEmptyServiceTest() { Map> map = manager.getVpcOffSvcProvidersMap(vpcOffId); assertNotNull(map); - assertEquals(map.size(),1); + assertEquals(map.size(), 1); } protected Map createFakeCapabilityInputMap() { @@ -94,10 +103,8 @@ public void testIsVpcOfferingForRegionLevelVpc() throws Exception { 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); + 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); @@ -112,8 +119,7 @@ public void testIsVpcOfferingForRegionLevelVpcFalse() throws Exception { serviceCapabilitystList.put("", createFakeCapabilityInputMap()); // Execute - boolean result = Whitebox.invokeMethod(this.manager, "isVpcOfferingForRegionLevelVpc", - serviceCapabilitystList); + boolean result = Whitebox.invokeMethod(this.manager, "isVpcOfferingForRegionLevelVpc", serviceCapabilitystList); // Assert assertEquals("VpcOffering should be created NOT for Region Level Vpc", false, result); @@ -152,8 +158,7 @@ protected Set prepareVpcManagerForCheckingCapabilityPerService 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); + when(this.manager._ntwkModel.getElementImplementingProvider(Provider.VPCVirtualRouter.getName())).thenReturn(nwElement1); final Map> capabilitiesService1 = new HashMap<>(); when(nwElement1.getCapabilities()).thenReturn(capabilitiesService1); capabilities.put(Capability.RegionLevelVpc, ""); @@ -162,4 +167,23 @@ protected Set prepareVpcManagerForCheckingCapabilityPerService return providers; } + + @Test + public void checkValidCidr() throws BadCIDRException { + Long zoneid = 1L; + DataCenterVO dc = new DataCenterVO(zoneid, "TestZone", null, null, null, null, null, null, null, 1L, null, null, null); + dc.setDetails(new HashMap()); + when(dcDao.findById(zoneid)).thenReturn(dc); + manager.updateQuaggaConfig(zoneid, "OSPF", "223", (short)10, (short)40, (short)5, (short)1, "MD5", "sfkjsdkk123", "192.168.100.0/20", true); + } + + @Test(expected=InvalidParameterValueException.class) + public void checkInValidCidr() throws BadCIDRException { + Long zoneid = 1L; + DataCenterVO dc = new DataCenterVO(zoneid, "TestZone", null, null, null, null, null, null, null, 1L, null, null, null); + dc.setDetails(new HashMap()); + when(manager._dcDao.findById(zoneid)).thenReturn(dc); + manager.updateQuaggaConfig(zoneid, "OSPF", "2222", (short)10, (short)40, (short)5, (short)1, "MD5", "sfkjsdkk123", "192.168.100.x", true); + } + } diff --git a/setup/db/db/schema-471to480.sql b/setup/db/db/schema-471to480.sql index b79af7f544d7..8848e47bb353 100644 --- a/setup/db/db/schema-471to480.sql +++ b/setup/db/db/schema-471to480.sql @@ -27,3 +27,4 @@ ALTER TABLE `cloud`.`image_store` MODIFY COLUMN `url` varchar(2048); ALTER TABLE `cloud`.`template_store_ref` MODIFY COLUMN `url` varchar(2048); ALTER TABLE `cloud`.`volume_store_ref` MODIFY COLUMN `url` varchar(2048); ALTER TABLE `cloud`.`volume_store_ref` MODIFY COLUMN `download_url` varchar(2048); + diff --git a/setup/db/db/schema-481to490.sql b/setup/db/db/schema-481to490.sql index b9a8b2fb934f..349d704ef685 100644 --- a/setup/db/db/schema-481to490.sql +++ b/setup/db/db/schema-481to490.sql @@ -413,3 +413,6 @@ VIEW `user_vm_view` AS -- Add cluster.storage.operations.exclude property INSERT INTO `cloud`.`configuration` (`category`, `instance`, `component`, `name`, `description`, `default_value`, `updated`, `scope`, `is_dynamic`) VALUES ('Advanced', 'DEFAULT', 'CapacityManager', 'cluster.storage.operations.exclude', 'Exclude cluster from storage operations', 'false', now(), 'Cluster', '1'); + +ALTER TABLE `cloud`.`physical_network_service_providers` +ADD COLUMN `dynamic_routing_provided` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `networkacl_service_provided`; diff --git a/systemvm/patches/debian/config/etc/quagga/daemons b/systemvm/patches/debian/config/etc/quagga/daemons new file mode 100644 index 000000000000..1f9ca7dbee52 --- /dev/null +++ b/systemvm/patches/debian/config/etc/quagga/daemons @@ -0,0 +1,32 @@ +# This file tells the quagga package which daemons to start. +# +# Entries are in the format: =(yes|no|priority) +# 0, "no" = disabled +# 1, "yes" = highest priority +# 2 .. 10 = lower priorities +# Read /usr/share/doc/quagga/README.Debian for details. +# +# Sample configurations for these daemons can be found in +# /usr/share/doc/quagga/examples/. +# +# ATTENTION: +# +# When activation a daemon at the first time, a config file, even if it is +# empty, has to be present *and* be owned by the user and group "quagga", else +# the daemon will not be started by /etc/init.d/quagga. The permissions should +# be u=rw,g=r,o=. +# When using "vtysh" such a config file is also needed. It should be owned by +# group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too. +# +# The watchquagga daemon is always started. Per default in monitoring-only but +# that can be changed via /etc/quagga/debian.conf. +# +zebra=yes +bgpd=no +ospfd=yes +ospf6d=no +ripd=no +ripngd=no +isisd=no +babeld=no + diff --git a/systemvm/patches/debian/config/etc/quagga/debian.conf b/systemvm/patches/debian/config/etc/quagga/debian.conf new file mode 100644 index 000000000000..55317401a272 --- /dev/null +++ b/systemvm/patches/debian/config/etc/quagga/debian.conf @@ -0,0 +1,24 @@ +# +# If this option is set the /etc/init.d/quagga script automatically loads +# the config via "vtysh -b" when the servers are started. +# Check /etc/pam.d/quagga if you intend to use "vtysh"! +# +vtysh_enable=yes +zebra_options=" --daemon -A 127.0.0.1" +bgpd_options=" --daemon -A 127.0.0.1" +ospfd_options=" --daemon -A 127.0.0.1" +ospf6d_options=" --daemon -A ::1" +ripd_options=" --daemon -A 127.0.0.1" +ripngd_options=" --daemon -A ::1" +isisd_options=" --daemon -A 127.0.0.1" +babeld_options=" --daemon -A 127.0.0.1" +# +# Please note that watchquagga_options is an array and not a string so that +# quotes can be used. +# +# The list of daemons to watch is automatically generated by the init script +# from daemons.conf and appended to the watchquagga_options. +# Example: +# watchquagga_options=("-Adz" "-r" '/sbin/service %s restart' -s '/sbin/service %s start' -k '/sbin/service %s stop') +watchquagga_enable=yes +watchquagga_options=(--daemon) diff --git a/systemvm/patches/debian/config/opt/cloud/bin/configure.py b/systemvm/patches/debian/config/opt/cloud/bin/configure.py index cb6db73cd8e9..6738b86ba180 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/configure.py +++ b/systemvm/patches/debian/config/opt/cloud/bin/configure.py @@ -42,6 +42,7 @@ from cs.CsLoadBalancer import CsLoadBalancer from cs.CsConfig import CsConfig from cs.CsProcess import CsProcess +from cs.CsQuagga import CsQuagga class CsPassword(CsDataBag): @@ -917,6 +918,7 @@ def main(argv): # Track if changes need to be committed to NetFilter iptables_change = False + quagga_rules = False # The "GLOBAL" Configuration object config = CsConfig() @@ -980,6 +982,13 @@ def main(argv): logging.debug("Configuring load balancer") iptables_change = True + if process_file in ["cmd_line.json", "quagga.json"]: + logging.debug("Configuring quagga ") + quagga = CsQuagga("quagga", config) + quagga.process() + iptables_change = True + quagga_rules = True + if process_file in ["cmd_line.json", "monitor_service.json"]: logging.debug("Configuring monitor service") mon = CsMonitor("monitorservice", config) @@ -987,6 +996,10 @@ def main(argv): # If iptable rules have changed, apply them. if iptables_change: + if quagga_rules: + logging.debug("applying quagga iptable rules ..") + quagga.applyFwRules() + acls = CsAcl('networkacl', config) acls.process() diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs/CsHelper.py b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsHelper.py index 9095558a55f2..835c18950f7c 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/cs/CsHelper.py +++ b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsHelper.py @@ -224,4 +224,4 @@ def copy(src, dest): except IOError: logging.Error("Could not copy %s to %s" % (src, dest)) else: - logging.info("Copied %s to %s" % (src, dest)) \ No newline at end of file + logging.info("Copied %s to %s" % (src, dest)) diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs/CsQuagga.py b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsQuagga.py new file mode 100755 index 000000000000..6f0c085c5c29 --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/cs/CsQuagga.py @@ -0,0 +1,85 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import logging +import os.path +import re +from cs.CsDatabag import CsDataBag +from CsProcess import CsProcess +from CsFile import CsFile +import CsHelper + +OSPFD_CONF = "/etc/quagga/ospfd.conf" +OSPFD_CONF_NEW = "/etc/quagga/ospfd.conf.new" +ZEBRA_CONF = "/etc/quagga/zebra.conf" +ZEBRA_CONF_NEW = "/etc/quagga/zebra.conf.new" + + +class CsQuagga(CsDataBag): + """ Manage Load Balancer entries """ + + def process(self): + #create quagga config + logging.debug("CsQuagga: zebra" + str(self.dbag["zebra_config"])) + logging.debug("CsQuagga: ospfd" + str(self.dbag["ospf_config"])) + + zebra_config = self.dbag["zebra_config"].split(',') + ospf_config = self.dbag["ospf_config"].split(',') + changed = False + #process zebra + zebra_conf_new = CsFile(ZEBRA_CONF_NEW) + zebra_conf_new.empty() + for x in zebra_config: + [zebra_conf_new.append(w, -1) for w in x.split('\n')] + + zebra_conf_new.commit() + zebra_conf = CsFile(ZEBRA_CONF) + if not zebra_conf.compare(zebra_conf_new): + CsHelper.copy(ZEBRA_CONF_NEW, ZEBRA_CONF) + changed = True + + #process ospfd + ospfd_conf_new = CsFile(OSPFD_CONF_NEW) + ospfd_conf_new.empty() + for x in ospf_config: + [ospfd_conf_new.append(w, -1) for w in x.split('\n')] + + ospfd_conf_new.commit() + ospfd_conf = CsFile(OSPFD_CONF) + if not ospfd_conf.compare(ospfd_conf_new): + CsHelper.copy(OSPFD_CONF_NEW, OSPFD_CONF) + changed = True + + if changed: + #reset zebra and quagga + proc = CsProcess(['/var/run/quagga.pid']) + logging.debug("CsQuagga: Resetted quagga ") + if not proc.find(): + logging.debug("CsQuagga:: will restart Quagga!") + CsHelper.service("quagga", "restart") + else: + logging.debug("CsQuagga:: will reload Quagga!") + CsHelper.service("quagga", "reload") + + + def applyFwRules(self): + # Firewall rules to allow OSPF LSA broadcasts + firewall = self.config.get_fw() + logging.debug("CsQuagga: Applying iptable rules for quagga ospf LSA adv:") + firewall.append(["", "", "-A INPUT -p 89 -j ACCEPT -m comment --comment 'quagga fw rule'"]) + firewall.append(["", "", "-I INPUT 2 -d 224.0.0.0/24 -j ACCEPT -m comment --comment 'quagga fw rule'"]) + + diff --git a/systemvm/patches/debian/config/opt/cloud/bin/cs_quagga.py b/systemvm/patches/debian/config/opt/cloud/bin/cs_quagga.py new file mode 100755 index 000000000000..56518a17133c --- /dev/null +++ b/systemvm/patches/debian/config/opt/cloud/bin/cs_quagga.py @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from pprint import pprint +import copy + + +def merge(dbag, data): + """ Simply return the data that has the full configuration """ + if "ospf_config" not in data: + print "[WARN] cs_quagga: no ospf_config in data " + return data + return data diff --git a/systemvm/patches/debian/config/opt/cloud/bin/merge.py b/systemvm/patches/debian/config/opt/cloud/bin/merge.py index 374cf2ccb4f8..1a3587dd9cd2 100755 --- a/systemvm/patches/debian/config/opt/cloud/bin/merge.py +++ b/systemvm/patches/debian/config/opt/cloud/bin/merge.py @@ -35,6 +35,7 @@ import cs_remoteaccessvpn import cs_vpnusers import cs_staticroutes +import cs_quagga from pprint import pprint @@ -129,6 +130,8 @@ def process(self): dbag = self.process_vpnusers(self.db.getDataBag()) elif self.qFile.type == 'staticroutes': dbag = self.process_staticroutes(self.db.getDataBag()) + elif self.qFile.type == 'quagga': + dbag = self.process_quagga(self.db.getDataBag()) else: logging.error("Error I do not know what to do with file of type %s", self.qFile.type) return @@ -178,6 +181,9 @@ def process_monitorservice(self, dbag): def process_staticroutes(self, dbag): return cs_staticroutes.merge(dbag, self.qFile.data) + def process_quagga(self, dbag): + return cs_quagga.merge(dbag, self.qFile.data) + def processVMpassword(self, dbag): return cs_vmp.merge(dbag, self.qFile.data) diff --git a/test/integration/component/test_ospf.py b/test/integration/component/test_ospf.py new file mode 100644 index 000000000000..ae864307ee40 --- /dev/null +++ b/test/integration/component/test_ospf.py @@ -0,0 +1,477 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" BVT tests for Service offerings""" + +# Import Local Modules +from marvin.codes import FAILED +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from nose.plugins.attrib import attr +from marvin.sshClient import SshClient + + +_multiprocess_shared_ = True + + +class TestCreateDynmaicServiceOffering(cloudstackTestCase): + + def setUp(self): + + self.logger = logging.getLogger('TestOSPF') + self.stream_handler = logging.StreamHandler() + self.logger.setLevel(logging.DEBUG) + self.logger.addHandler(self.stream_handler) + + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + print str(self) + self.dbclient = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.cleanup = [] + self.services = { + "batman_vpc": { + "name": "Batman VPC", + "displaytext": "Marvin Batman VPC", + "netmask": "255.255.252.0" + }, + "superman_vpc": { + "name": "Superman VPC", + "displaytext": "Marvin Superman VPC", + "netmask": "255.255.252.0" + }, + "vpc_offering": { + "name": 'Cosmic VPC off', + "displaytext": 'Cosmic VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,VPCDynamicRouting', + }, + "network_offering": { + "name": 'Milkyway VPC Network offering', + "displaytext": 'Milkyway VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL,VPCDynamicRouting', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "VPCDynamicRouting": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "batman_network_tier1": { + "name": "Batman Network Tier 1", + "displaytext": "Batman Network Tier 1", + "netmask": '255.255.255.0' + }, + "superman_network_tier1": { + "name": "Superman Network Tier 1", + "displaytext": "Superman Network Tier 1", + "netmask": '255.255.255.0' + }, + "service_offering": { + "name": "Ultra Tiny Instance", + "displaytext": "Ultra Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "batman_vm_1": { + "displayname": "Batman-VPC-VM-001", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "superman_vm_1": { + "displayname": "Superman-VPC-VM-001", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "template_name" : "macchinina-xen", + "ostype": 'Other Linux (64-bit)', + "sleep": 60, + "timeout": 10, + } + + + def tearDown(self): + try: + # Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.logger.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.logger.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + + def validate_network(self, network, vpcid): + """Validates the VPC offering""" + + self.logger.debug( + "Verifying list network response to check if network created?") + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + nw = networks[0] + + self.assertEqual( + nw.networkofferingid, + self.network_offering.id, + "Network should be created from network offering - %s" % + self.network_offering.id + ) + self.assertEqual( + nw.vpcid, + vpcid, + "Network should be created in VPC: %s" % vpcid + ) + + return + + def validate_vpc_network(self, network): + """Validates the VPC network""" + + self.logger.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + self.logger.debug("VPC network created successfully - %s" % network.name) + return + + @attr( + tags=[ + "advanced", + "advancedns", + "smoke", + "basic", + "eip", + "sg"], + required_hardware="false") + def test_01_dynamic_routing_using_ospf(self): + cmd = vpcOSPFConfigUpdate.vpcOSPFConfigUpdateCmd() + cmd.zoneid = self.zone.id + cmd.superCIDR = "200.100.0.0/16" + cmd.enabled = "true" + response = self.apiclient.vpcOSPFConfigUpdate(cmd) + self.logger.debug("Response ospfEnabled: %s" % response.enabled) + self.logger.debug("Response ospfSuperCIDR: %s" % response.superCIDR) + + cmd = vpcOSPFConfig.vpcOSPFConfigCmd() + cmd.zoneid = self.zone.id + response = self.apiclient.vpcOSPFConfig(cmd) + self.logger.debug("Response ospf Enabled: %s" % response.enabled) + self.logger.debug("Response ospfSuperCIDR: %s" % response.superCIDR) + + cmd.zoneid = self.zone.id + + + self.assertEqual( + response.enabled, True + ) + + + self.assertEqual( + response.superCIDR, "200.100.0.0/16" + ) + + self.vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + self.vpc_off.update(self.apiclient, state='Enabled') + + self.validate_vpc_offering(self.vpc_off) + self.logger.debug("VPC Offering id = %s" % self.vpc_off.id) + + """ vpc_super_netmask=255.255.252.0 """ + self.batman_vpc = VPC.create( + self.apiclient, + self.services["batman_vpc"], + netmask="255.255.252.0", + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id + ) + + self.validate_vpc_network(self.batman_vpc) + self.logger.debug("VPC batman_vpc id = %s" % self.batman_vpc.id) + + self.superman_vpc = VPC.create( + self.apiclient, + self.services["superman_vpc"], + netmask="255.255.252.0", + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id + ) + + self.validate_vpc_network(self.superman_vpc) + self.logger.debug("VPC superman_vpc id = %s" % self.superman_vpc.id) + + """ -----------------------------------------------""" + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self.logger.debug("Dynamic Network offering id = %s" % self.network_offering.id) + + """ --------------------BATMAN---------------------------""" + # 2) Create ACL + self.batman_aclgroup = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl", vpcid=self.batman_vpc.id) + self.assertIsNotNone(self.batman_aclgroup, "Failed to create NetworkACL list") + self.logger.debug("Created a network ACL list %s" % self.batman_aclgroup.name) + + # 3) Create ACL Items + self.batman_aclitem1 = NetworkACL.create(apiclient=self.apiclient, services={}, + protocol="ICMP", action="Allow", aclid=self.batman_aclgroup.id, cidrlist=["0.0.0.0/0"]) + self.assertIsNotNone(self.batman_aclitem1, "Network failed to aclItem") + self.logger.debug("Added a network ACL %s to ACL list %s" % (self.batman_aclitem1.id, self.batman_aclgroup.name)) + + self.batman_aclitem2 = NetworkACL.create( self.apiclient, aclid=self.batman_aclgroup.id, services=self.services["natrule"], + traffictype='Ingress' ) + + self.assertIsNotNone(self.batman_aclitem2, "Network failed to aclItem") + self.logger.debug("Added a network ACL %s to ACL list %s" % (self.batman_aclitem2.id, self.batman_aclgroup.name)) + + """ create tiers for batman vpc """ + """ + 32 vpc_tier1_name=batman-tier-1 + 33 vpc_tier1_display_name='"Batman Tier 1"' + 34 vpc_tier1_gateway=200.100.1.1 + 35 vpc_tier1_netmask=255.255.255.0 + + """ + self.batman_network_tier1 = Network.create( + self.apiclient, + self.services["batman_network_tier1"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + aclid=self.batman_aclgroup.id, + gateway='200.100.1.1', + vpcid=self.batman_vpc.id + ) + self.validate_network(self.batman_network_tier1, self.batman_vpc.id) + self.logger.debug("Created batman_network_tier1 with ID: %s" % self.batman_network_tier1.id) + + + """ ----------------------SUPERMAN-------------------------""" + # 2) Create ACL + self.superman_aclgroup = NetworkACLList.create(apiclient=self.apiclient, services={}, name="acl", description="acl", vpcid=self.superman_vpc.id) + self.assertIsNotNone(self.superman_aclgroup, "Failed to create NetworkACL list") + self.logger.debug("Created a network ACL list %s" % self.superman_aclgroup.name) + + # 3) Create ACL Item + self.superman_aclitem1 = NetworkACL.create(apiclient=self.apiclient, services={}, + protocol="ICMP", action="Allow", aclid=self.superman_aclgroup.id, cidrlist=["0.0.0.0/0"]) + self.assertIsNotNone(self.superman_aclitem1, "Network failed to aclItem") + self.logger.debug("Added a network ACL %s to ACL list %s" % (self.superman_aclitem1.id, self.superman_aclgroup.name)) + + + self.superman_aclitem2 = NetworkACL.create( self.apiclient, aclid=self.superman_aclgroup.id, services=self.services["natrule"], + traffictype='Ingress' ) + self.assertIsNotNone(self.superman_aclitem2, "Network failed to aclItem") + self.logger.debug("Added a network ACL %s to ACL list %s" % (self.superman_aclitem2.id, self.superman_aclgroup.name)) + + """ + 57 vpc2_tier1_name=robin-tier-1 + 58 vpc2_tier1_display_name='"Robin Tier 1"' + 59 vpc2_tier1_gateway=200.100.5.1 + 60 vpc2_tier1_netmask=255.255.255.0 + 61 + """ + + #create tiers + self.superman_network_tier1 = Network.create( + self.apiclient, + self.services["superman_network_tier1"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + aclid=self.superman_aclgroup.id, + gateway='200.100.5.1', + vpcid=self.superman_vpc.id + ) + self.validate_network(self.superman_network_tier1, self.superman_vpc.id) + self.logger.debug("Created superman_network_tier1 with ID: %s" % self.superman_network_tier1.id) + + """---------------------------------------------------------""" + + #create VMs + self.template = get_template( + self.apiclient, + self.zone.id, + template_name = self.services["template_name"] + ) + + self.logger.debug("Using template %s " % self.template.id) + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"] + ) + self.logger.debug("Using service offering %s " % self.service_offering.id) + + self.services["batman_vm_1"]["zoneid"] = self.zone.id + self.services["batman_vm_1"]["template"] = self.template.id + self.batman_vm_1 = VirtualMachine.create( + self.apiclient, + self.services["batman_vm_1"], + serviceofferingid=self.service_offering.id, + ipaddress="200.100.1.101", + networkids=self.batman_network_tier1.id + ) + self.logger.debug("Deployed VM %s in network: %s" % (self.batman_vm_1.id, self.batman_network_tier1.id)) + + self.services["superman_vm_1"]["zoneid"] = self.zone.id + self.services["superman_vm_1"]["template"] = self.template.id + self.superman_vm_1 = VirtualMachine.create( + self.apiclient, + self.services["superman_vm_1"], + serviceofferingid=self.service_offering.id, + ipaddress="200.100.5.101", + networkids=self.superman_network_tier1.id + ) + self.logger.debug("Deployed VM %s in network: %s" % (self.superman_vm_1.id, self.superman_network_tier1.id)) + + """ check ping from VR of batman to vm of superman""" + self.batman_vm_pip = PublicIPAddress.create( + self.apiclient, + zoneid=self.zone.id, + networkid=self.batman_network_tier1.id, + vpcid=self.batman_vpc.id + ) + self.logger.debug("Acquired public ip for batman vm %s" % self.batman_vm_pip.ipaddress.ipaddress ) + + StaticNATRule.enable( + self.apiclient, + ipaddressid= self.batman_vm_pip.ipaddress.id, + virtualmachineid=self.batman_vm_1.id, + networkid=self.batman_network_tier1.id + ) + + self.logger.debug("Static Nat enabled on ip %s" % self.batman_vm_pip.ipaddress.ipaddress ) + + ssh = SshClient(self.batman_vm_pip.ipaddress.ipaddress, 22, "root", "password") + res = ssh.execute("ping -c 1 200.100.5.101") + print res + result = str(res) + self.assertEqual( + result.count("0% packet loss"), + 1, + "Ping to other VM @ 200.100.5.101 succeeded" + ) + res = ssh.execute("ping -c 1 200.100.1.101") + print res + result = str(res) + self.assertEqual( + result.count("0% packet loss"), + 1, + "Ping to other VM @ 200.100.5.101 succeeded" + ) + + self.logger.debug("Test successful clearing VMs") + self.cleanup.append(self.batman_vm_1) + self.cleanup.append(self.superman_vm_1) + self.cleanup.append(self.service_offering) + self.logger.debug("Test successful clearing VPC Tiers") + self.cleanup.append(self.superman_network_tier1) + self.cleanup.append(self.batman_network_tier1) + self.cleanup.append(self.network_offering) + self.logger.debug("Test successful clearing VPCs") + self.cleanup.append(self.superman_vpc) + self.cleanup.append(self.batman_vpc) + self.cleanup.append(self.vpc_off) + + return + + \ No newline at end of file diff --git a/test/integration/smoke/test_ospf_zone_config.py b/test/integration/smoke/test_ospf_zone_config.py new file mode 100644 index 000000000000..5568490a124e --- /dev/null +++ b/test/integration/smoke/test_ospf_zone_config.py @@ -0,0 +1,165 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" Test cases for checking quagga API +""" + +# Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.lib.utils import * +from marvin.lib.base import * +from marvin.lib.common import * +from marvin.lib.utils import (random_gen) +from nose.plugins.attrib import attr + +# Import System modules +import time + +class TestQuagga(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + # Create Account + testClient = super(TestQuagga, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + + # Get Zone, Domain + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, cls.testClient.getZoneForTests()) + + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.hypervisor = self.testClient.getHypervisorInfo() + self.dbclient = self.testClient.getDbConnection() + self.services = self.testClient.getParsedTestDataConfig() + self.zone = get_zone(self.apiclient, self.testClient.getZoneForTests()) + self.pod = get_pod(self.apiclient, self.zone.id) + self.cleanup = [] + return + + def tearDown(self): + try: + # Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + # Check vpcQuaggaConfigCmd positive test case + #VPCQuaggaConfigUpdateCmd [zoneid=1, quaggaProtocol=null, ospfArea=null, quaggaHelloInterval=null, quaggaDeadInterval=null, quaggaRetransmitInterval=null, quaggaTransitDelay=null, quaggaAuthentication=null, quaggaPassword=junk, ospfSuperCIDR=null, quaggaEnabled=null] + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_01_quaggaConfig(self): + + cmd = vpcQuaggaConfig.vpcQuaggaConfigCmd() + cmd.zoneid = self.zone.id + response = self.apiclient.vpcQuaggaConfig(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + + cmd = vpcQuaggaConfigUpdate.vpcQuaggaConfigUpdateCmd() + cmd.zoneid = self.zone.id + cmd.ospfSuperCIDR = "200.100.0.0/18,216.100.0.0/20" + cmd.quaggaEnabled = "true" + cmd.quaggaPassword = "6P33lsadEbmiJ7ZN7gK8vylOY2dTza3rAuY8UFboH7I=:Xb1G4VhzBkSXmTa8vDqExQQo8PiIUUSNtpxmdOkX1z8=" + response = self.apiclient.vpcQuaggaConfigUpdate(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + + cmd = vpcQuaggaConfig.vpcQuaggaConfigCmd() + cmd.zoneid = self.zone.id + response = self.apiclient.vpcQuaggaConfig(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + cmd.zoneid = self.zone.id + + + self.assertEqual( + response.quaggaEnabled, "true" + ) + + + self.assertEqual( + response.quaggaPassword, "6P33lsadEbmiJ7ZN7gK8vylOY2dTza3rAuY8UFboH7I=:Xb1G4VhzBkSXmTa8vDqExQQo8PiIUUSNtpxmdOkX1z8=" + ) + + self.assertEqual( + response.ospfSuperCIDR, "200.100.0.0/18,216.100.0.0/20" + ) + + return + + + # Check vpcQuaggaConfigCmd positive test case + #VPCQuaggaConfigUpdateCmd [zoneid=1, quaggaProtocol=null, ospfArea=null, quaggaHelloInterval=null, quaggaDeadInterval=null, quaggaRetransmitInterval=null, quaggaTransitDelay=null, quaggaAuthentication=null, quaggaPassword=junk, ospfSuperCIDR=null, quaggaEnabled=null] + @attr(tags=["smoke", "advanced"], required_hardware="false") + def test_02_quaggaConfig(self): + + cmd = vpcQuaggaConfig.vpcQuaggaConfigCmd() + cmd.zoneid = self.zone.id + response = self.apiclient.vpcQuaggaConfig(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + + cmd = vpcQuaggaConfigUpdate.vpcQuaggaConfigUpdateCmd() + cmd.zoneid = self.zone.id + cmd.ospfSuperCIDR = "200.100.0.0/18,216.100.0.0/20" + cmd.quaggaEnabled = "false" + cmd.quaggaPassword = "6P33lsadEbmiJ7ZN7gK8vylOY2dTza3rAuY8UFboH7I=:Xb1G4VhzBkSXmTa8vDqExQQo8PiIUUSNtpxmdOkX1z8=" + response = self.apiclient.vpcQuaggaConfigUpdate(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + + cmd = vpcQuaggaConfig.vpcQuaggaConfigCmd() + cmd.zoneid = self.zone.id + response = self.apiclient.vpcQuaggaConfig(cmd) + self.debug("Response quaggaEnabled: %s" % response.quaggaEnabled) + self.debug("Response quaggaPassword: %s" % response.quaggaPassword) + self.debug("Response ospfSuperCIDR: %s" % response.ospfSuperCIDR) + + cmd.zoneid = self.zone.id + + + self.assertEqual( + response.quaggaEnabled, "false" + ) + + + self.assertEqual( + response.quaggaPassword, "6P33lsadEbmiJ7ZN7gK8vylOY2dTza3rAuY8UFboH7I=:Xb1G4VhzBkSXmTa8vDqExQQo8PiIUUSNtpxmdOkX1z8=" + ) + + self.assertEqual( + response.ospfSuperCIDR, "200.100.0.0/18,216.100.0.0/20" + ) + + return + + \ No newline at end of file diff --git a/tools/apidoc/gen_toc.py b/tools/apidoc/gen_toc.py index 6974fd74231a..d72628d8ac28 100644 --- a/tools/apidoc/gen_toc.py +++ b/tools/apidoc/gen_toc.py @@ -137,6 +137,7 @@ 'Lun': 'Storage', 'Pool': 'Pool', 'VPC': 'VPC', + 'OSPF': 'OSPF', 'PrivateGateway': 'VPC', 'Simulator': 'simulator', 'StaticRoute': 'VPC', @@ -144,7 +145,7 @@ 'NiciraNvpDevice': 'Nicira NVP', 'BrocadeVcsDevice': 'Brocade VCS', 'BigSwitchBcfDevice': 'BigSwitch BCF', - 'NuageVsp': 'Nuage VSP', + 'NuageVsp': 'Nuage VSP', 'AutoScale': 'AutoScale', 'Counter': 'AutoScale', 'Condition': 'AutoScale', @@ -155,7 +156,7 @@ 'removeIpFromNic': 'Nic', 'updateVmNicIp': 'Nic', 'listNics':'Nic', - 'AffinityGroup': 'Affinity Group', + 'AffinityGroup': 'Affinity Group', 'addImageStore': 'Image Store', 'listImageStore': 'Image Store', 'deleteImageStore': 'Image Store', @@ -163,8 +164,8 @@ 'deleteSecondaryStagingStore': 'Image Store', 'listSecondaryStagingStores': 'Image Store', 'InternalLoadBalancer': 'Internal LB', - 'DeploymentPlanners': 'Configuration', - 'ObjectStore': 'Image Store', + 'DeploymentPlanners': 'Configuration', + 'ObjectStore': 'Image Store', 'PortableIp': 'Portable IP', 'dedicateHost': 'Dedicate Resources', 'releaseDedicatedHost': 'Dedicate Resources', @@ -302,9 +303,9 @@ def write_java(out): public class XmlToHtmlConverterData { - Set rootAdminCommandNames = new HashSet(); - Set domainAdminCommandNames = new HashSet(); - Set userCommandNames = new HashSet(); + Set rootAdminCommandNames = new HashSet(); + Set domainAdminCommandNames = new HashSet(); + Set userCommandNames = new HashSet(); ''') f.write(java_for_user(REGULAR_USER) + "\n"); diff --git a/tools/appliance/Gemfile b/tools/appliance/Gemfile index 386601c192fd..b74d3388837a 100644 --- a/tools/appliance/Gemfile +++ b/tools/appliance/Gemfile @@ -19,4 +19,6 @@ source 'https://rubygems.org' # gem 'veewee', :git => 'https://github.com/jedi4ever/veewee.git' gem 'veewee', '~> 0.4.5.1' gem 'em-winrm' +gem 'net-scp' gem 'sys-proctable' +gem 'net-ssh', '~>2.9.2' # v3 requires Ruby 2.0 diff --git a/tools/appliance/README.md b/tools/appliance/README.md index 82b048810907..7f3fc2d85a73 100644 --- a/tools/appliance/README.md +++ b/tools/appliance/README.md @@ -71,7 +71,7 @@ bundle_args="--path vendor/bundle" Just run build.sh, it will export archived appliances for KVM, XenServer, VMWare and HyperV in `dist`: - bash build.sh [systemvmtemplate|systemvmtemplate64] + bash build.sh systemvmtemplate # Building SystemVM template appliance manually diff --git a/tools/appliance/definitions/systemvmtemplate/install_systemvm_packages.sh b/tools/appliance/definitions/systemvmtemplate/install_systemvm_packages.sh index c8b7b91e7b4d..f8501c32194b 100644 --- a/tools/appliance/definitions/systemvmtemplate/install_systemvm_packages.sh +++ b/tools/appliance/definitions/systemvmtemplate/install_systemvm_packages.sh @@ -71,7 +71,7 @@ function install_packages() { iptables-persistent \ libtcnative-1 libssl-dev libapr1-dev \ python-flask \ - haproxy \ + haproxy quagga \ radvd \ sharutils diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp index b97141ca3b83..8448070641b0 100644 --- a/ui/dictionary.jsp +++ b/ui/dictionary.jsp @@ -1125,5 +1125,22 @@ dictionary = { 'label.root.disk.offering': '', 'message.configure.firewall.rules.allow.traffic': '', 'message.configure.firewall.rules.block.traffic': '', +'label.vpc.dynamicallyrouted': '', +'label.vpc.dynamicallyrouted.enabled': '', +'label.vpc.dynamicallyrouted.protocol': '', +'label.vpc.dynamicallyrouted.ospfarea': '', +'label.vpc.dynamicallyrouted.hellointerval': '', +'label.vpc.dynamicallyrouted.deadinterval': '', +'label.vpc.dynamicallyrouted.retransmitinterval': '', +'label.vpc.dynamicallyrouted.transitdelay': '', +'label.vpc.dynamicallyrouted.authentication': '', +'label.vpc.dynamicallyrouted.password': '', +'label.vpc.dynamicallyrouted.supercidr': '', +'label.vpc.dynamicallyrouted.configitemname': '', +'label.vpc.dynamicallyrouted.configitemvalue': '', +'label.vpc.dynamicrouting.service': '', +'label.vpc.dynamicrouting.add': '', +'label.vpc.dynamicrouting.ipv4.netmask': '', + }; diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 14b0e156ffb3..7497b8379e38 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -3611,6 +3611,10 @@ {name: 'NuageVsp'}, {name: 'BigSwitchBcf'}] }); + networkServiceObjs.push({ + name: 'VPCDynamicRouting', + provider: [{name: 'VpcVirtualRouter'}] + }); networkServiceObjs.push({ name: 'PortForwarding', provider: [{name: 'VpcVirtualRouter'}] @@ -3660,8 +3664,8 @@ case 'SourceNat': serviceDisplayName = _l('label.source.nat'); break; - case 'StaticNat': - serviceDisplayName = _l('label.static.nat'); + case 'VPCDynamicRouting': + serviceDisplayName = _l('label.vpc.dynamicrouting.service'); break; case 'PortForwarding': serviceDisplayName = _l('label.port.forwarding'); diff --git a/ui/scripts/docs.js b/ui/scripts/docs.js index 11622f1f7dec..6d87aabcb46f 100755 --- a/ui/scripts/docs.js +++ b/ui/scripts/docs.js @@ -1040,6 +1040,10 @@ cloudStack.docs = { desc: 'CIDR range for all the tiers within a VPC. Each tier\'s CIDR must be within the Super CIDR.', externalLink: '' }, + helpVPCNetmask: { + desc: 'IpV4 Netmask that will carve out a cidr for this dynamic VPC from Zone Cidr', + externalLink: '' + }, helpVPCDomain: { desc: 'If you want to assign a special domain name to this VPC\'s guest VM network, specify the DNS suffix', externalLink: '' diff --git a/ui/scripts/network.js b/ui/scripts/network.js index 704f39913950..7f90e0be517d 100755 --- a/ui/scripts/network.js +++ b/ui/scripts/network.js @@ -5401,6 +5401,7 @@ }); }, actions: { + add: { label: 'label.add.vpc', messages: { @@ -5566,7 +5567,10 @@ action: { custom: cloudStack.uiCustom.vpc(cloudStack.vpc) } - } + }, + addDynamicVpcDialog: $.extend({}, addDynamicVpcDialog.def, { + isHeader: true + }) }, detailView: { @@ -5784,6 +5788,9 @@ return "No"; } }, + dynamicallyroutedvpcrouter: { + label: 'label.vpc.dynamicallyrouted' + }, redundantvpcrouter: { label: 'label.redundant.vpc', converter: function(booleanValue) { @@ -5824,6 +5831,13 @@ async: true, success: function(json) { var item = json.listvpcsresponse.vpc[0]; + item.dynamicallyroutedvpcrouter = "No"; + for (var i = 0; i < item.service.length; i += 1 ){ + if (_l('label.vpc.dynamicrouting.service') == item.service[i].name){ + item.dynamicallyroutedvpcrouter = "Yes"; + break; + } + } args.response.success({ data: item }); diff --git a/ui/scripts/sharedFunctions.js b/ui/scripts/sharedFunctions.js index 7b4b26a0ca2a..dcb2b0c3272e 100644 --- a/ui/scripts/sharedFunctions.js +++ b/ui/scripts/sharedFunctions.js @@ -819,6 +819,179 @@ var addGuestNetworkDialog = { } + +//Add Guest Network in Advanced zone (for root-admin only) +var addDynamicVpcDialog = { + zoneObjs: [], + physicalNetworkObjs: [], + networkOfferingObjs: [], + def: { + label: 'label.vpc.dynamicrouting.add', + + messages: { + notification: function(args) { + return 'label.vpc.dynamicrouting.add'; + } + }, + createForm: { + title: 'label.add.vpc', + messages: { + notification: function(args) { + return 'label.add.vpc'; + } + }, + fields: { + name: { + label: 'label.name', + docID: 'helpVPCName', + validation: { + required: true + } + }, + displaytext: { + label: 'label.description', + docID: 'helpVPCDescription', + validation: { + required: true + } + }, + zoneid: { + label: 'label.zone', + docID: 'helpVPCZone', + validation: { + required: true + }, + select: function(args) { + var data = {}; + $.ajax({ + url: createURL('listZones'), + data: data, + success: function(json) { + var zones = json.listzonesresponse.zone ? json.listzonesresponse.zone : []; + var advZones = $.grep(zones, function(zone) { + return zone.networktype == 'Advanced' && !zone.securitygroupsenabled; + }); + args.response.success({ + data: $.map(advZones, function(zone) { + return { + id: zone.id, + description: zone.name + }; + }) + }); + } + }); + } + }, + netmask: { + label: 'label.vpc.dynamicrouting.ipv4.netmask', + docID: 'helpVPCNetmask' + }, + networkdomain: { + docID: 'helpVPCDomain', + label: 'label.DNS.domain.for.guest.networks' + //format: FQDN + }, + publicLoadBalancerProvider: { + label: 'label.public.load.balancer.provider', + select: function(args) { + var items = []; + items.push({ + id: 'VpcVirtualRouter', + description: 'VpcVirtualRouter' + }); + items.push({ + id: 'Netscaler', + description: 'Netscaler' + }); + args.response.success({ + data: items + }); + } + }, + vpcoffering: { + label: 'label.vpc.offering', + validation: { + required: true + }, + + select: function(args) { + var data = {}; + $.ajax({ + url: createURL('listVPCOfferings&supportedservices=VPCDynamicRouting'), + data: {}, + success: function(json) { + var offerings = json.listvpcofferingsresponse.vpcoffering ? json.listvpcofferingsresponse.vpcoffering : []; + var filteredofferings = $.grep(offerings, function(offering) { + return offering.state == 'Enabled'; + }); + args.response.success({ + data: $.map(filteredofferings, function(vpco) { + return { + id: vpco.id, + description: vpco.name + }; + }) + }); + } + }); + } + } + } + }, + + action: function(args) { + var vpcOfferingName = args.data.vpcoffering + var dataObj = { + name: args.data.name, + displaytext: args.data.displaytext, + zoneid: args.data.zoneid, + cidr: args.data.cidr, + vpcofferingid: args.data.vpcoffering, + netmask: args.data.netmask + }; + + if (args.data.networkdomain != null && args.data.networkdomain.length > 0) + $.extend(dataObj, { + networkdomain: args.data.networkdomain + }); + + $.ajax({ + url: createURL("createVPC"), + dataType: "json", + data: dataObj, + async: true, + success: function(json) { + var jid = json.createvpcresponse.jobid; + args.response.success({ + _custom: { + jobId: jid, + getUpdatedItem: function(json) { + return json.queryasyncjobresultresponse.jobresult.vpc; + } + } + }); + }, + error: function(data) { + args.response.error(parseXMLHttpResponse(data)); + } + }); + + }, + notification: { + poll: function(args) { + args.complete(); + } + } + } +} + + + + + + + function isLdapEnabled() { var result; $.ajax({ diff --git a/ui/scripts/system.js b/ui/scripts/system.js index 4cb8094add32..f0c77d4ef9a7 100644 --- a/ui/scripts/system.js +++ b/ui/scripts/system.js @@ -8893,6 +8893,100 @@ } } }, + + // START OSPF ZONE + + + + vpcRouted: { + type: 'select', + title: 'label.vpc.dynamicallyrouted', + listView: { + label: 'label.vpc.dynamicallyrouted', + disableInfiniteScrolling: true, + actions: { + edit: { + label: 'label.change.value', + action: function(args) { + if (isAdmin()) { + $.ajax({ + url: createURL("vpcOSPFConfigUpdate&zoneid=" + args.context.physicalResources[0].id + "&" + args.data.jsonObj.configName + "=" + args.data.configValue), + type: "GET", + success: function(json) { + var items = { + name: args.data.jsonObj.configName, + value : args.data.configValue + }; + args.response.success({ + data: items + }); + }, + error: function(data) { + cloudStack.dialog.notice({ + message: parseXMLHttpResponse(data) + }); + } + }); + + } // if is ADMIN + } // end action + }//edits + },//actions + + fields: { + configDisplayName: { + label: 'label.vpc.dynamicallyrouted.configitemname', + id: true + }, + configValue: { + label: 'label.vpc.dynamicallyrouted.configitemvalue', + editable: true + } + }, + dataProvider: function(args) { + var data = {}; + if (args.filterBy.search.value) { + data.startdate = args.filterBy.search.value; + } + $.ajax({ + url: createURL("vpcOSPFConfig&zoneid=" + args.context.physicalResources[0].id), + data: data, + dataType: "json", + async: true, + success: function(json) { + var jsonObj = json.vpcospfconfigresponse.ospfconfig; + var items = new Array(); + //console.log(jsonObj); + if (jsonObj.quaggaEnabled == null){ + jsonObj.quaggaEnabled = false; + } + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.enabled'), configName: 'enabled', configValue: jsonObj.enabled ? "true" : "false" }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.protocol'), configName: 'protocol', configValue: jsonObj.protocol == null ? "--" : jsonObj.protocol }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.ospfarea'), configName: 'area', configValue: jsonObj.area == null ? "--" : jsonObj.area }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.hellointerval'), configName: 'hellointerval', configValue: jsonObj.helloInterval == null ? "--" : jsonObj.helloInterval }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.deadinterval'), configName: 'deadinterval', configValue: jsonObj.deadInterval == null ? "--" : jsonObj.deadInterval }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.retransmitinterval'), configName: 'retransmitinterval', configValue: jsonObj.retransmitInterval == null ? "--" : jsonObj.retransmitInterval }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.transitdelay'), configName: 'transitdelay', configValue: jsonObj.transitDelay == null ? "--" : jsonObj.transitDelay }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.authentication'), configName: 'authentication', configValue: jsonObj.authentication == null ? "--" : jsonObj.authentication }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.password'), configName: 'password', configValue: jsonObj.password == null ? "--" : jsonObj.password }); + items.push({ configDisplayName: _l('label.vpc.dynamicallyrouted.supercidr'), configName: 'supercidr', configValue: jsonObj.superCIDR == null ? "--" : jsonObj.superCIDR }); + + args.response.success({ + data: items + }); + }, + error: function(data) { + cloudStack.dialog.notice({ + message: parseXMLHttpResponse(data) + }); + } + }); + } + } + }, + + + // END QUAGGA ZONE // Granular settings for zone settings: { diff --git a/utils/src/main/java/com/cloud/utils/Nullable.java b/utils/src/main/java/com/cloud/utils/Nullable.java new file mode 100644 index 000000000000..2598124cb06a --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/Nullable.java @@ -0,0 +1,25 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + + +package com.cloud.utils; + +public interface Nullable { + boolean isNull(); +} \ No newline at end of file diff --git a/utils/src/main/java/com/cloud/utils/net/NetUtils.java b/utils/src/main/java/com/cloud/utils/net/NetUtils.java index a73813c28d84..7d5fa9c359c4 100644 --- a/utils/src/main/java/com/cloud/utils/net/NetUtils.java +++ b/utils/src/main/java/com/cloud/utils/net/NetUtils.java @@ -30,6 +30,7 @@ import java.net.URI; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Formatter; import java.util.List; import java.util.Random; @@ -40,6 +41,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.commons.net.util.SubnetUtils; @@ -49,6 +51,9 @@ import com.cloud.utils.IteratorUtil; import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; +import com.cloud.utils.net.cidr.CIDRFactory; import com.cloud.utils.script.Script; import com.googlecode.ipv6.IPv6Address; import com.googlecode.ipv6.IPv6AddressRange; @@ -479,9 +484,7 @@ public static String byte2Mac(final byte[] m) { public static String long2Mac(final long macAddress) { final StringBuilder result = new StringBuilder(17); try (Formatter formatter = new Formatter(result)) { - formatter.format("%02x:%02x:%02x:%02x:%02x:%02x", - macAddress >> 40 & 0xff, macAddress >> 32 & 0xff, - macAddress >> 24 & 0xff, macAddress >> 16 & 0xff, + formatter.format("%02x:%02x:%02x:%02x:%02x:%02x", macAddress >> 40 & 0xff, macAddress >> 32 & 0xff, macAddress >> 24 & 0xff, macAddress >> 16 & 0xff, macAddress >> 8 & 0xff, macAddress & 0xff); } return result.toString(); @@ -516,7 +519,7 @@ public static boolean isSiteLocalAddress(final String ipAddress) { return false; } else { final InetAddress ip = parseIpAddress(ipAddress); - if(ip != null) { + if (ip != null) { return ip.isSiteLocalAddress(); } return false; @@ -541,7 +544,7 @@ public static boolean isValidIp(final String ip) { public static boolean is31PrefixCidr(final String cidr) { final boolean isValidCird = isValidCIDR(cidr); - if (isValidCird){ + if (isValidCird) { final String[] cidrPair = cidr.split("\\/"); final String cidrSize = cidrPair[1]; @@ -888,7 +891,7 @@ public static Long[] cidrToLong(final String cidr) { } final String[] cidrPair = cidr.split("\\/"); if (cidrPair.length != 2) { - throw new CloudRuntimeException("cidr is not formatted correctly: "+ cidr); + throw new CloudRuntimeException("cidr is not formatted correctly: " + cidr); } final String cidrAddress = cidrPair[0]; final String cidrSize = cidrPair[1]; @@ -903,6 +906,10 @@ public static Long[] cidrToLong(final String cidr) { } + public static Long[] cidrToLong(final CIDR ocidr) { + return cidrToLong(ocidr.toString()); + } + /** * @param cidrSize * @return @@ -916,7 +923,7 @@ static long getCidrSizeFromString(final String cidrSize) throws CloudRuntimeExce } catch (final NumberFormatException e) { throw new CloudRuntimeException("cidrsize is not a valid int: " + cidrSize, e); } - if(cidrSizeNum > 32 || cidrSizeNum < 0) {// assuming IPv4 + if (cidrSizeNum > 32 || cidrSizeNum < 0) {// assuming IPv4 throw new CloudRuntimeException("cidr size out of range: " + cidrSizeNum); } return cidrSizeNum; @@ -1135,6 +1142,21 @@ public static boolean isSameIpRange(final String cidrA, final String cidrB) { return false; } + public static boolean validateGuestCidrForOSPF(final CIDR cidr, final CIDR[] ospfSuperCIDRList) { + if (!ArrayUtils.isEmpty(ospfSuperCIDRList)) { + for (CIDR superCidr : ospfSuperCIDRList) { + if (cidr.overlaps(superCidr)) { + return true; + } + } + s_logger.warn("cidr " + cidr + " is not within Zone superCIDR " + Arrays.toString(ospfSuperCIDRList)); + return false; + } else { + s_logger.warn("Zone super cidr is empty"); + return false; + } + } + public static boolean validateGuestCidr(final String cidr) { // RFC 1918 - The Internet Assigned Numbers Authority (IANA) has reserved the // following three blocks of the IP address space for private internets: @@ -1159,6 +1181,25 @@ public static boolean validateGuestCidr(final String cidr) { } } + public static boolean validateGuestCidr(final CIDR cidr) throws BadCIDRException { + // RFC 1918 - The Internet Assigned Numbers Authority (IANA) has reserved the + // following three blocks of the IP address space for private internets: + // 10.0.0.0 - 10.255.255.255 (10/8 prefix) + // 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) + // 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) + + final CIDR cidr1 = CIDRFactory.getCIDR("10.0.0.0/8"); + final CIDR cidr2 = CIDRFactory.getCIDR("172.16.0.0/12"); + final CIDR cidr3 = CIDRFactory.getCIDR("192.168.0.0/16"); + + if (cidr1.contains(cidr) || cidr2.contains(cidr) || cidr3.contains(cidr)) { + return true; + } else { + s_logger.warn("cidr " + cidr + " is not RFC 1918 compliant"); + return false; + } + } + public static boolean verifyInstanceName(final String instanceName) { //instance name for cloudstack vms shouldn't contain - and spaces if (instanceName.contains("-") || instanceName.contains(" ") || instanceName.contains("+")) { @@ -1176,7 +1217,7 @@ public static boolean isNetworksOverlap(final String cidrA, final String cidrB) final long shift = MAX_CIDR - (cidrALong[1] > cidrBLong[1] ? cidrBLong[1] : cidrALong[1]); return cidrALong[0] >> shift == cidrBLong[0] >> shift; } catch (CloudRuntimeException e) { - s_logger.error(e.getLocalizedMessage(),e); + s_logger.error(e.getLocalizedMessage(), e); } return false; } @@ -1302,7 +1343,7 @@ public static String getIp6FromRange(final String ip6Range) { return null; } } - if( resultAddr != null) { + if (resultAddr != null) { final IPv6Address ip = IPv6Address.fromInetAddress(resultAddr); return ip.toString(); } @@ -1431,7 +1472,7 @@ public static String standardizeIp6Address(final String ip6Addr) { } } - public static String standardizeIp6Cidr(final String ip6Cidr){ + public static String standardizeIp6Cidr(final String ip6Cidr) { try { return IPv6Network.fromString(ip6Cidr).toString(); } catch (final IllegalArgumentException ex) { @@ -1570,13 +1611,143 @@ public static Boolean IsIpEqualToNetworkOrBroadCastIp(final String requestedIp, } return false; } - public static boolean isNetworkorBroadcastIP(String ip, String netmask){ - String cidr = getCidrFromGatewayAndNetmask(ip,netmask); + + public static boolean isNetworkorBroadcastIP(String ip, String netmask) { + String cidr = getCidrFromGatewayAndNetmask(ip, netmask); final SubnetUtils subnetUtils = new SubnetUtils(cidr); subnetUtils.setInclusiveHostCount(false); final boolean isInRange = subnetUtils.getInfo().isInRange(ip); return !isInRange; } + public static List getAllSubnets(final String[] superCidrList, final String netmask) { + if (!NetUtils.isValidNetmask(netmask)) { + throw new IllegalStateException("Invalid netmask"); + } + + List addresses = new ArrayList(); + if (!ArrayUtils.isEmpty(superCidrList)) { + for (String superCidr : superCidrList) { + SubnetUtils utils = new SubnetUtils(superCidr); + addresses.addAll(Arrays.asList(utils.getInfo().getAllAddresses())); + } + } + + List subnets = new ArrayList(); + String cidr = ""; + for (String tip : addresses) { + String new_cidr = NetUtils.getCidrFromGatewayAndNetmask(tip, netmask); + if (!cidr.endsWith(new_cidr)) { + subnets.add(new_cidr); + cidr = new_cidr; + } + } + return subnets; + } + + public static List getAllSubnets(final CIDR[] superCidrList, final String netmask) throws BadCIDRException { + if (!NetUtils.isValidNetmask(netmask)) { + throw new IllegalStateException("Invalid netmask"); + } + + List addresses = new ArrayList(); + if (!ArrayUtils.isEmpty(superCidrList)) { + for (CIDR superCidr : superCidrList) { + SubnetUtils utils = new SubnetUtils(superCidr.toString()); + addresses.addAll(Arrays.asList(utils.getInfo().getAllAddresses())); + } + } + + List subnets = new ArrayList(); + String cidr = ""; + for (String tip : addresses) { + String new_cidr = NetUtils.getCidrFromGatewayAndNetmask(tip, netmask); + if (!cidr.endsWith(new_cidr)) { + subnets.add(CIDRFactory.getCIDR(new_cidr)); + cidr = new_cidr; + } + } + return subnets; + } + + public static boolean isCidrOverlap(final String cidr, final List usedCidrs) { + for (String usedCidr : usedCidrs) { + boolean result = NetUtils.isNetworksOverlap(cidr, usedCidr); + if (result) { + return true; + } + } + return false; + } + + public static boolean isCidrOverlap(final CIDR cidr, final List usedCidrs) { + for (CIDR usedCidr : usedCidrs) { + if (cidr.overlaps(usedCidr)) { + return true; + } + } + return false; + } + + public static boolean cidrListConsistency(final CIDR[] cidrList) throws BadCIDRException, IllegalStateException { + if (ArrayUtils.isEmpty(cidrList)) { + throw new IllegalStateException("Null or empty cidrList"); + } + boolean isGuestCidr = false; + if (validateGuestCidr(cidrList[0])) { + isGuestCidr = true; + } + // check if there is any overlap of cidrs + for (int i = 0; i < cidrList.length; i++) { + for (int j = i + 1; j < cidrList.length; j++) { + if (cidrList[i].overlaps(cidrList[j])) { + throw new IllegalStateException("Invalid cidr in the list the overlapping cidrs are " + cidrList[i] + " and " + cidrList[j]); + } + } + } + + if (isGuestCidr) { + for (CIDR cidr : cidrList) { + if (!validateGuestCidr(cidr)) { + return false; + } + } + return true; + } else { //inverted check + for (CIDR cidr : cidrList) { + if (validateGuestCidr(cidr)) { + return false; + } + } + return true; + } + } + + public static InetAddress addressStringToInet(String addr) throws UnknownHostException { + return InetAddress.getByName(addr); + } + + public static int getNetMask(String netMask) { + StringTokenizer nm = new StringTokenizer(netMask, "."); + int i = 0; + int[] netmask = new int[4]; + while (nm.hasMoreTokens()) { + netmask[i] = Integer.parseInt(nm.nextToken()); + i++; + } + int mask1 = 0; + for (i = 0; i < 4; i++) { + mask1 += Integer.bitCount(netmask[i]); + } + return mask1; + } + + public static CIDR[] convertToCIDR(String[] cidrs) throws BadCIDRException { + List v_cidr = new ArrayList(); + for (String cidr : cidrs) { + v_cidr.add(CIDRFactory.getCIDR(cidr)); + } + return (CIDR[])v_cidr.toArray(new CIDR[v_cidr.size()]); + } } diff --git a/utils/src/main/java/com/cloud/utils/net/cidr/BadCIDRException.java b/utils/src/main/java/com/cloud/utils/net/cidr/BadCIDRException.java new file mode 100644 index 000000000000..ce3384791489 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/net/cidr/BadCIDRException.java @@ -0,0 +1,33 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +package com.cloud.utils.net.cidr; + +import java.io.IOException; + +public class BadCIDRException extends IOException { + + private static final long serialVersionUID = -432126076052875403L; + + public BadCIDRException(String msg) { + super(msg); + } + + public BadCIDRException() { + } +} diff --git a/utils/src/main/java/com/cloud/utils/net/cidr/CIDR.java b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR.java new file mode 100644 index 000000000000..18f49623958a --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR.java @@ -0,0 +1,98 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.utils.net.cidr; + +import java.net.InetAddress; +import com.cloud.utils.Nullable; + +public interface CIDR extends Comparable, Nullable { + + final static CIDR NULL = new NullCIDR(); + final static int MAX_CIDR = 32; + + public InetAddress getBaseAddress(); + + public int getMask(); + + public boolean contains(InetAddress inetAddress); + + public boolean contains(CIDR cidr); + + public boolean overlaps(CIDR cidr); + + public String toString(); + + public boolean equals(Object o); + + public int hashCode(); + + class NullCIDR implements CIDR { + + private NullCIDR() { + super(); + } + + public boolean isNull() { + return true; + } + + @Override + public String toString() { + return "Null CIDR"; + } + + @Override + public InetAddress getBaseAddress() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getMask() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean contains(CIDR cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean overlaps(CIDR cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean contains(InetAddress cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public int compareTo(CIDR o) { + // TODO Auto-generated method stub + return 0; + } + } + +} \ No newline at end of file diff --git a/utils/src/main/java/com/cloud/utils/net/cidr/CIDR4.java b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR4.java new file mode 100644 index 000000000000..23452dcf8e1b --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR4.java @@ -0,0 +1,172 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.utils.net.cidr; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import org.apache.commons.lang.NotImplementedException; +import org.apache.log4j.Logger; + +import com.cloud.utils.net.NetUtils; + +/** + */ +public class CIDR4 implements CIDR { + protected final static Logger s_logger = Logger.getLogger(CIDR4.class); + + protected InetAddress baseAddress; + protected int cidrMask; + private int addressInt; + private final int addressEndInt; + + protected CIDR4(Inet4Address newaddr, int mask) { + cidrMask = mask; + addressInt = ipv4AddressToInt(newaddr); + int newmask = ipv4PrefixLengthToMask(mask); + addressInt &= newmask; + try { + baseAddress = intToIPv4Address(addressInt); + } catch (UnknownHostException e) { + // this should never happen + } + addressEndInt = addressInt + ipv4PrefixLengthToLength(cidrMask) - 1; + } + + public int compareTo(CIDR arg) { + if (arg instanceof CIDR6) { + throw new NotImplementedException("Not implemented for CIDR6"); + } + CIDR4 o = (CIDR4)arg; + if (o.addressInt == addressInt && o.cidrMask == cidrMask) { + return 0; + } + if (o.addressInt < addressInt) { + return 1; + } + if (o.addressInt > addressInt) { + return -1; + } + if (o.cidrMask < cidrMask) { + // greater Mask means less IpAddresses so -1 + return -1; + } + return 1; + } + + @Override + public boolean isNull() { + return false; + } + + @Override + public boolean contains(InetAddress inetAddress) { + if (inetAddress == null) { + throw new NullPointerException("inetAddress"); + } + + if (cidrMask == 0) { + return true; + } + + int search = ipv4AddressToInt(inetAddress); + return search >= addressInt && search <= addressEndInt; + } + + private static int ipv4PrefixLengthToLength(int prefixLength) { + return 1 << 32 - prefixLength; + } + + private static int ipv4PrefixLengthToMask(int prefixLength) { + return ~((1 << 32 - prefixLength) - 1); + } + + private static InetAddress intToIPv4Address(int addr) throws UnknownHostException { + byte[] a = new byte[4]; + a[0] = (byte)(addr >> 24 & 0xFF); + a[1] = (byte)(addr >> 16 & 0xFF); + a[2] = (byte)(addr >> 8 & 0xFF); + a[3] = (byte)(addr & 0xFF); + return InetAddress.getByAddress(a); + } + + private static int ipv4AddressToInt(InetAddress addr) { + byte[] address; + if (addr instanceof Inet6Address) { + throw new NotImplementedException("Not implemented for ipv6 address"); + } else { + address = addr.getAddress(); + } + return ipv4AddressToInt(address); + } + + private static int ipv4AddressToInt(byte[] address) { + int net = 0; + for (byte addres : address) { + net <<= 8; + net |= addres & 0xFF; + } + return net; + } + + @Override + public InetAddress getBaseAddress() { + return baseAddress; + } + + @Override + public int getMask() { + return cidrMask; + } + + @Override + public boolean contains(CIDR cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean overlaps(CIDR cidr) { + Long[] cidrALong = NetUtils.cidrToLong(this); + Long[] cidrBLong = NetUtils.cidrToLong(cidr); + final long shift = MAX_CIDR - (cidrALong[1] > cidrBLong[1] ? cidrBLong[1] : cidrALong[1]); + return cidrALong[0] >> shift == cidrBLong[0] >> shift; + } + + @Override + public String toString() { + return baseAddress.getHostAddress() + '/' + cidrMask; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CIDR)) { + return false; + } + return compareTo((CIDR)o) == 0; + } + + @Override + public int hashCode() { + return baseAddress.hashCode(); + } +} \ No newline at end of file diff --git a/utils/src/main/java/com/cloud/utils/net/cidr/CIDR6.java b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR6.java new file mode 100644 index 000000000000..84da1734c753 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/net/cidr/CIDR6.java @@ -0,0 +1,95 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.utils.net.cidr; + +import java.net.Inet6Address; +import java.net.InetAddress; + +import org.apache.commons.lang.NotImplementedException; +import org.apache.log4j.Logger; + +public class CIDR6 implements CIDR { + protected final static Logger s_logger = Logger.getLogger(CIDR6.class); + + protected InetAddress baseAddress; + protected int cidrMask; + + protected CIDR6(Inet6Address newaddress, int newmask) { + } + + @Override + public boolean isNull() { + return false; + } + + public int compareTo(CIDR arg) { + throw new NotImplementedException(); + } + + @Override + public boolean contains(InetAddress inetAddress) { + throw new NotImplementedException(); + // TODO Auto-generated method stub + //return false; + } + + @Override + public InetAddress getBaseAddress() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getMask() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean contains(CIDR cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean overlaps(CIDR cidr) { + // TODO Auto-generated method stub + return false; + } + + @Override + public String toString() { + return baseAddress.getHostAddress() + '/' + cidrMask; + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof CIDR)) { + return false; + } + return compareTo((CIDR)o) == 0; + } + + @Override + public int hashCode() { + return baseAddress.hashCode(); + } + +} \ No newline at end of file diff --git a/utils/src/main/java/com/cloud/utils/net/cidr/CIDRFactory.java b/utils/src/main/java/com/cloud/utils/net/cidr/CIDRFactory.java new file mode 100644 index 000000000000..b5dedadd8f02 --- /dev/null +++ b/utils/src/main/java/com/cloud/utils/net/cidr/CIDRFactory.java @@ -0,0 +1,79 @@ +// +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// + +package com.cloud.utils.net.cidr; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +import com.cloud.utils.net.NetUtils; + +public class CIDRFactory { + + public static CIDR getCIDR(InetAddress baseAddress, int cidrMask) throws BadCIDRException { + if (cidrMask < 0) { + throw new BadCIDRException("Invalid mask length used: " + cidrMask); + } + if (baseAddress instanceof Inet4Address) { + if (cidrMask > 32) { + throw new BadCIDRException("Invalid mask length used: " + cidrMask); + } + return new CIDR4((Inet4Address)baseAddress, cidrMask); + } + // IPv6. + if (cidrMask > 128) { + throw new BadCIDRException("Invalid mask length used: " + cidrMask); + } + return new CIDR6((Inet6Address)baseAddress, cidrMask); + } + + public static CIDR getCIDR(String cidr) throws BadCIDRException { + int p = cidr.indexOf('/'); + if (p < 0) { + throw new BadCIDRException("Invalid CIDR notation used: " + cidr); + } + String addrString = cidr.substring(0, p); + String maskString = cidr.substring(p + 1); + InetAddress addr = addressStringToInet(addrString); + int mask; + if (maskString.indexOf('.') < 0) { + mask = Integer.decode(maskString); + } else { + mask = NetUtils.getNetMask(maskString); + if (addr instanceof Inet6Address) { + mask += 96; + } + } + if (mask < 0) { + throw new BadCIDRException("Invalid mask length used: " + maskString); + } + return getCIDR(addr, mask); + } + + public static InetAddress addressStringToInet(String addr) throws BadCIDRException { + try { + return InetAddress.getByName(addr); + } catch (UnknownHostException e) { + throw new BadCIDRException("The fomat of address string is not valid " + addr); + } + } + +} diff --git a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java index 490d0df4eb09..a587afaefcbf 100644 --- a/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/src/test/java/com/cloud/utils/net/NetUtilsTest.java @@ -30,16 +30,20 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.apache.log4j.Logger; import org.junit.Test; - import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.net.NetUtils.SupersetOrSubset; +import com.cloud.utils.net.cidr.BadCIDRException; +import com.cloud.utils.net.cidr.CIDR; import com.googlecode.ipv6.IPv6Address; public class NetUtilsTest { @@ -54,8 +58,8 @@ public void testGetRandomIpFromCidrWithSize24() throws Exception { final long ip = NetUtils.getRandomIpFromCidr(cidr, size, new TreeSet()); - assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), equalTo(NetUtils.long2Ip(ip) - .substring(0, netCharacters))); + assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), + equalTo(NetUtils.long2Ip(ip).substring(0, netCharacters))); } @Test @@ -66,8 +70,8 @@ public void testGetRandomIpFromCidrWithSize16() throws Exception { final long ip = NetUtils.getRandomIpFromCidr(cidr, 16, new TreeSet()); - assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), equalTo(NetUtils.long2Ip(ip) - .substring(0, netCharacters))); + assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), + equalTo(NetUtils.long2Ip(ip).substring(0, netCharacters))); } @Test @@ -78,8 +82,8 @@ public void testGetRandomIpFromCidrWithSize8() throws Exception { final long ip = NetUtils.getRandomIpFromCidr(cidr, 16, new TreeSet()); - assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), equalTo(NetUtils.long2Ip(ip) - .substring(0, netCharacters))); + assertThat("The ip " + NetUtils.long2Ip(ip) + " retrieved must be within the cidr " + cidr + "/" + size, cidr.substring(0, netCharacters), + equalTo(NetUtils.long2Ip(ip).substring(0, netCharacters))); } @Test @@ -425,50 +429,50 @@ public void testIs31PrefixCidr() { public void testGetCidrNetMask() { final String cidr = "10.10.0.0/16"; String netmask = NetUtils.getCidrNetmask("10.10.10.10/16"); - assertTrue(cidr + " does not generate valid netmask " + netmask,NetUtils.isValidNetmask(netmask)); + assertTrue(cidr + " does not generate valid netmask " + netmask, NetUtils.isValidNetmask(netmask)); } @Test public void testGetCidrSubNet() { final String cidr = "10.10.0.0/16"; String subnet = NetUtils.getCidrSubNet("10.10.10.10/16"); - assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithtInCidrRange(subnet, cidr)); + assertTrue(cidr + " does not contain " + subnet, NetUtils.isIpWithtInCidrRange(subnet, cidr)); } @Test public void testGetCidrSubNetWithWidth() { final String cidr = "10.10.0.0/16"; String subnet = NetUtils.getCidrSubNet("10.10.10.10", 16); - assertTrue(cidr + " does not contain " + subnet,NetUtils.isIpWithtInCidrRange(subnet, cidr)); + assertTrue(cidr + " does not contain " + subnet, NetUtils.isIpWithtInCidrRange(subnet, cidr)); } @Test public void testIsValidCidrSize() { final String cidrsize = "16"; long netbits = NetUtils.getCidrSizeFromString(cidrsize); - assertTrue(" does not compute " + cidrsize,netbits == 16); + assertTrue(" does not compute " + cidrsize, netbits == 16); } - @Test(expected=CloudRuntimeException.class) + @Test(expected = CloudRuntimeException.class) public void testIsInvalidCidrSize() { final String cidrsize = "33"; long netbits = NetUtils.getCidrSizeFromString(cidrsize); - assertTrue(" does not compute " + cidrsize,netbits == 16); + assertTrue(" does not compute " + cidrsize, netbits == 16); } - @Test(expected=CloudRuntimeException.class) + @Test(expected = CloudRuntimeException.class) public void testIsInvalidCidrString() { final String cidrsize = "ggg"; long netbits = NetUtils.getCidrSizeFromString(cidrsize); - assertTrue(" does not compute " + cidrsize,netbits == 16); + assertTrue(" does not compute " + cidrsize, netbits == 16); } @Test public void testCidrToLongArray() { final String cidr = "10.192.10.10/10"; Long[] netbits = NetUtils.cidrToLong(cidr); - assertEquals("unexpected cidrsize " + netbits[1],10l, netbits[1].longValue()); - assertEquals("(un)expected <" + 0x0ac00000L + "> netaddress " + netbits[0].longValue(),netbits[0].longValue(),0x0ac00000l); + assertEquals("unexpected cidrsize " + netbits[1], 10l, netbits[1].longValue()); + assertEquals("(un)expected <" + 0x0ac00000L + "> netaddress " + netbits[0].longValue(), netbits[0].longValue(), 0x0ac00000l); } @Test @@ -508,22 +512,85 @@ public void testIsNetworkAWithinNetworkBWithEmptyValues() { public void testIsNetworksOverlapWithEmptyValues() { assertEquals(false, NetUtils.isNetworksOverlap("", null)); } + @Test - public void testisNetworkorBroadCastIP(){ - //Checking the True conditions - assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.0","255.255.255.0")); - assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.255","255.255.255.0")); - assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.127","255.255.255.128")); - assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.63","255.255.255.192")); + public void testisNetworkorBroadCastIP() { + //Checking the True conditions + assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.0", "255.255.255.0")); + assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.255", "255.255.255.0")); + assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.127", "255.255.255.128")); + assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.63", "255.255.255.192")); //Checking the False conditions - assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.1","255.255.255.0")); - assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.127","255.255.255.0")); - assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.126","255.255.255.128")); - assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.62","255.255.255.192")); + assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.1", "255.255.255.0")); + assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.127", "255.255.255.0")); + assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.126", "255.255.255.128")); + assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.62", "255.255.255.192")); + + assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.63", "255.255.255.192")); + assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.63", "255.255.255.128")); + } + + @Test + public void testListallSubnets() { + String netmask = "255.255.255.128"; + String[] cidr = {"200.100.0.0/20"}; + assertEquals(32, NetUtils.getAllSubnets(cidr, netmask).size()); //200.100.0.0/25, 200.100.0.128/25 + } + + @Test + public void testCidrOverlapWithSubnets1() { + List usedSubnets = new ArrayList(); + usedSubnets.add("200.100.0.0/25"); + usedSubnets.add("200.100.0.128/25"); + String[] cidr = {"200.100.0.0/26"}; + assertTrue(NetUtils.isCidrOverlap(cidr[0], usedSubnets)); + } + + @Test + public void testCidrOverlapWithSubnets2() { + List usedSubnets = new ArrayList(); + usedSubnets.add("200.100.0.0/25"); + usedSubnets.add("200.100.0.128/25"); + String[] cidr = {"200.100.5.0/25"}; + assertFalse(NetUtils.isCidrOverlap(cidr[0], usedSubnets)); + } - assertTrue(NetUtils.isNetworkorBroadcastIP("192.168.0.63","255.255.255.192")); - assertFalse(NetUtils.isNetworkorBroadcastIP("192.168.0.63","255.255.255.128")); + @Test + public void testCidrOverlapWithSubnets3() { + List usedSubnets = new ArrayList(); + usedSubnets.add("200.100.0.0/25"); + usedSubnets.add("200.100.0.128/25"); + String[] cidr = {"200.100.5.0/26"}; + assertFalse(NetUtils.isCidrOverlap(cidr[0], usedSubnets)); + } + + @Test + public void testCidrConsistency_ConsistentGuestCidr() throws BadCIDRException { + String[] str_cidr_list = {"10.0.0.0/16", "172.16.0.0/16", "192.168.0.0/16", "10.5.5.0/16"}; + CIDR[] cidr_list = NetUtils.convertToCIDR(str_cidr_list); + assertTrue(NetUtils.cidrListConsistency(cidr_list)); + } + + @Test + public void testCidrConsistency_ConsistentPublicCidr() throws BadCIDRException { + String[] str_cidr_list = {"207.46.130.0/24", "216.58.199.174/16", "54.84.216.68/16", "64.210.140.1/16", "200.100.0.0/16"}; + CIDR[] cidr_list = NetUtils.convertToCIDR(str_cidr_list); + assertTrue(NetUtils.cidrListConsistency(cidr_list)); + } + + @Test(expected = IllegalStateException.class) + public void testCidrOverlapsOne() throws BadCIDRException { + String[] str_cidr_list = {"207.46.130.0/24", "216.58.199.174/16", "54.84.216.68/16", "64.210.140.1/16", "200.100.0.0/16", "207.46.130.0/28"}; + CIDR[] cidr_list = NetUtils.convertToCIDR(str_cidr_list); + given(NetUtils.cidrListConsistency(cidr_list)).willThrow(new IllegalStateException()); + } + + @Test + public void testCidrConsistency_InConsistentGuestCidr() throws BadCIDRException { + String[] str_cidr_list = {"10.0.0.0/16", "172.16.0.0/16", "192.168.0.0/16", "10.5.5.0/16", "200.100.0.0/16"}; + CIDR[] cidr_list = NetUtils.convertToCIDR(str_cidr_list); + assertTrue(NetUtils.cidrListConsistency(cidr_list)); } }