Initial implementation of gateway load balancer for SONA app
Change-Id: Idd03646d637acd448985eb6e62204a8a9d759867
diff --git a/apps/openstacknetworking/app/BUCK b/apps/openstacknetworking/app/BUCK
index b4c5f92..34933f4 100644
--- a/apps/openstacknetworking/app/BUCK
+++ b/apps/openstacknetworking/app/BUCK
@@ -27,6 +27,7 @@
'//core/common:onos-core-common-tests',
'//web/api:onos-rest-tests',
'//lib:TEST_REST',
+ '//apps/openstacknode/app:onos-apps-openstacknode-app-tests',
]
osgi_jar_with_tests (
diff --git a/apps/openstacknetworking/app/pom.xml b/apps/openstacknetworking/app/pom.xml
index 832d298..eea170c 100644
--- a/apps/openstacknetworking/app/pom.xml
+++ b/apps/openstacknetworking/app/pom.xml
@@ -47,8 +47,9 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
- <artifactId>onos-apps-openstacknetworking-api</artifactId>
+ <artifactId>onos-apps-openstacknode-app</artifactId>
<version>${project.version}</version>
+ <classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
@@ -109,11 +110,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-apps-openstacknode-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index c72b511..dced0df 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -16,7 +16,9 @@
package org.onosproject.openstacknetworking.impl;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -54,8 +56,10 @@
import org.onosproject.net.packet.PacketService;
import org.onosproject.openstacknetworking.api.Constants;
import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortService;
import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
+import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
import org.onosproject.openstacknetworking.api.OpenstackRouterService;
@@ -92,6 +96,7 @@
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
import static org.slf4j.LoggerFactory.getLogger;
@@ -123,6 +128,9 @@
protected OpenstackNodeService osNodeService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected InstancePortService instancePortService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -132,6 +140,9 @@
protected OpenstackFlowRuleService osFlowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackNetworkService osNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -231,10 +242,20 @@
return;
}
+ OpenstackNode gw = getGwByTargetMac(osNodeService.completeNodes(GATEWAY), targetMac);
+
+ if (gw == null) {
+ return;
+ }
+
+ // if the ARP packet_in received from non-relevant GWs, we simply ignore it
+ if (!Objects.equals(gw.intgBridge(), context.inPacket().receivedFrom().deviceId())) {
+ return;
+ }
+
Ethernet ethReply = ARP.buildArpReply(targetIp.getIp4Address(),
targetMac, ethernet);
-
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(context.inPacket().receivedFrom().port()).build();
@@ -314,14 +335,72 @@
/**
* Installs static ARP rules used in ARP BROAD_CAST mode.
+ *
+ * @param gateway gateway node
+ * @param install flow rule installation flag
+ */
+ private void setFloatingIpArpRuleForGateway(OpenstackNode gateway, boolean install) {
+ if (arpMode.equals(ARP_BROADCAST_MODE)) {
+
+ Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
+ Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
+ finalGws.addAll(ImmutableSet.copyOf(completedGws));
+
+ if (install) {
+ if (completedGws.contains(gateway)) {
+ if (completedGws.size() > 1) {
+ finalGws.remove(gateway);
+ osRouterService.floatingIps().forEach(fip -> {
+ if (fip.getPortId() != null) {
+ setFloatingIpArpRule(fip, finalGws, false);
+ finalGws.add(gateway);
+ }
+ });
+ }
+ osRouterService.floatingIps().forEach(fip -> {
+ if (fip.getPortId() != null) {
+ setFloatingIpArpRule(fip, finalGws, true);
+ }
+ });
+ } else {
+ log.warn("Detected node should be included in completed gateway set");
+ }
+ } else {
+ if (!completedGws.contains(gateway)) {
+ finalGws.add(gateway);
+ osRouterService.floatingIps().forEach(fip -> {
+ if (fip.getPortId() != null) {
+ setFloatingIpArpRule(fip, finalGws, false);
+ }
+ });
+ finalGws.remove(gateway);
+ if (completedGws.size() >= 1) {
+ osRouterService.floatingIps().forEach(fip -> {
+ if (fip.getPortId() != null) {
+ setFloatingIpArpRule(fip, finalGws, true);
+ }
+ });
+ }
+ } else {
+ log.warn("Detected node should NOT be included in completed gateway set");
+ }
+ }
+ }
+ }
+
+ /**
+ * Installs static ARP rules used in ARP BROAD_CAST mode.
* Note that, those rules will be only matched ARP_REQUEST packets,
* used for telling gateway node the mapped MAC address of requested IP,
* without the helps from controller.
*
* @param fip floating IP address
+ * @param gateways a set of gateway nodes
* @param install flow rule installation flag
*/
- private void setFloatingIpArpRule(NetFloatingIP fip, boolean install) {
+ private synchronized void setFloatingIpArpRule(NetFloatingIP fip,
+ Set<OpenstackNode> gateways,
+ boolean install) {
if (arpMode.equals(ARP_BROADCAST_MODE)) {
if (fip == null) {
@@ -346,6 +425,12 @@
MacAddress targetMac = MacAddress.valueOf(macString);
+ OpenstackNode gw = getGwByTargetMac(gateways, targetMac);
+
+ if (gw == null) {
+ return;
+ }
+
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.matchArpOp(ARP.OP_REQUEST)
@@ -359,16 +444,14 @@
.setOutput(PortNumber.IN_PORT)
.build();
- osNodeService.completeNodes(GATEWAY).forEach(n ->
- osFlowRuleService.setRule(
- appId,
- n.intgBridge(),
- selector,
- treatment,
- PRIORITY_ARP_GATEWAY_RULE,
- GW_COMMON_TABLE,
- install
- )
+ osFlowRuleService.setRule(
+ appId,
+ gw.intgBridge(),
+ selector,
+ treatment,
+ PRIORITY_ARP_GATEWAY_RULE,
+ GW_COMMON_TABLE,
+ install
);
if (install) {
@@ -381,6 +464,17 @@
}
}
+ // a helper method
+ private OpenstackNode getGwByTargetMac(Set<OpenstackNode> gateways,
+ MacAddress targetMac) {
+ InstancePort instPort = instancePortService.instancePort(targetMac);
+ OpenstackNode gw = null;
+ if (instPort != null && instPort.deviceId() != null) {
+ gw = getGwByComputeDevId(gateways, instPort.deviceId());
+ }
+ return gw;
+ }
+
/**
* An internal router event listener, intended to install/uninstall
* ARP rules for forwarding packets created from floating IPs.
@@ -396,6 +490,9 @@
@Override
public void event(OpenstackRouterEvent event) {
+
+ Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
+
switch (event.type()) {
case OPENSTACK_ROUTER_CREATED:
eventExecutor.execute(() ->
@@ -424,13 +521,13 @@
case OPENSTACK_FLOATING_IP_ASSOCIATED:
eventExecutor.execute(() ->
// associate a floating IP with an existing VM
- setFloatingIpArpRule(event.floatingIp(), true)
+ setFloatingIpArpRule(event.floatingIp(), completedGws, true)
);
break;
case OPENSTACK_FLOATING_IP_DISASSOCIATED:
eventExecutor.execute(() ->
// disassociate a floating IP with the existing VM
- setFloatingIpArpRule(event.floatingIp(), false)
+ setFloatingIpArpRule(event.floatingIp(), completedGws, false)
);
break;
case OPENSTACK_FLOATING_IP_CREATED:
@@ -441,7 +538,7 @@
// associated with any port of VM, then we will set
// floating IP related ARP rules to gateway node
if (!Strings.isNullOrEmpty(osFip.getPortId())) {
- setFloatingIpArpRule(osFip, true);
+ setFloatingIpArpRule(osFip, completedGws, true);
}
});
break;
@@ -453,7 +550,7 @@
// still associated with any port of VM, then we will
// remove floating IP related ARP rules from gateway node
if (!Strings.isNullOrEmpty(osFip.getPortId())) {
- setFloatingIpArpRule(event.floatingIp(), false);
+ setFloatingIpArpRule(event.floatingIp(), completedGws, false);
}
});
break;
@@ -564,7 +661,8 @@
}
if (fip.getFixedIpAddress().equals(port.ipAddress().toString())) {
eventExecutor.execute(() ->
- setFloatingIpArpRule(fip, false)
+ setFloatingIpArpRule(fip,
+ osNodeService.completeNodes(GATEWAY), false)
);
}
}
@@ -594,11 +692,14 @@
case OPENSTACK_NODE_COMPLETE:
if (osNode.type().equals(GATEWAY)) {
setDefaultArpRule(osNode, true);
+ setFloatingIpArpRuleForGateway(osNode, true);
}
+
break;
case OPENSTACK_NODE_INCOMPLETE:
if (osNode.type().equals(GATEWAY)) {
setDefaultArpRule(osNode, false);
+ setFloatingIpArpRuleForGateway(osNode, false);
}
break;
default:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index 42fd73d..dfe20b8 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -16,7 +16,9 @@
package org.onosproject.openstacknetworking.impl;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -80,6 +82,7 @@
import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
@@ -158,7 +161,7 @@
}
private void setFloatingIpRules(NetFloatingIP floatingIp, Port osPort,
- boolean install) {
+ OpenstackNode gateway, boolean install) {
Network osNet = osNetworkService.network(osPort.getNetworkId());
if (osNet == null) {
final String errorFormat = ERR_FLOW + "no network(%s) exists";
@@ -192,7 +195,7 @@
throw new IllegalStateException(errorFormat);
}
- setComputeNodeToGateway(instPort, osNet, install);
+ setComputeNodeToGateway(instPort, osNet, gateway, install);
setDownstreamRules(floatingIp, osNet, instPort, externalPeerRouter, install);
setUpstreamRules(floatingIp, osNet, instPort, externalPeerRouter, install);
log.trace("Succeeded to set flow rules for floating ip {}:{} and install: {}",
@@ -201,7 +204,57 @@
install);
}
- private void setComputeNodeToGateway(InstancePort instPort, Network osNet, boolean install) {
+ private synchronized void setComputeNodeToGateway(InstancePort instPort,
+ Network osNet,
+ OpenstackNode gateway,
+ boolean install) {
+
+ Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
+ Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
+ finalGws.addAll(ImmutableSet.copyOf(completedGws));
+
+ if (gateway == null) {
+ // these are floating IP related cases...
+ setComputeNodeToGatewayHelper(instPort, osNet,
+ ImmutableSet.copyOf(finalGws), install);
+ } else {
+ // these are openstack node related cases...
+ if (install) {
+ if (completedGws.contains(gateway)) {
+ if (completedGws.size() > 1) {
+ finalGws.remove(gateway);
+ setComputeNodeToGatewayHelper(instPort, osNet,
+ ImmutableSet.copyOf(finalGws), false);
+ finalGws.add(gateway);
+ }
+
+ setComputeNodeToGatewayHelper(instPort, osNet,
+ ImmutableSet.copyOf(finalGws), true);
+ } else {
+ log.warn("Detected node should be included in completed gateway set");
+ }
+ } else {
+ if (!completedGws.contains(gateway)) {
+ finalGws.add(gateway);
+ setComputeNodeToGatewayHelper(instPort, osNet,
+ ImmutableSet.copyOf(finalGws), false);
+ finalGws.remove(gateway);
+ if (completedGws.size() >= 1) {
+ setComputeNodeToGatewayHelper(instPort, osNet,
+ ImmutableSet.copyOf(finalGws), true);
+ }
+ } else {
+ log.warn("Detected node should NOT be included in completed gateway set");
+ }
+ }
+ }
+ }
+
+ // a helper method
+ private void setComputeNodeToGatewayHelper(InstancePort instPort,
+ Network osNet,
+ Set<OpenstackNode> gateways,
+ boolean install) {
TrafficTreatment treatment;
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
@@ -223,7 +276,8 @@
throw new IllegalStateException(error);
}
- OpenstackNode selectedGatewayNode = selectGatewayNode();
+ OpenstackNode selectedGatewayNode = getGwByComputeDevId(gateways, instPort.deviceId());
+
if (selectedGatewayNode == null) {
final String errorFormat = ERR_FLOW + "no gateway node selected";
throw new IllegalStateException(errorFormat);
@@ -248,11 +302,6 @@
log.trace("Succeeded to set flow rules from compute node to gateway on compute node");
}
- private OpenstackNode selectGatewayNode() {
- //TODO support multiple loadbalancing options.
- return osNodeService.completeNodes(GATEWAY).stream().findAny().orElse(null);
- }
-
private void setDownstreamRules(NetFloatingIP floatingIp, Network osNet,
InstancePort instPort, ExternalPeerRouter externalPeerRouter,
boolean install) {
@@ -454,7 +503,7 @@
}
// set floating IP rules only if the port is associated to a VM
if (!Strings.isNullOrEmpty(osPort.getDeviceId())) {
- setFloatingIpRules(osFip, osPort, true);
+ setFloatingIpRules(osFip, osPort, null, true);
}
}
@@ -467,7 +516,7 @@
}
// set floating IP rules only if the port is associated to a VM
if (!Strings.isNullOrEmpty(osPort.getDeviceId())) {
- setFloatingIpRules(osFip, osPort, false);
+ setFloatingIpRules(osFip, osPort, null, false);
}
}
@@ -561,14 +610,51 @@
log.warn("Failed to set floating IP {}", fip.getId());
continue;
}
- setFloatingIpRules(fip, osPort, true);
+ setFloatingIpRules(fip, osPort, event.subject(), true);
}
});
break;
- case OPENSTACK_NODE_CREATED:
- case OPENSTACK_NODE_UPDATED:
- case OPENSTACK_NODE_REMOVED:
case OPENSTACK_NODE_INCOMPLETE:
+
+ // we only purge the routing related rules stored in each
+ // compute node when gateway node becomes unavailable
+ if (!event.subject().type().equals(GATEWAY)) {
+ return;
+ }
+
+ eventExecutor.execute(() -> {
+ for (NetFloatingIP fip : osRouterService.floatingIps()) {
+ if (Strings.isNullOrEmpty(fip.getPortId())) {
+ continue;
+ }
+ Port osPort = osNetworkService.port(fip.getPortId());
+ if (osPort == null) {
+ log.warn("Failed to set floating IP {}", fip.getId());
+ continue;
+ }
+ Network osNet = osNetworkService.network(osPort.getNetworkId());
+ if (osNet == null) {
+ final String errorFormat = ERR_FLOW + "no network(%s) exists";
+ final String error = String.format(errorFormat,
+ fip.getFloatingIpAddress(),
+ osPort.getNetworkId());
+ throw new IllegalStateException(error);
+ }
+ MacAddress srcMac = MacAddress.valueOf(osPort.getMacAddress());
+ log.trace("Mac address of openstack port: {}", srcMac);
+ InstancePort instPort = instancePortService.instancePort(srcMac);
+
+ if (instPort == null) {
+ final String errorFormat = ERR_FLOW + "no host(MAC:%s) found";
+ final String error = String.format(errorFormat,
+ fip.getFloatingIpAddress(), srcMac);
+ throw new IllegalStateException(error);
+ }
+
+ setComputeNodeToGateway(instPort, osNet, event.subject(), false);
+ }
+ });
+ break;
default:
// do nothing
break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index ffd5ab7..98fc0a9 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -18,12 +18,19 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.net.DeviceId;
+import org.onosproject.openstacknode.api.OpenstackNode;
import org.openstack4j.core.transport.ObjectMapperSingleton;
import org.openstack4j.model.ModelEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
@@ -79,4 +86,43 @@
throw new IllegalStateException();
}
}
+
+ /**
+ * Obtains the gateway node by device in compute node. Note that the gateway
+ * node is determined by device's device identifier.
+ *
+ * @param gws a collection of gateway nodes
+ * @param deviceId device identifier
+ * @return a gateway node
+ */
+ public static OpenstackNode getGwByComputeDevId(Set<OpenstackNode> gws, DeviceId deviceId) {
+ int numOfGw = gws.size();
+
+ if (numOfGw == 0) {
+ return null;
+ }
+
+ int gwIndex = Math.abs(deviceId.hashCode()) % numOfGw;
+
+ return getGwByIndex(gws, gwIndex);
+ }
+
+ private static OpenstackNode getGwByIndex(Set<OpenstackNode> gws, int index) {
+ Map<String, OpenstackNode> hashMap = new HashMap<>();
+ gws.forEach(gw -> hashMap.put(gw.hostname(), gw));
+ TreeMap<String, OpenstackNode> treeMap = new TreeMap<>(hashMap);
+ Iterator<String> iteratorKey = treeMap.keySet().iterator();
+
+ int intIndex = 0;
+ OpenstackNode gw = null;
+ while (iteratorKey.hasNext()) {
+ String key = iteratorKey.next();
+
+ if (intIndex == index) {
+ gw = treeMap.get(key);
+ }
+ intIndex++;
+ }
+ return gw;
+ }
}
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtilTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtilTest.java
index a6c4bc3..e33637e 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtilTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtilTest.java
@@ -16,17 +16,32 @@
package org.onosproject.openstacknetworking.util;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import com.google.common.testing.EqualsTester;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.openstacknode.api.NodeState;
+import org.onosproject.openstacknode.api.OpenstackNode;
+import org.onosproject.openstacknode.impl.OpenstackNodeTest;
import org.openstack4j.model.network.NetFloatingIP;
import org.openstack4j.openstack.networking.domain.NeutronFloatingIP;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
public final class OpenstackNetworkingUtilTest {
@@ -56,4 +71,58 @@
OpenstackNetworkingUtil.jsonToModelEntity(is, NeutronFloatingIP.class);
new EqualsTester().addEqualityGroup(floatingIp, floatingIp2).testEquals();
}
+
+ /**
+ * Tests the getGwByComputeDevId method.
+ */
+ @Test
+ public void testGetGwByComputeDevId() {
+ Set<OpenstackNode> gws = Sets.newConcurrentHashSet();
+ gws.add(genGateway(1));
+ gws.add(genGateway(2));
+ gws.add(genGateway(3));
+
+ Set<OpenstackNode> cloneOfGws = ImmutableSet.copyOf(gws);
+
+ Map<String, Integer> gwCountMap = Maps.newConcurrentMap();
+ int numOfDev = 99;
+
+ for (int i = 1; i < 1 + numOfDev; i++) {
+ OpenstackNode gw = getGwByComputeDevId(gws, genDeviceId(i));
+
+ if (gwCountMap.get(gw.hostname()) == null) {
+ gwCountMap.put(gw.hostname(), 1);
+ } else {
+ gwCountMap.compute(gw.hostname(), (k, v) -> v + 1);
+ }
+
+ new EqualsTester().addEqualityGroup(
+ getGwByComputeDevId(gws, genDeviceId(i)),
+ getGwByComputeDevId(cloneOfGws, genDeviceId(i)))
+ .testEquals();
+ }
+
+ int sum = gwCountMap.values().stream().mapToInt(Integer::intValue).sum();
+ assertEquals(numOfDev, sum);
+ }
+
+ private OpenstackNode genGateway(int index) {
+
+ Device intgBrg = InternalOpenstackNodeTest.createDevice(index);
+
+ String hostname = "gateway-" + index;
+ IpAddress ip = Ip4Address.valueOf("10.10.10." + index);
+ NodeState state = NodeState.COMPLETE;
+ String uplinkPort = "eth0";
+ return InternalOpenstackNodeTest.createNode(hostname,
+ OpenstackNode.NodeType.GATEWAY, intgBrg, ip, uplinkPort, state);
+
+ }
+
+ private DeviceId genDeviceId(int index) {
+ return DeviceId.deviceId("of:compute-" + index);
+ }
+
+ protected class InternalOpenstackNodeTest extends OpenstackNodeTest {
+ }
}
diff --git a/apps/openstacknetworking/pom.xml b/apps/openstacknetworking/pom.xml
index 1610dd0..a9cb838 100644
--- a/apps/openstacknetworking/pom.xml
+++ b/apps/openstacknetworking/pom.xml
@@ -44,4 +44,22 @@
<module>app</module>
</modules>
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps-openstacknetworking-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps-openstacknode-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps-openstacknode-app</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
</project>
diff --git a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/OpenstackNodeTest.java b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/OpenstackNodeTest.java
index fbec333..7deca06 100644
--- a/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/OpenstackNodeTest.java
+++ b/apps/openstacknode/app/src/test/java/org/onosproject/openstacknode/impl/OpenstackNodeTest.java
@@ -30,9 +30,9 @@
/**
* Provides a set of test OpenstackNode parameters for use with OpenstackNode related tests.
*/
-abstract class OpenstackNodeTest {
+public abstract class OpenstackNodeTest {
- protected static Device createDevice(long devIdNum) {
+ public static Device createDevice(long devIdNum) {
return new DefaultDevice(new ProviderId("of", "foo"),
DeviceId.deviceId(String.format("of:%016d", devIdNum)),
SWITCH,
@@ -43,10 +43,10 @@
new ChassisId(1));
}
- protected static OpenstackNode createNode(String hostname, NodeType type,
+ public static OpenstackNode createNode(String hostname, NodeType type,
Device intgBridge, IpAddress ipAddr,
NodeState state) {
- return org.onosproject.openstacknode.impl.DefaultOpenstackNode.builder()
+ return DefaultOpenstackNode.builder()
.hostname(hostname)
.type(type)
.intgBridge(intgBridge.id())
@@ -56,10 +56,10 @@
.build();
}
- protected static OpenstackNode createNode(String hostname, NodeType type,
+ public static OpenstackNode createNode(String hostname, NodeType type,
Device intgBridge, IpAddress ipAddr,
String uplinkPort, NodeState state) {
- return org.onosproject.openstacknode.impl.DefaultOpenstackNode.builder()
+ return DefaultOpenstackNode.builder()
.hostname(hostname)
.type(type)
.intgBridge(intgBridge.id())