You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ya...@apache.org on 2013/02/05 23:40:07 UTC

[9/9] git commit: refs/heads/network-refactor - IPv6: CLOUDSTACK-1113: Fix the mechanism to find the usable IP in the IPv6

Updated Branches:
  refs/heads/network-refactor e89d9e627 -> ec206d69b


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/ec206d69
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/ec206d69
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/ec206d69

Branch: refs/heads/network-refactor
Commit: ec206d69bef980e7f83fd930adf4a8de941d0ba0
Parents: 81a4061
Author: Sheng Yang <sh...@citrix.com>
Authored: Mon Feb 4 18:04:42 2013 -0800
Committer: Sheng Yang <sh...@citrix.com>
Committed: Tue Feb 5 14:33:06 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/network/NetworkModel.java        |    2 +
 server/src/com/cloud/configuration/Config.java     |    2 +-
 .../com/cloud/network/Ipv6AddressManagerImpl.java  |   42 +++++++++++----
 server/src/com/cloud/network/NetworkModelImpl.java |    9 +++-
 .../com/cloud/network/MockNetworkModelImpl.java    |    6 ++
 utils/src/com/cloud/utils/net/NetUtils.java        |   23 ++++++++
 utils/test/com/cloud/utils/net/NetUtilsTest.java   |    2 +
 7 files changed, 73 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ec206d69/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 e43ed8e..5d7dc60 100644
--- a/api/src/com/cloud/network/NetworkModel.java
+++ b/api/src/com/cloud/network/NetworkModel.java
@@ -248,4 +248,6 @@ public interface NetworkModel {
     PublicIpAddress getSourceNatIpAddressForGuestNetwork(Account owner, Network guestNetwork);
 
 	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/ec206d69/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 ea32025..22e3d62 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),
@@ -354,6 +353,7 @@ public enum Config {
 	HaTag("Advanced", ManagementServer.class, String.class, "ha.tag", null, "HA tag defining that the host marked with this tag can be used for HA purposes only", null),
 	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),
+	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),
     
 	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);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ec206d69/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 6666596..6633018 100644
--- a/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
+++ b/server/src/com/cloud/network/Ipv6AddressManagerImpl.java
@@ -24,13 +24,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.NumbersUtil;
+import com.cloud.utils.component.ComponentLocator;
 import com.cloud.utils.component.Inject;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.net.NetUtils;
@@ -40,6 +46,7 @@ public class Ipv6AddressManagerImpl implements Ipv6AddressManager {
     public static final Logger s_logger = Logger.getLogger(Ipv6AddressManagerImpl.class.getName());
 
 	String _name = null;
+	int _ipv6RetryMax = 0;
 			
     @Inject
     DataCenterDao _dcDao;
@@ -49,11 +56,18 @@ public class Ipv6AddressManagerImpl implements Ipv6AddressManager {
     NetworkModel _networkModel;
     @Inject
     UserIpv6AddressDao _ipv6Dao;
+    @Inject
+    NetworkDao _networkDao;
     
 	@Override
 	public boolean configure(String name, Map<String, Object> params)
 			throws ConfigurationException {
 		_name = name;
+		
+        ComponentLocator locator = ComponentLocator.getCurrentLocator();
+        ConfigurationDao configDao = locator.getDao(ConfigurationDao.class);
+        Map<String, String> configs = configDao.getConfiguration(params);
+        _ipv6RetryMax = NumbersUtil.parseInt(configs.get(Config.NetworkIPv6SearchRetryMax.key()), 10000);
 		return true;
 	}
 
@@ -71,30 +85,38 @@ public class Ipv6AddressManagerImpl implements Ipv6AddressManager {
 	public String getName() {
 		return _name;
 	}
-
+	
 	@Override
 	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/ec206d69/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 92db26f..f682a06 100644
--- a/server/src/com/cloud/network/NetworkModelImpl.java
+++ b/server/src/com/cloud/network/NetworkModelImpl.java
@@ -520,7 +520,7 @@ public class NetworkModelImpl  implements NetworkModel, Manager{
         		return false;
         	}
         	if (network.getIp6Gateway() != null) {
-        		hasFreeIps = isIP6AddressAvailable(network);
+        		hasFreeIps = isIP6AddressAvailable(network.getId());
         	}
         } else {
             hasFreeIps = (getAvailableIps(network, null)).size() > 0;
@@ -539,7 +539,12 @@ public class NetworkModelImpl  implements NetworkModel, Manager{
     	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;
     	}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ec206d69/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 0ca6a3d..1963455 100644
--- a/server/test/com/cloud/network/MockNetworkModelImpl.java
+++ b/server/test/com/cloud/network/MockNetworkModelImpl.java
@@ -802,4 +802,10 @@ public class MockNetworkModelImpl implements NetworkModel, Manager {
 		// TODO Auto-generated method stub
 		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/ec206d69/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 da67fc1..2772ce4 100755
--- a/utils/src/com/cloud/utils/net/NetUtils.java
+++ b/utils/src/com/cloud/utils/net/NetUtils.java
@@ -1267,4 +1267,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/ec206d69/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 9ff8c5e..ccf0991 100644
--- a/utils/test/com/cloud/utils/net/NetUtilsTest.java
+++ b/utils/test/com/cloud/utils/net/NetUtilsTest.java
@@ -87,6 +87,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 ++) {
@@ -96,6 +97,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"));