Skip to content

Commit 1af11e6

Browse files
Allow CIDR update for the shared network when the network IPs are not in use (i.e. IPs not allocated)
1 parent f0838cd commit 1af11e6

File tree

4 files changed

+68
-12
lines changed

4 files changed

+68
-12
lines changed

engine/schema/src/main/java/com/cloud/vm/dao/NicDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public interface NicDao extends GenericDao<NicVO, Long> {
3434

3535
List<NicVO> listByNetworkId(long networkId);
3636

37+
List<NicVO> listNonDeallocatedByNetworkId(long networkId);
38+
3739
NicVO findByNtwkIdAndInstanceId(long networkId, long instanceId);
3840

3941
NicVO findByInstanceIdAndNetworkIdIncludingRemoved(long networkId, long instanceId);

engine/schema/src/main/java/com/cloud/vm/dao/NicDaoImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ protected void init() {
8484
NonReleasedSearch.and("instance", NonReleasedSearch.entity().getInstanceId(), Op.EQ);
8585
NonReleasedSearch.and("network", NonReleasedSearch.entity().getNetworkId(), Op.EQ);
8686
NonReleasedSearch.and("state", NonReleasedSearch.entity().getState(), Op.NOTIN);
87+
NonReleasedSearch.and("strategy", NonReleasedSearch.entity().getReservationStrategy(), Op.NEQ);
8788
NonReleasedSearch.done();
8889

8990
deviceIdSearch = createSearchBuilder(Integer.class);
@@ -151,6 +152,15 @@ public List<NicVO> listByNetworkId(long networkId) {
151152
return listBy(sc);
152153
}
153154

155+
@Override
156+
public List<NicVO> listNonDeallocatedByNetworkId(long networkId) {
157+
SearchCriteria<NicVO> sc = NonReleasedSearch.create();
158+
sc.setParameters("network", networkId);
159+
sc.setParameters("state", Nic.State.Deallocating);
160+
sc.setParameters("strategy", Nic.ReservationStrategy.PlaceHolder.toString());
161+
return listBy(sc);
162+
}
163+
154164
@Override
155165
public NicVO findByNtwkIdAndInstanceId(long networkId, long instanceId) {
156166
SearchCriteria<NicVO> sc = AllFieldsSearch.create();

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

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3090,15 +3090,18 @@ public Network updateGuestNetwork(final UpdateNetworkCmd cmd) {
30903090
if (dc.getNetworkType() == NetworkType.Basic) {
30913091
throw new InvalidParameterValueException("Guest VM CIDR can't be specified for zone with " + NetworkType.Basic + " networking");
30923092
}
3093-
if (network.getGuestType() != GuestType.Isolated) {
3094-
throw new InvalidParameterValueException("Can only allow IP Reservation in networks with guest type " + GuestType.Isolated);
3093+
if (network.getGuestType() != GuestType.Isolated && network.getGuestType() != GuestType.Shared) {
3094+
throw new InvalidParameterValueException("Can only allow IP Reservation in networks with guest types: " + GuestType.Isolated + " or " + GuestType.Shared);
30953095
}
30963096
if (networkOfferingChanged) {
30973097
throw new InvalidParameterValueException("Cannot specify this network offering change and guestVmCidr at same time. Specify only one.");
30983098
}
3099-
if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Allocated) {
3100-
throw new InvalidParameterValueException(String.format("The network must be in %s or %s state. IP Reservation cannot be applied in %s state",
3101-
Network.State.Implemented, Network.State.Allocated, network.getState()));
3099+
if (network.getGuestType() != GuestType.Isolated && network.getGuestType() != GuestType.Shared) {
3100+
throw new InvalidParameterValueException("Can only allow IP Reservation in networks with guest types: " + GuestType.Isolated + " or " + GuestType.Shared);
3101+
}
3102+
if (network.getState() != Network.State.Implemented && network.getState() != Network.State.Allocated && network.getState() != Network.State.Setup) {
3103+
throw new InvalidParameterValueException(String.format("The network must be in %s, $s or %s state. IP Reservation cannot be applied in %s state",
3104+
Network.State.Implemented, Network.State.Allocated, Network.State.Setup, network.getState()));
31023105
}
31033106
if (!NetUtils.isValidIp4Cidr(guestVmCidr)) {
31043107
throw new InvalidParameterValueException("Invalid format of Guest VM CIDR.");
@@ -3111,34 +3114,57 @@ public Network updateGuestNetwork(final UpdateNetworkCmd cmd) {
31113114
// But in case networkCidr is a non null value (IP reservation already exists), it implies network cidr is networkCidr
31123115
if (networkCidr != null) {
31133116
if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, networkCidr)) {
3114-
throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + networkCidr);
3117+
throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR: " + networkCidr);
31153118
}
31163119
} else {
31173120
if (!NetUtils.isNetworkAWithinNetworkB(guestVmCidr, network.getCidr())) {
3118-
throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR : " + network.getCidr());
3121+
throw new InvalidParameterValueException("Invalid value of Guest VM CIDR. For IP Reservation, Guest VM CIDR should be a subset of network CIDR: " + network.getCidr());
31193122
}
31203123
}
31213124

31223125
// This check makes sure there are no active IPs existing outside the guestVmCidr in the network
31233126
String[] guestVmCidrPair = guestVmCidr.split("\\/");
31243127
Long size = Long.valueOf(guestVmCidrPair[1]);
3125-
List<NicVO> nicsPresent = _nicDao.listByNetworkId(networkId);
3126-
31273128
String cidrIpRange[] = NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], size);
31283129
s_logger.info("The start IP of the specified guest vm cidr is: " + cidrIpRange[0] + " and end IP is: " + cidrIpRange[1]);
31293130
long startIp = NetUtils.ip2Long(cidrIpRange[0]);
31303131
long endIp = NetUtils.ip2Long(cidrIpRange[1]);
31313132
long range = endIp - startIp + 1;
31323133
s_logger.info("The specified guest vm cidr has " + range + " IPs");
31333134

3134-
for (NicVO nic : nicsPresent) {
3135+
List<NicVO> nonDellocatedNicsPresent = _nicDao.listNonDeallocatedByNetworkId(networkId);
3136+
if (network.getGuestType() == GuestType.Shared) {
3137+
if (CollectionUtils.isNotEmpty(nonDellocatedNicsPresent)) {
3138+
throw new InvalidParameterValueException("IPs are in use, cannot apply reservation");
3139+
}
3140+
List<VlanVO> vlans = _vlanDao.listVlansByNetworkId(networkId);
3141+
if (CollectionUtils.isNotEmpty(vlans)) {
3142+
for (VlanVO vlan : vlans) {
3143+
if (vlan == null) {
3144+
continue;
3145+
}
3146+
String vlanIpRange = vlan.getIpRange();
3147+
if (vlanIpRange == null) {
3148+
continue;
3149+
}
3150+
String[] vlanRange = vlanIpRange.split("-");
3151+
String vlanStartIP = vlanRange[0];
3152+
String vlanEndIP = vlanRange[1];
3153+
if (!NetUtils.isIpWithInCidrRange(vlanStartIP, guestVmCidr) || !NetUtils.isIpWithInCidrRange(vlanEndIP, guestVmCidr)) {
3154+
throw new InvalidParameterValueException(String.format("CIDR doesn't include the IP range %s, cannot apply reservation", vlanIpRange));
3155+
}
3156+
}
3157+
}
3158+
}
3159+
3160+
for (NicVO nic : nonDellocatedNicsPresent) {
31353161
if (nic.getIPv4Address() == null) {
31363162
continue;
31373163
}
31383164
long nicIp = NetUtils.ip2Long(nic.getIPv4Address());
31393165
//check if nic IP is outside the guest vm cidr
31403166
if ((nicIp < startIp || nicIp > endIp) && nic.getState() != Nic.State.Deallocating) {
3141-
throw new InvalidParameterValueException("Active IPs like " + nic.getIPv4Address() + " exist outside the Guest VM CIDR. Cannot apply reservation ");
3167+
throw new InvalidParameterValueException("Active IPs like " + nic.getIPv4Address() + " exist outside the Guest VM CIDR. Cannot apply reservation");
31423168
}
31433169
}
31443170

@@ -3171,6 +3197,24 @@ public Network updateGuestNetwork(final UpdateNetworkCmd cmd) {
31713197
s_logger.warn("Guest VM CIDR and Network CIDR both are same, reservation will reset.");
31723198
network.setNetworkCidr(null);
31733199
}
3200+
3201+
// Remove any placeholder nic before updating the cidr
3202+
final List<NicVO> placeholderNics = _nicDao.listPlaceholderNicsByNetworkId(network.getId());
3203+
if (CollectionUtils.isNotEmpty(placeholderNics)) {
3204+
for (NicVO nic : placeholderNics) {
3205+
if (nic.getIPv4Address() != null) {
3206+
s_logger.debug("Releasing ip " + nic.getIPv4Address() + " of placeholder nic " + nic);
3207+
IPAddressVO ip = _ipAddressDao.findByIpAndSourceNetworkId(nic.getNetworkId(), nic.getIPv4Address());
3208+
if (ip != null) {
3209+
_ipAddrMgr.markIpAsUnavailable(ip.getId());
3210+
_ipAddressDao.unassignIpAddress(ip.getId());
3211+
}
3212+
}
3213+
s_logger.debug("Removing placeholder nic " + nic);
3214+
_nicDao.remove(nic.getId());
3215+
}
3216+
}
3217+
31743218
// Finally update "cidr" with the guestVmCidr
31753219
// which becomes the effective address space for CloudStack guest VMs
31763220
network.setCidr(guestVmCidr);

server/src/main/java/com/cloud/network/guru/GuestNetworkGuru.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ public NicProfile allocate(final Network network, NicProfile nic, final VirtualM
444444
nic.setIpv4AllocationRaceCheck(true);
445445
}
446446
if (guestIp == null && network.getGuestType() != GuestType.L2 && !_networkModel.listNetworkOfferingServices(network.getNetworkOfferingId()).isEmpty()) {
447-
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP" + " address for network " + network, DataCenter.class,
447+
throw new InsufficientVirtualNetworkCapacityException("Unable to acquire Guest IP address for network " + network, DataCenter.class,
448448
dc.getId());
449449
}
450450
}

0 commit comments

Comments
 (0)