Skip to content

Commit 0c5c08b

Browse files
author
Sheng Yang
committed
IPv6: CLOUDSTACK-1107: Add support for createVlanIpRange to extend existed network
1 parent 1cf85aa commit 0c5c08b

7 files changed

Lines changed: 159 additions & 53 deletions

File tree

api/src/com/cloud/network/NetworkModel.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import com.cloud.dc.Vlan;
2626
import com.cloud.exception.InsufficientAddressCapacityException;
27+
import com.cloud.exception.InvalidParameterValueException;
2728
import com.cloud.hypervisor.Hypervisor.HypervisorType;
2829
import com.cloud.network.Network.Capability;
2930
import com.cloud.network.Network.Provider;
@@ -252,4 +253,6 @@ Map<PublicIpAddress, Set<Service>> getIpToServices(List<? extends PublicIpAddres
252253
boolean isIP6AddressAvailableInNetwork(long networkId);
253254

254255
boolean isIP6AddressAvailableInVlan(long vlanId);
256+
257+
void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException;
255258
}

api/src/org/apache/cloudstack/api/command/admin/vlan/CreateVlanIpRangeCmd.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
7575
description="optional parameter. Have to be specified for Direct Untagged vlan only.")
7676
private Long podId;
7777

78-
@Parameter(name=ApiConstants.START_IP, type=CommandType.STRING, required=true, description="the beginning IP address in the VLAN IP range")
78+
@Parameter(name=ApiConstants.START_IP, type=CommandType.STRING, description="the beginning IP address in the VLAN IP range")
7979
private String startIp;
8080

8181
@Parameter(name=ApiConstants.VLAN, type=CommandType.STRING, description="the ID or VID of the VLAN. If not specified," +
@@ -94,6 +94,19 @@ public class CreateVlanIpRangeCmd extends BaseCmd {
9494
description="the physical network id")
9595
private Long physicalNetworkId;
9696

97+
@Parameter(name=ApiConstants.START_IPV6, type=CommandType.STRING, description="the beginning IPv6 address in the IPv6 network range")
98+
private String startIpv6;
99+
100+
@Parameter(name=ApiConstants.END_IPV6, type=CommandType.STRING, description="the ending IPv6 address in the IPv6 network range")
101+
private String endIpv6;
102+
103+
@Parameter(name=ApiConstants.IP6_GATEWAY, type=CommandType.STRING, description="the gateway of the IPv6 network. Required " +
104+
"for Shared networks and Isolated networks when it belongs to VPC")
105+
private String ip6Gateway;
106+
107+
@Parameter(name=ApiConstants.IP6_CIDR, type=CommandType.STRING, description="the CIDR of IPv6 network, must be at least /64")
108+
private String ip6Cidr;
109+
97110
/////////////////////////////////////////////////////
98111
/////////////////// Accessors ///////////////////////
99112
/////////////////////////////////////////////////////
@@ -141,6 +154,35 @@ public Long getZoneId() {
141154
public Long getProjectId() {
142155
return projectId;
143156
}
157+
158+
public String getStartIpv6() {
159+
if (startIpv6 == null) {
160+
return null;
161+
}
162+
return startIpv6.toLowerCase();
163+
}
164+
165+
public String getEndIpv6() {
166+
if (endIpv6 == null) {
167+
return null;
168+
}
169+
return endIpv6.toLowerCase();
170+
}
171+
172+
public String getIp6Gateway() {
173+
if (ip6Gateway == null) {
174+
return null;
175+
}
176+
return ip6Gateway.toLowerCase();
177+
}
178+
179+
public String getIp6Cidr() {
180+
if (ip6Cidr == null) {
181+
return null;
182+
}
183+
return ip6Cidr.toLowerCase();
184+
}
185+
144186
/////////////////////////////////////////////////////
145187
/////////////// API Implementation///////////////////
146188
/////////////////////////////////////////////////////
@@ -153,7 +195,6 @@ public Long getPhysicalNetworkId() {
153195
return physicalNetworkId;
154196
}
155197

156-
157198
@Override
158199
public String getCommandName() {
159200
return s_name;

server/src/com/cloud/configuration/ConfigurationManagerImpl.java

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,13 +2073,34 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
20732073
String accountName = cmd.getAccountName();
20742074
Long projectId = cmd.getProjectId();
20752075
Long domainId = cmd.getDomainId();
2076+
String startIPv6 = cmd.getStartIpv6();
2077+
String endIPv6 = cmd.getEndIpv6();
2078+
String ip6Gateway = cmd.getIp6Gateway();
2079+
String ip6Cidr = cmd.getIp6Cidr();
2080+
20762081
Account vlanOwner = null;
20772082

2078-
// if end ip is not specified, default it to startIp
2079-
if (endIP == null && startIP != null) {
2080-
endIP = startIP;
2083+
boolean ipv4 = (startIP != null);
2084+
boolean ipv6 = (startIPv6 != null);
2085+
2086+
if (!ipv4 && !ipv6) {
2087+
throw new InvalidParameterValueException("StartIP or StartIPv6 is missing in the parameters!");
20812088
}
2082-
2089+
2090+
if (ipv4) {
2091+
// if end ip is not specified, default it to startIp
2092+
if (endIP == null && startIP != null) {
2093+
endIP = startIP;
2094+
}
2095+
}
2096+
2097+
if (ipv6) {
2098+
// if end ip is not specified, default it to startIp
2099+
if (endIPv6 == null && startIPv6 != null) {
2100+
endIPv6 = startIPv6;
2101+
}
2102+
}
2103+
20832104
if (projectId != null) {
20842105
if (accountName != null) {
20852106
throw new InvalidParameterValueException("Account and projectId are mutually exclusive");
@@ -2109,6 +2130,8 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
21092130
zoneId = network.getDataCenterId();
21102131
physicalNetworkId = network.getPhysicalNetworkId();
21112132
}
2133+
} else if (ipv6) {
2134+
throw new InvalidParameterValueException("Only support IPv6 on extending existed network");
21122135
}
21132136

21142137
// Verify that zone exists
@@ -2117,6 +2140,11 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
21172140
throw new InvalidParameterValueException("Unable to find zone by id " + zoneId);
21182141
}
21192142

2143+
if (ipv6) {
2144+
if (network.getGuestType() != GuestType.Shared || zone.isSecurityGroupEnabled()) {
2145+
throw new InvalidParameterValueException("Only support IPv6 on extending existed share network without SG");
2146+
}
2147+
}
21202148
// verify that physical network exists
21212149
PhysicalNetworkVO pNtwk = null;
21222150
if (physicalNetworkId != null) {
@@ -2163,7 +2191,7 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
21632191
if (zone.isSecurityGroupEnabled() && zone.getNetworkType() != DataCenter.NetworkType.Basic && forVirtualNetwork) {
21642192
throw new InvalidParameterValueException("Can't add virtual ip range into a zone with security group enabled");
21652193
}
2166-
2194+
21672195
// If networkId is not specified, and vlan is Virtual or Direct Untagged, try to locate default networks
21682196
if (forVirtualNetwork) {
21692197
if (network == null) {
@@ -2196,11 +2224,6 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
21962224
throw new InvalidParameterValueException("Network " + network + " doesn't support adding ip ranges");
21972225
}
21982226

2199-
// if end ip is not specified, default it to startIp
2200-
if (endIP == null && startIP != null) {
2201-
endIP = startIP;
2202-
}
2203-
22042227
if ( zone.getNetworkType() == DataCenter.NetworkType.Advanced ) {
22052228
if (network.getTrafficType() == TrafficType.Guest) {
22062229
if (network.getGuestType() != GuestType.Shared) {
@@ -2216,19 +2239,38 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
22162239
throw new InvalidParameterValueException("there is already one vlan " + vlan.getVlanTag() + " on network :" +
22172240
+ network.getId() + ", only one vlan is allowed on guest network");
22182241
}
2219-
vlanGateway = vlan.getVlanGateway();
2220-
vlanNetmask = vlan.getVlanNetmask();
2242+
if (ipv4) {
2243+
vlanGateway = vlan.getVlanGateway();
2244+
vlanNetmask = vlan.getVlanNetmask();
2245+
// Check if ip addresses are in network range
2246+
if (!NetUtils.sameSubnet(startIP, vlanGateway, vlanNetmask)) {
2247+
throw new InvalidParameterValueException("Start ip is not in vlan range!");
2248+
}
2249+
if (!NetUtils.sameSubnet(endIP, vlanGateway, vlanNetmask)) {
2250+
throw new InvalidParameterValueException("End ip is not in vlan range!");
2251+
}
2252+
}
2253+
if (ipv6) {
2254+
if (ip6Gateway != null && !ip6Gateway.equals(network.getIp6Gateway())) {
2255+
throw new InvalidParameterValueException("The input gateway " + ip6Gateway + " is not same as network gateway " + network.getIp6Gateway());
2256+
}
2257+
if (ip6Cidr != null && !ip6Cidr.equals(network.getIp6Cidr())) {
2258+
throw new InvalidParameterValueException("The input cidr " + ip6Cidr + " is not same as network ciddr " + network.getIp6Cidr());
2259+
}
2260+
ip6Gateway = network.getIp6Gateway();
2261+
ip6Cidr = network.getIp6Cidr();
2262+
_networkModel.checkIp6Parameters(startIPv6, endIPv6, ip6Gateway, ip6Cidr);
2263+
}
22212264
}
22222265
} else if (network.getTrafficType() == TrafficType.Management) {
22232266
throw new InvalidParameterValueException("Cannot execute createVLANIpRanges on management network");
22242267
}
22252268
}
22262269

2227-
if (vlanGateway == null || vlanNetmask == null || zoneId == null) {
2270+
if (zoneId == null || (ipv4 && (vlanGateway == null || vlanNetmask == null)) || (ipv6 && (ip6Gateway == null || ip6Cidr == null))) {
22282271
throw new InvalidParameterValueException("Gateway, netmask and zoneId have to be passed in for virtual and direct untagged networks");
22292272
}
22302273

2231-
22322274
// if it's an account specific range, associate ip address list to the account
22332275
boolean associateIpRangeToAccount = false;
22342276

@@ -2245,12 +2287,14 @@ public Vlan createVlanAndPublicIpRange(CreateVlanIpRangeCmd cmd) throws Insuffic
22452287
}
22462288

22472289
// Check if the IP range overlaps with the private ip
2248-
checkOverlapPrivateIpRange(zoneId, startIP, endIP);
2290+
if (ipv4) {
2291+
checkOverlapPrivateIpRange(zoneId, startIP, endIP);
2292+
}
22492293
Transaction txn = Transaction.currentTxn();
22502294
txn.start();
22512295

22522296
Vlan vlan = createVlanAndPublicIpRange(zoneId, networkId, physicalNetworkId, forVirtualNetwork, podId, startIP,
2253-
endIP, vlanGateway, vlanNetmask, vlanId, vlanOwner, null, null, null, null);
2297+
endIP, vlanGateway, vlanNetmask, vlanId, vlanOwner, startIPv6, endIPv6, ip6Gateway, ip6Cidr);
22542298

22552299
if (associateIpRangeToAccount) {
22562300
_networkMgr.associateIpAddressListToAccount(userId, vlanOwner.getId(), zoneId, vlan.getId(), null);

server/src/com/cloud/network/NetworkModelImpl.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,4 +1876,40 @@ public boolean isNetworkInlineMode(Network network) {
18761876
return offering.isInline();
18771877
}
18781878

1879+
@Override
1880+
public void checkIp6Parameters(String startIPv6, String endIPv6,
1881+
String ip6Gateway, String ip6Cidr) throws InvalidParameterValueException {
1882+
if (!NetUtils.isValidIpv6(startIPv6)) {
1883+
throw new InvalidParameterValueException("Invalid format for the startIPv6 parameter");
1884+
}
1885+
if (!NetUtils.isValidIpv6(endIPv6)) {
1886+
throw new InvalidParameterValueException("Invalid format for the endIPv6 parameter");
1887+
}
1888+
1889+
if (!(ip6Gateway != null && ip6Cidr != null)) {
1890+
throw new InvalidParameterValueException("ip6Gateway and ip6Cidr should be defined when startIPv6/endIPv6 are passed in");
1891+
}
1892+
1893+
if (!NetUtils.isValidIpv6(ip6Gateway)) {
1894+
throw new InvalidParameterValueException("Invalid ip6Gateway");
1895+
}
1896+
if (!NetUtils.isValidIp6Cidr(ip6Cidr)) {
1897+
throw new InvalidParameterValueException("Invalid ip6cidr");
1898+
}
1899+
if (!NetUtils.isIp6InNetwork(startIPv6, ip6Cidr)) {
1900+
throw new InvalidParameterValueException("startIPv6 is not in ip6cidr indicated network!");
1901+
}
1902+
if (!NetUtils.isIp6InNetwork(endIPv6, ip6Cidr)) {
1903+
throw new InvalidParameterValueException("endIPv6 is not in ip6cidr indicated network!");
1904+
}
1905+
if (!NetUtils.isIp6InNetwork(ip6Gateway, ip6Cidr)) {
1906+
throw new InvalidParameterValueException("ip6Gateway is not in ip6cidr indicated network!");
1907+
}
1908+
1909+
int cidrSize = NetUtils.getIp6CidrSize(ip6Cidr);
1910+
// Ipv6 cidr limit should be at least /64
1911+
if (cidrSize < 64) {
1912+
throw new InvalidParameterValueException("The cidr size of IPv6 network must be no less than 64 bits!");
1913+
}
1914+
}
18791915
}

server/src/com/cloud/network/NetworkServiceImpl.java

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -761,43 +761,11 @@ public Network createGuestNetwork(CreateNetworkCmd cmd) throws InsufficientCapac
761761
}
762762

763763
if (ipv6) {
764-
if (!NetUtils.isValidIpv6(startIPv6)) {
765-
throw new InvalidParameterValueException("Invalid format for the startIPv6 parameter");
766-
}
767764
if (endIPv6 == null) {
768765
endIPv6 = startIPv6;
769-
} else if (!NetUtils.isValidIpv6(endIPv6)) {
770-
throw new InvalidParameterValueException("Invalid format for the endIPv6 parameter");
771-
}
772-
773-
if (!(ip6Gateway != null && ip6Cidr != null)) {
774-
throw new InvalidParameterValueException("ip6Gateway and ip6Cidr should be defined when startIPv6/endIPv6 are passed in");
775766
}
767+
_networkModel.checkIp6Parameters(startIPv6, endIPv6, ip6Gateway, ip6Cidr);
776768

777-
if (!NetUtils.isValidIpv6(ip6Gateway)) {
778-
throw new InvalidParameterValueException("Invalid ip6Gateway");
779-
}
780-
if (!NetUtils.isValidIp6Cidr(ip6Cidr)) {
781-
throw new InvalidParameterValueException("Invalid ip6cidr");
782-
}
783-
if (!NetUtils.isIp6InNetwork(startIPv6, ip6Cidr)) {
784-
throw new InvalidParameterValueException("startIPv6 is not in ip6cidr indicated network!");
785-
}
786-
if (!NetUtils.isIp6InNetwork(endIPv6, ip6Cidr)) {
787-
throw new InvalidParameterValueException("endIPv6 is not in ip6cidr indicated network!");
788-
}
789-
if (!NetUtils.isIp6InNetwork(ip6Gateway, ip6Cidr)) {
790-
throw new InvalidParameterValueException("ip6Gateway is not in ip6cidr indicated network!");
791-
}
792-
793-
int cidrSize = NetUtils.getIp6CidrSize(ip6Cidr);
794-
// Ipv6 cidr limit should be at least /64
795-
if (cidrSize < 64) {
796-
throw new InvalidParameterValueException("The cidr size of IPv6 network must be no less than 64 bits!");
797-
}
798-
}
799-
800-
if (ipv6) {
801769
if (zone.getNetworkType() != NetworkType.Advanced || ntwkOff.getGuestType() != Network.GuestType.Shared) {
802770
throw new InvalidParameterValueException("Can only support create IPv6 network with advance shared network!");
803771
}
@@ -2942,10 +2910,8 @@ private NetworkOfferingVO findSystemNetworkOffering(String offeringName) {
29422910
return null;
29432911
}
29442912

2945-
29462913
@Override
29472914
public Network getNetwork(String networkUuid) {
29482915
return _networksDao.findByUuid(networkUuid);
29492916
}
2950-
29512917
}

server/test/com/cloud/network/MockNetworkModelImpl.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import com.cloud.dc.Vlan;
2929
import com.cloud.exception.InsufficientAddressCapacityException;
30+
import com.cloud.exception.InvalidParameterValueException;
3031
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3132
import com.cloud.network.Network.Capability;
3233
import com.cloud.network.Network.GuestType;
@@ -820,4 +821,12 @@ public boolean isIP6AddressAvailableInVlan(long vlanId) {
820821
// TODO Auto-generated method stub
821822
return false;
822823
}
824+
825+
@Override
826+
public void checkIp6Parameters(String startIPv6, String endIPv6,
827+
String ip6Gateway, String ip6Cidr)
828+
throws InvalidParameterValueException {
829+
// TODO Auto-generated method stub
830+
831+
}
823832
}

server/test/com/cloud/vpc/MockNetworkModelImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import com.cloud.dc.Vlan;
3030
import com.cloud.exception.InsufficientAddressCapacityException;
31+
import com.cloud.exception.InvalidParameterValueException;
3132
import com.cloud.hypervisor.Hypervisor.HypervisorType;
3233
import com.cloud.network.IpAddress;
3334
import com.cloud.network.Network;
@@ -835,4 +836,10 @@ public boolean isIP6AddressAvailableInVlan(long vlanId) {
835836
return false;
836837
}
837838

839+
@Override
840+
public void checkIp6Parameters(String startIPv6, String endIPv6, String ip6Gateway, String ip6Cidr)
841+
throws InvalidParameterValueException {
842+
// TODO Auto-generated method stub
843+
}
844+
838845
}

0 commit comments

Comments
 (0)