Initial implementation of managing IPs for kubevirt spawned VMIs
Change-Id: I68127e1fe42a142765e7696d8ce80de16d3d94a9
diff --git a/apps/kubevirt-networking/api/BUILD b/apps/kubevirt-networking/api/BUILD
index e1e477c..3f1c431 100644
--- a/apps/kubevirt-networking/api/BUILD
+++ b/apps/kubevirt-networking/api/BUILD
@@ -1,6 +1,7 @@
COMPILE_DEPS = CORE_DEPS + [
"@k8s_client//jar",
"@k8s_model//jar",
+ "@ipaddress//jar",
"@okhttp//jar",
"@okio//jar",
"@logging_interceptor//jar",
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
index 9f8201a..7a5d873 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/Constants.java
@@ -59,6 +59,7 @@
public static final int CLI_NAME_LENGTH = 30;
public static final int CLI_IP_ADDRESSES_LENGTH = 50;
public static final int CLI_IP_ADDRESS_LENGTH = 25;
+ public static final int CLI_IP_ADDRESS_AVAILABILITY = 15;
public static final int CLI_MAC_ADDRESS_LENGTH = 25;
public static final int CLI_PORTS_LENGTH = 20;
public static final int CLI_NAMESPACE_LENGTH = 15;
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
index 049a336..410c098 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPort.java
@@ -32,6 +32,7 @@
private static final String NOT_NULL_MSG = "Port % cannot be null";
+ private final String networkId;
private final MacAddress macAddress;
private final IpAddress ipAddress;
private final DeviceId deviceId;
@@ -40,13 +41,15 @@
/**
* Default constructor.
*
+ * @param networkId network identifier
* @param macAddress MAC address
* @param ipAddress IP address
* @param deviceId device identifier
* @param portNumber port number
*/
- public DefaultKubevirtPort(MacAddress macAddress, IpAddress ipAddress,
+ public DefaultKubevirtPort(String networkId, MacAddress macAddress, IpAddress ipAddress,
DeviceId deviceId, PortNumber portNumber) {
+ this.networkId = networkId;
this.macAddress = macAddress;
this.ipAddress = ipAddress;
this.deviceId = deviceId;
@@ -54,6 +57,11 @@
}
@Override
+ public String networkId() {
+ return networkId;
+ }
+
+ @Override
public MacAddress macAddress() {
return macAddress;
}
@@ -92,18 +100,20 @@
return false;
}
DefaultKubevirtPort that = (DefaultKubevirtPort) o;
- return macAddress.equals(that.macAddress) && ipAddress.equals(that.ipAddress) &&
- deviceId.equals(that.deviceId) && portNumber.equals(that.portNumber);
+ return networkId.equals(that.networkId) && macAddress.equals(that.macAddress) &&
+ ipAddress.equals(that.ipAddress) && deviceId.equals(that.deviceId) &&
+ portNumber.equals(that.portNumber);
}
@Override
public int hashCode() {
- return Objects.hash(macAddress, ipAddress, deviceId, portNumber);
+ return Objects.hash(networkId, macAddress, ipAddress, deviceId, portNumber);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
+ .add("networkId", networkId)
.add("macAddress", macAddress)
.add("ipAddress", ipAddress)
.add("deviceId", deviceId)
@@ -125,6 +135,7 @@
*/
public static final class Builder implements KubevirtPort.Builder {
+ private String networkId;
private MacAddress macAddress;
private IpAddress ipAddress;
private DeviceId deviceId;
@@ -136,10 +147,18 @@
@Override
public KubevirtPort build() {
+ checkArgument(networkId != null, NOT_NULL_MSG, "networkId");
checkArgument(macAddress != null, NOT_NULL_MSG, "macAddress");
checkArgument(ipAddress != null, NOT_NULL_MSG, "ipAddress");
- return new DefaultKubevirtPort(macAddress, ipAddress, deviceId, portNumber);
+ return new DefaultKubevirtPort(networkId, macAddress, ipAddress,
+ deviceId, portNumber);
+ }
+
+ @Override
+ public Builder networkId(String networkId) {
+ this.networkId = networkId;
+ return this;
}
@Override
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtIpPool.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtIpPool.java
index 64874fd..fb2906e 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtIpPool.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtIpPool.java
@@ -16,9 +16,19 @@
package org.onosproject.kubevirtnetworking.api;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
+import inet.ipaddr.AddressStringException;
+import inet.ipaddr.IPAddress;
+import inet.ipaddr.IPAddressSeqRange;
+import inet.ipaddr.IPAddressString;
import org.onlab.packet.IpAddress;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Kubevirt IP Pool.
@@ -27,16 +37,25 @@
private final IpAddress start;
private final IpAddress end;
+ private final Set<IpAddress> allocatedIps;
+ private final Set<IpAddress> availableIps;
/**
* Default constructor.
*
- * @param start start address of IP pool
- * @param end end address of IP pool
+ * @param start start address of IP pool
+ * @param end end address of IP pool
*/
public KubevirtIpPool(IpAddress start, IpAddress end) {
this.start = start;
this.end = end;
+ this.allocatedIps = new HashSet<>();
+ this.availableIps = new HashSet<>();
+ try {
+ this.availableIps.addAll(getRangedIps(start.toString(), end.toString()));
+ } catch (AddressStringException e) {
+ e.printStackTrace();
+ }
}
/**
@@ -57,6 +76,61 @@
return end;
}
+ /**
+ * Returns the set of IP addresses that have been allocated.
+ *
+ * @return set of IP addresses that have been allocated
+ */
+ public Set<IpAddress> allocatedIps() {
+ return ImmutableSet.copyOf(allocatedIps);
+ }
+
+ /**
+ * Returns the set of IP addresses for allocation.
+ *
+ * @return set of IP addresses for allocation.
+ */
+ public Set<IpAddress> availableIps() {
+ return ImmutableSet.copyOf(availableIps);
+ }
+
+ /**
+ * Allocates a random IP address.
+ *
+ * @return allocated IP address
+ * @throws Exception exception
+ */
+ public synchronized IpAddress allocateIp() throws Exception {
+ if (availableIps.size() <= 0) {
+ throw new Exception("No IP address is available for allocation.");
+ }
+
+ List<IpAddress> sortedList = new ArrayList<>(availableIps);
+ Collections.sort(sortedList);
+
+ IpAddress ip = sortedList.get(0);
+
+ availableIps.remove(ip);
+ allocatedIps.add(ip);
+
+ return ip;
+ }
+
+ /**
+ * Releases the given IP address.
+ *
+ * @param ip IP address to be released
+ * @throws Exception exception
+ */
+ public synchronized void releaseIp(IpAddress ip) throws Exception {
+ if (!allocatedIps.contains(ip)) {
+ throw new Exception("The given IP address is not able to be released.");
+ }
+
+ allocatedIps.remove(ip);
+ availableIps.add(ip);
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -81,4 +155,24 @@
.add("end", end)
.toString();
}
+
+ /**
+ * Obtains the IP address list from the given start and end range.
+ *
+ * @param start start range
+ * @param end end range
+ * @return IP address list from the given start and end range
+ * @throws AddressStringException exception
+ */
+ public Set<IpAddress> getRangedIps(String start, String end) throws AddressStringException {
+ Set<IpAddress> ips = new HashSet<>();
+ IPAddress lower = new IPAddressString(start).toAddress();
+ IPAddress upper = new IPAddressString(end).toAddress();
+ IPAddressSeqRange range = lower.toSequentialRange(upper);
+ for (IPAddress addr : range.getIterable()) {
+ ips.add(IpAddress.valueOf(addr.toString()));
+ }
+
+ return ips;
+ }
}
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
index d7c1ff2..a7ae75e 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPort.java
@@ -26,6 +26,13 @@
public interface KubevirtPort {
/**
+ * Returns the network identifier associated with the port.
+ *
+ * @return network identifier
+ */
+ String networkId();
+
+ /**
* Returns the MAC address of the port.
*
* @return MAC address
@@ -82,6 +89,14 @@
KubevirtPort build();
/**
+ * Returns port builder with supplied network identifier.
+ *
+ * @param networkId network identifier
+ * @return port builder
+ */
+ Builder networkId(String networkId);
+
+ /**
* Returns port builder with supplied MAC address.
*
* @param macAddress MAC address
diff --git a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
index c1e59b6..c391eb4 100644
--- a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
+++ b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtInstanceTest.java
@@ -36,6 +36,8 @@
private static final String UID_2 = "2";
private static final String NAME_1 = "instance-1";
private static final String NAME_2 = "instance-2";
+ private static final String NETWORK_ID_1 = "net-1";
+ private static final String NETWORK_ID_2 = "net-2";
private static final MacAddress MAC_1 = MacAddress.valueOf("11:22:33:44:55:66");
private static final MacAddress MAC_2 = MacAddress.valueOf("66:55:44:33:22:11");
private static final IpAddress IP_1 = IpAddress.valueOf("10.10.10.10");
@@ -44,8 +46,8 @@
private static final DeviceId DID_2 = DeviceId.deviceId("did2");
private static final PortNumber PN_1 = PortNumber.portNumber(1);
private static final PortNumber PN_2 = PortNumber.portNumber(2);
- private static final KubevirtPort PORT_1 = createPort(MAC_1, IP_1, DID_1, PN_1);
- private static final KubevirtPort PORT_2 = createPort(MAC_2, IP_2, DID_2, PN_2);
+ private static final KubevirtPort PORT_1 = createPort(NETWORK_ID_1, MAC_1, IP_1, DID_1, PN_1);
+ private static final KubevirtPort PORT_2 = createPort(NETWORK_ID_2, MAC_2, IP_2, DID_2, PN_2);
private KubevirtInstance instance1;
private KubevirtInstance sameAsInstance1;
@@ -105,8 +107,10 @@
assertEquals(ImmutableSet.of(PORT_1), instance1.ports());
}
- static KubevirtPort createPort(MacAddress mac, IpAddress ip, DeviceId did, PortNumber pn) {
+ static KubevirtPort createPort(String networkId, MacAddress mac, IpAddress ip,
+ DeviceId did, PortNumber pn) {
return DefaultKubevirtPort.builder()
+ .networkId(networkId)
.macAddress(mac)
.ipAddress(ip)
.deviceId(did)
diff --git a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetworkTest.java b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetworkTest.java
index 32ca958..1b39db8 100644
--- a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetworkTest.java
+++ b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtNetworkTest.java
@@ -22,6 +22,7 @@
import org.onlab.packet.IpAddress;
import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VXLAN;
@@ -128,4 +129,31 @@
assertEquals(CIDR_1, network.cidr());
assertEquals(new KubevirtIpPool(IP_POOL_START_1, IP_POOL_END_1), network.ipPool());
}
+
+ /**
+ * Test IP address initialization.
+ */
+ @Test
+ public void testIpInitialization() {
+ KubevirtIpPool ipPool1 = network1.ipPool();
+ assertEquals(101, ipPool1.availableIps().size());
+ assertEquals(0, ipPool1.allocatedIps().size());
+ }
+
+ /**
+ * Test IP address allocation.
+ */
+ @Test
+ public void testIpAllocationAndRelease() throws Exception {
+ KubevirtIpPool ipPool1 = network1.ipPool();
+ IpAddress ip = ipPool1.allocateIp();
+ assertEquals(100, ipPool1.availableIps().size());
+ assertEquals(1, ipPool1.allocatedIps().size());
+ assertEquals(IpAddress.valueOf("10.10.10.100"), ip);
+
+ ipPool1.releaseIp(ip);
+ assertEquals(101, ipPool1.availableIps().size());
+ assertEquals(0, ipPool1.allocatedIps().size());
+ assertTrue(ipPool1.availableIps().contains(ip));
+ }
}
diff --git a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
index 00f3cd4..f91ad2e 100644
--- a/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
+++ b/apps/kubevirt-networking/api/src/test/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtPortTest.java
@@ -30,6 +30,8 @@
* Unit tests for the default kubevirt port class.
*/
public class DefaultKubevirtPortTest {
+ private static final String NETWORK_ID_1 = "net-1";
+ private static final String NETWORK_ID_2 = "net-2";
private static final MacAddress MAC_ADDRESS_1 = MacAddress.valueOf("00:11:22:33:44:55");
private static final MacAddress MAC_ADDRESS_2 = MacAddress.valueOf("11:22:33:44:55:66");
private static final IpAddress IP_ADDRESS_1 = IpAddress.valueOf("10.10.10.10");
@@ -57,6 +59,7 @@
@Before
public void setUp() {
port1 = DefaultKubevirtPort.builder()
+ .networkId(NETWORK_ID_1)
.macAddress(MAC_ADDRESS_1)
.ipAddress(IP_ADDRESS_1)
.deviceId(DEVICE_ID_1)
@@ -64,6 +67,7 @@
.build();
sameAsPort1 = DefaultKubevirtPort.builder()
+ .networkId(NETWORK_ID_1)
.macAddress(MAC_ADDRESS_1)
.ipAddress(IP_ADDRESS_1)
.deviceId(DEVICE_ID_1)
@@ -71,6 +75,7 @@
.build();
port2 = DefaultKubevirtPort.builder()
+ .networkId(NETWORK_ID_2)
.macAddress(MAC_ADDRESS_2)
.ipAddress(IP_ADDRESS_2)
.deviceId(DEVICE_ID_2)
@@ -95,6 +100,7 @@
public void testConstruction() {
KubevirtPort port = port1;
+ assertEquals(NETWORK_ID_1, port.networkId());
assertEquals(MAC_ADDRESS_1, port.macAddress());
assertEquals(IP_ADDRESS_1, port.ipAddress());
assertEquals(DEVICE_ID_1, port.deviceId());