Updated Branches:
  refs/heads/master e5866cf2e -> f89dd9050

IPv6: CLOUDSTACK-1113: Fix the mechanism to find the usable IP in the IPv6

The new policy is:
1. Generate a random IP.
2. Find the next available IP, start from the generated IP.
3. If we cannot find an available IP after certain times(10000 by default,
network.ipv6.search.retry.max) retry, give up.


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

Branch: refs/heads/master
Commit: f89dd9050cadb590830df1e05c544ae61f85898b
Parents: 2e236a8
Author: Sheng Yang <[email protected]>
Authored: Mon Feb 4 18:04:42 2013 -0800
Committer: Sheng Yang <[email protected]>
Committed: Tue Feb 5 14:31:12 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/network/NetworkModel.java        |    2 +
 server/src/com/cloud/configuration/Config.java     |    3 +-
 .../com/cloud/network/Ipv6AddressManagerImpl.java  |   46 ++++++++++++---
 server/src/com/cloud/network/NetworkModelImpl.java |   13 +++-
 .../com/cloud/network/MockNetworkModelImpl.java    |    5 ++
 .../test/com/cloud/vpc/MockNetworkModelImpl.java   |    6 ++
 utils/src/com/cloud/utils/net/NetUtils.java        |   23 +++++++
 utils/test/com/cloud/utils/net/NetUtilsTest.java   |    2 +
 8 files changed, 85 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/api/src/com/cloud/network/NetworkModel.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/network/NetworkModel.java 
b/api/src/com/cloud/network/NetworkModel.java
index 7e17405..57eeb29 100644
--- a/api/src/com/cloud/network/NetworkModel.java
+++ b/api/src/com/cloud/network/NetworkModel.java
@@ -250,4 +250,6 @@ public interface NetworkModel {
     boolean isNetworkInlineMode(Network network);
 
        Vlan getVlanForNetwork(long networkId);
+
+       boolean isIP6AddressAvailable(long networkId);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java 
b/server/src/com/cloud/configuration/Config.java
index 5e4996b..7592b6b 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -97,7 +97,6 @@ public enum Config {
        VmNetworkThrottlingRate("Network", ManagementServer.class, 
Integer.class, "vm.network.throttling.rate", "200", "Default data transfer rate 
in megabits per second allowed in User vm's default network.", null),
        NetworkLockTimeout("Network", ManagementServer.class, Integer.class, 
"network.lock.timeout", "600", "Lock wait timeout (seconds) while implementing 
network", null),
 
-
        SecurityGroupWorkCleanupInterval("Network", ManagementServer.class, 
Integer.class, "network.securitygroups.work.cleanup.interval", "120", "Time 
interval (seconds) in which finished work is cleaned up from the work table", 
null),
        SecurityGroupWorkerThreads("Network", ManagementServer.class, 
Integer.class, "network.securitygroups.workers.pool.size", "50", "Number of 
worker threads processing the security group update work queue", null),
        SecurityGroupWorkGlobalLockTimeout("Network", ManagementServer.class, 
Integer.class, "network.securitygroups.work.lock.timeout", "300", "Lock wait 
timeout (seconds) while updating the security group work queue", null),
@@ -356,9 +355,9 @@ public enum Config {
        VpcCleanupInterval("Advanced", ManagementServer.class, Integer.class, 
"vpc.cleanup.interval", "3600", "The interval (in seconds) between cleanup for 
Inactive VPCs", null),
     VpcMaxNetworks("Advanced", ManagementServer.class, Integer.class, 
"vpc.max.networks", "3", "Maximum number of networks per vpc", null),
     DetailBatchQuerySize("Advanced", ManagementServer.class, Integer.class, 
"detail.batch.query.size", "2000", "Default entity detail batch query size for 
listing", null),
-
        ConcurrentSnapshotsThresholdPerHost("Advanced", ManagementServer.class, 
Long.class, "concurrent.snapshots.threshold.perhost",
                        null, "Limits number of snapshots that can be handled 
by the host concurrently; default is NULL - unlimited", null),
+       NetworkIPv6SearchRetryMax("Network", ManagementServer.class, 
Integer.class, "network.ipv6.search.retry.max", "10000", "The maximum number of 
retrying times to search for an available IPv6 address in the table", null),
        
        ExternalBaremetalSystemUrl("Advanced", ManagementServer.class, 
String.class, "external.baremetal.system.url", null, "url of external baremetal 
system that CloudStack will talk to", null),
        ExternalBaremetalResourceClassName("Advanced", ManagementServer.class, 
String.class, "external,baremetal.resource.classname", null, "class name for 
handling external baremetal resource", null),

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/Ipv6AddressManagerImpl.java 
b/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
index 0122772..f5ad7da 100644
--- a/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
+++ b/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
@@ -25,14 +25,19 @@ import javax.naming.ConfigurationException;
 
 import org.apache.log4j.Logger;
 
+import com.cloud.configuration.Config;
+import com.cloud.configuration.dao.ConfigurationDao;
+import com.cloud.dc.DataCenter;
 import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.Vlan;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.dc.dao.VlanDao;
 import com.cloud.exception.InsufficientAddressCapacityException;
+import com.cloud.network.dao.NetworkDao;
 import com.cloud.network.dao.UserIpv6AddressDao;
 import com.cloud.user.Account;
 import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
 
@@ -40,6 +45,9 @@ import com.cloud.utils.net.NetUtils;
 public class Ipv6AddressManagerImpl extends ManagerBase implements 
Ipv6AddressManager {
     public static final Logger s_logger = 
Logger.getLogger(Ipv6AddressManagerImpl.class.getName());
 
+       String _name = null;
+       int _ipv6RetryMax = 0;
+                       
     @Inject
     DataCenterDao _dcDao;
     @Inject
@@ -48,30 +56,50 @@ public class Ipv6AddressManagerImpl extends ManagerBase 
implements Ipv6AddressMa
     NetworkModel _networkModel;
     @Inject
     UserIpv6AddressDao _ipv6Dao;
+    @Inject
+    NetworkDao _networkDao;
+    @Inject
+    ConfigurationDao _configDao;
     
        @Override
+       public boolean configure(String name, Map<String, Object> params)
+                       throws ConfigurationException {
+               _name = name;
+        Map<String, String> configs = _configDao.getConfiguration(params);
+        _ipv6RetryMax = 
NumbersUtil.parseInt(configs.get(Config.NetworkIPv6SearchRetryMax.key()), 
10000);
+               return true;
+       }
+
        public UserIpv6Address assignDirectIp6Address(long dcId, Account owner, 
Long networkId, String requestedIp6)
                        throws InsufficientAddressCapacityException {
+               Network network = _networkDao.findById(networkId);
+               if (network == null) {
+                       return null;
+               }
        Vlan vlan = _networkModel.getVlanForNetwork(networkId);
        if (vlan == null) {
                s_logger.debug("Cannot find related vlan or too many vlan 
attached to network " + networkId);
                return null;
        }
-       String ip = null;
+       String ip = null; 
        if (requestedIp6 == null) {
+               if (!_networkModel.isIP6AddressAvailable(networkId)) {
+                       throw new InsufficientAddressCapacityException("There 
is no more address available in the network " + network.getName(), 
DataCenter.class, network.getDataCenterId());
+               }
+               ip = NetUtils.getIp6FromRange(vlan.getIp6Range());
                int count = 0;
-               while (ip == null || count >= 10) {
-                       ip = NetUtils.getIp6FromRange(vlan.getIp6Range());
-                       //Check for duplicate IP
-                       if (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) == 
null) {
-                               break;
-                       } else {
+               while (_ipv6Dao.findByNetworkIdAndIp(networkId, ip) != null) {
+                       ip = NetUtils.getNextIp6InRange(ip, vlan.getIp6Range());
+                       count ++;
+                       // It's an arbitrate number to prevent the infinite 
loop 
+                       if (count > _ipv6RetryMax) {
                                ip = null;
+                               break;
                        }
-                       count ++;
                }
                if (ip == null) {
-                       throw new CloudRuntimeException("Fail to get unique 
ipv6 address after 10 times trying!");
+                       throw new InsufficientAddressCapacityException("Cannot 
find a usable IP in the network " + network.getName() + " after 
network.ipv6.search.retry.max = " + _ipv6RetryMax + " times retry!",
+                                               DataCenter.class, 
network.getDataCenterId());
                }
        } else {
                if (!NetUtils.isIp6InRange(requestedIp6, vlan.getIp6Range())) {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/server/src/com/cloud/network/NetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/network/NetworkModelImpl.java 
b/server/src/com/cloud/network/NetworkModelImpl.java
index ff97911..6e22782 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -526,7 +526,7 @@ public class NetworkModelImpl extends ManagerBase 
implements NetworkModel {
                        return false;
                }
                if (network.getIp6Gateway() != null) {
-                       hasFreeIps = isIP6AddressAvailable(network);
+                       hasFreeIps = isIP6AddressAvailable(network.getId());
                }
         } else {
             hasFreeIps = (getAvailableIps(network, null)).size() > 0;
@@ -544,8 +544,13 @@ public class NetworkModelImpl extends ManagerBase 
implements NetworkModel {
        }
        return vlans.get(0);
     }
-   
-    private boolean isIP6AddressAvailable(Network network) {
+
+    @Override
+    public boolean isIP6AddressAvailable(long networkId) {
+       Network network = _networksDao.findById(networkId);
+       if (network == null) {
+               return false;
+       }
        if (network.getIp6Gateway() == null) {
                return false;
        }
@@ -1868,4 +1873,4 @@ public class NetworkModelImpl extends ManagerBase 
implements NetworkModel {
         return offering.isInline();
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/server/test/com/cloud/network/MockNetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/network/MockNetworkModelImpl.java 
b/server/test/com/cloud/network/MockNetworkModelImpl.java
index 1c36364..502354e 100644
--- a/server/test/com/cloud/network/MockNetworkModelImpl.java
+++ b/server/test/com/cloud/network/MockNetworkModelImpl.java
@@ -815,4 +815,9 @@ public class MockNetworkModelImpl extends ManagerBase 
implements NetworkModel {
                return null;
        }
 
+       @Override
+       public boolean isIP6AddressAvailable(long networkId) {
+               // TODO Auto-generated method stub
+               return false;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/server/test/com/cloud/vpc/MockNetworkModelImpl.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vpc/MockNetworkModelImpl.java 
b/server/test/com/cloud/vpc/MockNetworkModelImpl.java
index 8097c34..1080d48 100644
--- a/server/test/com/cloud/vpc/MockNetworkModelImpl.java
+++ b/server/test/com/cloud/vpc/MockNetworkModelImpl.java
@@ -829,4 +829,10 @@ public class MockNetworkModelImpl extends ManagerBase 
implements NetworkModel {
                return null;
        }
 
+       @Override
+       public boolean isIP6AddressAvailable(long networkId) {
+               // TODO Auto-generated method stub
+               return false;
+       }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/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 8d3ff6d..0875f88 100755
--- a/utils/src/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/com/cloud/utils/net/NetUtils.java
@@ -1243,4 +1243,27 @@ public class NetUtils {
        IPv6AddressRange range2 = IPv6AddressRange.fromFirstAndLast(start2, 
end2);
        return range1.overlaps(range2);
        }
+
+       public static String getNextIp6InRange(String currentIp, String 
ipRange) {
+               String[] ips = ipRange.split("-");
+       String startIp = ips[0];
+       String endIp = null;
+       if (ips.length > 1) {
+               endIp = ips[1];
+       }
+       IPv6Address start = IPv6Address.fromString(startIp);
+       IPv6Address end = IPv6Address.fromString(endIp);
+       IPv6Address current = IPv6Address.fromString(currentIp); 
+       IPv6Address result = null;
+       if (current.equals(end)) {
+               result = start;
+       } else{
+               result = current.add(1);
+       }
+       String resultIp = null;
+       if (result != null) {
+               resultIp = result.toString();
+       }
+               return resultIp;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/f89dd905/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 763a798..686025e 100644
--- a/utils/test/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java
@@ -88,6 +88,7 @@ public class NetUtilsTest extends TestCase {
        assertEquals(NetUtils.countIp6InRange("1234:5678::2-1234:5678::0"), 0);
        assertEquals(NetUtils.getIp6FromRange("1234:5678::1-1234:5678::1"), 
"1234:5678::1");
        String ipString = null;
+       String range = "1234:5678::1-1234:5678::8000:0000";
        IPv6Address ipStart = IPv6Address.fromString("1234:5678::1");
        IPv6Address ipEnd = IPv6Address.fromString("1234:5678::8000:0000");
        for (int i = 0; i < 10; i ++) {
@@ -97,6 +98,7 @@ public class NetUtilsTest extends TestCase {
                assertTrue(ip.compareTo(ipStart) >= 0);
                assertTrue(ip.compareTo(ipEnd) <= 0);
        }
+       //Test isIp6RangeOverlap
        assertFalse(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", 
"1234:5678:1::1-1234:5678:1::ffff"));
        assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::1-1234:5678::ffff", 
"1234:5678::2-1234:5678::f"));
        assertTrue(NetUtils.isIp6RangeOverlap("1234:5678::f-1234:5678::ffff", 
"1234:5678::2-1234:5678::f"));

Reply via email to