Merge remote-tracking branch 'origin/master'
diff --git a/apps/foo/src/main/java/org/onlab/onos/foo/SimpleNettyClient.java b/apps/foo/src/main/java/org/onlab/onos/foo/SimpleNettyClient.java
index 337d506..b2250e1 100644
--- a/apps/foo/src/main/java/org/onlab/onos/foo/SimpleNettyClient.java
+++ b/apps/foo/src/main/java/org/onlab/onos/foo/SimpleNettyClient.java
@@ -102,7 +102,7 @@
// System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS)));
}
- sleep(1000);
+ //sleep(1000);
log.info("measuring async sender");
Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
@@ -111,7 +111,7 @@
messaging.sendAsync(endpoint, "simple", "Hello World".getBytes());
context.stop();
}
- sleep(1000);
+ sleep(10000);
}
public static void stop() {
diff --git a/cli/src/main/java/org/onlab/onos/cli/MastersListCommand.java b/cli/src/main/java/org/onlab/onos/cli/MastersListCommand.java
index 2da76fd..0f7857f 100644
--- a/cli/src/main/java/org/onlab/onos/cli/MastersListCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/MastersListCommand.java
@@ -1,10 +1,11 @@
package org.onlab.onos.cli;
import com.google.common.collect.Lists;
+
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
-import org.onlab.onos.cluster.MastershipService;
+import org.onlab.onos.mastership.MastershipService;
import org.onlab.onos.net.DeviceId;
import java.util.Collections;
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/AddMultiPointToSinglePointIntentCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/AddMultiPointToSinglePointIntentCommand.java
new file mode 100644
index 0000000..cdae8a6
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/AddMultiPointToSinglePointIntentCommand.java
@@ -0,0 +1,102 @@
+package org.onlab.onos.cli.net;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentService;
+import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
+import org.onlab.packet.Ethernet;
+
+/**
+ * Installs point-to-point connectivity intents.
+ */
+@Command(scope = "onos", name = "add-multi-to-single-intent",
+ description = "Installs point-to-point connectivity intent")
+public class AddMultiPointToSinglePointIntentCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "ingressDevices",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = true)
+ String[] deviceStrings = null;
+
+ private static long id = 0x7070001;
+
+ @Override
+ protected void execute() {
+ IntentService service = get(IntentService.class);
+
+ if (deviceStrings.length < 2) {
+ return;
+ }
+
+ String egressDeviceString = deviceStrings[deviceStrings.length - 1];
+ DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
+ PortNumber egressPortNumber =
+ PortNumber.portNumber(getPortNumber(egressDeviceString));
+ ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
+ Set<ConnectPoint> ingressPoints = new HashSet<>();
+
+ for (int index = 0; index < deviceStrings.length - 1; index++) {
+ String ingressDeviceString = deviceStrings[index];
+ DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
+ PortNumber ingressPortNumber =
+ PortNumber.portNumber(getPortNumber(ingressDeviceString));
+ ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+ ingressPoints.add(ingress);
+ }
+
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+ Intent intent =
+ new MultiPointToSinglePointIntent(new IntentId(id++),
+ selector,
+ treatment,
+ ingressPoints,
+ egress);
+ service.submit(intent);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/DeviceRoleCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/DeviceRoleCommand.java
index dfb8283..a5fdb3f 100644
--- a/cli/src/main/java/org/onlab/onos/cli/net/DeviceRoleCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/net/DeviceRoleCommand.java
@@ -3,8 +3,8 @@
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.onos.cli.AbstractShellCommand;
-import org.onlab.onos.cluster.MastershipAdminService;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipAdminService;
import org.onlab.onos.net.MastershipRole;
import static org.onlab.onos.net.DeviceId.deviceId;
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/IntentPushTestCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/IntentPushTestCommand.java
new file mode 100644
index 0000000..60181bd
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/IntentPushTestCommand.java
@@ -0,0 +1,145 @@
+package org.onlab.onos.cli.net;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.DefaultTrafficTreatment;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentEvent;
+import org.onlab.onos.net.intent.IntentEvent.Type;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.IntentListener;
+import org.onlab.onos.net.intent.IntentService;
+import org.onlab.onos.net.intent.PointToPointIntent;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+
+/**
+ * Installs point-to-point connectivity intents.
+ */
+@Command(scope = "onos", name = "push-test-intents",
+ description = "Installs random intents to test throughput")
+public class IntentPushTestCommand extends AbstractShellCommand
+ implements IntentListener {
+
+ @Argument(index = 0, name = "ingressDevice",
+ description = "Ingress Device/Port Description",
+ required = true, multiValued = false)
+ String ingressDeviceString = null;
+
+ @Argument(index = 1, name = "egressDevice",
+ description = "Egress Device/Port Description",
+ required = true, multiValued = false)
+ String egressDeviceString = null;
+
+ @Argument(index = 2, name = "count",
+ description = "Number of intents to push",
+ required = true, multiValued = false)
+ String countString = null;
+
+
+ private static long id = 0x7870001;
+
+ private IntentService service;
+ private CountDownLatch latch;
+ private long start, end;
+
+ @Override
+ protected void execute() {
+ service = get(IntentService.class);
+
+ DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
+ PortNumber ingressPortNumber =
+ PortNumber.portNumber(getPortNumber(ingressDeviceString));
+ ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
+ PortNumber egressPortNumber =
+ PortNumber.portNumber(getPortNumber(egressDeviceString));
+ ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4);
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+
+ int count = Integer.parseInt(countString);
+
+ service.addListener(this);
+ latch = new CountDownLatch(count);
+
+ start = System.currentTimeMillis();
+ for (int i = 0; i < count; i++) {
+ TrafficSelector s = selector
+ .matchEthSrc(MacAddress.valueOf(i))
+ .build();
+ Intent intent =
+ new PointToPointIntent(new IntentId(id++),
+ s,
+ treatment,
+ ingress,
+ egress);
+ service.submit(intent);
+ }
+ try {
+ latch.await(5, TimeUnit.SECONDS);
+ printResults(count);
+ } catch (InterruptedException e) {
+ print(e.toString());
+ }
+ service.removeListener(this);
+ }
+
+ private void printResults(int count) {
+ long delta = end - start;
+ print("Time to install %d intents: %d ms", count, delta);
+ }
+
+ /**
+ * Extracts the port number portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return port number as a string, empty string if the port is not found
+ */
+ private String getPortNumber(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(slash + 1, deviceString.length());
+ }
+
+ /**
+ * Extracts the device ID portion of the ConnectPoint.
+ *
+ * @param deviceString string representing the device/port
+ * @return device ID string
+ */
+ private String getDeviceId(String deviceString) {
+ int slash = deviceString.indexOf('/');
+ if (slash <= 0) {
+ return "";
+ }
+ return deviceString.substring(0, slash);
+ }
+
+ @Override
+ public void event(IntentEvent event) {
+ if (event.type() == Type.INSTALLED) {
+ end = event.time();
+ if (latch != null) {
+ latch.countDown();
+ } else {
+ log.warn("install event latch is null");
+ }
+ }
+ }
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 6120d30..f6fa0ff 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -82,6 +82,19 @@
<ref component-id="connectPointCompleter"/>
</completers>
</command>
+ <command>
+ <action class="org.onlab.onos.cli.net.AddMultiPointToSinglePointIntentCommand"/>
+ <completers>
+ <ref component-id="connectPointCompleter"/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onlab.onos.cli.net.IntentPushTestCommand"/>
+ <completers>
+ <ref component-id="connectPointCompleter"/>
+ <ref component-id="connectPointCompleter"/>
+ </completers>
+ </command>
<command>
<action class="org.onlab.onos.cli.net.ClustersListCommand"/>
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipAdminService.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipAdminService.java
similarity index 87%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipAdminService.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipAdminService.java
index 907b3f8..e558dd4 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipAdminService.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipAdminService.java
@@ -1,5 +1,6 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
+import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipEvent.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
similarity index 95%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipEvent.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
index 15811fb..bd7462d 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
@@ -1,5 +1,6 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
+import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractEvent;
import org.onlab.onos.net.DeviceId;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipListener.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipListener.java
similarity index 84%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipListener.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipListener.java
index 71d65be..e4295e0 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipListener.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipListener.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import org.onlab.onos.event.EventListener;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipService.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
similarity index 96%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipService.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
index 51b6f6a..029e357 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipService.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
@@ -1,7 +1,8 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import java.util.Set;
+import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
similarity index 97%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
index dc5603f..0117d0d 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
@@ -1,7 +1,8 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import java.util.Set;
+import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.store.Store;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStoreDelegate.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStoreDelegate.java
similarity index 83%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipStoreDelegate.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipStoreDelegate.java
index b4d923c..2537630 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStoreDelegate.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStoreDelegate.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import org.onlab.onos.store.StoreDelegate;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipTerm.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipTerm.java
similarity index 93%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipTerm.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipTerm.java
index 71d08f2..640180d 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipTerm.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipTerm.java
@@ -1,7 +1,9 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import java.util.Objects;
+import org.onlab.onos.cluster.NodeId;
+
public final class MastershipTerm {
private final NodeId master;
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipTermService.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipTermService.java
similarity index 93%
rename from core/api/src/main/java/org/onlab/onos/cluster/MastershipTermService.java
rename to core/api/src/main/java/org/onlab/onos/mastership/MastershipTermService.java
index b03ed81..567962e 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipTermService.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipTermService.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import org.onlab.onos.net.DeviceId;
diff --git a/core/api/src/main/java/org/onlab/onos/mastership/package-info.java b/core/api/src/main/java/org/onlab/onos/mastership/package-info.java
new file mode 100644
index 0000000..36f7271
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/mastership/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Set of abstractions for dealing with controller mastership related topics.
+ */
+package org.onlab.onos.mastership;
diff --git a/core/api/src/main/java/org/onlab/onos/store/ClockProviderService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
similarity index 69%
rename from core/api/src/main/java/org/onlab/onos/store/ClockProviderService.java
rename to core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
index a5f81c7..1fb4899 100644
--- a/core/api/src/main/java/org/onlab/onos/store/ClockProviderService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
@@ -1,14 +1,13 @@
-package org.onlab.onos.store;
+package org.onlab.onos.net.device;
-import org.onlab.onos.cluster.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
-//TODO: Consider renaming to DeviceClockProviderService?
/**
* Interface for feeding term information to a logical clock service
* that vends per device timestamps.
*/
-public interface ClockProviderService {
+public interface DeviceClockProviderService {
/**
* Updates the mastership term for the specified deviceId.
diff --git a/core/api/src/main/java/org/onlab/onos/store/ClockService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
similarity index 76%
rename from core/api/src/main/java/org/onlab/onos/store/ClockService.java
rename to core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
index 20549e8..ccdfeb0 100644
--- a/core/api/src/main/java/org/onlab/onos/store/ClockService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
@@ -1,12 +1,13 @@
-package org.onlab.onos.store;
+package org.onlab.onos.net.device;
import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.store.Timestamp;
// TODO: Consider renaming to DeviceClockService?
/**
* Interface for a logical clock service that vends per device timestamps.
*/
-public interface ClockService {
+public interface DeviceClockService {
/**
* Returns a new timestamp for the specified deviceId.
diff --git a/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
new file mode 100644
index 0000000..78c95cf
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/intent/LinkCollectionIntent.java
@@ -0,0 +1,84 @@
+package org.onlab.onos.net.intent;
+
+import java.util.Collection;
+import java.util.Objects;
+import java.util.Set;
+
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Abstraction of a connectivity intent that is implemented by a set of path
+ * segments.
+ */
+public class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
+
+ private final Set<Link> links;
+
+ /**
+ * Creates a new point-to-point intent with the supplied ingress/egress
+ * ports and using the specified explicit path.
+ *
+ * @param id intent identifier
+ * @param selector traffic match
+ * @param treatment action
+ * @param links traversed links
+ * @throws NullPointerException {@code path} is null
+ */
+ public LinkCollectionIntent(IntentId id,
+ TrafficSelector selector,
+ TrafficTreatment treatment,
+ Set<Link> links) {
+ super(id, selector, treatment);
+ this.links = links;
+ }
+
+ protected LinkCollectionIntent() {
+ super();
+ this.links = null;
+ }
+
+ @Override
+ public Collection<Link> requiredLinks() {
+ return links;
+ }
+
+ public Set<Link> links() {
+ return links;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ LinkCollectionIntent that = (LinkCollectionIntent) o;
+
+ return Objects.equals(this.links, that.links);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), links);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("id", id())
+ .add("match", selector())
+ .add("action", treatment())
+ .add("links", links())
+ .toString();
+ }
+}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java
similarity index 97%
rename from core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java
rename to core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java
index a95283d..8b966ed 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java
+++ b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterCommunicationService.java
@@ -5,6 +5,7 @@
import org.onlab.onos.cluster.NodeId;
+// TODO: remove IOExceptions?
/**
* Service for assisting communications between controller cluster nodes.
*/
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessage.java b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessage.java
similarity index 100%
rename from core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessage.java
rename to core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessage.java
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageHandler.java b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageHandler.java
similarity index 100%
rename from core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageHandler.java
rename to core/api/src/main/java/org/onlab/onos/store/cluster/messaging/ClusterMessageHandler.java
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/MessageSubject.java b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/MessageSubject.java
similarity index 100%
rename from core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/MessageSubject.java
rename to core/api/src/main/java/org/onlab/onos/store/cluster/messaging/MessageSubject.java
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/package-info.java b/core/api/src/main/java/org/onlab/onos/store/cluster/messaging/package-info.java
similarity index 100%
rename from core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/package-info.java
rename to core/api/src/main/java/org/onlab/onos/store/cluster/messaging/package-info.java
diff --git a/core/api/src/test/java/org/onlab/onos/cluster/MastershipServiceAdapter.java b/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
similarity index 92%
rename from core/api/src/test/java/org/onlab/onos/cluster/MastershipServiceAdapter.java
rename to core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
index 2e92f5b..97b57e5 100644
--- a/core/api/src/test/java/org/onlab/onos/cluster/MastershipServiceAdapter.java
+++ b/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
@@ -1,5 +1,6 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
+import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
diff --git a/core/api/src/test/java/org/onlab/onos/cluster/MastershipTermTest.java b/core/api/src/test/java/org/onlab/onos/mastership/MastershipTermTest.java
similarity index 92%
rename from core/api/src/test/java/org/onlab/onos/cluster/MastershipTermTest.java
rename to core/api/src/test/java/org/onlab/onos/mastership/MastershipTermTest.java
index 139c695..9b2a4e6 100644
--- a/core/api/src/test/java/org/onlab/onos/cluster/MastershipTermTest.java
+++ b/core/api/src/test/java/org/onlab/onos/mastership/MastershipTermTest.java
@@ -1,8 +1,9 @@
-package org.onlab.onos.cluster;
+package org.onlab.onos.mastership;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
+import org.onlab.onos.cluster.NodeId;
import com.google.common.testing.EqualsTester;
diff --git a/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java b/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
index 125745b..59614da 100644
--- a/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
+++ b/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
@@ -4,6 +4,7 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -14,17 +15,18 @@
import org.onlab.onos.cluster.ClusterEvent;
import org.onlab.onos.cluster.ClusterEventListener;
import org.onlab.onos.cluster.ClusterService;
-import org.onlab.onos.cluster.MastershipAdminService;
-import org.onlab.onos.cluster.MastershipEvent;
-import org.onlab.onos.cluster.MastershipListener;
-import org.onlab.onos.cluster.MastershipService;
-import org.onlab.onos.cluster.MastershipStore;
-import org.onlab.onos.cluster.MastershipStoreDelegate;
-import org.onlab.onos.cluster.MastershipTerm;
-import org.onlab.onos.cluster.MastershipTermService;
+import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
+import org.onlab.onos.mastership.MastershipAdminService;
+import org.onlab.onos.mastership.MastershipEvent;
+import org.onlab.onos.mastership.MastershipListener;
+import org.onlab.onos.mastership.MastershipService;
+import org.onlab.onos.mastership.MastershipStore;
+import org.onlab.onos.mastership.MastershipStoreDelegate;
+import org.onlab.onos.mastership.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTermService;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.slf4j.Logger;
@@ -164,21 +166,68 @@
//callback for reacting to cluster events
private class InternalClusterEventListener implements ClusterEventListener {
+ // A notion of a local maximum cluster size, used to tie-break.
+ // Think of a better way to do this.
+ private AtomicInteger clusterSize;
+
+ InternalClusterEventListener() {
+ clusterSize = new AtomicInteger(0);
+ }
+
@Override
public void event(ClusterEvent event) {
switch (event.type()) {
//FIXME: worry about addition when the time comes
case INSTANCE_ADDED:
case INSTANCE_ACTIVATED:
- break;
+ clusterSize.incrementAndGet();
+ log.info("instance {} added/activated", event.subject());
+ break;
case INSTANCE_REMOVED:
case INSTANCE_DEACTIVATED:
+ ControllerNode node = event.subject();
+
+ if (node.equals(clusterService.getLocalNode())) {
+ //If we are in smaller cluster, relinquish and return
+ for (DeviceId device : getDevicesOf(node.id())) {
+ if (!isInMajority()) {
+ //own DeviceManager should catch event and tell switch
+ store.relinquishRole(node.id(), device);
+ }
+ }
+ log.info("broke off from cluster, relinquished devices");
+ break;
+ }
+
+ // if we are the larger one and the removed node(s) are brain dead,
+ // force relinquish on behalf of disabled node.
+ // check network channel to do this?
+ for (DeviceId device : getDevicesOf(node.id())) {
+ //some things to check:
+ // 1. we didn't break off as well while we're at it
+ // 2. others don't pile in and try too - maybe a lock
+ if (isInMajority()) {
+ store.relinquishRole(node.id(), device);
+ }
+ }
+ clusterSize.decrementAndGet();
+ log.info("instance {} removed/deactivated", event.subject());
break;
default:
log.warn("unknown cluster event {}", event);
}
}
+ private boolean isInMajority() {
+ if (clusterService.getNodes().size() > (clusterSize.intValue() / 2)) {
+ return true;
+ }
+ //else {
+ //FIXME: break tie for equal-sized clusters, can we use hz's functions?
+ // }
+ return false;
+ }
+
}
public class InternalDelegate implements MastershipStoreDelegate {
diff --git a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
index 8cde5a3..28bdac1 100644
--- a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
@@ -13,20 +13,22 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
-import org.onlab.onos.cluster.MastershipEvent;
-import org.onlab.onos.cluster.MastershipListener;
-import org.onlab.onos.cluster.MastershipService;
-import org.onlab.onos.cluster.MastershipTermService;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
+import org.onlab.onos.mastership.MastershipEvent;
+import org.onlab.onos.mastership.MastershipListener;
+import org.onlab.onos.mastership.MastershipService;
+import org.onlab.onos.mastership.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTermService;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DeviceAdminService;
+import org.onlab.onos.net.device.DeviceClockProviderService;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceListener;
@@ -39,7 +41,6 @@
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
-import org.onlab.onos.store.ClockProviderService;
import org.slf4j.Logger;
/**
@@ -81,7 +82,7 @@
protected MastershipTermService termService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClockProviderService clockProviderService;
+ protected DeviceClockProviderService deviceClockProviderService;
@Activate
public void activate() {
@@ -216,7 +217,7 @@
return;
}
// tell clock provider if this instance is the master
- clockProviderService.setMastershipTerm(deviceId, term);
+ deviceClockProviderService.setMastershipTerm(deviceId, term);
DeviceEvent event = store.createOrUpdateDevice(provider().id(),
deviceId, deviceDescription);
@@ -257,12 +258,12 @@
// temporarily request for Master Role and mark offline.
if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
log.debug("Device {} disconnected, but I am not the master", deviceId);
- //let go of any role anyways
+ //let go of ability to be backup
mastershipService.relinquishMastership(deviceId);
return;
}
DeviceEvent event = store.markOffline(deviceId);
- //we're no longer capable of being master or a candidate.
+ //relinquish master role and ability to be backup.
mastershipService.relinquishMastership(deviceId);
if (event != null) {
@@ -325,23 +326,31 @@
@Override
public void event(MastershipEvent event) {
final DeviceId did = event.subject();
- if (isAvailable(did)) {
- final NodeId myNodeId = clusterService.getLocalNode().id();
+ final NodeId myNodeId = clusterService.getLocalNode().id();
- if (myNodeId.equals(event.master())) {
- MastershipTerm term = termService.getMastershipTerm(did);
+ if (myNodeId.equals(event.master())) {
+ MastershipTerm term = termService.getMastershipTerm(did);
- if (term.master().equals(myNodeId)) {
- // only set the new term if I am the master
- clockProviderService.setMastershipTerm(did, term);
- }
- applyRole(did, MastershipRole.MASTER);
- } else {
- applyRole(did, MastershipRole.STANDBY);
+ if (term.master().equals(myNodeId)) {
+ // only set the new term if I am the master
+ deviceClockProviderService.setMastershipTerm(did, term);
}
+
+ // FIXME: we should check that the device is connected on our end.
+ // currently, this is not straight forward as the actual switch
+ // implementation is hidden from the registry.
+ if (!isAvailable(did)) {
+ //flag the device as online. Is there a better way to do this?
+ Device device = getDevice(did);
+ store.createOrUpdateDevice(device.providerId(), did,
+ new DefaultDeviceDescription(
+ did.uri(), device.type(), device.manufacturer(),
+ device.hwVersion(), device.swVersion(),
+ device.serialNumber()));
+ }
+
+ applyRole(did, MastershipRole.MASTER);
} else {
- //device dead to node, give up
- mastershipService.relinquishMastership(did);
applyRole(did, MastershipRole.STANDBY);
}
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java
new file mode 100644
index 0000000..51e0d2e
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/LinkCollectionIntentInstaller.java
@@ -0,0 +1,110 @@
+package org.onlab.onos.net.intent.impl;
+
+import java.util.List;
+import java.util.concurrent.Future;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.ApplicationId;
+import org.onlab.onos.CoreService;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.flow.CompletedBatchOperation;
+import org.onlab.onos.net.flow.DefaultFlowRule;
+import org.onlab.onos.net.flow.DefaultTrafficSelector;
+import org.onlab.onos.net.flow.FlowRule;
+import org.onlab.onos.net.flow.FlowRuleBatchEntry;
+import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
+import org.onlab.onos.net.flow.FlowRuleBatchOperation;
+import org.onlab.onos.net.flow.FlowRuleService;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.intent.IntentExtensionService;
+import org.onlab.onos.net.intent.IntentInstaller;
+import org.onlab.onos.net.intent.LinkCollectionIntent;
+import org.onlab.onos.net.intent.PathIntent;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Installer for {@link org.onlab.onos.net.intent.LinkCollectionIntent}
+ * path segment intents.
+ */
+@Component(immediate = true)
+public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollectionIntent> {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IntentExtensionService intentManager;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowRuleService flowRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ private ApplicationId appId;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication("org.onlab.onos.net.intent");
+ intentManager.registerInstaller(LinkCollectionIntent.class, this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ intentManager.unregisterInstaller(PathIntent.class);
+ }
+
+ /**
+ * Apply a list of FlowRules.
+ *
+ * @param rules rules to apply
+ */
+ private Future<CompletedBatchOperation> applyBatch(List<FlowRuleBatchEntry> rules) {
+ FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
+ return flowRuleService.applyBatch(batch);
+ }
+
+ @Override
+ public Future<CompletedBatchOperation> install(LinkCollectionIntent intent) {
+ TrafficSelector.Builder builder =
+ DefaultTrafficSelector.builder(intent.selector());
+ List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+ for (Link link : intent.links()) {
+ TrafficTreatment treatment = builder()
+ .setOutput(link.src().port()).build();
+
+ FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
+ builder.build(), treatment,
+ 123, appId, 600);
+ rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
+ }
+
+ return applyBatch(rules);
+ }
+
+ @Override
+ public Future<CompletedBatchOperation> uninstall(LinkCollectionIntent intent) {
+ TrafficSelector.Builder builder =
+ DefaultTrafficSelector.builder(intent.selector());
+ List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
+
+ for (Link link : intent.links()) {
+ TrafficTreatment treatment = builder()
+ .setOutput(link.src().port()).build();
+ FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
+ builder.build(), treatment,
+ 123, appId, 600);
+ rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
+ }
+ return applyBatch(rules);
+ }
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java
new file mode 100644
index 0000000..68c55dd
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/MultiPointToSinglePointIntentCompiler.java
@@ -0,0 +1,85 @@
+package org.onlab.onos.net.intent.impl;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.Path;
+import org.onlab.onos.net.intent.IdGenerator;
+import org.onlab.onos.net.intent.Intent;
+import org.onlab.onos.net.intent.IntentCompiler;
+import org.onlab.onos.net.intent.IntentExtensionService;
+import org.onlab.onos.net.intent.IntentId;
+import org.onlab.onos.net.intent.LinkCollectionIntent;
+import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
+import org.onlab.onos.net.intent.PointToPointIntent;
+import org.onlab.onos.net.topology.PathService;
+
+/**
+ * An intent compiler for
+ * {@link org.onlab.onos.net.intent.MultiPointToSinglePointIntent}.
+ */
+@Component(immediate = true)
+public class MultiPointToSinglePointIntentCompiler
+ implements IntentCompiler<MultiPointToSinglePointIntent> {
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IntentExtensionService intentManager;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PathService pathService;
+
+ private IdGenerator<IntentId> intentIdGenerator;
+
+ @Activate
+ public void activate() {
+ IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
+ intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
+ intentManager.registerCompiler(MultiPointToSinglePointIntent.class, this);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ intentManager.unregisterCompiler(PointToPointIntent.class);
+ }
+
+ @Override
+ public List<Intent> compile(MultiPointToSinglePointIntent intent) {
+ Set<Link> links = new HashSet<>();
+
+ for (ConnectPoint ingressPoint : intent.ingressPoints()) {
+ Path path = getPath(ingressPoint, intent.egressPoint());
+ links.addAll(path.links());
+ }
+
+ Intent result = new LinkCollectionIntent(intentIdGenerator.getNewId(),
+ intent.selector(), intent.treatment(),
+ links);
+ return Arrays.asList(result);
+ }
+
+ /**
+ * Computes a path between two ConnectPoints.
+ *
+ * @param one start of the path
+ * @param two end of the path
+ * @return Path between the two
+ * @throws org.onlab.onos.net.intent.impl.PathNotFoundException if a path cannot be found
+ */
+ private Path getPath(ConnectPoint one, ConnectPoint two) {
+ Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
+ if (paths.isEmpty()) {
+ throw new PathNotFoundException("No path from " + one + " to " + two);
+ }
+ // TODO: let's be more intelligent about this eventually
+ return paths.iterator().next();
+ }
+}
diff --git a/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java b/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java
index 29b4ddf..c5c152c 100644
--- a/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java
@@ -10,14 +10,16 @@
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipService;
-import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.event.impl.TestEventDispatcher;
+import org.onlab.onos.mastership.MastershipService;
+import org.onlab.onos.mastership.MastershipTermService;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
import org.onlab.packet.IpPrefix;
+import com.google.common.collect.Sets;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.onlab.onos.net.MastershipRole.*;
@@ -143,7 +145,7 @@
@Override
public Set<ControllerNode> getNodes() {
- return null;
+ return Sets.newHashSet();
}
@Override
diff --git a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
index e833b4a..0b017cf 100644
--- a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
@@ -10,13 +10,13 @@
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipServiceAdapter;
-import org.onlab.onos.cluster.MastershipTerm;
-import org.onlab.onos.cluster.MastershipTermService;
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.event.Event;
import org.onlab.onos.event.impl.TestEventDispatcher;
+import org.onlab.onos.mastership.MastershipServiceAdapter;
+import org.onlab.onos.mastership.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTermService;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
@@ -25,6 +25,7 @@
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.device.DeviceAdminService;
+import org.onlab.onos.net.device.DeviceClockProviderService;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceListener;
@@ -35,7 +36,6 @@
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
-import org.onlab.onos.store.ClockProviderService;
import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
import org.onlab.packet.IpPrefix;
@@ -88,7 +88,7 @@
mgr.eventDispatcher = new TestEventDispatcher();
mgr.mastershipService = new TestMastershipService();
mgr.clusterService = new TestClusterService();
- mgr.clockProviderService = new TestClockProviderService();
+ mgr.deviceClockProviderService = new TestClockProviderService();
mgr.activate();
service.addListener(listener);
@@ -336,7 +336,7 @@
}
private final class TestClockProviderService implements
- ClockProviderService {
+ DeviceClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
diff --git a/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java b/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java
new file mode 100644
index 0000000..ba67a6a
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/net/intent/TestLinkCollectionIntent.java
@@ -0,0 +1,47 @@
+package org.onlab.onos.net.intent;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.flow.TrafficSelector;
+import org.onlab.onos.net.flow.TrafficTreatment;
+import org.onlab.onos.net.flow.criteria.Criterion;
+import org.onlab.onos.net.flow.instructions.Instruction;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+public class TestLinkCollectionIntent {
+
+ private static class MockSelector implements TrafficSelector {
+ @Override
+ public Set<Criterion> criteria() {
+ return new HashSet<Criterion>();
+ }
+ }
+
+ private static class MockTreatment implements TrafficTreatment {
+ @Override
+ public List<Instruction> instructions() {
+ return new ArrayList<>();
+ }
+ }
+
+ @Test
+ public void testComparison() {
+ TrafficSelector selector = new MockSelector();
+ TrafficTreatment treatment = new MockTreatment();
+ Set<Link> links = new HashSet<>();
+ LinkCollectionIntent i1 = new LinkCollectionIntent(new IntentId(12),
+ selector, treatment, links);
+ LinkCollectionIntent i2 = new LinkCollectionIntent(new IntentId(12),
+ selector, treatment, links);
+
+ assertThat(i1.equals(i2), is(true));
+ }
+
+}
diff --git a/core/store/dist/pom.xml b/core/store/dist/pom.xml
index 7b00833..33517c7 100644
--- a/core/store/dist/pom.xml
+++ b/core/store/dist/pom.xml
@@ -62,6 +62,11 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/SerializationService.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/SerializationService.java
index 4d76ce3..3082718 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/SerializationService.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/SerializationService.java
@@ -1,5 +1,6 @@
package org.onlab.onos.store.cluster.messaging;
+// FIXME: not used any more? remove
/**
* Service for encoding & decoding intra-cluster message payload.
*/
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/MessageSerializer.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/MessageSerializer.java
index bf47f49..07a97bc 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/MessageSerializer.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/MessageSerializer.java
@@ -11,6 +11,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+//FIXME: not used any more? remove
/**
* Factory for parsing messages sent between cluster members.
*/
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/package-info.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/package-info.java
index 6c1e71b..3364dd2 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/package-info.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/package-info.java
@@ -1,4 +1,4 @@
/**
* Implementation of the cluster messaging mechanism.
*/
-package org.onlab.onos.store.cluster.messaging.impl;
\ No newline at end of file
+package org.onlab.onos.store.cluster.messaging.impl;
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/Timestamped.java b/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/Timestamped.java
index e803e74..8d2aee1 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/Timestamped.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/Timestamped.java
@@ -10,7 +10,8 @@
/**
* Wrapper class to store Timestamped value.
- * @param <T>
+ *
+ * @param <T> Timestamped value type
*/
public final class Timestamped<T> {
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyAdvertisement.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyAdvertisement.java
similarity index 96%
rename from core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyAdvertisement.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyAdvertisement.java
index 00873ad..7e754fc 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyAdvertisement.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyAdvertisement.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyRequest.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyRequest.java
similarity index 95%
rename from core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyRequest.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyRequest.java
index 6f3096b..7b63c08 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceAntiEntropyRequest.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceAntiEntropyRequest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
index e1e3692..48355cf 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
@@ -10,12 +10,12 @@
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
-import org.onlab.onos.cluster.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.store.ClockProviderService;
-import org.onlab.onos.store.ClockService;
+import org.onlab.onos.net.device.DeviceClockProviderService;
+import org.onlab.onos.net.device.DeviceClockService;
import org.onlab.onos.store.Timestamp;
-import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
+import org.onlab.onos.store.impl.MastershipBasedTimestamp;
import org.slf4j.Logger;
/**
@@ -23,7 +23,7 @@
*/
@Component(immediate = true)
@Service
-public class DeviceClockManager implements ClockService, ClockProviderService {
+public class DeviceClockManager implements DeviceClockService, DeviceClockProviderService {
private final Logger log = getLogger(getClass());
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceDescriptions.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceDescriptions.java
index f7fd7bc..03c293a 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceDescriptions.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceDescriptions.java
@@ -58,7 +58,7 @@
*
* @param newDesc new DeviceDescription
*/
- public synchronized void putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
+ public void putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
Timestamped<DeviceDescription> oldOne = deviceDesc;
Timestamped<DeviceDescription> newOne = newDesc;
if (oldOne != null) {
@@ -76,7 +76,7 @@
*
* @param newDesc new PortDescription
*/
- public synchronized void putPortDesc(Timestamped<PortDescription> newDesc) {
+ public void putPortDesc(Timestamped<PortDescription> newDesc) {
Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber());
Timestamped<PortDescription> newOne = newDesc;
if (oldOne != null) {
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentId.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceFragmentId.java
similarity index 96%
rename from core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentId.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceFragmentId.java
index d4fcda9..411a9e8 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentId.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceFragmentId.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import java.util.Objects;
@@ -51,4 +51,4 @@
this.providerId = null;
this.deviceId = null;
}
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
index 6ab529a..9c2c759 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
@@ -1,5 +1,6 @@
package org.onlab.onos.store.device.impl;
+import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
@@ -24,6 +25,7 @@
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.device.DeviceClockService;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceStore;
@@ -31,16 +33,12 @@
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.AbstractStore;
-import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.common.impl.Timestamped;
-import org.onlab.onos.store.device.impl.peermsg.DeviceAntiEntropyAdvertisement;
-import org.onlab.onos.store.device.impl.peermsg.DeviceFragmentId;
-import org.onlab.onos.store.device.impl.peermsg.PortFragmentId;
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.onos.store.serializers.DistributedStoreSerializers;
import org.onlab.util.KryoPool;
@@ -110,7 +108,7 @@
private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClockService clockService;
+ protected DeviceClockService deviceClockService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService clusterCommunicator;
@@ -118,7 +116,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
- private static final KryoSerializer SERIALIZER = new KryoSerializer() {
+ protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
@Override
protected void setupKryoPool() {
serializerPool = KryoPool.newBuilder()
@@ -206,14 +204,19 @@
public synchronized DeviceEvent createOrUpdateDevice(ProviderId providerId,
DeviceId deviceId,
DeviceDescription deviceDescription) {
- Timestamp newTimestamp = clockService.getTimestamp(deviceId);
+ final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp);
- DeviceEvent event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc);
+ final DeviceEvent event;
+ final Timestamped<DeviceDescription> mergedDesc;
+ synchronized (getDeviceDescriptions(deviceId)) {
+ event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc);
+ mergedDesc = getDeviceDescriptions(deviceId).get(providerId).getDeviceDesc();
+ }
if (event != null) {
log.info("Notifying peers of a device update topology event for providerId: {} and deviceId: {}",
providerId, deviceId);
try {
- notifyPeers(new InternalDeviceEvent(providerId, deviceId, deltaDesc));
+ notifyPeers(new InternalDeviceEvent(providerId, deviceId, mergedDesc));
} catch (IOException e) {
log.error("Failed to notify peers of a device update topology event for providerId: "
+ providerId + " and deviceId: " + deviceId, e);
@@ -317,8 +320,8 @@
@Override
public DeviceEvent markOffline(DeviceId deviceId) {
- Timestamp timestamp = clockService.getTimestamp(deviceId);
- DeviceEvent event = markOfflineInternal(deviceId, timestamp);
+ final Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
+ final DeviceEvent event = markOfflineInternal(deviceId, timestamp);
if (event != null) {
log.info("Notifying peers of a device offline topology event for deviceId: {}",
deviceId);
@@ -390,17 +393,33 @@
public synchronized List<DeviceEvent> updatePorts(ProviderId providerId,
DeviceId deviceId,
List<PortDescription> portDescriptions) {
- Timestamp newTimestamp = clockService.getTimestamp(deviceId);
- Timestamped<List<PortDescription>> timestampedPortDescriptions =
- new Timestamped<>(portDescriptions, newTimestamp);
+ final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
- List<DeviceEvent> events = updatePortsInternal(providerId, deviceId, timestampedPortDescriptions);
+ final Timestamped<List<PortDescription>> timestampedInput
+ = new Timestamped<>(portDescriptions, newTimestamp);
+ final List<DeviceEvent> events;
+ final Timestamped<List<PortDescription>> merged;
+
+ synchronized (getDeviceDescriptions(deviceId)) {
+ events = updatePortsInternal(providerId, deviceId, timestampedInput);
+ final DeviceDescriptions descs = getDeviceDescriptions(deviceId).get(providerId);
+ List<PortDescription> mergedList =
+ FluentIterable.from(portDescriptions)
+ .transform(new Function<PortDescription, PortDescription>() {
+ @Override
+ public PortDescription apply(PortDescription input) {
+ // lookup merged port description
+ return descs.getPortDesc(input.portNumber()).value();
+ }
+ }).toList();
+ merged = new Timestamped<List<PortDescription>>(mergedList, newTimestamp);
+ }
if (!events.isEmpty()) {
log.info("Notifying peers of a port update topology event for providerId: {} and deviceId: {}",
providerId, deviceId);
try {
- notifyPeers(new InternalPortEvent(providerId, deviceId, timestampedPortDescriptions));
+ notifyPeers(new InternalPortEvent(providerId, deviceId, merged));
} catch (IOException e) {
log.error("Failed to notify peers of a port update topology event or providerId: "
+ providerId + " and deviceId: " + deviceId, e);
@@ -527,16 +546,25 @@
}
@Override
- public synchronized DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
- PortDescription portDescription) {
- Timestamp newTimestamp = clockService.getTimestamp(deviceId);
- final Timestamped<PortDescription> deltaDesc = new Timestamped<>(portDescription, newTimestamp);
- DeviceEvent event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
+ public synchronized DeviceEvent updatePortStatus(ProviderId providerId,
+ DeviceId deviceId,
+ PortDescription portDescription) {
+
+ final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
+ final Timestamped<PortDescription> deltaDesc
+ = new Timestamped<>(portDescription, newTimestamp);
+ final DeviceEvent event;
+ final Timestamped<PortDescription> mergedDesc;
+ synchronized (getDeviceDescriptions(deviceId)) {
+ event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
+ mergedDesc = getDeviceDescriptions(deviceId).get(providerId)
+ .getPortDesc(portDescription.portNumber());
+ }
if (event != null) {
log.info("Notifying peers of a port status update topology event for providerId: {} and deviceId: {}",
providerId, deviceId);
try {
- notifyPeers(new InternalPortStatusEvent(providerId, deviceId, deltaDesc));
+ notifyPeers(new InternalPortStatusEvent(providerId, deviceId, mergedDesc));
} catch (IOException e) {
log.error("Failed to notify peers of a port status update topology event or providerId: "
+ providerId + " and deviceId: " + deviceId, e);
@@ -615,7 +643,7 @@
@Override
public synchronized DeviceEvent removeDevice(DeviceId deviceId) {
- Timestamp timestamp = clockService.getTimestamp(deviceId);
+ Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
DeviceEvent event = removeDeviceInternal(deviceId, timestamp);
if (event != null) {
log.info("Notifying peers of a device removed topology event for deviceId: {}",
@@ -684,7 +712,7 @@
* @return Device instance
*/
private Device composeDevice(DeviceId deviceId,
- ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) {
+ Map<ProviderId, DeviceDescriptions> providerDescs) {
checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied");
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InitDeviceDescs.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InitDeviceDescs.java
index 2de2364..936723a 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InitDeviceDescs.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/InitDeviceDescs.java
@@ -20,4 +20,4 @@
public DeviceDescriptions get() throws ConcurrentException {
return new DeviceDescriptions(deviceDesc);
}
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentId.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/PortFragmentId.java
similarity index 96%
rename from core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentId.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/device/impl/PortFragmentId.java
index 8e7bac3..0ac3643 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentId.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/PortFragmentId.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import java.util.Objects;
@@ -58,4 +58,4 @@
this.deviceId = null;
this.portNumber = null;
}
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/package-info.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/package-info.java
deleted file mode 100644
index 5d9dc4b..0000000
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/peermsg/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Structure and utilities used for inter-Node messaging.
- */
-package org.onlab.onos.store.device.impl.peermsg;
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/MastershipBasedTimestamp.java b/core/store/dist/src/main/java/org/onlab/onos/store/impl/MastershipBasedTimestamp.java
similarity index 98%
rename from core/store/dist/src/main/java/org/onlab/onos/store/common/impl/MastershipBasedTimestamp.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/impl/MastershipBasedTimestamp.java
index 0f4f894..e6317bb 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/common/impl/MastershipBasedTimestamp.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/impl/MastershipBasedTimestamp.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.common.impl;
+package org.onlab.onos.store.impl;
import static com.google.common.base.Preconditions.checkArgument;
diff --git a/core/store/hz/common/src/main/java/org/onlab/onos/store/impl/package-info.java b/core/store/dist/src/main/java/org/onlab/onos/store/impl/package-info.java
similarity index 100%
rename from core/store/hz/common/src/main/java/org/onlab/onos/store/impl/package-info.java
rename to core/store/dist/src/main/java/org/onlab/onos/store/impl/package-info.java
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/GossipLinkStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/GossipLinkStore.java
index 3c3cc5a..4cb936e 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/GossipLinkStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/GossipLinkStore.java
@@ -29,6 +29,7 @@
import org.onlab.onos.net.Link.Type;
import org.onlab.onos.net.LinkKey;
import org.onlab.onos.net.Provided;
+import org.onlab.onos.net.device.DeviceClockService;
import org.onlab.onos.net.link.DefaultLinkDescription;
import org.onlab.onos.net.link.LinkDescription;
import org.onlab.onos.net.link.LinkEvent;
@@ -36,7 +37,6 @@
import org.onlab.onos.net.link.LinkStoreDelegate;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.AbstractStore;
-import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.Timestamp;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
@@ -100,7 +100,7 @@
private final Map<LinkKey, Timestamp> removedLinks = Maps.newHashMap();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClockService clockService;
+ protected DeviceClockService deviceClockService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService clusterCommunicator;
@@ -223,7 +223,7 @@
LinkDescription linkDescription) {
DeviceId dstDeviceId = linkDescription.dst().deviceId();
- Timestamp newTimestamp = clockService.getTimestamp(dstDeviceId);
+ Timestamp newTimestamp = deviceClockService.getTimestamp(dstDeviceId);
final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp);
@@ -344,7 +344,7 @@
final LinkKey key = new LinkKey(src, dst);
DeviceId dstDeviceId = dst.deviceId();
- Timestamp timestamp = clockService.getTimestamp(dstDeviceId);
+ Timestamp timestamp = deviceClockService.getTimestamp(dstDeviceId);
LinkEvent event = removeLinkInternal(key, timestamp);
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/InternalLinkRemovedEvent.java b/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/InternalLinkRemovedEvent.java
index 22e65ed..7864580 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/InternalLinkRemovedEvent.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/link/impl/InternalLinkRemovedEvent.java
@@ -46,4 +46,4 @@
linkKey = null;
timestamp = null;
}
-}
\ No newline at end of file
+}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/serializers/DistributedStoreSerializers.java b/core/store/dist/src/main/java/org/onlab/onos/store/serializers/DistributedStoreSerializers.java
index e0ba906..c410103 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/serializers/DistributedStoreSerializers.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/serializers/DistributedStoreSerializers.java
@@ -1,7 +1,7 @@
package org.onlab.onos.store.serializers;
-import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
import org.onlab.onos.store.common.impl.Timestamped;
+import org.onlab.onos.store.impl.MastershipBasedTimestamp;
import org.onlab.util.KryoPool;
public final class DistributedStoreSerializers {
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/serializers/MastershipBasedTimestampSerializer.java b/core/store/dist/src/main/java/org/onlab/onos/store/serializers/MastershipBasedTimestampSerializer.java
index 516915e..062ae03 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/serializers/MastershipBasedTimestampSerializer.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/serializers/MastershipBasedTimestampSerializer.java
@@ -1,6 +1,6 @@
package org.onlab.onos.store.serializers;
-import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
+import org.onlab.onos.store.impl.MastershipBasedTimestamp;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/cluster/impl/ClusterCommunicationManagerTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java
similarity index 95%
rename from core/store/dist/src/test/java/org/onlab/onos/store/cluster/impl/ClusterCommunicationManagerTest.java
rename to core/store/dist/src/test/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java
index e63fcaa..dcbe437 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/cluster/impl/ClusterCommunicationManagerTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManagerTest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.cluster.impl;
+package org.onlab.onos.store.cluster.messaging.impl;
import org.junit.After;
import org.junit.Before;
@@ -6,8 +6,7 @@
import org.junit.Test;
import org.onlab.onos.cluster.DefaultControllerNode;
import org.onlab.onos.cluster.NodeId;
-import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager;
-import org.onlab.onos.store.cluster.messaging.impl.MessageSerializer;
+import org.onlab.onos.store.cluster.impl.ClusterNodesDelegate;
import org.onlab.netty.NettyMessagingService;
import org.onlab.packet.IpPrefix;
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/TimestampedTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/TimestampedTest.java
index 4b44d40..deb3e4d 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/TimestampedTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/TimestampedTest.java
@@ -6,6 +6,7 @@
import org.junit.Test;
import org.onlab.onos.store.Timestamp;
+import org.onlab.onos.store.impl.MastershipBasedTimestamp;
import org.onlab.util.KryoPool;
import com.google.common.testing.EqualsTester;
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentIdTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/DeviceFragmentIdTest.java
similarity index 95%
rename from core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentIdTest.java
rename to core/store/dist/src/test/java/org/onlab/onos/store/device/impl/DeviceFragmentIdTest.java
index 85ba4a7..3a532fd 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/DeviceFragmentIdTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/DeviceFragmentIdTest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import static org.onlab.onos.net.DeviceId.deviceId;
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/GossipDeviceStoreTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/GossipDeviceStoreTest.java
index fa42a6b..141f2b2 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/GossipDeviceStoreTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/GossipDeviceStoreTest.java
@@ -1,12 +1,17 @@
package org.onlab.onos.store.device.impl;
+import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import static org.onlab.onos.net.Device.Type.SWITCH;
import static org.onlab.onos.net.DeviceId.deviceId;
import static org.onlab.onos.net.device.DeviceEvent.Type.*;
+import static org.onlab.onos.cluster.ControllerNode.State.*;
+import static org.onlab.onos.net.DefaultAnnotations.union;
+import static java.util.Arrays.asList;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -14,6 +19,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.easymock.Capture;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -25,8 +31,8 @@
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.Device;
@@ -36,13 +42,13 @@
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.device.DefaultDeviceDescription;
import org.onlab.onos.net.device.DefaultPortDescription;
+import org.onlab.onos.net.device.DeviceClockService;
import org.onlab.onos.net.device.DeviceDescription;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceStore;
import org.onlab.onos.net.device.DeviceStoreDelegate;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
-import org.onlab.onos.store.ClockService;
import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
@@ -90,14 +96,25 @@
.set("B4", "b4")
.build();
- private static final NodeId MYSELF = new NodeId("myself");
+ // local node
+ private static final NodeId NID1 = new NodeId("local");
+ private static final ControllerNode ONOS1 =
+ new DefaultControllerNode(NID1, IpPrefix.valueOf("127.0.0.1"));
+ // remote node
+ private static final NodeId NID2 = new NodeId("remote");
+ private static final ControllerNode ONOS2 =
+ new DefaultControllerNode(NID2, IpPrefix.valueOf("127.0.0.2"));
+ private static final List<SparseAnnotations> NO_ANNOTATION = Collections.<SparseAnnotations>emptyList();
+
+
+ private TestGossipDeviceStore testGossipDeviceStore;
private GossipDeviceStore gossipDeviceStore;
private DeviceStore deviceStore;
private DeviceClockManager deviceClockManager;
- private ClockService clockService;
-
+ private DeviceClockService deviceClockService;
+ private ClusterCommunicationService clusterCommunicator;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
@@ -111,17 +128,24 @@
public void setUp() throws Exception {
deviceClockManager = new DeviceClockManager();
deviceClockManager.activate();
- clockService = deviceClockManager;
+ deviceClockService = deviceClockManager;
- deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(MYSELF, 1));
- deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(MYSELF, 2));
+ deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1));
+ deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2));
- ClusterCommunicationService clusterCommunicator = new TestClusterCommunicationService();
+ clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
+ clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
+ anyObject(ClusterMessageHandler.class));
+ expectLastCall().anyTimes();
+ replay(clusterCommunicator);
ClusterService clusterService = new TestClusterService();
- gossipDeviceStore = new TestGossipDeviceStore(clockService, clusterService, clusterCommunicator);
+ testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
+ gossipDeviceStore = testGossipDeviceStore;
gossipDeviceStore.activate();
deviceStore = gossipDeviceStore;
+ verify(clusterCommunicator);
+ reset(clusterCommunicator);
}
@After
@@ -135,7 +159,16 @@
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN, annotations);
+ reset(clusterCommunicator);
+ try {
+ expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class)))
+ .andReturn(true).anyTimes();
+ } catch (IOException e) {
+ fail("Should never reach here");
+ }
+ replay(clusterCommunicator);
deviceStore.createOrUpdateDevice(PID, deviceId, description);
+ verify(clusterCommunicator);
}
private void putDeviceAncillary(DeviceId deviceId, String swVersion,
@@ -163,9 +196,9 @@
* @param annotations
*/
private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
- DefaultAnnotations expected = DefaultAnnotations.builder().build();
+ SparseAnnotations expected = DefaultAnnotations.builder().build();
for (SparseAnnotations a : annotations) {
- expected = DefaultAnnotations.merge(expected, a);
+ expected = DefaultAnnotations.union(expected, a);
}
assertEquals(expected.keys(), actual.keys());
for (String key : expected.keys()) {
@@ -173,6 +206,36 @@
}
}
+ private static void assertDeviceDescriptionEquals(DeviceDescription expected,
+ DeviceDescription actual) {
+ if (expected == actual) {
+ return;
+ }
+ assertEquals(expected.deviceURI(), actual.deviceURI());
+ assertEquals(expected.hwVersion(), actual.hwVersion());
+ assertEquals(expected.manufacturer(), actual.manufacturer());
+ assertEquals(expected.serialNumber(), actual.serialNumber());
+ assertEquals(expected.swVersion(), actual.swVersion());
+
+ assertAnnotationsEquals(actual.annotations(), expected.annotations());
+ }
+
+ private static void assertDeviceDescriptionEquals(DeviceDescription expected,
+ List<SparseAnnotations> expectedAnnotations,
+ DeviceDescription actual) {
+ if (expected == actual) {
+ return;
+ }
+ assertEquals(expected.deviceURI(), actual.deviceURI());
+ assertEquals(expected.hwVersion(), actual.hwVersion());
+ assertEquals(expected.manufacturer(), actual.manufacturer());
+ assertEquals(expected.serialNumber(), actual.serialNumber());
+ assertEquals(expected.swVersion(), actual.swVersion());
+
+ assertAnnotationsEquals(actual.annotations(),
+ expectedAnnotations.toArray(new SparseAnnotations[0]));
+ }
+
@Test
public final void testGetDeviceCount() {
assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
@@ -215,56 +278,123 @@
assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
}
+ private void assertInternalDeviceEvent(NodeId sender,
+ DeviceId deviceId,
+ ProviderId providerId,
+ DeviceDescription expectedDesc,
+ Capture<ClusterMessage> actualMsg) {
+ assertTrue(actualMsg.hasCaptured());
+ assertEquals(sender, actualMsg.getValue().sender());
+ assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
+ actualMsg.getValue().subject());
+ InternalDeviceEvent addEvent
+ = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
+ assertEquals(deviceId, addEvent.deviceId());
+ assertEquals(providerId, addEvent.providerId());
+ assertDeviceDescriptionEquals(expectedDesc, addEvent.deviceDescription().value());
+ }
+
+ private void assertInternalDeviceEvent(NodeId sender,
+ DeviceId deviceId,
+ ProviderId providerId,
+ DeviceDescription expectedDesc,
+ List<SparseAnnotations> expectedAnnotations,
+ Capture<ClusterMessage> actualMsg) {
+ assertTrue(actualMsg.hasCaptured());
+ assertEquals(sender, actualMsg.getValue().sender());
+ assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
+ actualMsg.getValue().subject());
+ InternalDeviceEvent addEvent
+ = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
+ assertEquals(deviceId, addEvent.deviceId());
+ assertEquals(providerId, addEvent.providerId());
+ assertDeviceDescriptionEquals(expectedDesc, expectedAnnotations, addEvent.deviceDescription().value());
+ }
+
@Test
- public final void testCreateOrUpdateDevice() {
+ public final void testCreateOrUpdateDevice() throws IOException {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+ resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
assertEquals(DEVICE_ADDED, event.type());
assertDevice(DID1, SW1, event.subject());
+ verify(clusterCommunicator);
+ assertInternalDeviceEvent(NID1, DID1, PID, description, bcast);
+
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
+ resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
assertDevice(DID1, SW2, event2.subject());
+ verify(clusterCommunicator);
+ assertInternalDeviceEvent(NID1, DID1, PID, description2, bcast);
+ reset(clusterCommunicator);
+
assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
}
@Test
- public final void testCreateOrUpdateDeviceAncillary() {
+ public final void testCreateOrUpdateDeviceAncillary() throws IOException {
+ // add
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2);
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+ resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
assertEquals(DEVICE_ADDED, event.type());
assertDevice(DID1, SW1, event.subject());
assertEquals(PIDA, event.subject().providerId());
assertAnnotationsEquals(event.subject().annotations(), A2);
assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
+ verify(clusterCommunicator);
+ assertInternalDeviceEvent(NID1, DID1, PIDA, description, bcast);
+ // update from primary
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN, A1);
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
assertDevice(DID1, SW2, event2.subject());
assertEquals(PID, event2.subject().providerId());
assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
assertTrue(deviceStore.isAvailable(DID1));
+ verify(clusterCommunicator);
+ assertInternalDeviceEvent(NID1, DID1, PID, description2, bcast);
+ // no-op update from primary
+ resetCommunicatorExpectingNoBroadcast(bcast);
assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
+ verify(clusterCommunicator);
+ assertFalse("no broadcast expected", bcast.hasCaptured());
+
// For now, Ancillary is ignored once primary appears
+ resetCommunicatorExpectingNoBroadcast(bcast);
+
assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
+ verify(clusterCommunicator);
+ assertFalse("no broadcast expected", bcast.hasCaptured());
+
// But, Ancillary annotations will be in effect
DeviceDescription description3 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2_2);
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+
DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
assertEquals(DEVICE_UPDATED, event3.type());
// basic information will be the one from Primary
@@ -273,6 +403,11 @@
// but annotation from Ancillary will be merged
assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
assertTrue(deviceStore.isAvailable(DID1));
+ verify(clusterCommunicator);
+ // note: only annotation from PIDA is sent over the wire
+ assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
+ asList(union(A2, A2_2)), bcast);
+
}
@@ -282,14 +417,24 @@
putDevice(DID1, SW1);
assertTrue(deviceStore.isAvailable(DID1));
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+ resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event = deviceStore.markOffline(DID1);
assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
assertDevice(DID1, SW1, event.subject());
assertFalse(deviceStore.isAvailable(DID1));
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message
+ assertTrue(bcast.hasCaptured());
+
+ resetCommunicatorExpectingNoBroadcast(bcast);
DeviceEvent event2 = deviceStore.markOffline(DID1);
assertNull("No change, no event", event2);
-}
+ verify(clusterCommunicator);
+ assertFalse(bcast.hasCaptured());
+ }
@Test
public final void testUpdatePorts() {
@@ -298,8 +443,13 @@
new DefaultPortDescription(P1, true),
new DefaultPortDescription(P2, true)
);
+ Capture<ClusterMessage> bcast = new Capture<>();
+ resetCommunicatorExpectingSingleBroadcast(bcast);
List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message
+ assertTrue(bcast.hasCaptured());
Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
for (DeviceEvent event : events) {
@@ -318,7 +468,12 @@
new DefaultPortDescription(P3, true)
);
+ resetCommunicatorExpectingSingleBroadcast(bcast);
events = deviceStore.updatePorts(PID, DID1, pds2);
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message
+ assertTrue(bcast.hasCaptured());
+
assertFalse("event should be triggered", events.isEmpty());
for (DeviceEvent event : events) {
PortNumber num = event.port().number();
@@ -341,7 +496,12 @@
new DefaultPortDescription(P1, false),
new DefaultPortDescription(P2, true)
);
+ resetCommunicatorExpectingSingleBroadcast(bcast);
events = deviceStore.updatePorts(PID, DID1, pds3);
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message
+ assertTrue(bcast.hasCaptured());
+
assertFalse("event should be triggered", events.isEmpty());
for (DeviceEvent event : events) {
PortNumber num = event.port().number();
@@ -357,7 +517,6 @@
fail("Unknown port number encountered: " + num);
}
}
-
}
@Test
@@ -368,16 +527,22 @@
);
deviceStore.updatePorts(PID, DID1, pds);
- DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
- new DefaultPortDescription(P1, false));
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+ final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
+ DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
assertEquals(PORT_UPDATED, event.type());
assertDevice(DID1, SW1, event.subject());
assertEquals(P1, event.port().number());
assertFalse("Port is disabled", event.port().isEnabled());
-
+ verify(clusterCommunicator);
+ assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, bcast);
+ assertTrue(bcast.hasCaptured());
}
+
@Test
- public final void testUpdatePortStatusAncillary() {
+ public final void testUpdatePortStatusAncillary() throws IOException {
putDeviceAncillary(DID1, SW1);
putDevice(DID1, SW1);
List<PortDescription> pds = Arrays.<PortDescription>asList(
@@ -385,36 +550,106 @@
);
deviceStore.updatePorts(PID, DID1, pds);
- DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
- new DefaultPortDescription(P1, false, A1_2));
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+
+ // update port from primary
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+ final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
+ DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
assertEquals(PORT_UPDATED, event.type());
assertDevice(DID1, SW1, event.subject());
assertEquals(P1, event.port().number());
assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
assertFalse("Port is disabled", event.port().isEnabled());
+ verify(clusterCommunicator);
+ assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), bcast);
+ assertTrue(bcast.hasCaptured());
- DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1,
- new DefaultPortDescription(P1, true));
+ // update port from ancillary with no attributes
+ resetCommunicatorExpectingNoBroadcast(bcast);
+ final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
+ DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
assertNull("Ancillary is ignored if primary exists", event2);
+ verify(clusterCommunicator);
+ assertFalse(bcast.hasCaptured());
// but, Ancillary annotation update will be notified
- DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1,
- new DefaultPortDescription(P1, true, A2));
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+ final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
+ DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
assertEquals(PORT_UPDATED, event3.type());
assertDevice(DID1, SW1, event3.subject());
assertEquals(P1, event3.port().number());
assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
assertFalse("Port is disabled", event3.port().isEnabled());
+ verify(clusterCommunicator);
+ assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), bcast);
+ assertTrue(bcast.hasCaptured());
// port only reported from Ancillary will be notified as down
- DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1,
- new DefaultPortDescription(P2, true));
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+ final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
+ DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
assertEquals(PORT_ADDED, event4.type());
assertDevice(DID1, SW1, event4.subject());
assertEquals(P2, event4.port().number());
assertAnnotationsEquals(event4.port().annotations());
assertFalse("Port is disabled if not given from primary provider",
event4.port().isEnabled());
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message content
+ assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, bcast);
+ assertTrue(bcast.hasCaptured());
+ }
+
+ private void assertInternalPortStatusEvent(NodeId sender, DeviceId did,
+ ProviderId pid, DefaultPortDescription expectedDesc,
+ List<SparseAnnotations> expectedAnnotations, Capture<ClusterMessage> actualMsg) {
+
+ assertTrue(actualMsg.hasCaptured());
+ assertEquals(sender, actualMsg.getValue().sender());
+ assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
+ actualMsg.getValue().subject());
+ InternalPortStatusEvent addEvent
+ = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
+ assertEquals(did, addEvent.deviceId());
+ assertEquals(pid, addEvent.providerId());
+ assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
+ addEvent.portDescription().value());
+
+ }
+
+ private void assertPortDescriptionEquals(
+ PortDescription expectedDesc,
+ List<SparseAnnotations> expectedAnnotations,
+ PortDescription actual) {
+
+ assertEquals(expectedDesc.portNumber(), actual.portNumber());
+ assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
+
+ assertAnnotationsEquals(actual.annotations(),
+ expectedAnnotations.toArray(new SparseAnnotations[0]));
+ }
+
+ private void resetCommunicatorExpectingNoBroadcast(
+ Capture<ClusterMessage> bcast) {
+ bcast.reset();
+ reset(clusterCommunicator);
+ replay(clusterCommunicator);
+ }
+
+ private void resetCommunicatorExpectingSingleBroadcast(
+ Capture<ClusterMessage> bcast) {
+
+ bcast.reset();
+ reset(clusterCommunicator);
+ try {
+ expect(clusterCommunicator.broadcast(capture(bcast))).andReturn(true).once();
+ } catch (IOException e) {
+ fail("Should never reach here");
+ }
+ replay(clusterCommunicator);
}
@Test
@@ -476,12 +711,19 @@
assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
+ Capture<ClusterMessage> bcast = new Capture<>();
+
+ resetCommunicatorExpectingSingleBroadcast(bcast);
+
DeviceEvent event = deviceStore.removeDevice(DID1);
assertEquals(DEVICE_REMOVED, event.type());
assertDevice(DID1, SW1, event.subject());
assertEquals(1, deviceStore.getDeviceCount());
assertEquals(0, deviceStore.getPorts(DID1).size());
+ verify(clusterCommunicator);
+ // TODO: verify broadcast message
+ assertTrue(bcast.hasCaptured());
// putBack Device, Port w/o annotation
putDevice(DID1, SW1);
@@ -556,41 +798,35 @@
private static final class TestGossipDeviceStore extends GossipDeviceStore {
public TestGossipDeviceStore(
- ClockService clockService,
+ DeviceClockService deviceClockService,
ClusterService clusterService,
ClusterCommunicationService clusterCommunicator) {
- this.clockService = clockService;
+ this.deviceClockService = deviceClockService;
this.clusterService = clusterService;
this.clusterCommunicator = clusterCommunicator;
}
- }
- private static final class TestClusterCommunicationService implements ClusterCommunicationService {
- @Override
- public boolean broadcast(ClusterMessage message) throws IOException { return true; }
- @Override
- public boolean unicast(ClusterMessage message, NodeId nodeId) throws IOException { return true; }
- @Override
- public boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) throws IOException { return true; }
- @Override
- public void addSubscriber(MessageSubject subject, ClusterMessageHandler subscriber) {}
+ public <T> T deserialize(byte[] bytes) {
+ return SERIALIZER.decode(bytes);
+ }
}
private static final class TestClusterService implements ClusterService {
- private static final ControllerNode ONOS1 =
- new DefaultControllerNode(new NodeId("N1"), IpPrefix.valueOf("127.0.0.1"));
private final Map<NodeId, ControllerNode> nodes = new HashMap<>();
private final Map<NodeId, ControllerNode.State> nodeStates = new HashMap<>();
public TestClusterService() {
- nodes.put(new NodeId("N1"), ONOS1);
- nodeStates.put(new NodeId("N1"), ControllerNode.State.ACTIVE);
+ nodes.put(NID1, ONOS1);
+ nodeStates.put(NID1, ACTIVE);
+
+ nodes.put(NID2, ONOS2);
+ nodeStates.put(NID2, ACTIVE);
}
@Override
public ControllerNode getLocalNode() {
- return ONOS1;
+ return GossipDeviceStoreTest.ONOS1;
}
@Override
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentIdTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/PortFragmentIdTest.java
similarity index 97%
rename from core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentIdTest.java
rename to core/store/dist/src/test/java/org/onlab/onos/store/device/impl/PortFragmentIdTest.java
index 97db29d..4e7c290 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/peermsg/PortFragmentIdTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/device/impl/PortFragmentIdTest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.device.impl.peermsg;
+package org.onlab.onos.store.device.impl;
import static org.onlab.onos.net.DeviceId.deviceId;
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/MastershipBasedTimestampTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/impl/MastershipBasedTimestampTest.java
similarity index 98%
rename from core/store/dist/src/test/java/org/onlab/onos/store/common/impl/MastershipBasedTimestampTest.java
rename to core/store/dist/src/test/java/org/onlab/onos/store/impl/MastershipBasedTimestampTest.java
index ea63ef8..b455989 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/common/impl/MastershipBasedTimestampTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/impl/MastershipBasedTimestampTest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.common.impl;
+package org.onlab.onos.store.impl;
import static org.junit.Assert.*;
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
similarity index 96%
rename from core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
rename to core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
index 71d42fa..e073b63 100644
--- a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
@@ -1,6 +1,6 @@
-package org.onlab.onos.store.cluster.impl;
+package org.onlab.onos.store.mastership.impl;
-import static org.onlab.onos.cluster.MastershipEvent.Type.MASTER_CHANGED;
+import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED;
import java.util.Map;
import java.util.Set;
@@ -12,11 +12,11 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
-import org.onlab.onos.cluster.MastershipEvent;
-import org.onlab.onos.cluster.MastershipStore;
-import org.onlab.onos.cluster.MastershipStoreDelegate;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipEvent;
+import org.onlab.onos.mastership.MastershipStore;
+import org.onlab.onos.mastership.MastershipStoreDelegate;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.store.common.AbstractHazelcastStore;
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/package-info.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/package-info.java
new file mode 100644
index 0000000..308c9ef
--- /dev/null
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Implementation of a distributed mastership store using Hazelcast.
+ */
+package org.onlab.onos.store.mastership.impl;
diff --git a/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java b/core/store/hz/cluster/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
similarity index 97%
rename from core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
rename to core/store/hz/cluster/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
index bf1bb38..89c4357 100644
--- a/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
+++ b/core/store/hz/cluster/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
@@ -1,4 +1,4 @@
-package org.onlab.onos.store.cluster.impl;
+package org.onlab.onos.store.mastership.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -21,11 +21,11 @@
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.ControllerNode.State;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipEvent;
-import org.onlab.onos.cluster.MastershipEvent.Type;
-import org.onlab.onos.cluster.MastershipStoreDelegate;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipEvent;
+import org.onlab.onos.mastership.MastershipStoreDelegate;
+import org.onlab.onos.mastership.MastershipTerm;
+import org.onlab.onos.mastership.MastershipEvent.Type;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.store.common.StoreManager;
import org.onlab.onos.store.common.StoreService;
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/NoOpClockProviderService.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/NoOpClockProviderService.java
index b68620a..4626fa4 100644
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/NoOpClockProviderService.java
+++ b/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/NoOpClockProviderService.java
@@ -2,17 +2,17 @@
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
-import org.onlab.onos.cluster.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.store.ClockProviderService;
+import org.onlab.onos.net.device.DeviceClockProviderService;
// FIXME: Code clone in onos-core-trivial, onos-core-hz-net
/**
- * Dummy implementation of {@link ClockProviderService}.
+ * Dummy implementation of {@link DeviceClockProviderService}.
*/
@Component(immediate = true)
@Service
-public class NoOpClockProviderService implements ClockProviderService {
+public class NoOpClockProviderService implements DeviceClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/package-info.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/package-info.java
deleted file mode 100644
index 2fd9f27..0000000
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Implementation of device store using Hazelcast distributed structures.
- */
-package org.onlab.onos.store.device.impl;
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/flow/impl/package-info.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/flow/impl/package-info.java
deleted file mode 100644
index f09ac11..0000000
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/flow/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Implementation of flow store using Hazelcast distributed structures.
- */
-package org.onlab.onos.store.flow.impl;
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/host/impl/package-info.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/host/impl/package-info.java
deleted file mode 100644
index 2a9998a..0000000
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/host/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Implementation of host store using Hazelcast distributed structures.
- */
-package org.onlab.onos.store.host.impl;
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/link/impl/package-info.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/link/impl/package-info.java
deleted file mode 100644
index 53b6f33..0000000
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/link/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Implementation of link store using Hazelcast distributed structures.
- */
-package org.onlab.onos.store.link.impl;
diff --git a/core/store/hz/net/src/main/java/org/onlab/onos/store/topology/impl/package-info.java b/core/store/hz/net/src/main/java/org/onlab/onos/store/topology/impl/package-info.java
deleted file mode 100644
index 28b7704..0000000
--- a/core/store/hz/net/src/main/java/org/onlab/onos/store/topology/impl/package-info.java
+++ /dev/null
@@ -1,4 +0,0 @@
-/**
- * Implementation of topology store using Hazelcast distributed structures.
- */
-package org.onlab.onos.store.topology.impl;
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/ImmutableListSerializer.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/ImmutableListSerializer.java
new file mode 100644
index 0000000..4bcc0a3
--- /dev/null
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/ImmutableListSerializer.java
@@ -0,0 +1,49 @@
+package org.onlab.onos.store.serializers;
+
+import org.onlab.util.KryoPool.FamilySerializer;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+
+/**
+ * Creates {@link ImmutableList} serializer instance.
+ */
+public class ImmutableListSerializer extends FamilySerializer<ImmutableList<?>> {
+
+ /**
+ * Creates {@link ImmutableList} serializer instance.
+ */
+ public ImmutableListSerializer() {
+ // non-null, immutable
+ super(false, true);
+ }
+ @Override
+ public void write(Kryo kryo, Output output, ImmutableList<?> object) {
+ output.writeInt(object.size());
+ for (Object e : object) {
+ kryo.writeClassAndObject(output, e);
+ }
+ }
+
+ @Override
+ public ImmutableList<?> read(Kryo kryo, Input input,
+ Class<ImmutableList<?>> type) {
+ final int size = input.readInt();
+ Builder<Object> builder = ImmutableList.builder();
+ for (int i = 0; i < size; ++i) {
+ builder.add(kryo.readClassAndObject(input));
+ }
+ return builder.build();
+ }
+
+ @Override
+ public void registerFamilies(Kryo kryo) {
+ kryo.register(ImmutableList.of(1).getClass(), this);
+ kryo.register(ImmutableList.of(1, 2).getClass(), this);
+ // TODO register required ImmutableList variants
+ }
+
+}
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoPoolUtil.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoPoolUtil.java
index efecb6c..b44c102 100644
--- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoPoolUtil.java
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/KryoPoolUtil.java
@@ -7,8 +7,8 @@
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
import org.onlab.onos.net.DefaultDevice;
@@ -31,6 +31,9 @@
import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoPool;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
public final class KryoPoolUtil {
/**
@@ -47,12 +50,15 @@
*/
public static final KryoPool API = KryoPool.newBuilder()
.register(MISC)
+ .register(ImmutableMap.class, new ImmutableMapSerializer())
+ .register(ImmutableList.class, new ImmutableListSerializer())
.register(
//
ArrayList.class,
Arrays.asList().getClass(),
HashMap.class,
//
+ //
ControllerNode.State.class,
Device.Type.class,
DefaultAnnotations.class,
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MastershipTermSerializer.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MastershipTermSerializer.java
index 0ac61a8..d99fcde 100644
--- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MastershipTermSerializer.java
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MastershipTermSerializer.java
@@ -1,14 +1,15 @@
package org.onlab.onos.store.serializers;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipTerm;
+
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
/**
- * Kryo Serializer for {@link org.onlab.onos.cluster.MastershipTerm}.
+ * Kryo Serializer for {@link org.onlab.onos.mastership.MastershipTerm}.
*/
public class MastershipTermSerializer extends Serializer<MastershipTerm> {
diff --git a/core/store/serializers/src/test/java/org/onlab/onos/store/serializers/KryoSerializerTest.java b/core/store/serializers/src/test/java/org/onlab/onos/store/serializers/KryoSerializerTest.java
index d651d56..d9157b4 100644
--- a/core/store/serializers/src/test/java/org/onlab/onos/store/serializers/KryoSerializerTest.java
+++ b/core/store/serializers/src/test/java/org/onlab/onos/store/serializers/KryoSerializerTest.java
@@ -10,8 +10,8 @@
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.Annotations;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.DefaultAnnotations;
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
index ff4b31a..6c1fae8 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
@@ -2,17 +2,17 @@
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
-import org.onlab.onos.cluster.MastershipTerm;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.store.ClockProviderService;
+import org.onlab.onos.net.device.DeviceClockProviderService;
//FIXME: Code clone in onos-core-trivial, onos-core-hz-net
/**
- * Dummy implementation of {@link ClockProviderService}.
+ * Dummy implementation of {@link DeviceClockProviderService}.
*/
@Component(immediate = true)
@Service
-public class NoOpClockProviderService implements ClockProviderService {
+public class NoOpClockProviderService implements DeviceClockProviderService {
@Override
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
index e8096ea..aba77d0 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
@@ -15,18 +15,18 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ControllerNode;
import org.onlab.onos.cluster.DefaultControllerNode;
-import org.onlab.onos.cluster.MastershipEvent;
-import org.onlab.onos.cluster.MastershipStore;
-import org.onlab.onos.cluster.MastershipStoreDelegate;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipEvent;
+import org.onlab.onos.mastership.MastershipStore;
+import org.onlab.onos.mastership.MastershipStoreDelegate;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.store.AbstractStore;
import org.onlab.packet.IpPrefix;
import org.slf4j.Logger;
-import static org.onlab.onos.cluster.MastershipEvent.Type.*;
+import static org.onlab.onos.mastership.MastershipEvent.Type.*;
/**
* Manages inventory of controller mastership over devices using
diff --git a/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java b/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java
index 1e8e5c7..9fa066e 100644
--- a/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java
+++ b/core/store/trivial/src/test/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStoreTest.java
@@ -6,8 +6,8 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import com.google.common.collect.Sets;
@@ -15,8 +15,8 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.onlab.onos.mastership.MastershipEvent.Type.*;
import static org.onlab.onos.net.MastershipRole.*;
-import static org.onlab.onos.cluster.MastershipEvent.Type.*;
/**
* Test for the simple MastershipStore implementation.
diff --git a/pom.xml b/pom.xml
index 4290769..1b75b52 100644
--- a/pom.xml
+++ b/pom.xml
@@ -500,7 +500,7 @@
<group>
<title>Core Subsystems</title>
<packages>
- org.onlab.onos.impl:org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl:org.onlab.onos.net.proxyarp.impl
+ org.onlab.onos.impl:org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*:org.onlab.onos.net.intent.impl:org.onlab.onos.net.proxyarp.impl:org.onlab.onos.mastership.impl
</packages>
</group>
<group>
diff --git a/tools/test/bin/onos-update-bundle b/tools/test/bin/onos-update-bundle
new file mode 100755
index 0000000..9998ea3
--- /dev/null
+++ b/tools/test/bin/onos-update-bundle
@@ -0,0 +1,16 @@
+#!/bin/bash
+#-------------------------------------------------------------------------------
+# Update bundle on locally running karaf.
+#-------------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+cd ~/.m2/repository
+jar=$(find org/onlab -type f -name '*.jar' | grep -e $1 | grep -v -e -tests | head -n 1)
+
+[ -z "$jar" ] && echo "No bundle $1 found for" && exit 1
+
+bundle=$(echo $(basename $jar .jar) | sed 's/-[0-9].*//g')
+
+client "bundle:update -f $bundle" 2>/dev/null