Return-Path: X-Original-To: apmail-cloudstack-commits-archive@www.apache.org Delivered-To: apmail-cloudstack-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 53004189EC for ; Wed, 10 Jun 2015 20:49:43 +0000 (UTC) Received: (qmail 29052 invoked by uid 500); 10 Jun 2015 20:49:42 -0000 Delivered-To: apmail-cloudstack-commits-archive@cloudstack.apache.org Received: (qmail 28867 invoked by uid 500); 10 Jun 2015 20:49:42 -0000 Mailing-List: contact commits-help@cloudstack.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cloudstack.apache.org Delivered-To: mailing list commits@cloudstack.apache.org Received: (qmail 28570 invoked by uid 99); 10 Jun 2015 20:49:42 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 10 Jun 2015 20:49:42 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0C718E04BE; Wed, 10 Jun 2015 20:49:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: ekho@apache.org To: commits@cloudstack.apache.org Date: Wed, 10 Jun 2015 20:49:45 -0000 Message-Id: In-Reply-To: <933e594c03724bf4819ee89b11b086d4@git.apache.org> References: <933e594c03724bf4819ee89b11b086d4@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [05/19] git commit: updated refs/heads/feature/vpc-ipv6 to c1b0900 Enhanced Zone API to support Ipv6 attributes like IPv6 Super CIDR and ASN Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/eb6c990b Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/eb6c990b Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/eb6c990b Branch: refs/heads/feature/vpc-ipv6 Commit: eb6c990b1a1a6c86129d1a7d7b61cf84969e80a8 Parents: 13cef9a Author: Suresh Ramamurthy Authored: Tue Jun 9 03:55:06 2015 -0400 Committer: Suresh Ramamurthy Committed: Tue Jun 9 04:46:21 2015 -0400 ---------------------------------------------------------------------- .../org/apache/cloudstack/api/ApiConstants.java | 2 + .../api/command/admin/zone/CreateZoneCmd.java | 14 +++ .../api/command/admin/zone/UpdateZoneCmd.java | 17 ++- .../cloudstack/api/response/ZoneResponse.java | 17 ++- .../configuration/ConfigurationManager.java | 16 +-- .../src/com/cloud/dc/dao/DataCenterDao.java | 4 + .../src/com/cloud/dc/dao/DataCenterDaoImpl.java | 25 +++++ .../management/ManagementServerMock.java | 2 +- .../configuration/ConfigurationManagerImpl.java | 106 +++++++++++++++---- .../configuration/ConfigurationManagerTest.java | 79 ++++++++++++++ .../cloud/vpc/MockConfigurationManagerImpl.java | 6 +- tools/marvin/marvin/deployDataCenter.py | 4 + utils/src/com/cloud/utils/net/NetUtils.java | 30 ++++++ .../test/com/cloud/utils/net/NetUtilsTest.java | 19 ++++ 14 files changed, 304 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/api/src/org/apache/cloudstack/api/ApiConstants.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/ApiConstants.java b/api/src/org/apache/cloudstack/api/ApiConstants.java index 2b64258..80b22a0 100644 --- a/api/src/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/org/apache/cloudstack/api/ApiConstants.java @@ -115,6 +115,8 @@ public class ApiConstants { public static final String GSLB_STICKY_SESSION_METHOD = "gslbstickysessionmethodname"; public static final String GSLB_LBRULE_WEIGHT_MAP = "gslblbruleweightsmap"; public static final String GUEST_CIDR_ADDRESS = "guestcidraddress"; + public static final String IP6_SUPER_CIDR_ADDRESS = "ip6supercidraddress"; + public static final String AUTONOMOUS_NUMBER = "asnumber"; public static final String GUEST_VLAN_RANGE = "guestvlanrange"; public static final String HA_ENABLE = "haenable"; public static final String HOST_ID = "hostid"; http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/api/src/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java b/api/src/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java index 414c058..c69285c 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/zone/CreateZoneCmd.java @@ -58,6 +58,12 @@ public class CreateZoneCmd extends BaseCmd { @Parameter(name = ApiConstants.GUEST_CIDR_ADDRESS, type = CommandType.STRING, description = "the guest CIDR address for the Zone") private String guestCidrAddress; + @Parameter(name = ApiConstants.IP6_SUPER_CIDR_ADDRESS, type = CommandType.STRING, description = "the IPv6 super CIDR address for the Zone. IPv6 CIDR of all the VPCs in this zone should be within this CIDR") + private String ip6SuperCidrAddress; + + @Parameter(name = ApiConstants.AUTONOMOUS_NUMBER, type = CommandType.STRING, description = "private autonomous system number for the Zone") + private String asNumber; + @Parameter(name = ApiConstants.INTERNAL_DNS1, type = CommandType.STRING, required = true, description = "the first internal DNS for the Zone") private String internalDns1; @@ -112,6 +118,14 @@ public class CreateZoneCmd extends BaseCmd { return guestCidrAddress; } + public String getIp6SuperCidrAddress() { + return ip6SuperCidrAddress; + } + + public String getAsNumber() { + return asNumber; + } + public String getInternalDns1() { return internalDns1; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/api/src/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java b/api/src/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java index 9ad8972..f9267e5 100644 --- a/api/src/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java +++ b/api/src/org/apache/cloudstack/api/command/admin/zone/UpdateZoneCmd.java @@ -19,8 +19,6 @@ package org.apache.cloudstack.api.command.admin.zone; import java.util.List; import java.util.Map; -import org.apache.log4j.Logger; - import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.ApiErrorCode; @@ -30,6 +28,7 @@ import org.apache.cloudstack.api.ResponseObject.ResponseView; import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.response.ZoneResponse; import org.apache.cloudstack.context.CallContext; +import org.apache.log4j.Logger; import com.cloud.dc.DataCenter; import com.cloud.user.Account; @@ -60,6 +59,12 @@ public class UpdateZoneCmd extends BaseCmd { @Parameter(name = ApiConstants.GUEST_CIDR_ADDRESS, type = CommandType.STRING, description = "the guest CIDR address for the Zone") private String guestCidrAddress; + @Parameter(name = ApiConstants.IP6_SUPER_CIDR_ADDRESS, type = CommandType.STRING, description = "the IPv6 super CIDR address for the Zone. IPv6 CIDR of all the VPCs in this zone should be within this CIDR") + private String ip6SuperCidrAddress; + + @Parameter(name = ApiConstants.AUTONOMOUS_NUMBER, type = CommandType.STRING, description = "private autonomous system number for the Zone") + private String asNumber; + @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = ZoneResponse.class, required = true, description = "the ID of the Zone") private Long id; @@ -111,6 +116,14 @@ public class UpdateZoneCmd extends BaseCmd { return guestCidrAddress; } + public String getIp6SuperCidrAddress() { + return ip6SuperCidrAddress; + } + + public String getAsNumber() { + return asNumber; + } + public Long getId() { return id; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java ---------------------------------------------------------------------- diff --git a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java index 7aee448..1288bee 100644 --- a/api/src/org/apache/cloudstack/api/response/ZoneResponse.java +++ b/api/src/org/apache/cloudstack/api/response/ZoneResponse.java @@ -29,7 +29,6 @@ import com.cloud.dc.DataCenter; import com.cloud.serializer.Param; import com.google.gson.annotations.SerializedName; -@SuppressWarnings("unused") @EntityReference(value = DataCenter.class) public class ZoneResponse extends BaseResponse { @SerializedName(ApiConstants.ID) @@ -72,6 +71,14 @@ public class ZoneResponse extends BaseResponse { @Param(description = "the guest CIDR address for the Zone") private String guestCidrAddress; + @SerializedName(ApiConstants.IP6_SUPER_CIDR_ADDRESS) + @Param(description = "the IPv6 super CIDR address for the Zone. IPv6 CIDR of all the VPCs in this zone should be within this CIDR") + private String ip6SuperCidrAddress; + + @SerializedName(ApiConstants.AUTONOMOUS_NUMBER) + @Param(description = "private autonomous system number for the Zone") + private String asNumber; + //TODO - generate description @SerializedName("status") private String status; @@ -164,6 +171,14 @@ public class ZoneResponse extends BaseResponse { this.guestCidrAddress = guestCidrAddress; } + public void setIp6SuperCidrAddress(String ip6SuperCidrAddress) { + this.ip6SuperCidrAddress = ip6SuperCidrAddress; + } + + public void setAsNumber(String asNumber) { + this.asNumber = asNumber; + } + public void setStatus(String status) { this.status = status; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java ---------------------------------------------------------------------- diff --git a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java index 13ca3f9..c291e8d 100644 --- a/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java +++ b/engine/components-api/src/com/cloud/configuration/ConfigurationManager.java @@ -149,19 +149,19 @@ public interface ConfigurationManager { * @param guestCidr * @param zoneType * @param allocationState - * @param networkDomain - * TODO + * @param networkDomainTODO * @param isSecurityGroupEnabled - * TODO - * @param ip6Dns1 TODO - * @param ip6Dns2 TODO + * @param ip6Dns1 + * @param ip6Dns2 + * @param ip6SuperCidr + * @param asNumber * @return * @throws * @throws */ - DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, - Long domainId, NetworkType zoneType, String allocationState, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled, String ip6Dns1, - String ip6Dns2); + DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, Long domainId, + NetworkType zoneType, String allocationState, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled, String ip6Dns1, String ip6Dns2, + String ip6SuperCidr, String asNumber); /** * Deletes a VLAN from the database, along with all of its IP addresses. Will not delete VLANs that have allocated http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java b/engine/schema/src/com/cloud/dc/dao/DataCenterDao.java index 4fc055e..ffaa7c1 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(); + + DataCenterVO findByIp6SuperCidr(String ip6SuperCidr); + + DataCenterVO findByAsn(String asNumber); } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java ---------------------------------------------------------------------- diff --git a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java index 373446e..eb6ceb1 100644 --- a/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java +++ b/engine/schema/src/com/cloud/dc/dao/DataCenterDaoImpl.java @@ -61,6 +61,8 @@ public class DataCenterDaoImpl extends GenericDaoBase implem private static final Logger s_logger = Logger.getLogger(DataCenterDaoImpl.class); protected SearchBuilder NameSearch; + protected SearchBuilder Ip6SuperCidrSearch; + protected SearchBuilder AsnSearch; protected SearchBuilder ListZonesByDomainIdSearch; protected SearchBuilder PublicZonesSearch; protected SearchBuilder ChildZonesSearch; @@ -92,6 +94,20 @@ public class DataCenterDaoImpl extends GenericDaoBase implem } @Override + public DataCenterVO findByIp6SuperCidr(String ip6SuperCidr) { + SearchCriteria sc = Ip6SuperCidrSearch.create(); + sc.setParameters("ip6SuperNetworkCidr", ip6SuperCidr); + return findOneBy(sc); + } + + @Override + public DataCenterVO findByAsn(String asNumber) { + SearchCriteria sc = AsnSearch.create(); + sc.setParameters("asNumber", asNumber); + return findOneBy(sc); + } + + @Override public DataCenterVO findByToken(String zoneToken) { SearchCriteria sc = TokenSearch.create(); sc.setParameters("zoneToken", zoneToken); @@ -323,6 +339,15 @@ public class DataCenterDaoImpl extends GenericDaoBase implem NameSearch.and("name", NameSearch.entity().getName(), SearchCriteria.Op.EQ); NameSearch.done(); + Ip6SuperCidrSearch = createSearchBuilder(); + Ip6SuperCidrSearch.and("ip6SuperNetworkCidr", Ip6SuperCidrSearch.entity().getIp6SuperNetworkCidr(), SearchCriteria.Op.EQ); + Ip6SuperCidrSearch.done(); + + + AsnSearch = createSearchBuilder(); + AsnSearch.and("asNumber", AsnSearch.entity().getAsNumber(), SearchCriteria.Op.EQ); + AsnSearch.done(); + ListZonesByDomainIdSearch = createSearchBuilder(); ListZonesByDomainIdSearch.and("domainId", ListZonesByDomainIdSearch.entity().getDomainId(), SearchCriteria.Op.EQ); ListZonesByDomainIdSearch.done(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ManagementServerMock.java ---------------------------------------------------------------------- diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ManagementServerMock.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ManagementServerMock.java index db06c88..c048b9d 100644 --- a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ManagementServerMock.java +++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ManagementServerMock.java @@ -386,7 +386,7 @@ public class ManagementServerMock { ConfigurationManager mgr = (ConfigurationManager)_configService; _zone = mgr.createZone(User.UID_SYSTEM, "default", "8.8.8.8", null, "8.8.4.4", null, null /* cidr */, "ROOT", Domain.ROOT_DOMAIN, NetworkType.Advanced, null, - null /* networkDomain */, false, false, null, null); + null /* networkDomain */, false, false, null, null, null, null); } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java index 6594dd9..8ee5af3 100644 --- a/server/src/com/cloud/configuration/ConfigurationManagerImpl.java +++ b/server/src/com/cloud/configuration/ConfigurationManagerImpl.java @@ -38,11 +38,11 @@ import javax.inject.Inject; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; - import org.apache.cloudstack.acl.SecurityChecker; import org.apache.cloudstack.affinity.AffinityGroup; import org.apache.cloudstack.affinity.AffinityGroupService; import org.apache.cloudstack.affinity.dao.AffinityGroupDao; +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.command.admin.config.UpdateCfgCmd; import org.apache.cloudstack.api.command.admin.network.CreateNetworkOfferingCmd; import org.apache.cloudstack.api.command.admin.network.DeleteNetworkOfferingCmd; @@ -1422,9 +1422,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } - private void checkZoneParameters(final String zoneName, final String dns1, final String dns2, final String internalDns1, final String internalDns2, final boolean checkForDuplicates, final Long domainId, - final String allocationStateStr, final String ip6Dns1, final String ip6Dns2) { - if (checkForDuplicates) { + private void checkZoneParameters(final boolean checkForDuplicateName, final String zoneName, final String dns1, final String dns2, final String internalDns1, final String internalDns2, final Long domainId, + final String allocationStateStr, final String ip6Dns1, final String ip6Dns2, boolean checkForDuplicateIp6SuperCidr, String ip6SuperCidr, boolean checkForDuplicateAsn, String asNumber) { + + if (checkForDuplicateName) { // Check if a zone with the specified name already exists if (validZone(zoneName)) { throw new InvalidParameterValueException("A zone with that name already exists. Please specify a unique zone name."); @@ -1458,13 +1459,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati throw new InvalidParameterValueException("Please enter a valid IP address for internal DNS2"); } - if (ip6Dns1 != null && ip6Dns1.length() > 0 && !NetUtils.isValidIpv6(ip6Dns1)) { - throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS1"); - } - - if (ip6Dns2 != null && ip6Dns2.length() > 0 && !NetUtils.isValidIpv6(ip6Dns2)) { - throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS2"); - } + //Check all the IPv6 parameters + validateIp6Parameters(ip6Dns1, ip6Dns2, ip6SuperCidr, asNumber, checkForDuplicateName, checkForDuplicateIp6SuperCidr, checkForDuplicateAsn); if (allocationStateStr != null && !allocationStateStr.isEmpty()) { try { @@ -1589,6 +1585,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati String internalDns1 = cmd.getInternalDns1(); String internalDns2 = cmd.getInternalDns2(); String guestCidr = cmd.getGuestCidrAddress(); + String ip6SuperCidr = cmd.getIp6SuperCidrAddress(); + String asNumber = cmd.getAsNumber(); final List dnsSearchOrder = cmd.getDnsSearchOrder(); final Boolean isPublic = cmd.isPublic(); final String allocationStateStr = cmd.getAllocationState(); @@ -1683,6 +1681,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati guestCidr = zone.getGuestNetworkCidr(); } + final String oldIp6SuperCidr = zone.getIp6SuperNetworkCidr(); + if (ip6SuperCidr == null) { + ip6SuperCidr = oldIp6SuperCidr; + } + + final String oldAsNumber = zone.getAsNumber(); + if (asNumber == null) { + asNumber = oldAsNumber; + } + // validate network domain if (networkDomain != null && !networkDomain.isEmpty()) { if (!NetUtils.verifyDomainName(networkDomain)) { @@ -1692,8 +1700,12 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - final boolean checkForDuplicates = !zoneName.equals(oldZoneName); - checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, checkForDuplicates, null, allocationStateStr, ip6Dns1, ip6Dns2);// not allowing updating + final boolean checkForDuplicateName = !zoneName.equals(oldZoneName); + final boolean checkForDuplicateIp6SuperCidr = !org.apache.commons.lang.StringUtils.equals(ip6SuperCidr, oldIp6SuperCidr); + final boolean checkForDuplicateAsn = !org.apache.commons.lang.StringUtils.equals(asNumber, oldAsNumber); + checkZoneParameters(checkForDuplicateName, zoneName, dns1, dns2, internalDns1, internalDns2, null, allocationStateStr, ip6Dns1, ip6Dns2, checkForDuplicateIp6SuperCidr, + ip6SuperCidr, checkForDuplicateAsn, asNumber); + // not allowing updating // domain associated with // a zone, once created @@ -1705,6 +1717,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati zone.setInternalDns1(internalDns1); zone.setInternalDns2(internalDns2); zone.setGuestNetworkCidr(guestCidr); + zone.setIp6SuperNetworkCidr(ip6SuperCidr); + zone.setAsNumber(asNumber); if (localStorageEnabled != null) { zone.setLocalStorageEnabled(localStorageEnabled.booleanValue()); } @@ -1799,9 +1813,9 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati @Override @DB - public DataCenterVO createZone(final long userId, final String zoneName, final String dns1, final String dns2, final String internalDns1, final String internalDns2, final String guestCidr, final String domain, - final Long domainId, final NetworkType zoneType, final String allocationStateStr, final String networkDomain, final boolean isSecurityGroupEnabled, final boolean isLocalStorageEnabled, - final String ip6Dns1, final String ip6Dns2) { + public DataCenterVO createZone(final long userId, final String zoneName, final String dns1, final String dns2, final String internalDns1, final String internalDns2, final String guestCidr, final String domain, final Long domainId, + final NetworkType zoneType, final String allocationStateStr, final String networkDomain, final boolean isSecurityGroupEnabled, final boolean isLocalStorageEnabled, final String ip6Dns1, + final String ip6Dns2, final String ip6SuperCidr, String asNumber) { // checking the following params outside checkzoneparams method as we do // not use these params for updatezone @@ -1819,14 +1833,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati } } - checkZoneParameters(zoneName, dns1, dns2, internalDns1, internalDns2, true, domainId, allocationStateStr, ip6Dns1, ip6Dns2); + checkZoneParameters(true, zoneName, dns1, dns2, internalDns1, internalDns2, domainId, allocationStateStr, ip6Dns1, ip6Dns2, true, ip6SuperCidr, true, asNumber); final byte[] bytes = (zoneName + System.currentTimeMillis()).getBytes(); final String zoneToken = UUID.nameUUIDFromBytes(bytes).toString(); // Create the new zone in the database final DataCenterVO zoneFinal = new DataCenterVO(zoneName, null, dns1, dns2, internalDns1, internalDns2, guestCidr, domain, domainId, zoneType, zoneToken, networkDomain, - isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2, null, null); + isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2, ip6SuperCidr, asNumber); if (allocationStateStr != null && !allocationStateStr.isEmpty()) { final Grouping.AllocationState allocationState = Grouping.AllocationState.valueOf(allocationStateStr); zoneFinal.setAllocationState(allocationState); @@ -1856,6 +1870,36 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati }); } + void validateIp6Parameters(String ip6Dns1, String ip6Dns2, String ip6SuperCidr, String asNumber, boolean checkDuplicateName, boolean checkDuplicateIp6SuperCidr, boolean checkDuplicateAsn) { + if (StringUtils.isNotBlank(ip6Dns1) && !NetUtils.isValidIpv6(ip6Dns1)) { + throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS1"); + } + + if (StringUtils.isNotBlank(ip6Dns2) && !NetUtils.isValidIpv6(ip6Dns2)) { + throw new InvalidParameterValueException("Please enter a valid IPv6 address for IP6 DNS2"); + } + + if (StringUtils.isNotBlank(ip6SuperCidr)) { + if (!NetUtils.isValidIp6Cidr(ip6SuperCidr)) { + throw new InvalidParameterValueException("Please enter a valid IPv6 cidr"); + } + + if (!NetUtils.isValidPrivateAsn(asNumber)) { + throw new InvalidParameterValueException(String.format("Please specify a valid private autonomous system number", ApiConstants.AUTONOMOUS_NUMBER)); + } + + // If IPv6 guest CIDR is configured, make sure that the CIDR/Private ASN is not duplicate. + if (checkDuplicateIp6SuperCidr && !isIp6SuperCidrAvailable(ip6SuperCidr)) { + throw new InvalidParameterValueException(String.format("A zone with %s already exists. Please specify a unique IPv6 Guest CIDR.", ip6SuperCidr)); + } + if (checkDuplicateAsn && !isAsnAvailable(asNumber)) { + throw new InvalidParameterValueException(String.format("A zone with %s already exists. Please specify a unique private ASN.", asNumber)); + } + } else if (StringUtils.isNotBlank(asNumber)) { + throw new InvalidParameterValueException(String.format("%s parameter can not be set if IPv6 super CIDR is not configured", ApiConstants.AUTONOMOUS_NUMBER)); + } + } + private AffinityGroup createDedicatedAffinityGroup(String affinityGroupName, final Long domainId, final Long accountId) { if (affinityGroupName == null) { // default to a groupname with account/domain information @@ -1937,6 +1981,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati final String internalDns1 = cmd.getInternalDns1(); final String internalDns2 = cmd.getInternalDns2(); final String guestCidr = cmd.getGuestCidrAddress(); + final String ip6SuperCidr = cmd.getIp6SuperCidrAddress(); + final String asNumber = cmd.getAsNumber(); final Long domainId = cmd.getDomainId(); final String type = cmd.getNetworkType(); Boolean isBasic = false; @@ -1958,8 +2004,16 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati final NetworkType zoneType = isBasic ? NetworkType.Basic : NetworkType.Advanced; // error out when the parameter specified for Basic zone - if (zoneType == NetworkType.Basic && guestCidr != null) { - throw new InvalidParameterValueException("guestCidrAddress parameter is not supported for Basic zone"); + if (zoneType == NetworkType.Basic) { + if (StringUtils.isNotBlank(guestCidr)) { + throw new InvalidParameterValueException(String.format("%s parameter is not supported for Basic zone", ApiConstants.GUEST_CIDR_ADDRESS)); + } + if (StringUtils.isNotBlank(ip6SuperCidr)) { + throw new InvalidParameterValueException(String.format("%s parameter is not supported for Basic zone", ApiConstants.IP6_SUPER_CIDR_ADDRESS)); + } + if (StringUtils.isNotBlank(asNumber)) { + throw new InvalidParameterValueException(String.format("%s parameter is not supported for Basic zone", ApiConstants.AUTONOMOUS_NUMBER)); + } } DomainVO domainVO = null; @@ -1972,8 +2026,8 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati isSecurityGroupEnabled = true; } - return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType, allocationState, - networkDomain, isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2); + return createZone(userId, zoneName, dns1, dns2, internalDns1, internalDns2, guestCidr, domainVO != null ? domainVO.getName() : null, domainId, zoneType, allocationState, networkDomain, + isSecurityGroupEnabled, isLocalStorageEnabled, ip6Dns1, ip6Dns2, ip6SuperCidr, asNumber); } @Override @@ -3742,6 +3796,14 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati return _zoneDao.findById(zoneId) != null; } + private boolean isIp6SuperCidrAvailable(String ip6SuperCidr) { + return (_zoneDao.findByIp6SuperCidr(ip6SuperCidr) == null); + } + + private boolean isAsnAvailable(String asNumber) { + return (_zoneDao.findByAsn(asNumber) == null); + } + private String getZoneName(final long zoneId) { final DataCenterVO zone = _zoneDao.findById(new Long(zoneId)); if (zone != null) { http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/server/test/com/cloud/configuration/ConfigurationManagerTest.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/configuration/ConfigurationManagerTest.java b/server/test/com/cloud/configuration/ConfigurationManagerTest.java index 5926a34..1125050 100644 --- a/server/test/com/cloud/configuration/ConfigurationManagerTest.java +++ b/server/test/com/cloud/configuration/ConfigurationManagerTest.java @@ -33,6 +33,7 @@ import java.util.Map; import java.util.UUID; import com.cloud.user.User; + import org.apache.log4j.Logger; import org.junit.After; import org.junit.Assert; @@ -533,4 +534,82 @@ public class ConfigurationManagerTest { Mockito.when(_accountMgr.getAccount(1l)).thenReturn(account); Assert.assertNotNull(configurationMgr.getVlanAccount(42l)); } + + @Test + public void validateIp6Parameters() { + + //Validate Zone create + //** with no IPv6 + validateIp6ParameterTest(false, null, null, null, null, true, true, true, "Zone create with no IPv6 parameters should be accepted"); + + //** with invalid IPv6 DNS1 and invalid IPv6 DNS2 + validateIp6ParameterTest(true, "8.8.8.8", "8.8.4.4", null, null, true, true, true, "Zone create with invalid IPv6 DNS1/DNS1 parameters should not be accepted"); + + //** with valid IPv6 DNS1 and DNS2 + validateIp6ParameterTest(false, "2620:0:ccc::2", "2620:0:ccd::2", null, null, true, true, true, "Zone create with valid IPv6 DNS1/DNS1 parameters should be accepted"); + + //** with valid IPv6 DNS and invalid IPv6 Super Cidr + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "8.8.8.8", null, true, true, true, "Zone create with valid IPv6 DNS1/DNS1 and invalid IPv6 Super CIDR parameters should not be accepted"); + + //** with valid IPv6 DNS, valid IPv6 Super Cidr and invalid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "6500", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, IPv6 Super CIDR and invalid asNumber parameters should not be accepted"); + + //** with valid IPv6 DNS, valid IPv6 Super Cidr and no asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", null, true, true, true, "Zone create with valid IPv6 DNS1/DNS1, IPv6 Super CIDR and no asNumber parameters should not be accepted"); + + //** with valid IPv6 DNS, invalid IPv6 Super Cidr and valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0:0/50", "65000", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, invalid IPv6 Super CIDR and valid asNumber parameters should not be accepted"); + + //** with valid IPv6 DNS, no IPv6 Super Cidr and valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "", "65000", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, no IPv6 Super CIDR and valid asNumber parameters should not be accepted"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(null); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(null); + //** with valid IPv6 DNS, Unique valid IPv6 Super Cidr and Unique valid asNumber + validateIp6ParameterTest(false, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, unique IPv6 Super CIDR and asNumber parameters should be accepted"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(null); + //** with valid IPv6 DNS, duplicate valid IPv6 Super Cidr and Unique valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, with duplicate IPv6 Super CIDR and unique asNumber parameters should not be accepted"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(null); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + //** with valid IPv6 DNS, Unique valid IPv6 Super Cidr and duplicate valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", true, true, true, "Zone create with valid IPv6 DNS1/DNS1, with unique IPv6 Super CIDR and duplicate asNumber parameters should not be accepted"); + + //Validate Zone Edit which check no duplicate + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(null); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(null); + //** with valid IPv6 DNS, Unique valid IPv6 Super Cidr and Unique valid asNumber + validateIp6ParameterTest(false, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", false, false, false, "Zone create with valid IPv6 DNS1/DNS1, unique IPv6 Super CIDR and asNumber parameters should be accepted with no duplicate checks"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + //** with valid IPv6 DNS, duplicate valid IPv6 Super Cidr and duplicate valid asNumber, with no duplicate checks. + validateIp6ParameterTest(false, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", false, false, false, "Zone create with valid IPv6 DNS1/DNS1, duplicate IPv6 Super CIDR and asNumber parameters should be accepted with no duplicate checks"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(null); + //** with valid IPv6 DNS, duplicate valid IPv6 Super Cidr and Unique valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", false, true, false, "Zone create with valid IPv6 DNS1/DNS1, duplicate IPv6 Super CIDR and unique asNumber parameters should not be accepted with no duplicate checks"); + + when(configurationMgr._zoneDao.findByIp6SuperCidr(anyString())).thenReturn(null); + when(configurationMgr._zoneDao.findByAsn(anyString())).thenReturn(new DataCenterVO(0l, null, null, null, null, null, null, null, null, null, null, null, null)); + //** with valid IPv6 DNS, Unique valid IPv6 Super Cidr and duplicate valid asNumber + validateIp6ParameterTest(true, "2620:0:ccc::2", "2620:0:ccd::2", "2001:67c:2834:0:0:0:0:0/50", "65000", false, false, true, "Zone create with valid IPv6 DNS1/DNS1, unique IPv6 Super CIDR and duplicate asNumber parameters should not be accepted"); + + } + + private void validateIp6ParameterTest(boolean shouldConditionFail, String ip6Dns1, String ip6Dns2, String ip6SuperCidr, String asNumber, boolean checkDuplicateName, + boolean checkDuplicateIp6SuperCidr, boolean checkDuplicateAsn, String message) { + boolean validationCheck = shouldConditionFail; + try { + configurationMgr.validateIp6Parameters(ip6Dns1, ip6Dns2, ip6SuperCidr, asNumber, checkDuplicateName, checkDuplicateIp6SuperCidr, checkDuplicateAsn); + } catch (InvalidParameterValueException e) { + validationCheck = !shouldConditionFail; + } + Assert.assertFalse(message, validationCheck); + } } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java ---------------------------------------------------------------------- diff --git a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java index fc535bd..7bac9b6 100644 --- a/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java +++ b/server/test/com/cloud/vpc/MockConfigurationManagerImpl.java @@ -505,9 +505,9 @@ public class MockConfigurationManagerImpl extends ManagerBase implements Configu * @see com.cloud.configuration.ConfigurationManager#createZone(long, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.Long, com.cloud.dc.DataCenter.NetworkType, java.lang.String, java.lang.String, boolean, boolean) */ @Override - public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, - Long domainId, NetworkType zoneType, String allocationState, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled, String ip6Dns1, - String ip6Dns2) { + public DataCenterVO createZone(long userId, String zoneName, String dns1, String dns2, String internalDns1, String internalDns2, String guestCidr, String domain, Long domainId, + NetworkType zoneType, String allocationState, String networkDomain, boolean isSecurityGroupEnabled, boolean isLocalStorageEnabled, String ip6Dns1, String ip6Dns2, + String ip6SuperCidr, String asNumber) { // TODO Auto-generated method stub return null; } http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/tools/marvin/marvin/deployDataCenter.py ---------------------------------------------------------------------- diff --git a/tools/marvin/marvin/deployDataCenter.py b/tools/marvin/marvin/deployDataCenter.py index 4fcd696..b8725a9 100644 --- a/tools/marvin/marvin/deployDataCenter.py +++ b/tools/marvin/marvin/deployDataCenter.py @@ -704,6 +704,10 @@ class DeployDataCenters(object): zonecmd.domain = zone.domain if zone.securitygroupenabled != "true": zonecmd.guestcidraddress = zone.guestcidraddress + if zone.asNumber != "": + zonecmd.asNumber = zone.asNumber + if zone.ip6supercidraddress != "": + zonecmd.ip6supercidraddress = zone.ip6supercidraddress zoneId = self.createZone(zonecmd) if zoneId == FAILED: self.__tcRunLogger.\ http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/utils/src/com/cloud/utils/net/NetUtils.java ---------------------------------------------------------------------- diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index 2cd4753..e263dce 100644 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -31,6 +31,7 @@ import java.net.URI; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Formatter; +import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; @@ -40,6 +41,7 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.commons.net.util.SubnetUtils; import org.apache.commons.validator.routines.InetAddressValidator; @@ -51,6 +53,7 @@ import com.cloud.utils.script.Script; import com.googlecode.ipv6.IPv6Address; import com.googlecode.ipv6.IPv6AddressRange; import com.googlecode.ipv6.IPv6Network; +import com.googlecode.ipv6.IPv6NetworkMask; public class NetUtils { protected final static Logger s_logger = Logger.getLogger(NetUtils.class); @@ -1399,6 +1402,16 @@ public class NetUtils { return resultIp; } + /** + * Split a given IPv6 CIDR into multiple subnets based on the given prefix length + * @param ip6SuperNetworkCidr + * @param prefixLength + * @return Iterator + */ + public static Iterator splitIp6Network(String ip6NetworkCidr, int prefixLength) { + return IPv6Network.fromString(ip6NetworkCidr).split(IPv6NetworkMask.fromPrefixLength(prefixLength)); + } + public static String standardizeIp6Address(final String ip6Addr) { try { return IPv6Address.fromString(ip6Addr).toString(); @@ -1415,6 +1428,23 @@ public class NetUtils { } } + /** + * Validate if asNumber is in valid private ASN range as defined in rfc6996 + * @param asNumber + * @return true if valid + */ + public static boolean isValidPrivateAsn(String asNumber) { + if (StringUtils.isNotBlank(asNumber)) { + try { + Long asNumberLong = Long.parseLong(asNumber); + return ((asNumberLong >= 64512 && asNumberLong <= 65534) || (asNumberLong >= 4200000000l && asNumberLong <= 4294967294l)); + } catch (NumberFormatException nfe) { + return false; + } + } + return false; + } + static final String VLAN_PREFIX = "vlan://"; static final int VLAN_PREFIX_LENGTH = VLAN_PREFIX.length(); http://git-wip-us.apache.org/repos/asf/cloudstack/blob/eb6c990b/utils/test/com/cloud/utils/net/NetUtilsTest.java ---------------------------------------------------------------------- diff --git a/utils/test/com/cloud/utils/net/NetUtilsTest.java b/utils/test/com/cloud/utils/net/NetUtilsTest.java index 1ab4459..44fd91a 100644 --- a/utils/test/com/cloud/utils/net/NetUtilsTest.java +++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java @@ -32,6 +32,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.math.BigInteger; +import java.util.Iterator; import java.util.SortedSet; import java.util.TreeSet; @@ -39,6 +40,7 @@ import org.apache.log4j.Logger; import org.junit.Test; import com.googlecode.ipv6.IPv6Address; +import com.googlecode.ipv6.IPv6Network; public class NetUtilsTest { @@ -418,4 +420,21 @@ public class NetUtilsTest { assertTrue("It should pass! 31 bit prefix.", is31PrefixCidr); } + + @Test + public void testIp6NetworkSplit() { + Iterator ipv6networks = NetUtils.splitIp6Network("2001:67c:2834:0:0:0:0:0/50", 60); + assertTrue("IPv6 address should be split with out error", ipv6networks.hasNext()); + } + + @Test + public void testValidAsn() { + assertTrue("65000 is a valid private ASN", NetUtils.isValidPrivateAsn("65000")); + assertTrue("4200000000l is a valid private ASN", NetUtils.isValidPrivateAsn("4200000000")); + + assertFalse("6500 is an invalid ASN", NetUtils.isValidPrivateAsn("6500")); + assertFalse("null is an invalid ASN", NetUtils.isValidPrivateAsn(null)); + assertFalse("empty string is an invalid ASN", NetUtils.isValidPrivateAsn("")); + assertFalse("abc string is an invalid ASN", NetUtils.isValidPrivateAsn("abc")); + } } \ No newline at end of file