Support to allocate/release IP address for multiple networks
Change-Id: Ibd9a73fc8675559ed2a1aff47e39759745fad400
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
index cb00052..cc4149e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkManager.java
@@ -139,7 +139,7 @@
networkStore.updateNetwork(network);
return ip;
} catch (Exception e) {
- log.error("Failed to allocate IP address");
+ log.error("Failed to allocate IP address", e);
}
return null;
}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtPodPortMapper.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtPodPortMapper.java
index a5379e8..9675ca2 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtPodPortMapper.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtPodPortMapper.java
@@ -46,12 +46,13 @@
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
-import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getPort;
+import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getPorts;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.k8sClient;
import static org.slf4j.LoggerFactory.getLogger;
@@ -185,14 +186,16 @@
log.error("Failed to reserve IP address", e);
}
- KubevirtPort port = getPort(kubevirtNetworkAdminService.networks(), pod);
- if (port == null) {
+ Set<KubevirtPort> ports = getPorts(kubevirtNetworkAdminService.networks(), pod);
+ if (ports.size() == 0) {
return;
}
- if (kubevirtPortAdminService.port(port.macAddress()) == null) {
- kubevirtPortAdminService.createPort(port);
- }
+ ports.forEach(port -> {
+ if (kubevirtPortAdminService.port(port.macAddress()) == null) {
+ kubevirtPortAdminService.createPort(port);
+ }
+ });
}
private void processPodUpdate(Pod pod) {
@@ -200,56 +203,57 @@
return;
}
- KubevirtPort port = getPort(kubevirtNetworkAdminService.networks(), pod);
- if (port == null) {
+ Set<KubevirtPort> ports = getPorts(kubevirtNetworkAdminService.networks(), pod);
+ if (ports.size() == 0) {
return;
}
- if (kubevirtPortAdminService.port(port.macAddress()) != null) {
- return;
- }
-
- if (port.ipAddress() == null) {
- try {
- IpAddress ip = kubevirtNetworkAdminService.allocateIp(port.networkId());
- port = port.updateIpAddress(ip);
-
- // update the POD annotation to inject the allocated IP address
- String networkStatusStr = pod.getMetadata().getAnnotations().get(NETWORK_STATUS_KEY);
- JSONArray networkStatus = new JSONArray(networkStatusStr);
- for (int i = 0; i < networkStatus.length(); i++) {
- JSONObject object = networkStatus.getJSONObject(i);
- String name = object.getString(NAME);
- KubevirtNetwork jsonNetwork = kubevirtNetworkAdminService.networks().stream()
- .filter(n -> (NETWORK_PREFIX + n.name()).equals(name))
- .findAny().orElse(null);
- if (jsonNetwork != null) {
- JSONArray ipsJson = new JSONArray();
- ipsJson.put(ip.toString());
- object.put(IPS, ipsJson);
- }
- }
- Map<String, String> annots = pod.getMetadata().getAnnotations();
- annots.put(NETWORK_STATUS_KEY, networkStatus.toString(4));
-
- KubernetesClient client = k8sClient(kubevirtApiConfigService);
-
- if (client == null) {
- return;
- }
-
- client.pods().inNamespace(pod.getMetadata().getNamespace())
- .withName(pod.getMetadata().getName())
- .edit(r -> new PodBuilder(r)
- .editMetadata()
- .addToAnnotations(annots)
- .endMetadata().build()
- );
- } catch (Exception e) {
- log.error("Failed to allocate IP address", e);
+ for (KubevirtPort port : ports) {
+ if (kubevirtPortAdminService.port(port.macAddress()) != null) {
+ continue;
}
+
+ if (port.ipAddress() == null) {
+ try {
+ IpAddress ip = kubevirtNetworkAdminService.allocateIp(port.networkId());
+ log.info("IP address {} is allocated from network {}", ip, port.networkId());
+ port = port.updateIpAddress(ip);
+
+ // update the POD annotation to inject the allocated IP address
+ String networkStatusStr = pod.getMetadata().getAnnotations().get(NETWORK_STATUS_KEY);
+ JSONArray networkStatus = new JSONArray(networkStatusStr);
+ for (int i = 0; i < networkStatus.length(); i++) {
+ JSONObject object = networkStatus.getJSONObject(i);
+ String name = object.getString(NAME);
+
+ if (name.equals(NETWORK_PREFIX + port.networkId())) {
+ JSONArray ipsJson = new JSONArray();
+ ipsJson.put(ip.toString());
+ object.put(IPS, ipsJson);
+ }
+ }
+ Map<String, String> annots = pod.getMetadata().getAnnotations();
+ annots.put(NETWORK_STATUS_KEY, networkStatus.toString(4));
+
+ KubernetesClient client = k8sClient(kubevirtApiConfigService);
+
+ if (client == null) {
+ return;
+ }
+
+ client.pods().inNamespace(pod.getMetadata().getNamespace())
+ .withName(pod.getMetadata().getName())
+ .edit(r -> new PodBuilder(r)
+ .editMetadata()
+ .addToAnnotations(annots)
+ .endMetadata().build()
+ );
+ } catch (Exception e) {
+ log.error("Failed to allocate IP address", e);
+ }
+ }
+ kubevirtPortAdminService.createPort(port);
}
- kubevirtPortAdminService.createPort(port);
}
private void processPodDeletion(Pod pod) {
@@ -257,16 +261,18 @@
return;
}
- KubevirtPort port = getPort(kubevirtNetworkAdminService.networks(), pod);
- if (port == null) {
+ Set<KubevirtPort> ports = getPorts(kubevirtNetworkAdminService.networks(), pod);
+ if (ports.size() == 0) {
return;
}
- if (port.ipAddress() != null) {
- kubevirtNetworkAdminService.releaseIp(port.networkId(), port.ipAddress());
- }
+ ports.forEach(port -> {
+ if (port.ipAddress() != null) {
+ kubevirtNetworkAdminService.releaseIp(port.networkId(), port.ipAddress());
+ }
- kubevirtPortAdminService.removePort(port.macAddress());
+ kubevirtPortAdminService.removePort(port.macAddress());
+ });
}
}
}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
index 01c32dd..91984af 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
@@ -52,6 +52,7 @@
import org.slf4j.Logger;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -61,7 +62,7 @@
import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
-import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getPort;
+import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getPorts;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelToTenantPort;
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
@@ -131,62 +132,64 @@
log.info("Stopped");
}
- private KubevirtPort getPortByPod(Pod pod) {
- return getPort(kubevirtNetworkService.networks(), pod);
+ private Set<KubevirtPort> getPortByPod(Pod pod) {
+ return getPorts(kubevirtNetworkService.networks(), pod);
}
private void setIngressRules(Pod pod, boolean install) {
- KubevirtPort port = getPortByPod(pod);
+ Set<KubevirtPort> ports = getPortByPod(pod);
- if (port == null) {
+ if (ports.size() == 0) {
return;
}
- if (port.ipAddress() == null) {
- return;
+ for (KubevirtPort port : ports) {
+ if (port.ipAddress() == null) {
+ return;
+ }
+
+ KubevirtNetwork network = kubevirtNetworkService.network(port.networkId());
+
+ if (network == null) {
+ return;
+ }
+
+ if (network.type() == FLAT || network.type() == VLAN) {
+ return;
+ }
+
+ if (network.segmentId() == null) {
+ return;
+ }
+
+ KubevirtNode localNode = kubevirtNodeService.node(pod.getSpec().getNodeName());
+ if (localNode == null || localNode.type() == MASTER) {
+ return;
+ }
+
+ PortNumber patchPortNumber = tunnelToTenantPort(localNode, network);
+ if (patchPortNumber == null) {
+ return;
+ }
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchTunnelId(Long.parseLong(network.segmentId()));
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setOutput(patchPortNumber);
+
+ flowRuleService.setRule(
+ appId,
+ localNode.tunBridge(),
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_TUNNEL_RULE,
+ TUNNEL_DEFAULT_TABLE,
+ install);
+
+ log.debug("Install ingress rules for instance {}, segment ID {}",
+ port.ipAddress(), network.segmentId());
}
-
- KubevirtNetwork network = kubevirtNetworkService.network(port.networkId());
-
- if (network == null) {
- return;
- }
-
- if (network.type() == FLAT || network.type() == VLAN) {
- return;
- }
-
- if (network.segmentId() == null) {
- return;
- }
-
- KubevirtNode localNode = kubevirtNodeService.node(pod.getSpec().getNodeName());
- if (localNode == null || localNode.type() == MASTER) {
- return;
- }
-
- PortNumber patchPortNumber = tunnelToTenantPort(localNode, network);
- if (patchPortNumber == null) {
- return;
- }
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchTunnelId(Long.parseLong(network.segmentId()));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(patchPortNumber);
-
- flowRuleService.setRule(
- appId,
- localNode.tunBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_TUNNEL_RULE,
- TUNNEL_DEFAULT_TABLE,
- install);
-
- log.debug("Install ingress rules for instance {}, segment ID {}",
- port.ipAddress(), network.segmentId());
}
private void setEgressRules(Pod pod, boolean install) {
@@ -200,85 +203,87 @@
return;
}
- KubevirtPort port = getPortByPod(pod);
+ Set<KubevirtPort> ports = getPortByPod(pod);
- if (port == null) {
+ if (ports.size() == 0) {
return;
}
- if (port.ipAddress() == null) {
- return;
- }
-
- KubevirtNetwork network = kubevirtNetworkService.network(port.networkId());
-
- if (network == null) {
- return;
- }
-
- if (network.type() == FLAT || network.type() == VLAN) {
- return;
- }
-
- if (network.segmentId() == null) {
- return;
- }
-
- for (KubevirtNode remoteNode : kubevirtNodeService.completeNodes(WORKER)) {
- if (remoteNode.hostname().equals(localNode.hostname())) {
- continue;
- }
-
- PortNumber patchPortNumber = tunnelToTenantPort(remoteNode, network);
- if (patchPortNumber == null) {
+ for (KubevirtPort port : ports) {
+ if (port.ipAddress() == null) {
return;
}
- PortNumber tunnelPortNumber = tunnelPort(remoteNode, network);
- if (tunnelPortNumber == null) {
+ KubevirtNetwork network = kubevirtNetworkService.network(port.networkId());
+
+ if (network == null) {
return;
}
- TrafficSelector.Builder sIpBuilder = DefaultTrafficSelector.builder()
- .matchInPort(patchPortNumber)
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(IpPrefix.valueOf(port.ipAddress(), 32));
+ if (network.type() == FLAT || network.type() == VLAN) {
+ return;
+ }
- TrafficSelector.Builder sArpBuilder = DefaultTrafficSelector.builder()
- .matchInPort(patchPortNumber)
- .matchEthType(Ethernet.TYPE_ARP)
- .matchArpTpa(Ip4Address.valueOf(port.ipAddress().toString()));
+ if (network.segmentId() == null) {
+ return;
+ }
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setTunnelId(Long.parseLong(network.segmentId()))
- .extension(buildExtension(
- deviceService,
- remoteNode.tunBridge(),
- localNode.dataIp().getIp4Address()),
- remoteNode.tunBridge())
- .setOutput(tunnelPortNumber);
+ for (KubevirtNode remoteNode : kubevirtNodeService.completeNodes(WORKER)) {
+ if (remoteNode.hostname().equals(localNode.hostname())) {
+ continue;
+ }
- flowRuleService.setRule(
- appId,
- remoteNode.tunBridge(),
- sIpBuilder.build(),
- tBuilder.build(),
- PRIORITY_TUNNEL_RULE,
- TUNNEL_DEFAULT_TABLE,
- install);
+ PortNumber patchPortNumber = tunnelToTenantPort(remoteNode, network);
+ if (patchPortNumber == null) {
+ return;
+ }
- flowRuleService.setRule(
- appId,
- remoteNode.tunBridge(),
- sArpBuilder.build(),
- tBuilder.build(),
- PRIORITY_TUNNEL_RULE,
- TUNNEL_DEFAULT_TABLE,
- install);
+ PortNumber tunnelPortNumber = tunnelPort(remoteNode, network);
+ if (tunnelPortNumber == null) {
+ return;
+ }
+
+ TrafficSelector.Builder sIpBuilder = DefaultTrafficSelector.builder()
+ .matchInPort(patchPortNumber)
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(IpPrefix.valueOf(port.ipAddress(), 32));
+
+ TrafficSelector.Builder sArpBuilder = DefaultTrafficSelector.builder()
+ .matchInPort(patchPortNumber)
+ .matchEthType(Ethernet.TYPE_ARP)
+ .matchArpTpa(Ip4Address.valueOf(port.ipAddress().toString()));
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setTunnelId(Long.parseLong(network.segmentId()))
+ .extension(buildExtension(
+ deviceService,
+ remoteNode.tunBridge(),
+ localNode.dataIp().getIp4Address()),
+ remoteNode.tunBridge())
+ .setOutput(tunnelPortNumber);
+
+ flowRuleService.setRule(
+ appId,
+ remoteNode.tunBridge(),
+ sIpBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_TUNNEL_RULE,
+ TUNNEL_DEFAULT_TABLE,
+ install);
+
+ flowRuleService.setRule(
+ appId,
+ remoteNode.tunBridge(),
+ sArpBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_TUNNEL_RULE,
+ TUNNEL_DEFAULT_TABLE,
+ install);
+ }
+
+ log.debug("Install egress rules for instance {}, segment ID {}",
+ port.ipAddress(), network.segmentId());
}
-
- log.debug("Install egress rules for instance {}, segment ID {}",
- port.ipAddress(), network.segmentId());
}
private class InternalKubevirtNodeListener implements KubevirtNodeListener {
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
index 8a9ee6c..e1a26d7 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
@@ -17,6 +17,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
@@ -319,26 +320,27 @@
*
* @param networks set of existing kubevirt networks
* @param pod kubevirt POD
- * @return kubevirt port
+ * @return kubevirt ports attached to the POD
*/
- public static KubevirtPort getPort(Set<KubevirtNetwork> networks, Pod pod) {
+ public static Set<KubevirtPort> getPorts(Set<KubevirtNetwork> networks, Pod pod) {
try {
Map<String, String> annots = pod.getMetadata().getAnnotations();
if (annots == null) {
- return null;
+ return ImmutableSet.of();
}
if (!annots.containsKey(NETWORK_STATUS_KEY)) {
- return null;
+ return ImmutableSet.of();
}
String networkStatusStr = annots.get(NETWORK_STATUS_KEY);
if (networkStatusStr == null) {
- return null;
+ return ImmutableSet.of();
}
JSONArray networkStatus = new JSONArray(networkStatusStr);
+ Set<KubevirtPort> ports = new HashSet<>();
for (int i = 0; i < networkStatus.length(); i++) {
JSONObject object = networkStatus.getJSONObject(i);
@@ -359,15 +361,17 @@
builder.ipAddress(IpAddress.valueOf(ip));
}
- return builder.build();
+ ports.add(builder.build());
}
}
+ return ports;
+
} catch (JSONException e) {
log.error("Failed to parse network status object", e);
}
- return null;
+ return ImmutableSet.of();
}
/**