Skip to content

Commit 86827f8

Browse files
Update CIDR/Gateway of the Shared Networks from Guest IP ranges (#11249)
1 parent f6ad184 commit 86827f8

File tree

5 files changed

+161
-35
lines changed

5 files changed

+161
-35
lines changed

engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,3 +659,8 @@ CALL `cloud`.`INSERT_EXTENSION_CUSTOM_ACTION_DETAILS_IF_NOT_EXISTS`(
659659
'Resume',
660660
'[]'
661661
);
662+
663+
ALTER TABLE `cloud`.`networks` MODIFY COLUMN `cidr` varchar(255) DEFAULT NULL COMMENT 'CloudStack managed vms get IP address from cidr.In general this cidr also serves as the network CIDR. But in case IP reservation feature is being used by a Guest network, networkcidr is the Effective network CIDR for that network';
664+
ALTER TABLE `cloud`.`networks` MODIFY COLUMN `gateway` varchar(255) DEFAULT NULL COMMENT 'gateway(s) for this network configuration';
665+
ALTER TABLE `cloud`.`networks` MODIFY COLUMN `ip6_cidr` varchar(1024) DEFAULT NULL COMMENT 'IPv6 cidr(s) for this network';
666+
ALTER TABLE `cloud`.`networks` MODIFY COLUMN `ip6_gateway` varchar(1024) DEFAULT NULL COMMENT 'IPv6 gateway(s) for this network';

plugins/network-elements/bigswitch/src/main/java/com/cloud/network/element/BigSwitchBcfElement.java

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm
237237
// get arguments for CreateBcfAttachmentCommand
238238
// determine whether this is VPC network or stand-alone network
239239
Vpc vpc = null;
240-
if(network.getVpcId()!=null){
240+
if (network.getVpcId() != null) {
241241
vpc = _vpcDao.acquireInLockTable(network.getVpcId());
242242
}
243243

@@ -264,7 +264,7 @@ public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm
264264
String vmwareVswitchLabel = _networkModel.getDefaultGuestTrafficLabel(zoneId, HypervisorType.VMware);
265265
String[] labelArray = null;
266266
String vswitchName = null;
267-
if(vmwareVswitchLabel!=null){
267+
if (vmwareVswitchLabel != null) {
268268
labelArray=vmwareVswitchLabel.split(",");
269269
vswitchName = labelArray[0];
270270
}
@@ -273,9 +273,9 @@ public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile vm
273273
// kvm: ivs port name
274274
// vmware: specific portgroup naming convention
275275
String pgName = "";
276-
if (dest.getHost().getHypervisorType() == HypervisorType.KVM){
276+
if (dest.getHost().getHypervisorType() == HypervisorType.KVM) {
277277
pgName = hostname;
278-
} else if (dest.getHost().getHypervisorType() == HypervisorType.VMware){
278+
} else if (dest.getHost().getHypervisorType() == HypervisorType.VMware) {
279279
pgName = hostname + "-" + vswitchName;
280280
}
281281

@@ -306,7 +306,7 @@ public boolean release(Network network, NicProfile nic, VirtualMachineProfile vm
306306
String nicId = nic.getUuid();
307307

308308
String tenantId;
309-
if(network.getVpcId()!=null) {
309+
if (network.getVpcId() != null) {
310310
tenantId = network.getNetworkDomain();
311311
} else {
312312
tenantId = networkId;
@@ -439,16 +439,16 @@ public BigSwitchBcfDeviceVO addBigSwitchBcfDevice(AddBigSwitchBcfDeviceCmd cmd)
439439

440440
DataCenterVO zone = _zoneDao.findById(physicalNetwork.getDataCenterId());
441441
String zoneName;
442-
if(zone!= null){
442+
if (zone != null) {
443443
zoneName = zone.getName();
444444
} else {
445445
zoneName = String.valueOf(zoneId);
446446
}
447447

448448
Boolean natNow = _bcfUtils.isNatEnabled();
449-
if (!nat && natNow){
449+
if (!nat && natNow) {
450450
throw new CloudRuntimeException("NAT is enabled in existing controller. Enable NAT for new controller or remove existing controller first.");
451-
} else if (nat && !natNow){
451+
} else if (nat && !natNow) {
452452
throw new CloudRuntimeException("NAT is disabled in existing controller. Disable NAT for new controller or remove existing controller first.");
453453
}
454454

@@ -582,7 +582,7 @@ public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] st
582582
BigSwitchBcfResource bcfResource = (BigSwitchBcfResource) resource;
583583
bcfUtilsInit();
584584

585-
if(_bcfUtils.getTopology()!=null){
585+
if (_bcfUtils.getTopology() != null) {
586586
bcfResource.setTopology(_bcfUtils.getTopology());
587587
}
588588

@@ -621,7 +621,7 @@ public boolean applyStaticNats(Network network,
621621
_bcfUtils.listACLbyNetwork(network);
622622

623623
Vpc vpc = null;
624-
if(network.getVpcId()!=null){
624+
if (network.getVpcId() != null) {
625625
vpc = _vpcDao.acquireInLockTable(network.getVpcId());
626626
}
627627

@@ -635,11 +635,11 @@ public boolean applyStaticNats(Network network,
635635
tenantId = network.getUuid();
636636
}
637637

638-
for (StaticNat rule: rules){
638+
for (StaticNat rule: rules) {
639639
String srcIp = _ipAddressDao.findById(rule.getSourceIpAddressId()).getAddress().addr();
640640
String dstIp = rule.getDestIpAddress();
641641
String mac = rule.getSourceMacAddress();
642-
if(!rule.isForRevoke()) {
642+
if (!rule.isForRevoke()) {
643643
logger.debug("BCF enables static NAT for public IP: " + srcIp + " private IP " + dstIp
644644
+ " mac " + mac);
645645
CreateBcfStaticNatCommand cmd = new CreateBcfStaticNatCommand(
@@ -671,13 +671,13 @@ public boolean applyNetworkACLs(Network network,
671671
SubnetUtils utils;
672672
String cidr = null;
673673
List<String> cidrList;
674-
for(NetworkACLItem r: rules){
675-
if(r.getState()==NetworkACLItem.State.Revoke){
674+
for (NetworkACLItem r: rules) {
675+
if (r.getState() == NetworkACLItem.State.Revoke) {
676676
continue;
677677
}
678678
cidrList = r.getSourceCidrList();
679-
if(cidrList != null){
680-
if(cidrList.size()>1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())){
679+
if (cidrList != null) {
680+
if (cidrList.size() > 1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())) {
681681
throw new ResourceUnavailableException("One CIDR and one port only please.",
682682
Network.class, network.getId());
683683
} else {
@@ -688,7 +688,7 @@ public boolean applyNetworkACLs(Network network,
688688
cidr = "";
689689
} else {
690690
utils = new SubnetUtils(cidr);
691-
if(!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())){
691+
if (!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())) {
692692
throw new ResourceUnavailableException("Invalid CIDR in Network ACL rule.",
693693
Network.class, network.getId());
694694
}
@@ -710,13 +710,13 @@ public boolean applyFWRules(Network network,
710710
SubnetUtils utils;
711711
String cidr = null;
712712
List<String> cidrList;
713-
for(FirewallRule r: rules){
714-
if(r.getState()==FirewallRule.State.Revoke){
713+
for (FirewallRule r: rules) {
714+
if (r.getState() == FirewallRule.State.Revoke) {
715715
continue;
716716
}
717717
cidrList = r.getSourceCidrList();
718-
if(cidrList != null){
719-
if(cidrList.size()>1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())){
718+
if (cidrList != null) {
719+
if (cidrList.size()>1 || !r.getSourcePortEnd().equals(r.getSourcePortStart())) {
720720
throw new ResourceUnavailableException("One CIDR and one port only please.",
721721
Network.class, network.getId());
722722
} else {
@@ -727,7 +727,7 @@ public boolean applyFWRules(Network network,
727727
cidr = "";
728728
} else {
729729
utils = new SubnetUtils(cidr);
730-
if(!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())){
730+
if (!utils.getInfo().getNetworkAddress().equals(utils.getInfo().getAddress())) {
731731
throw new ResourceUnavailableException("Invalid CIDR in Firewall rule.",
732732
Network.class, network.getId());
733733
}
@@ -741,7 +741,7 @@ private void updateBcfRouter(Network network) throws IllegalArgumentException{
741741
bcfUtilsInit();
742742

743743
Vpc vpc = null;
744-
if(network.getVpcId()!=null){
744+
if (network.getVpcId() != null) {
745745
vpc = _vpcDao.acquireInLockTable(network.getVpcId());
746746
}
747747

@@ -756,23 +756,23 @@ private void updateBcfRouter(Network network) throws IllegalArgumentException{
756756
UpdateBcfRouterCommand cmd = new UpdateBcfRouterCommand(tenantId);
757757

758758
List<AclData> aclList = _bcfUtils.listACLbyNetwork(network);
759-
for(AclData acl: aclList){
759+
for (AclData acl: aclList) {
760760
cmd.addAcl(acl);
761761
}
762762

763-
if(vpc != null){
763+
if (vpc != null) {
764764
cmd.setPublicIp(_bcfUtils.getPublicIpByVpc(vpc));
765765
} else {
766766
cmd.setPublicIp(_bcfUtils.getPublicIpByNetwork(network));
767767
}
768768

769769
BcfAnswer answer = _bcfUtils.sendBcfCommandWithNetworkSyncCheck(cmd, network);
770-
if(answer != null && !answer.getResult()){
770+
if (answer != null && !answer.getResult()) {
771771
throw new IllegalArgumentException("Illegal router update arguments");
772772
}
773773
}
774774

775-
private void bcfUtilsInit(){
775+
private void bcfUtilsInit() {
776776
if (_bcfUtils == null) {
777777
_bcfUtils = new BigSwitchBcfUtils(_networkDao, _nicDao,
778778
_vmDao, _hostDao, _vpcDao, _bigswitchBcfDao,

server/src/main/java/com/cloud/api/ApiResponseHelper.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,10 +2539,11 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network)
25392539
response.setType(network.getGuestType().toString());
25402540
}
25412541

2542-
response.setGateway(network.getGateway());
2542+
response.setGateway(com.cloud.utils.StringUtils.getFirstValueFromCommaSeparatedString(network.getGateway()));
2543+
String cidr = com.cloud.utils.StringUtils.getFirstValueFromCommaSeparatedString(network.getCidr());
25432544

25442545
// FIXME - either set netmask or cidr
2545-
response.setCidr(network.getCidr());
2546+
response.setCidr(cidr);
25462547
if (network.getNetworkCidr() != null) {
25472548
response.setNetworkCidr((network.getNetworkCidr()));
25482549
}
@@ -2553,18 +2554,18 @@ public NetworkResponse createNetworkResponse(ResponseView view, Network network)
25532554
if (network.getNetworkCidr() != null) {
25542555
response.setNetmask(NetUtils.cidr2Netmask(network.getNetworkCidr()));
25552556
}
2556-
if (((network.getCidr()) != null) && (network.getNetworkCidr() == null)) {
2557-
response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
2557+
if ((cidr != null) && (network.getNetworkCidr() == null)) {
2558+
response.setNetmask(NetUtils.cidr2Netmask(cidr));
25582559
}
25592560

2560-
response.setIp6Gateway(network.getIp6Gateway());
2561-
response.setIp6Cidr(network.getIp6Cidr());
2561+
response.setIp6Gateway(com.cloud.utils.StringUtils.getFirstValueFromCommaSeparatedString(network.getIp6Gateway()));
2562+
response.setIp6Cidr(com.cloud.utils.StringUtils.getFirstValueFromCommaSeparatedString(network.getIp6Cidr()));
25622563

25632564
// create response for reserved IP ranges that can be used for
25642565
// non-cloudstack purposes
25652566
String reservation = null;
2566-
if ((network.getCidr() != null) && (NetUtils.isNetworkAWithinNetworkB(network.getCidr(), network.getNetworkCidr()))) {
2567-
String[] guestVmCidrPair = network.getCidr().split("\\/");
2567+
if ((cidr != null) && (NetUtils.isNetworkAWithinNetworkB(cidr, network.getNetworkCidr()))) {
2568+
String[] guestVmCidrPair = cidr.split("\\/");
25682569
String[] guestCidrPair = network.getNetworkCidr().split("\\/");
25692570

25702571
Long guestVmCidrSize = Long.valueOf(guestVmCidrPair[1]);

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

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5397,9 +5397,42 @@ public Vlan createVlanAndPublicIpRange(final long zoneId, final long networkId,
53975397
final VlanVO vlan = commitVlanAndIpRange(zoneId, networkId, physicalNetworkId, podId, startIP, endIP, vlanGateway, vlanNetmask, vlanId, domain, vlanOwner, vlanIp6Gateway, vlanIp6Cidr,
53985398
ipv4, zone, vlanType, ipv6Range, ipRange, forSystemVms, provider);
53995399

5400+
if (vlan != null) {
5401+
if (ipv4) {
5402+
addCidrAndGatewayForIpv4(networkId, vlanGateway, vlanNetmask);
5403+
} else if (ipv6) {
5404+
addCidrAndGatewayForIpv6(networkId, vlanIp6Gateway, vlanIp6Cidr);
5405+
}
5406+
}
5407+
54005408
return vlan;
54015409
}
54025410

5411+
private void addCidrAndGatewayForIpv4(final long networkId, final String vlanGateway, final String vlanNetmask) {
5412+
final NetworkVO networkVO = _networkDao.findById(networkId);
5413+
String networkCidr = networkVO.getCidr();
5414+
String newCidr = NetUtils.getCidrFromGatewayAndNetmask(vlanGateway, vlanNetmask);
5415+
String newNetworkCidr = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkCidr, newCidr, true);
5416+
networkVO.setCidr(newNetworkCidr);
5417+
5418+
String networkGateway = networkVO.getGateway();
5419+
String newNetworkGateway = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkGateway, vlanGateway, true);
5420+
networkVO.setGateway(newNetworkGateway);
5421+
_networkDao.update(networkId, networkVO);
5422+
}
5423+
5424+
private void addCidrAndGatewayForIpv6(final long networkId, final String vlanIp6Gateway, final String vlanIp6Cidr) {
5425+
final NetworkVO networkVO = _networkDao.findById(networkId);
5426+
String networkIp6Cidr = networkVO.getIp6Cidr();
5427+
String newNetworkIp6Cidr = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkIp6Cidr, vlanIp6Cidr, true);
5428+
networkVO.setIp6Cidr(newNetworkIp6Cidr);
5429+
5430+
String networkIp6Gateway = networkVO.getIp6Gateway();
5431+
String newNetworkIp6Gateway = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkIp6Gateway, vlanIp6Gateway, true);
5432+
networkVO.setIp6Gateway(newNetworkIp6Gateway);
5433+
_networkDao.update(networkId, networkVO);
5434+
}
5435+
54035436
private boolean isConnectivityWithoutVlan(Network network) {
54045437
boolean connectivityWithoutVlan = false;
54055438
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Connectivity)) {
@@ -6440,12 +6473,47 @@ public boolean deleteVlanIpRange(final DeleteVlanIpRangeCmd cmd) {
64406473
private boolean deleteAndPublishVlanAndPublicIpRange(final long userId, final long vlanDbId, final Account caller) {
64416474
VlanVO deletedVlan = deleteVlanAndPublicIpRange(userId, vlanDbId, caller);
64426475
if (deletedVlan != null) {
6476+
final boolean ipv4 = deletedVlan.getVlanGateway() != null;
6477+
final boolean ipv6 = deletedVlan.getIp6Gateway() != null;
6478+
final long networkId = deletedVlan.getNetworkId();
6479+
6480+
if (ipv4) {
6481+
removeCidrAndGatewayForIpv4(networkId, deletedVlan);
6482+
} else if (ipv6) {
6483+
removeCidrAndGatewayForIpv6(networkId, deletedVlan);
6484+
}
6485+
64436486
messageBus.publish(_name, MESSAGE_DELETE_VLAN_IP_RANGE_EVENT, PublishScope.LOCAL, deletedVlan);
64446487
return true;
64456488
}
64466489
return false;
64476490
}
64486491

6492+
private void removeCidrAndGatewayForIpv4(final long networkId, VlanVO deletedVlan) {
6493+
final NetworkVO networkVO = _networkDao.findById(networkId);
6494+
String networkCidr = networkVO.getCidr();
6495+
String cidrToRemove = NetUtils.getCidrFromGatewayAndNetmask(deletedVlan.getVlanGateway(), deletedVlan.getVlanNetmask());
6496+
String newNetworkCidr = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkCidr, cidrToRemove, false);
6497+
networkVO.setCidr(newNetworkCidr);
6498+
6499+
String networkGateway = networkVO.getGateway();
6500+
String newNetworkGateway = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkGateway, deletedVlan.getVlanGateway(), false);
6501+
networkVO.setGateway(newNetworkGateway);
6502+
_networkDao.update(networkId, networkVO);
6503+
}
6504+
6505+
private void removeCidrAndGatewayForIpv6(final long networkId, VlanVO deletedVlan) {
6506+
final NetworkVO networkVO = _networkDao.findById(networkId);
6507+
String networkIp6Cidr = networkVO.getIp6Cidr();
6508+
String newNetworkIp6Cidr = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkIp6Cidr, deletedVlan.getIp6Cidr(), false);
6509+
networkVO.setIp6Cidr(newNetworkIp6Cidr);
6510+
6511+
String networkIp6Gateway = networkVO.getIp6Gateway();
6512+
String newNetworkIp6Gateway = com.cloud.utils.StringUtils.updateCommaSeparatedStringWithValue(networkIp6Gateway, deletedVlan.getIp6Gateway(), false);
6513+
networkVO.setIp6Gateway(newNetworkIp6Gateway);
6514+
_networkDao.update(networkId, networkVO);
6515+
}
6516+
64496517
@Override
64506518
public void checkDiskOfferingAccess(final Account caller, final DiskOffering dof, DataCenter zone) {
64516519
for (final SecurityChecker checker : _secChecker) {

utils/src/main/java/com/cloud/utils/StringUtils.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,17 @@
2424
import com.fasterxml.jackson.databind.ObjectMapper;
2525

2626
import java.nio.charset.Charset;
27+
import java.util.Arrays;
2728
import java.util.ArrayList;
2829
import java.util.HashMap;
2930
import java.util.List;
31+
import java.util.LinkedHashSet;
3032
import java.util.Map;
3133
import java.util.Set;
3234
import java.util.TreeSet;
3335
import java.util.regex.Matcher;
3436
import java.util.regex.Pattern;
37+
import java.util.stream.Collectors;
3538

3639
public class StringUtils extends org.apache.commons.lang3.StringUtils {
3740
private static final char[] hexChar = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
@@ -409,4 +412,53 @@ public static String[] splitCommaSeparatedStrings(String... tags) {
409412
String[] finalMergedTagsArray = appendedTags.split(",");
410413
return finalMergedTagsArray;
411414
}
415+
416+
417+
/**
418+
* Converts the comma separated numbers and ranges to numbers
419+
* @param originalString the original string (can be null or empty) containing list of comma separated values that has to be updated
420+
* @param value the value to add to, or remove from the original string
421+
* @param add if true, adds the input value; if false, removes it
422+
* @return String containing the modified original string (or null if empty)
423+
*/
424+
public static String updateCommaSeparatedStringWithValue(String originalString, String value, boolean add) {
425+
if (org.apache.commons.lang3.StringUtils.isEmpty(value)) {
426+
return originalString;
427+
}
428+
429+
Set<String> values = new LinkedHashSet<>();
430+
431+
if (org.apache.commons.lang3.StringUtils.isNotEmpty(originalString)) {
432+
values.addAll(Arrays.stream(originalString.split(","))
433+
.map(String::trim)
434+
.filter(s -> !s.isEmpty())
435+
.collect(Collectors.toList()));
436+
}
437+
438+
if (add) {
439+
values.add(value);
440+
} else {
441+
values.remove(value);
442+
}
443+
444+
return values.isEmpty() ? null : String.join(",", values);
445+
}
446+
447+
/**
448+
* Returns the first value from a comma-separated string.
449+
* @param inputString the input string (can be null or empty) containing list of comma separated values
450+
* @return the first value, or null if none found
451+
*/
452+
public static String getFirstValueFromCommaSeparatedString(String inputString) {
453+
if (org.apache.commons.lang3.StringUtils.isEmpty(inputString)) {
454+
return inputString;
455+
}
456+
457+
String[] values = inputString.split(",");
458+
if (values.length > 0) {
459+
return values[0].trim();
460+
}
461+
462+
return null;
463+
}
412464
}

0 commit comments

Comments
 (0)