CLOUDSTACK-705 IP Address reservation for Isolated Guest Networks

CloudStack uses Guest CIDR for dhcp-range for the Guest VMs. The entire
CIDR is used by CloudStack for assigning IPs to Guest VMs. IP Address
Reservation will allow part of address space to be used fornon CloudStack
hosts/physical servers also, by restricting the address space of CloudStack
Guest VMs. Reservation can be configured using update Network API by specifying
guestvmCidr as an additional parameter. Reservation will be applicable for
Isolated Guest Networks including VPC. reservediprange in the response
will return the IP range that can be used for non Cloudstack hosts.

Tested manually the following scenarios:
Applying reservation when there are running VMs inside the
guest_vm_cidr.
Applying reservation when there are running VMs outside the
guest_vm_cidr.(not allowed)
Applying reservation when external device like Netscaler is configured
in the guest_cidr.
Applying reservation in VPC tiers.
Applying reservation outside the range of guest_cidr.(not allowed)


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/ea3db2f0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/ea3db2f0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/ea3db2f0

Branch: refs/heads/qemu-img
Commit: ea3db2f073a5076d7822497a3032a0cd2d47a297
Parents: 79fee52
Author: Saksham Srivastava <[email protected]>
Authored: Fri Feb 22 15:46:45 2013 +0530
Committer: Murali Reddy <[email protected]>
Committed: Fri Feb 22 15:50:33 2013 +0530

----------------------------------------------------------------------
 api/src/com/cloud/network/Network.java             |   13 ++-
 api/src/com/cloud/network/NetworkProfile.java      |    7 +
 api/src/com/cloud/network/NetworkService.java      |    4 +-
 api/src/com/cloud/network/vpc/VpcService.java      |    2 +-
 .../org/apache/cloudstack/api/ApiConstants.java    |    3 +
 .../api/command/user/network/UpdateNetworkCmd.java |   11 ++-
 .../cloudstack/api/response/NetworkResponse.java   |   16 +++-
 server/src/com/cloud/api/ApiResponseHelper.java    |   37 ++++++-
 .../src/com/cloud/network/NetworkServiceImpl.java  |   98 +++++++++++++-
 server/src/com/cloud/network/dao/NetworkVO.java    |   21 +++-
 .../src/com/cloud/network/vpc/VpcManagerImpl.java  |    4 +-
 .../src/com/cloud/upgrade/dao/Upgrade410to420.java |    4 +-
 .../com/cloud/network/MockNetworkManagerImpl.java  |    2 +-
 .../test/com/cloud/vpc/MockNetworkManagerImpl.java |    6 +-
 server/test/com/cloud/vpc/MockVpcManagerImpl.java  |   12 +-
 setup/db/db/schema-410to420.sql                    |    4 +
 16 files changed, 211 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/com/cloud/network/Network.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/Network.java 
b/api/src/com/cloud/network/Network.java
index 2bf7b7f..efed5cd 100644
--- a/api/src/com/cloud/network/Network.java
+++ b/api/src/com/cloud/network/Network.java
@@ -283,12 +283,21 @@ public interface Network extends ControlledEntity, 
StateObject<Network.State>, I
 
     String getGateway();
 
+    // "cidr" is the Cloudstack managed address space, all CloudStack managed 
vms get IP address from "cidr",
+    // In general "cidr" also serves as the network CIDR
+    // But in case IP reservation is configured for a Guest network, 
"networkcidr" is the Effective network CIDR for that network,
+    // "cidr" will still continue to be the effective address space for 
CloudStack managed vms in that Guest network
     String getCidr();
 
+    // "networkcidr" is the network CIDR of the guest network which uses IP 
reservation.
+    // It is the summation of "cidr" and the reservedIPrange(the address space 
used for non CloudStack purposes).
+    // For networks not configured with IP reservation, "networkcidr" is 
always null
+    String getNetworkCidr();
+
     String getIp6Gateway();
-    
+
     String getIp6Cidr();
-    
+
     long getDataCenterId();
 
     long getNetworkOfferingId();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/com/cloud/network/NetworkProfile.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkProfile.java 
b/api/src/com/cloud/network/NetworkProfile.java
index 37d46ac..2f56645 100644
--- a/api/src/com/cloud/network/NetworkProfile.java
+++ b/api/src/com/cloud/network/NetworkProfile.java
@@ -38,6 +38,7 @@ public class NetworkProfile implements Network {
     private TrafficType trafficType;
     private String gateway;
     private String cidr;
+    private String networkCidr;
     private String ip6Gateway;
     private String ip6Cidr;
     private long networkOfferingId;
@@ -65,6 +66,7 @@ public class NetworkProfile implements Network {
         this.trafficType = network.getTrafficType();
         this.gateway = network.getGateway();
         this.cidr = network.getCidr();
+        this.networkCidr = network.getNetworkCidr();
         this.ip6Gateway = network.getIp6Gateway();
         this.ip6Cidr = network.getIp6Cidr();
         this.networkOfferingId = network.getNetworkOfferingId();
@@ -163,6 +165,11 @@ public class NetworkProfile implements Network {
     }
 
     @Override
+    public String getNetworkCidr() {
+        return networkCidr;
+    }
+
+    @Override
     public long getNetworkOfferingId() {
         return networkOfferingId;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/com/cloud/network/NetworkService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkService.java 
b/api/src/com/cloud/network/NetworkService.java
index ace1bb6..95bcc42 100755
--- a/api/src/com/cloud/network/NetworkService.java
+++ b/api/src/com/cloud/network/NetworkService.java
@@ -66,10 +66,8 @@ public interface NetworkService {
 
     IpAddress getIp(long id);
 
-
     Network updateGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount, User callerUser,
-            String domainSuffix, Long networkOfferingId, Boolean changeCidr);
-
+            String domainSuffix, Long networkOfferingId, Boolean changeCidr, 
String guestVmCidr);
 
     PhysicalNetwork createPhysicalNetwork(Long zoneId, String vnetRange, 
String networkSpeed, 
             List<String> isolationMethods, String broadcastDomainRange, Long 
domainId, List<String> tags, String name);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/com/cloud/network/vpc/VpcService.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/vpc/VpcService.java 
b/api/src/com/cloud/network/vpc/VpcService.java
index cc66b58..79ad75c 100644
--- a/api/src/com/cloud/network/vpc/VpcService.java
+++ b/api/src/com/cloud/network/vpc/VpcService.java
@@ -246,5 +246,5 @@ public interface VpcService {
         InsufficientAddressCapacityException, ConcurrentOperationException;
 
     public Network updateVpcGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount,
-            User callerUser, String domainSuffix, Long ntwkOffId, Boolean 
changeCidr);
+            User callerUser, String domainSuffix, Long ntwkOffId, Boolean 
changeCidr, String guestVmCidr);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/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 252e31d..b12e4cd 100755
--- a/api/src/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/org/apache/cloudstack/api/ApiConstants.java
@@ -445,6 +445,9 @@ public class ApiConstants {
     public static final String VM_SNAPSHOT_DISK_IDS = "vmsnapshotdiskids";
     public static final String VM_SNAPSHOT_MEMORY = "snapshotmemory";
     public static final String IMAGE_STORE_UUID = "imagestoreuuid";
+    public static final String GUEST_VM_CIDR = "guestvmcidr";
+    public static final String NETWORK_CIDR = "networkcidr";
+    public static final String RESERVED_IP_RANGE = "reservediprange";
 
     public enum HostDetails {
         all, capacity, events, stats, min;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java
----------------------------------------------------------------------
diff --git 
a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java 
b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java
index 6777407..41aaaaa 100644
--- 
a/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java
+++ 
b/api/src/org/apache/cloudstack/api/command/user/network/UpdateNetworkCmd.java
@@ -64,6 +64,9 @@ public class UpdateNetworkCmd extends BaseAsyncCmd {
             description="network offering ID")
     private Long networkOfferingId;
 
+    @Parameter(name=ApiConstants.GUEST_VM_CIDR, type=CommandType.STRING, 
description="CIDR for Guest VMs,Cloudstack allocates IPs to Guest VMs only from 
this CIDR")
+    private String guestVmCidr;
+
     /////////////////////////////////////////////////////
     /////////////////// Accessors ///////////////////////
     /////////////////////////////////////////////////////
@@ -94,6 +97,10 @@ public class UpdateNetworkCmd extends BaseAsyncCmd {
         }
         return false;
     }
+
+    private String getGuestVmCidr() {
+        return guestVmCidr;
+    }
     /////////////////////////////////////////////////////
     /////////////// API Implementation///////////////////
     /////////////////////////////////////////////////////
@@ -125,10 +132,10 @@ public class UpdateNetworkCmd extends BaseAsyncCmd {
         Network result = null;
         if (network.getVpcId() != null) {
             result = _vpcService.updateVpcGuestNetwork(getId(), 
getNetworkName(), getDisplayText(), callerAccount,
-                    callerUser, getNetworkDomain(), getNetworkOfferingId(), 
getChangeCidr());
+                    callerUser, getNetworkDomain(), getNetworkOfferingId(), 
getChangeCidr(), getGuestVmCidr());
         } else {
             result = _networkService.updateGuestNetwork(getId(), 
getNetworkName(), getDisplayText(), callerAccount,
-                    callerUser, getNetworkDomain(), getNetworkOfferingId(), 
getChangeCidr());
+                    callerUser, getNetworkDomain(), getNetworkOfferingId(), 
getChangeCidr(), getGuestVmCidr());
         }
 
         if (result != null) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
----------------------------------------------------------------------
diff --git a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java 
b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
index 7b29efb..cd32ded 100644
--- a/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
+++ b/api/src/org/apache/cloudstack/api/response/NetworkResponse.java
@@ -52,9 +52,15 @@ public class NetworkResponse extends BaseResponse implements 
ControlledEntityRes
     @SerializedName(ApiConstants.NETMASK) @Param(description="the network's 
netmask")
     private String netmask;
 
-    @SerializedName(ApiConstants.CIDR) @Param(description="the cidr the 
network")
+    @SerializedName(ApiConstants.CIDR) @Param(description="Cloudstack managed 
address space, all CloudStack managed VMs get IP address from CIDR")
     private String cidr;
 
+    @SerializedName(ApiConstants.NETWORK_CIDR) @Param(description="the network 
CIDR of the guest network configured with IP reservation. It is the summation 
of CIDR and RESERVED_IP_RANGE")
+    private String networkCidr;
+
+    @SerializedName(ApiConstants.RESERVED_IP_RANGE) @Param(description="the 
network's IP range not to be used by CloudStack guest VMs and can be used for 
non CloudStack purposes")
+    private String reservedIpRange;
+
     @SerializedName(ApiConstants.ZONE_ID) @Param(description="zone id of the 
network")
     private String zoneId;
 
@@ -289,6 +295,14 @@ public class NetworkResponse extends BaseResponse 
implements ControlledEntityRes
         this.cidr = cidr;
     }
 
+    public void setNetworkCidr(String networkCidr) {
+        this.networkCidr = networkCidr;
+    }
+
+    public void setReservedIpRange(String reservedIpRange) {
+        this.reservedIpRange = reservedIpRange;
+    }
+
     public void setRestartRequired(Boolean restartRequired) {
         this.restartRequired = restartRequired;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/src/com/cloud/api/ApiResponseHelper.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/api/ApiResponseHelper.java 
b/server/src/com/cloud/api/ApiResponseHelper.java
index 845b242..41cf96e 100755
--- a/server/src/com/cloud/api/ApiResponseHelper.java
+++ b/server/src/com/cloud/api/ApiResponseHelper.java
@@ -2153,13 +2153,48 @@ public class ApiResponseHelper implements 
ResponseGenerator {
 
         // FIXME - either set netmask or cidr
         response.setCidr(network.getCidr());
-        if (network.getCidr() != null) {
+        response.setNetworkCidr((network.getNetworkCidr()));
+        // If network has reservation its entire network cidr is defined by 
getNetworkCidr()
+        // if no reservation is present then getCidr() will define the entire 
network cidr
+        if (network.getNetworkCidr() != null) {
+            
response.setNetmask(NetUtils.cidr2Netmask(network.getNetworkCidr()));
+        }
+        if (((network.getCidr()) != null) && (network.getNetworkCidr() == 
null)) {
             response.setNetmask(NetUtils.cidr2Netmask(network.getCidr()));
         }
         
         response.setIp6Gateway(network.getIp6Gateway());
         response.setIp6Cidr(network.getIp6Cidr());
 
+        // create response for reserved IP ranges that can be used for 
non-cloudstack purposes
+        String  reservation = null;
+        if ((network.getCidr() != null) && 
(NetUtils.isNetworkAWithinNetworkB(network.getCidr(), 
network.getNetworkCidr()))) {
+                String[] guestVmCidrPair = network.getCidr().split("\\/");
+                String[] guestCidrPair = network.getNetworkCidr().split("\\/");
+
+                Long guestVmCidrSize = Long.valueOf(guestVmCidrPair[1]);
+                Long guestCidrSize = Long.valueOf(guestCidrPair[1]);
+
+                String[] guestVmIpRange = 
NetUtils.getIpRangeFromCidr(guestVmCidrPair[0], guestVmCidrSize);
+                String[] guestIpRange = 
NetUtils.getIpRangeFromCidr(guestCidrPair[0], guestCidrSize);
+                long startGuestIp = NetUtils.ip2Long(guestIpRange[0]);
+                long endGuestIp = NetUtils.ip2Long(guestIpRange[1]);
+                long startVmIp = NetUtils.ip2Long(guestVmIpRange[0]);
+                long endVmIp = NetUtils.ip2Long(guestVmIpRange[1]);
+
+                if (startVmIp == startGuestIp && endVmIp < endGuestIp -1) {
+                    reservation = (NetUtils.long2Ip(endVmIp + 1) + "-" + 
NetUtils.long2Ip(endGuestIp));
+                }
+                if (endVmIp == endGuestIp && startVmIp > startGuestIp + 1) {
+                    reservation = (NetUtils.long2Ip(startGuestIp) + "-" + 
NetUtils.long2Ip(startVmIp-1));
+                }
+                if(startVmIp > startGuestIp + 1 && endVmIp < endGuestIp - 1) {
+                reservation = (NetUtils.long2Ip(startGuestIp) + "-" +  
NetUtils.long2Ip(startVmIp-1) + " ,  " +
+                        NetUtils.long2Ip(endVmIp + 1) + "-"+  
NetUtils.long2Ip(endGuestIp));
+            }
+        }
+        response.setReservedIpRange(reservation);
+
         //return vlan information only to Root admin
         if (network.getBroadcastUri() != null && 
UserContext.current().getCaller().getType() == Account.ACCOUNT_TYPE_ADMIN) {
             String broadcastUri = network.getBroadcastUri().toString();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/src/com/cloud/network/NetworkServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkServiceImpl.java 
b/server/src/com/cloud/network/NetworkServiceImpl.java
index d4150d5..ce527b7 100755
--- a/server/src/com/cloud/network/NetworkServiceImpl.java
+++ b/server/src/com/cloud/network/NetworkServiceImpl.java
@@ -66,6 +66,7 @@ import com.cloud.event.dao.EventDao;
 import com.cloud.event.dao.UsageEventDao;
 import com.cloud.exception.*;
 import com.cloud.network.IpAddress.State;
+import com.cloud.vm.Nic;
 import com.cloud.network.Network.Capability;
 import com.cloud.network.Network.GuestType;
 import com.cloud.network.Network.Provider;
@@ -1491,7 +1492,7 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
     @DB
     @ActionEvent(eventType = EventTypes.EVENT_NETWORK_UPDATE, eventDescription 
= "updating network", async = true)
     public Network updateGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount, 
-            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr) {
+            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr, String guestVmCidr) {
         boolean restartNetwork = false;
 
         // verify input parameters
@@ -1552,8 +1553,6 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
                 ex.addProxyObject(networkOffering, networkOfferingId, 
"networkOfferingId");                
                 throw ex;
             }
-            
-            
             //can't update from vpc to non-vpc network offering
             boolean forVpcNew = _configMgr.isOfferingForVpc(networkOffering);
             boolean vorVpcOriginal = 
_configMgr.isOfferingForVpc(_configMgr.getNetworkOffering(oldNetworkOfferingId));
@@ -1585,6 +1584,7 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
                 networkOfferingChanged = true;
             }
         }
+
         Map<String, String> newSvcProviders = new HashMap<String, String>();
         if (networkOfferingChanged) {
             newSvcProviders = 
_networkMgr.finalizeServicesAndProvidersForNetwork(_configMgr.getNetworkOffering(networkOfferingId),
 network.getPhysicalNetworkId());
@@ -1616,6 +1616,81 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
             restartNetwork = true;
         }
 
+        //IP reservation checks
+        // allow reservation only to Isolated Guest networks
+        DataCenter dc = _dcDao.findById(network.getDataCenterId());
+        String networkCidr = network.getNetworkCidr();
+
+        if (guestVmCidr!= null ) {
+            if(dc.getNetworkType() == NetworkType.Basic) {
+                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);
+            }
+            if (networkOfferingChanged == true) {
+                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");
+            }
+            if (!NetUtils.isValidCIDR(guestVmCidr)) {
+                throw new InvalidParameterValueException ("Invalid format of 
Guest VM CIDR.");
+            }
+            if (!NetUtils.validateGuestCidr(guestVmCidr)) {
+                throw new InvalidParameterValueException ("Invalid format of 
Guest VM CIDR. Make sure it is RFC1918 compliant. ");
+            }
+
+            // If networkCidr is null it implies that there was no prior IP 
reservation, so the network cidr is network.getCidr()
+            // But in case networkCidr is a non null value (IP reservation 
already exists), it implies network cidr is networkCidr
+            if (networkCidr != null && ! 
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);
+            } 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());
+                }
+            }
+
+            // 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<NicVO> nicsPresent = _nicDao.listByNetworkId(networkId);
+
+                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.getIp4Address());
+                    //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.getIp4Address() + " exist outside the Guest VM CIDR. Cannot 
apply reservation ");
+                            }
+                        }
+                    }
+
+                // 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);
+            }
+
         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
@@ -1635,6 +1710,15 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
                     // We need to shutdown the network, since we want to 
re-implement the network.
                     s_logger.debug("Shutting down network id=" + networkId + " 
as a part of network update");
 
+                    //check if network has reservation
+                    if(NetUtils.isNetworkAWithinNetworkB(network.getCidr(), 
network.getNetworkCidr())) {
+                        s_logger.warn ("Existing IP reservation will become 
ineffective for the network with id =  " + networkId + " You need to reapply 
reservation after network reimplementation.");
+                        //set cidr to the newtork cidr
+                        network.setCidr(network.getNetworkCidr());
+                        //set networkCidr to null to bring network back to no 
IP reservation state
+                        network.setNetworkCidr(null);
+                    }
+
                     if (!_networkMgr.shutdownNetwork(network.getId(), context, 
true)) {
                         s_logger.warn("Failed to shutdown the network as a 
part of update to network with specified id");
                         CloudRuntimeException ex = new 
CloudRuntimeException("Failed to shutdown the network as a part of update of 
specified network id");
@@ -1655,7 +1739,7 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
         boolean validStateToImplement = (networkState == 
Network.State.Implemented || networkState == Network.State.Setup || 
networkState == Network.State.Allocated);
         if (restartNetwork && !validStateToImplement) {
             CloudRuntimeException ex = new CloudRuntimeException("Failed to 
implement the network elements and resources as a part of update to network 
with specified id; network is in wrong state: " + networkState);
-            ex.addProxyObject(network, networkId, "networkId");            
+            ex.addProxyObject(network, networkId, "networkId");
             throw ex;
         }
 
@@ -1681,11 +1765,11 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
                     
UsageEventUtils.saveUsageEvent(EventTypes.EVENT_NETWORK_OFFERING_ASSIGN, 
vm.getAccountId(), vm.getDataCenterId(), vm.getId(), vm.getHostName(), 
networkOfferingId, null, isDefault);
                 }
                 txn.commit();
-            } else {
+            }   else {
                 network.setNetworkOfferingId(networkOfferingId);
                 _networksDao.update(networkId, network, 
_networkMgr.finalizeServicesAndProvidersForNetwork(_configMgr.getNetworkOffering(networkOfferingId),
 network.getPhysicalNetworkId()));
             }
-        } else {
+        }   else {
             _networksDao.update(networkId, network);
         }
 
@@ -1731,7 +1815,7 @@ public class NetworkServiceImpl extends ManagerBase 
implements  NetworkService {
     }
 
 
-    
+
 
     protected Set<Long> getAvailableIps(Network network, String requestedIp) {
         String[] cidr = network.getCidr().split("/");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/src/com/cloud/network/dao/NetworkVO.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/dao/NetworkVO.java 
b/server/src/com/cloud/network/dao/NetworkVO.java
index d51a065..77b40c8 100644
--- a/server/src/com/cloud/network/dao/NetworkVO.java
+++ b/server/src/com/cloud/network/dao/NetworkVO.java
@@ -81,6 +81,9 @@ public class NetworkVO implements Network {
     @Column(name="cidr")
     String cidr;
 
+    @Column(name="network_cidr")
+    String networkCidr;
+
     @Column(name="network_offering_id")
     long networkOfferingId;
 
@@ -198,6 +201,7 @@ public class NetworkVO implements Network {
                 related, name, displayText, networkDomain, guestType, dcId, 
physicalNetworkId, aclType, specifyIpRanges, vpcId);
         this.gateway = that.getGateway();
         this.cidr = that.getCidr();
+        this.networkCidr = that.getNetworkCidr();
         this.broadcastUri = that.getBroadcastUri();
         this.broadcastDomainType = that.getBroadcastDomainType();
         this.guruName = guruName;
@@ -353,7 +357,10 @@ public class NetworkVO implements Network {
     public void setGateway(String gateway) {
         this.gateway = gateway;
     }
-
+    // "cidr" is the Cloudstack managed address space, all CloudStack managed 
vms get IP address from "cidr"
+    // In general "cidr" also serves as the network cidr
+    // But in case IP reservation feature is configured for a Guest network, 
"network_cidr" is the Effective network cidr for the network,
+    //  "cidr" will still continue to be the effective address space for 
CloudStack managed vms in that Guest network
     @Override
     public String getCidr() {
         return cidr;
@@ -363,6 +370,18 @@ public class NetworkVO implements Network {
         this.cidr = cidr;
     }
 
+    // "networkcidr" is the network CIDR of the guest network which is 
configured with IP reservation feature
+    // It is the summation of "cidr" and the reservedIPrange(the address space 
used for non cloudstack purposes.)
+    //  For networks not using IP reservation "networkcidr" is always null
+    @Override
+    public String getNetworkCidr() {
+        return networkCidr;
+    }
+
+    public void setNetworkCidr(String networkCidr) {
+        this.networkCidr = networkCidr;
+    }
+
     @Override
     public URI getBroadcastUri() {
         return broadcastUri;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/src/com/cloud/network/vpc/VpcManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/vpc/VpcManagerImpl.java 
b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
index fbb5788..60e2a38 100644
--- a/server/src/com/cloud/network/vpc/VpcManagerImpl.java
+++ b/server/src/com/cloud/network/vpc/VpcManagerImpl.java
@@ -1935,7 +1935,7 @@ public class VpcManagerImpl extends ManagerBase 
implements VpcManager{
 
     @Override
     public Network updateVpcGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount, 
-            User callerUser, String domainSuffix, Long ntwkOffId, Boolean 
changeCidr) {
+            User callerUser, String domainSuffix, Long ntwkOffId, Boolean 
changeCidr, String guestVmCidr) {
         NetworkVO network = _ntwkDao.findById(networkId);
         if (network == null) {
             throw new InvalidParameterValueException("Couldn't find network by 
id");
@@ -1947,7 +1947,7 @@ public class VpcManagerImpl extends ManagerBase 
implements VpcManager{
         }
         
         return _ntwkSvc.updateGuestNetwork(networkId, name, displayText, 
callerAccount, callerUser, domainSuffix,
-                ntwkOffId, changeCidr);
+                ntwkOffId, changeCidr, guestVmCidr);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/src/com/cloud/upgrade/dao/Upgrade410to420.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java 
b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java
index a43727c..a059257 100644
--- a/server/src/com/cloud/upgrade/dao/Upgrade410to420.java
+++ b/server/src/com/cloud/upgrade/dao/Upgrade410to420.java
@@ -69,5 +69,5 @@ public class Upgrade410to420 implements DbUpgrade {
         }
 
         return new File[] { new File(script) };
-       }
-}
+           }
+    }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/test/com/cloud/network/MockNetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/network/MockNetworkManagerImpl.java 
b/server/test/com/cloud/network/MockNetworkManagerImpl.java
index 4a24f9a..3568da5 100755
--- a/server/test/com/cloud/network/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/network/MockNetworkManagerImpl.java
@@ -569,7 +569,7 @@ public class MockNetworkManagerImpl extends ManagerBase 
implements NetworkManage
      */
     @Override
     public Network updateGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount,
-            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr) {
+            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr, String guestVmCidr) {
         // TODO Auto-generated method stub
         return null;
     }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java 
b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
index bcaaa26..828a555 100644
--- a/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkManagerImpl.java
@@ -303,15 +303,11 @@ public class MockNetworkManagerImpl extends ManagerBase 
implements NetworkManage
      */
     @Override
     public Network updateGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount,
-            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr) {
+            User callerUser, String domainSuffix, Long networkOfferingId, 
Boolean changeCidr, String guestVmCidr) {
         // TODO Auto-generated method stub
         return null;
     }
 
-
-
-
-
     /* (non-Javadoc)
      * @see 
com.cloud.network.NetworkService#createPhysicalNetwork(java.lang.Long, 
java.lang.String, java.lang.String, java.util.List, java.lang.String, 
java.lang.Long, java.util.List, java.lang.String)
      */

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/server/test/com/cloud/vpc/MockVpcManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockVpcManagerImpl.java 
b/server/test/com/cloud/vpc/MockVpcManagerImpl.java
index 0a44a49..b0a89ee 100644
--- a/server/test/com/cloud/vpc/MockVpcManagerImpl.java
+++ b/server/test/com/cloud/vpc/MockVpcManagerImpl.java
@@ -320,11 +320,6 @@ public class MockVpcManagerImpl extends ManagerBase 
implements VpcManager {
     /* (non-Javadoc)
      * @see com.cloud.network.vpc.VpcService#updateVpcGuestNetwork(long, 
java.lang.String, java.lang.String, com.cloud.user.Account, 
com.cloud.user.User, java.lang.String, java.lang.Long, java.lang.Boolean)
      */
-    @Override
-    public Network updateVpcGuestNetwork(long networkId, String name, String 
displayText, Account callerAccount, User callerUser, String domainSuffix, Long 
ntwkOffId, Boolean changeCidr) {
-        // TODO Auto-generated method stub
-        return null;
-    }
 
     /* (non-Javadoc)
      * @see com.cloud.network.vpc.VpcManager#validateNtkwOffForVpc(long, 
java.lang.String, java.lang.String, com.cloud.user.Account, 
com.cloud.network.vpc.Vpc, java.lang.Long, java.lang.String)
@@ -471,4 +466,11 @@ public class MockVpcManagerImpl extends ManagerBase 
implements VpcManager {
         return null;
     }
 
+       @Override
+       public Network updateVpcGuestNetwork(long networkId, String name,  
String displayText, Account callerAccount, User callerUser,
+                       String domainSuffix, Long ntwkOffId, Boolean 
changeCidr,        String guestVmCidr) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ea3db2f0/setup/db/db/schema-410to420.sql
----------------------------------------------------------------------
diff --git a/setup/db/db/schema-410to420.sql b/setup/db/db/schema-410to420.sql
index eed7390..461de7f 100644
--- a/setup/db/db/schema-410to420.sql
+++ b/setup/db/db/schema-410to420.sql
@@ -19,6 +19,7 @@
 -- Schema upgrade from 4.1.0 to 4.2.0;
 --;
 
+
 ALTER TABLE `cloud`.`hypervisor_capabilities` ADD COLUMN 
`max_hosts_per_cluster` int unsigned DEFAULT NULL COMMENT 'Max. hosts in 
cluster supported by hypervisor';
 UPDATE `cloud`.`hypervisor_capabilities` SET `max_hosts_per_cluster`=32 WHERE 
`hypervisor_type`='VMware';
 INSERT IGNORE INTO `cloud`.`hypervisor_capabilities`(hypervisor_type, 
hypervisor_version, max_guests_limit, security_group_enabled, 
max_hosts_per_cluster) VALUES ('VMware', '5.1', 128, 0, 32);
@@ -76,3 +77,6 @@ CREATE TABLE `cloud`.`image_data_store` (
 
 
 ALTER TABLE `cloud`.`service_offering` ADD COLUMN `is_volatile` tinyint(1) 
unsigned NOT NULL DEFAULT 0  COMMENT 'true if the vm needs to be volatile, 
i.e., on every reboot of vm from API root disk is discarded and creates a new 
root disk';
+
+ALTER TABLE `cloud`.`networks` ADD COLUMN `network_cidr` VARCHAR(18) COMMENT 
'The network cidr for the isolated guest network which uses IP Reservation 
facility.For networks not using IP reservation, network_cidr is always null.';
+ALTER TABLE `cloud`.`networks` CHANGE `cidr` `cidr` varchar(18) 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';

Reply via email to