tom

Merge remote-tracking branch 'origin/master'

Showing 74 changed files with 1183 additions and 199 deletions
...@@ -102,7 +102,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); ...@@ -102,7 +102,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class);
102 // System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS))); 102 // System.out.println("Got back:" + new String(response.get(2, TimeUnit.SECONDS)));
103 } 103 }
104 104
105 - sleep(1000); 105 + //sleep(1000);
106 log.info("measuring async sender"); 106 log.info("measuring async sender");
107 Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender"); 107 Timer sendAsyncTimer = metrics.createTimer(component, feature, "AsyncSender");
108 108
...@@ -111,7 +111,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class); ...@@ -111,7 +111,7 @@ private static Logger log = LoggerFactory.getLogger(SimpleNettyClient.class);
111 messaging.sendAsync(endpoint, "simple", "Hello World".getBytes()); 111 messaging.sendAsync(endpoint, "simple", "Hello World".getBytes());
112 context.stop(); 112 context.stop();
113 } 113 }
114 - sleep(1000); 114 + sleep(10000);
115 } 115 }
116 116
117 public static void stop() { 117 public static void stop() {
......
1 package org.onlab.onos.cli; 1 package org.onlab.onos.cli;
2 2
3 import com.google.common.collect.Lists; 3 import com.google.common.collect.Lists;
4 +
4 import org.apache.karaf.shell.commands.Command; 5 import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.cluster.ClusterService; 6 import org.onlab.onos.cluster.ClusterService;
6 import org.onlab.onos.cluster.ControllerNode; 7 import org.onlab.onos.cluster.ControllerNode;
7 -import org.onlab.onos.cluster.MastershipService; 8 +import org.onlab.onos.mastership.MastershipService;
8 import org.onlab.onos.net.DeviceId; 9 import org.onlab.onos.net.DeviceId;
9 10
10 import java.util.Collections; 11 import java.util.Collections;
......
1 +package org.onlab.onos.cli.net;
2 +
3 +import java.util.HashSet;
4 +import java.util.Set;
5 +
6 +import org.apache.karaf.shell.commands.Argument;
7 +import org.apache.karaf.shell.commands.Command;
8 +import org.onlab.onos.cli.AbstractShellCommand;
9 +import org.onlab.onos.net.ConnectPoint;
10 +import org.onlab.onos.net.DeviceId;
11 +import org.onlab.onos.net.PortNumber;
12 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
13 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
14 +import org.onlab.onos.net.flow.TrafficSelector;
15 +import org.onlab.onos.net.flow.TrafficTreatment;
16 +import org.onlab.onos.net.intent.Intent;
17 +import org.onlab.onos.net.intent.IntentId;
18 +import org.onlab.onos.net.intent.IntentService;
19 +import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
20 +import org.onlab.packet.Ethernet;
21 +
22 +/**
23 + * Installs point-to-point connectivity intents.
24 + */
25 +@Command(scope = "onos", name = "add-multi-to-single-intent",
26 + description = "Installs point-to-point connectivity intent")
27 +public class AddMultiPointToSinglePointIntentCommand extends AbstractShellCommand {
28 +
29 + @Argument(index = 0, name = "ingressDevices",
30 + description = "Ingress Device/Port Description",
31 + required = true, multiValued = true)
32 + String[] deviceStrings = null;
33 +
34 + private static long id = 0x7070001;
35 +
36 + @Override
37 + protected void execute() {
38 + IntentService service = get(IntentService.class);
39 +
40 + if (deviceStrings.length < 2) {
41 + return;
42 + }
43 +
44 + String egressDeviceString = deviceStrings[deviceStrings.length - 1];
45 + DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
46 + PortNumber egressPortNumber =
47 + PortNumber.portNumber(getPortNumber(egressDeviceString));
48 + ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
49 + Set<ConnectPoint> ingressPoints = new HashSet<>();
50 +
51 + for (int index = 0; index < deviceStrings.length - 1; index++) {
52 + String ingressDeviceString = deviceStrings[index];
53 + DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
54 + PortNumber ingressPortNumber =
55 + PortNumber.portNumber(getPortNumber(ingressDeviceString));
56 + ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
57 + ingressPoints.add(ingress);
58 + }
59 +
60 +
61 + TrafficSelector selector = DefaultTrafficSelector.builder()
62 + .matchEthType(Ethernet.TYPE_IPV4)
63 + .build();
64 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
65 +
66 + Intent intent =
67 + new MultiPointToSinglePointIntent(new IntentId(id++),
68 + selector,
69 + treatment,
70 + ingressPoints,
71 + egress);
72 + service.submit(intent);
73 + }
74 +
75 + /**
76 + * Extracts the port number portion of the ConnectPoint.
77 + *
78 + * @param deviceString string representing the device/port
79 + * @return port number as a string, empty string if the port is not found
80 + */
81 + private String getPortNumber(String deviceString) {
82 + int slash = deviceString.indexOf('/');
83 + if (slash <= 0) {
84 + return "";
85 + }
86 + return deviceString.substring(slash + 1, deviceString.length());
87 + }
88 +
89 + /**
90 + * Extracts the device ID portion of the ConnectPoint.
91 + *
92 + * @param deviceString string representing the device/port
93 + * @return device ID string
94 + */
95 + private String getDeviceId(String deviceString) {
96 + int slash = deviceString.indexOf('/');
97 + if (slash <= 0) {
98 + return "";
99 + }
100 + return deviceString.substring(0, slash);
101 + }
102 +}
...@@ -3,8 +3,8 @@ package org.onlab.onos.cli.net; ...@@ -3,8 +3,8 @@ package org.onlab.onos.cli.net;
3 import org.apache.karaf.shell.commands.Argument; 3 import org.apache.karaf.shell.commands.Argument;
4 import org.apache.karaf.shell.commands.Command; 4 import org.apache.karaf.shell.commands.Command;
5 import org.onlab.onos.cli.AbstractShellCommand; 5 import org.onlab.onos.cli.AbstractShellCommand;
6 -import org.onlab.onos.cluster.MastershipAdminService;
7 import org.onlab.onos.cluster.NodeId; 6 import org.onlab.onos.cluster.NodeId;
7 +import org.onlab.onos.mastership.MastershipAdminService;
8 import org.onlab.onos.net.MastershipRole; 8 import org.onlab.onos.net.MastershipRole;
9 9
10 import static org.onlab.onos.net.DeviceId.deviceId; 10 import static org.onlab.onos.net.DeviceId.deviceId;
......
1 +package org.onlab.onos.cli.net;
2 +
3 +import java.util.concurrent.CountDownLatch;
4 +import java.util.concurrent.TimeUnit;
5 +
6 +import org.apache.karaf.shell.commands.Argument;
7 +import org.apache.karaf.shell.commands.Command;
8 +import org.onlab.onos.cli.AbstractShellCommand;
9 +import org.onlab.onos.net.ConnectPoint;
10 +import org.onlab.onos.net.DeviceId;
11 +import org.onlab.onos.net.PortNumber;
12 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
13 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
14 +import org.onlab.onos.net.flow.TrafficSelector;
15 +import org.onlab.onos.net.flow.TrafficTreatment;
16 +import org.onlab.onos.net.intent.Intent;
17 +import org.onlab.onos.net.intent.IntentEvent;
18 +import org.onlab.onos.net.intent.IntentEvent.Type;
19 +import org.onlab.onos.net.intent.IntentId;
20 +import org.onlab.onos.net.intent.IntentListener;
21 +import org.onlab.onos.net.intent.IntentService;
22 +import org.onlab.onos.net.intent.PointToPointIntent;
23 +import org.onlab.packet.Ethernet;
24 +import org.onlab.packet.MacAddress;
25 +
26 +/**
27 + * Installs point-to-point connectivity intents.
28 + */
29 +@Command(scope = "onos", name = "push-test-intents",
30 + description = "Installs random intents to test throughput")
31 +public class IntentPushTestCommand extends AbstractShellCommand
32 + implements IntentListener {
33 +
34 + @Argument(index = 0, name = "ingressDevice",
35 + description = "Ingress Device/Port Description",
36 + required = true, multiValued = false)
37 + String ingressDeviceString = null;
38 +
39 + @Argument(index = 1, name = "egressDevice",
40 + description = "Egress Device/Port Description",
41 + required = true, multiValued = false)
42 + String egressDeviceString = null;
43 +
44 + @Argument(index = 2, name = "count",
45 + description = "Number of intents to push",
46 + required = true, multiValued = false)
47 + String countString = null;
48 +
49 +
50 + private static long id = 0x7870001;
51 +
52 + private IntentService service;
53 + private CountDownLatch latch;
54 + private long start, end;
55 +
56 + @Override
57 + protected void execute() {
58 + service = get(IntentService.class);
59 +
60 + DeviceId ingressDeviceId = DeviceId.deviceId(getDeviceId(ingressDeviceString));
61 + PortNumber ingressPortNumber =
62 + PortNumber.portNumber(getPortNumber(ingressDeviceString));
63 + ConnectPoint ingress = new ConnectPoint(ingressDeviceId, ingressPortNumber);
64 +
65 + DeviceId egressDeviceId = DeviceId.deviceId(getDeviceId(egressDeviceString));
66 + PortNumber egressPortNumber =
67 + PortNumber.portNumber(getPortNumber(egressDeviceString));
68 + ConnectPoint egress = new ConnectPoint(egressDeviceId, egressPortNumber);
69 +
70 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
71 + .matchEthType(Ethernet.TYPE_IPV4);
72 + TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
73 +
74 + int count = Integer.parseInt(countString);
75 +
76 + service.addListener(this);
77 + latch = new CountDownLatch(count);
78 +
79 + start = System.currentTimeMillis();
80 + for (int i = 0; i < count; i++) {
81 + TrafficSelector s = selector
82 + .matchEthSrc(MacAddress.valueOf(i))
83 + .build();
84 + Intent intent =
85 + new PointToPointIntent(new IntentId(id++),
86 + s,
87 + treatment,
88 + ingress,
89 + egress);
90 + service.submit(intent);
91 + }
92 + try {
93 + latch.await(5, TimeUnit.SECONDS);
94 + printResults(count);
95 + } catch (InterruptedException e) {
96 + print(e.toString());
97 + }
98 + service.removeListener(this);
99 + }
100 +
101 + private void printResults(int count) {
102 + long delta = end - start;
103 + print("Time to install %d intents: %d ms", count, delta);
104 + }
105 +
106 + /**
107 + * Extracts the port number portion of the ConnectPoint.
108 + *
109 + * @param deviceString string representing the device/port
110 + * @return port number as a string, empty string if the port is not found
111 + */
112 + private String getPortNumber(String deviceString) {
113 + int slash = deviceString.indexOf('/');
114 + if (slash <= 0) {
115 + return "";
116 + }
117 + return deviceString.substring(slash + 1, deviceString.length());
118 + }
119 +
120 + /**
121 + * Extracts the device ID portion of the ConnectPoint.
122 + *
123 + * @param deviceString string representing the device/port
124 + * @return device ID string
125 + */
126 + private String getDeviceId(String deviceString) {
127 + int slash = deviceString.indexOf('/');
128 + if (slash <= 0) {
129 + return "";
130 + }
131 + return deviceString.substring(0, slash);
132 + }
133 +
134 + @Override
135 + public void event(IntentEvent event) {
136 + if (event.type() == Type.INSTALLED) {
137 + end = event.time();
138 + if (latch != null) {
139 + latch.countDown();
140 + } else {
141 + log.warn("install event latch is null");
142 + }
143 + }
144 + }
145 +}
...@@ -82,6 +82,19 @@ ...@@ -82,6 +82,19 @@
82 <ref component-id="connectPointCompleter"/> 82 <ref component-id="connectPointCompleter"/>
83 </completers> 83 </completers>
84 </command> 84 </command>
85 + <command>
86 + <action class="org.onlab.onos.cli.net.AddMultiPointToSinglePointIntentCommand"/>
87 + <completers>
88 + <ref component-id="connectPointCompleter"/>
89 + </completers>
90 + </command>
91 + <command>
92 + <action class="org.onlab.onos.cli.net.IntentPushTestCommand"/>
93 + <completers>
94 + <ref component-id="connectPointCompleter"/>
95 + <ref component-id="connectPointCompleter"/>
96 + </completers>
97 + </command>
85 98
86 <command> 99 <command>
87 <action class="org.onlab.onos.cli.net.ClustersListCommand"/> 100 <action class="org.onlab.onos.cli.net.ClustersListCommand"/>
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 +import org.onlab.onos.cluster.NodeId;
3 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
4 import org.onlab.onos.net.MastershipRole; 5 import org.onlab.onos.net.MastershipRole;
5 6
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 +import org.onlab.onos.cluster.NodeId;
3 import org.onlab.onos.event.AbstractEvent; 4 import org.onlab.onos.event.AbstractEvent;
4 import org.onlab.onos.net.DeviceId; 5 import org.onlab.onos.net.DeviceId;
5 6
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import org.onlab.onos.event.EventListener; 3 import org.onlab.onos.event.EventListener;
4 4
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import java.util.Set; 3 import java.util.Set;
4 4
5 +import org.onlab.onos.cluster.NodeId;
5 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
6 import org.onlab.onos.net.MastershipRole; 7 import org.onlab.onos.net.MastershipRole;
7 8
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import java.util.Set; 3 import java.util.Set;
4 4
5 +import org.onlab.onos.cluster.NodeId;
5 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
6 import org.onlab.onos.net.MastershipRole; 7 import org.onlab.onos.net.MastershipRole;
7 import org.onlab.onos.store.Store; 8 import org.onlab.onos.store.Store;
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import org.onlab.onos.store.StoreDelegate; 3 import org.onlab.onos.store.StoreDelegate;
4 4
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import java.util.Objects; 3 import java.util.Objects;
4 4
5 +import org.onlab.onos.cluster.NodeId;
6 +
5 public final class MastershipTerm { 7 public final class MastershipTerm {
6 8
7 private final NodeId master; 9 private final NodeId master;
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 4
......
1 /** 1 /**
2 - * Implementation of device store using Hazelcast distributed structures. 2 + * Set of abstractions for dealing with controller mastership related topics.
3 */ 3 */
4 -package org.onlab.onos.store.device.impl; 4 +package org.onlab.onos.mastership;
......
1 -package org.onlab.onos.store; 1 +package org.onlab.onos.net.device;
2 2
3 -import org.onlab.onos.cluster.MastershipTerm; 3 +import org.onlab.onos.mastership.MastershipTerm;
4 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
5 5
6 -//TODO: Consider renaming to DeviceClockProviderService?
7 /** 6 /**
8 * Interface for feeding term information to a logical clock service 7 * Interface for feeding term information to a logical clock service
9 * that vends per device timestamps. 8 * that vends per device timestamps.
10 */ 9 */
11 -public interface ClockProviderService { 10 +public interface DeviceClockProviderService {
12 11
13 /** 12 /**
14 * Updates the mastership term for the specified deviceId. 13 * Updates the mastership term for the specified deviceId.
......
1 -package org.onlab.onos.store; 1 +package org.onlab.onos.net.device;
2 2
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 +import org.onlab.onos.store.Timestamp;
4 5
5 // TODO: Consider renaming to DeviceClockService? 6 // TODO: Consider renaming to DeviceClockService?
6 /** 7 /**
7 * Interface for a logical clock service that vends per device timestamps. 8 * Interface for a logical clock service that vends per device timestamps.
8 */ 9 */
9 -public interface ClockService { 10 +public interface DeviceClockService {
10 11
11 /** 12 /**
12 * Returns a new timestamp for the specified deviceId. 13 * Returns a new timestamp for the specified deviceId.
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import java.util.Collection;
4 +import java.util.Objects;
5 +import java.util.Set;
6 +
7 +import org.onlab.onos.net.Link;
8 +import org.onlab.onos.net.flow.TrafficSelector;
9 +import org.onlab.onos.net.flow.TrafficTreatment;
10 +
11 +import com.google.common.base.MoreObjects;
12 +
13 +/**
14 + * Abstraction of a connectivity intent that is implemented by a set of path
15 + * segments.
16 + */
17 +public class LinkCollectionIntent extends ConnectivityIntent implements InstallableIntent {
18 +
19 + private final Set<Link> links;
20 +
21 + /**
22 + * Creates a new point-to-point intent with the supplied ingress/egress
23 + * ports and using the specified explicit path.
24 + *
25 + * @param id intent identifier
26 + * @param selector traffic match
27 + * @param treatment action
28 + * @param links traversed links
29 + * @throws NullPointerException {@code path} is null
30 + */
31 + public LinkCollectionIntent(IntentId id,
32 + TrafficSelector selector,
33 + TrafficTreatment treatment,
34 + Set<Link> links) {
35 + super(id, selector, treatment);
36 + this.links = links;
37 + }
38 +
39 + protected LinkCollectionIntent() {
40 + super();
41 + this.links = null;
42 + }
43 +
44 + @Override
45 + public Collection<Link> requiredLinks() {
46 + return links;
47 + }
48 +
49 + public Set<Link> links() {
50 + return links;
51 + }
52 +
53 + @Override
54 + public boolean equals(Object o) {
55 + if (this == o) {
56 + return true;
57 + }
58 + if (o == null || getClass() != o.getClass()) {
59 + return false;
60 + }
61 + if (!super.equals(o)) {
62 + return false;
63 + }
64 +
65 + LinkCollectionIntent that = (LinkCollectionIntent) o;
66 +
67 + return Objects.equals(this.links, that.links);
68 + }
69 +
70 + @Override
71 + public int hashCode() {
72 + return Objects.hash(super.hashCode(), links);
73 + }
74 +
75 + @Override
76 + public String toString() {
77 + return MoreObjects.toStringHelper(getClass())
78 + .add("id", id())
79 + .add("match", selector())
80 + .add("action", treatment())
81 + .add("links", links())
82 + .toString();
83 + }
84 +}
...@@ -5,6 +5,7 @@ import java.util.Set; ...@@ -5,6 +5,7 @@ import java.util.Set;
5 5
6 import org.onlab.onos.cluster.NodeId; 6 import org.onlab.onos.cluster.NodeId;
7 7
8 +// TODO: remove IOExceptions?
8 /** 9 /**
9 * Service for assisting communications between controller cluster nodes. 10 * Service for assisting communications between controller cluster nodes.
10 */ 11 */
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 +import org.onlab.onos.cluster.NodeId;
3 import org.onlab.onos.net.DeviceId; 4 import org.onlab.onos.net.DeviceId;
4 import org.onlab.onos.net.MastershipRole; 5 import org.onlab.onos.net.MastershipRole;
5 6
......
1 -package org.onlab.onos.cluster; 1 +package org.onlab.onos.mastership;
2 2
3 import static org.junit.Assert.assertEquals; 3 import static org.junit.Assert.assertEquals;
4 4
5 import org.junit.Test; 5 import org.junit.Test;
6 +import org.onlab.onos.cluster.NodeId;
6 7
7 import com.google.common.testing.EqualsTester; 8 import com.google.common.testing.EqualsTester;
8 9
......
...@@ -4,6 +4,7 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -4,6 +4,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
4 import static org.slf4j.LoggerFactory.getLogger; 4 import static org.slf4j.LoggerFactory.getLogger;
5 5
6 import java.util.Set; 6 import java.util.Set;
7 +import java.util.concurrent.atomic.AtomicInteger;
7 8
8 import org.apache.felix.scr.annotations.Activate; 9 import org.apache.felix.scr.annotations.Activate;
9 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
...@@ -14,17 +15,18 @@ import org.apache.felix.scr.annotations.Service; ...@@ -14,17 +15,18 @@ import org.apache.felix.scr.annotations.Service;
14 import org.onlab.onos.cluster.ClusterEvent; 15 import org.onlab.onos.cluster.ClusterEvent;
15 import org.onlab.onos.cluster.ClusterEventListener; 16 import org.onlab.onos.cluster.ClusterEventListener;
16 import org.onlab.onos.cluster.ClusterService; 17 import org.onlab.onos.cluster.ClusterService;
17 -import org.onlab.onos.cluster.MastershipAdminService; 18 +import org.onlab.onos.cluster.ControllerNode;
18 -import org.onlab.onos.cluster.MastershipEvent;
19 -import org.onlab.onos.cluster.MastershipListener;
20 -import org.onlab.onos.cluster.MastershipService;
21 -import org.onlab.onos.cluster.MastershipStore;
22 -import org.onlab.onos.cluster.MastershipStoreDelegate;
23 -import org.onlab.onos.cluster.MastershipTerm;
24 -import org.onlab.onos.cluster.MastershipTermService;
25 import org.onlab.onos.cluster.NodeId; 19 import org.onlab.onos.cluster.NodeId;
26 import org.onlab.onos.event.AbstractListenerRegistry; 20 import org.onlab.onos.event.AbstractListenerRegistry;
27 import org.onlab.onos.event.EventDeliveryService; 21 import org.onlab.onos.event.EventDeliveryService;
22 +import org.onlab.onos.mastership.MastershipAdminService;
23 +import org.onlab.onos.mastership.MastershipEvent;
24 +import org.onlab.onos.mastership.MastershipListener;
25 +import org.onlab.onos.mastership.MastershipService;
26 +import org.onlab.onos.mastership.MastershipStore;
27 +import org.onlab.onos.mastership.MastershipStoreDelegate;
28 +import org.onlab.onos.mastership.MastershipTerm;
29 +import org.onlab.onos.mastership.MastershipTermService;
28 import org.onlab.onos.net.DeviceId; 30 import org.onlab.onos.net.DeviceId;
29 import org.onlab.onos.net.MastershipRole; 31 import org.onlab.onos.net.MastershipRole;
30 import org.slf4j.Logger; 32 import org.slf4j.Logger;
...@@ -164,21 +166,68 @@ implements MastershipService, MastershipAdminService { ...@@ -164,21 +166,68 @@ implements MastershipService, MastershipAdminService {
164 //callback for reacting to cluster events 166 //callback for reacting to cluster events
165 private class InternalClusterEventListener implements ClusterEventListener { 167 private class InternalClusterEventListener implements ClusterEventListener {
166 168
169 + // A notion of a local maximum cluster size, used to tie-break.
170 + // Think of a better way to do this.
171 + private AtomicInteger clusterSize;
172 +
173 + InternalClusterEventListener() {
174 + clusterSize = new AtomicInteger(0);
175 + }
176 +
167 @Override 177 @Override
168 public void event(ClusterEvent event) { 178 public void event(ClusterEvent event) {
169 switch (event.type()) { 179 switch (event.type()) {
170 //FIXME: worry about addition when the time comes 180 //FIXME: worry about addition when the time comes
171 case INSTANCE_ADDED: 181 case INSTANCE_ADDED:
172 case INSTANCE_ACTIVATED: 182 case INSTANCE_ACTIVATED:
183 + clusterSize.incrementAndGet();
184 + log.info("instance {} added/activated", event.subject());
173 break; 185 break;
174 case INSTANCE_REMOVED: 186 case INSTANCE_REMOVED:
175 case INSTANCE_DEACTIVATED: 187 case INSTANCE_DEACTIVATED:
188 + ControllerNode node = event.subject();
189 +
190 + if (node.equals(clusterService.getLocalNode())) {
191 + //If we are in smaller cluster, relinquish and return
192 + for (DeviceId device : getDevicesOf(node.id())) {
193 + if (!isInMajority()) {
194 + //own DeviceManager should catch event and tell switch
195 + store.relinquishRole(node.id(), device);
196 + }
197 + }
198 + log.info("broke off from cluster, relinquished devices");
199 + break;
200 + }
201 +
202 + // if we are the larger one and the removed node(s) are brain dead,
203 + // force relinquish on behalf of disabled node.
204 + // check network channel to do this?
205 + for (DeviceId device : getDevicesOf(node.id())) {
206 + //some things to check:
207 + // 1. we didn't break off as well while we're at it
208 + // 2. others don't pile in and try too - maybe a lock
209 + if (isInMajority()) {
210 + store.relinquishRole(node.id(), device);
211 + }
212 + }
213 + clusterSize.decrementAndGet();
214 + log.info("instance {} removed/deactivated", event.subject());
176 break; 215 break;
177 default: 216 default:
178 log.warn("unknown cluster event {}", event); 217 log.warn("unknown cluster event {}", event);
179 } 218 }
180 } 219 }
181 220
221 + private boolean isInMajority() {
222 + if (clusterService.getNodes().size() > (clusterSize.intValue() / 2)) {
223 + return true;
224 + }
225 + //else {
226 + //FIXME: break tie for equal-sized clusters, can we use hz's functions?
227 + // }
228 + return false;
229 + }
230 +
182 } 231 }
183 232
184 public class InternalDelegate implements MastershipStoreDelegate { 233 public class InternalDelegate implements MastershipStoreDelegate {
......
...@@ -13,20 +13,22 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -13,20 +13,22 @@ import org.apache.felix.scr.annotations.Reference;
13 import org.apache.felix.scr.annotations.ReferenceCardinality; 13 import org.apache.felix.scr.annotations.ReferenceCardinality;
14 import org.apache.felix.scr.annotations.Service; 14 import org.apache.felix.scr.annotations.Service;
15 import org.onlab.onos.cluster.ClusterService; 15 import org.onlab.onos.cluster.ClusterService;
16 -import org.onlab.onos.cluster.MastershipEvent;
17 -import org.onlab.onos.cluster.MastershipListener;
18 -import org.onlab.onos.cluster.MastershipService;
19 -import org.onlab.onos.cluster.MastershipTermService;
20 -import org.onlab.onos.cluster.MastershipTerm;
21 import org.onlab.onos.cluster.NodeId; 16 import org.onlab.onos.cluster.NodeId;
22 import org.onlab.onos.event.AbstractListenerRegistry; 17 import org.onlab.onos.event.AbstractListenerRegistry;
23 import org.onlab.onos.event.EventDeliveryService; 18 import org.onlab.onos.event.EventDeliveryService;
19 +import org.onlab.onos.mastership.MastershipEvent;
20 +import org.onlab.onos.mastership.MastershipListener;
21 +import org.onlab.onos.mastership.MastershipService;
22 +import org.onlab.onos.mastership.MastershipTerm;
23 +import org.onlab.onos.mastership.MastershipTermService;
24 import org.onlab.onos.net.Device; 24 import org.onlab.onos.net.Device;
25 import org.onlab.onos.net.DeviceId; 25 import org.onlab.onos.net.DeviceId;
26 import org.onlab.onos.net.MastershipRole; 26 import org.onlab.onos.net.MastershipRole;
27 import org.onlab.onos.net.Port; 27 import org.onlab.onos.net.Port;
28 import org.onlab.onos.net.PortNumber; 28 import org.onlab.onos.net.PortNumber;
29 +import org.onlab.onos.net.device.DefaultDeviceDescription;
29 import org.onlab.onos.net.device.DeviceAdminService; 30 import org.onlab.onos.net.device.DeviceAdminService;
31 +import org.onlab.onos.net.device.DeviceClockProviderService;
30 import org.onlab.onos.net.device.DeviceDescription; 32 import org.onlab.onos.net.device.DeviceDescription;
31 import org.onlab.onos.net.device.DeviceEvent; 33 import org.onlab.onos.net.device.DeviceEvent;
32 import org.onlab.onos.net.device.DeviceListener; 34 import org.onlab.onos.net.device.DeviceListener;
...@@ -39,7 +41,6 @@ import org.onlab.onos.net.device.DeviceStoreDelegate; ...@@ -39,7 +41,6 @@ import org.onlab.onos.net.device.DeviceStoreDelegate;
39 import org.onlab.onos.net.device.PortDescription; 41 import org.onlab.onos.net.device.PortDescription;
40 import org.onlab.onos.net.provider.AbstractProviderRegistry; 42 import org.onlab.onos.net.provider.AbstractProviderRegistry;
41 import org.onlab.onos.net.provider.AbstractProviderService; 43 import org.onlab.onos.net.provider.AbstractProviderService;
42 -import org.onlab.onos.store.ClockProviderService;
43 import org.slf4j.Logger; 44 import org.slf4j.Logger;
44 45
45 /** 46 /**
...@@ -81,7 +82,7 @@ public class DeviceManager ...@@ -81,7 +82,7 @@ public class DeviceManager
81 protected MastershipTermService termService; 82 protected MastershipTermService termService;
82 83
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 - protected ClockProviderService clockProviderService; 85 + protected DeviceClockProviderService deviceClockProviderService;
85 86
86 @Activate 87 @Activate
87 public void activate() { 88 public void activate() {
...@@ -216,7 +217,7 @@ public class DeviceManager ...@@ -216,7 +217,7 @@ public class DeviceManager
216 return; 217 return;
217 } 218 }
218 // tell clock provider if this instance is the master 219 // tell clock provider if this instance is the master
219 - clockProviderService.setMastershipTerm(deviceId, term); 220 + deviceClockProviderService.setMastershipTerm(deviceId, term);
220 221
221 DeviceEvent event = store.createOrUpdateDevice(provider().id(), 222 DeviceEvent event = store.createOrUpdateDevice(provider().id(),
222 deviceId, deviceDescription); 223 deviceId, deviceDescription);
...@@ -257,12 +258,12 @@ public class DeviceManager ...@@ -257,12 +258,12 @@ public class DeviceManager
257 // temporarily request for Master Role and mark offline. 258 // temporarily request for Master Role and mark offline.
258 if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) { 259 if (!mastershipService.getLocalRole(deviceId).equals(MastershipRole.MASTER)) {
259 log.debug("Device {} disconnected, but I am not the master", deviceId); 260 log.debug("Device {} disconnected, but I am not the master", deviceId);
260 - //let go of any role anyways 261 + //let go of ability to be backup
261 mastershipService.relinquishMastership(deviceId); 262 mastershipService.relinquishMastership(deviceId);
262 return; 263 return;
263 } 264 }
264 DeviceEvent event = store.markOffline(deviceId); 265 DeviceEvent event = store.markOffline(deviceId);
265 - //we're no longer capable of being master or a candidate. 266 + //relinquish master role and ability to be backup.
266 mastershipService.relinquishMastership(deviceId); 267 mastershipService.relinquishMastership(deviceId);
267 268
268 if (event != null) { 269 if (event != null) {
...@@ -325,7 +326,6 @@ public class DeviceManager ...@@ -325,7 +326,6 @@ public class DeviceManager
325 @Override 326 @Override
326 public void event(MastershipEvent event) { 327 public void event(MastershipEvent event) {
327 final DeviceId did = event.subject(); 328 final DeviceId did = event.subject();
328 - if (isAvailable(did)) {
329 final NodeId myNodeId = clusterService.getLocalNode().id(); 329 final NodeId myNodeId = clusterService.getLocalNode().id();
330 330
331 if (myNodeId.equals(event.master())) { 331 if (myNodeId.equals(event.master())) {
...@@ -333,15 +333,24 @@ public class DeviceManager ...@@ -333,15 +333,24 @@ public class DeviceManager
333 333
334 if (term.master().equals(myNodeId)) { 334 if (term.master().equals(myNodeId)) {
335 // only set the new term if I am the master 335 // only set the new term if I am the master
336 - clockProviderService.setMastershipTerm(did, term); 336 + deviceClockProviderService.setMastershipTerm(did, term);
337 } 337 }
338 - applyRole(did, MastershipRole.MASTER); 338 +
339 - } else { 339 + // FIXME: we should check that the device is connected on our end.
340 - applyRole(did, MastershipRole.STANDBY); 340 + // currently, this is not straight forward as the actual switch
341 + // implementation is hidden from the registry.
342 + if (!isAvailable(did)) {
343 + //flag the device as online. Is there a better way to do this?
344 + Device device = getDevice(did);
345 + store.createOrUpdateDevice(device.providerId(), did,
346 + new DefaultDeviceDescription(
347 + did.uri(), device.type(), device.manufacturer(),
348 + device.hwVersion(), device.swVersion(),
349 + device.serialNumber()));
341 } 350 }
351 +
352 + applyRole(did, MastershipRole.MASTER);
342 } else { 353 } else {
343 - //device dead to node, give up
344 - mastershipService.relinquishMastership(did);
345 applyRole(did, MastershipRole.STANDBY); 354 applyRole(did, MastershipRole.STANDBY);
346 } 355 }
347 } 356 }
......
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import java.util.List;
4 +import java.util.concurrent.Future;
5 +
6 +import org.apache.felix.scr.annotations.Activate;
7 +import org.apache.felix.scr.annotations.Component;
8 +import org.apache.felix.scr.annotations.Deactivate;
9 +import org.apache.felix.scr.annotations.Reference;
10 +import org.apache.felix.scr.annotations.ReferenceCardinality;
11 +import org.onlab.onos.ApplicationId;
12 +import org.onlab.onos.CoreService;
13 +import org.onlab.onos.net.Link;
14 +import org.onlab.onos.net.flow.CompletedBatchOperation;
15 +import org.onlab.onos.net.flow.DefaultFlowRule;
16 +import org.onlab.onos.net.flow.DefaultTrafficSelector;
17 +import org.onlab.onos.net.flow.FlowRule;
18 +import org.onlab.onos.net.flow.FlowRuleBatchEntry;
19 +import org.onlab.onos.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
20 +import org.onlab.onos.net.flow.FlowRuleBatchOperation;
21 +import org.onlab.onos.net.flow.FlowRuleService;
22 +import org.onlab.onos.net.flow.TrafficSelector;
23 +import org.onlab.onos.net.flow.TrafficTreatment;
24 +import org.onlab.onos.net.intent.IntentExtensionService;
25 +import org.onlab.onos.net.intent.IntentInstaller;
26 +import org.onlab.onos.net.intent.LinkCollectionIntent;
27 +import org.onlab.onos.net.intent.PathIntent;
28 +import org.slf4j.Logger;
29 +
30 +import com.google.common.collect.Lists;
31 +
32 +import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
33 +import static org.slf4j.LoggerFactory.getLogger;
34 +
35 +/**
36 + * Installer for {@link org.onlab.onos.net.intent.LinkCollectionIntent}
37 + * path segment intents.
38 + */
39 +@Component(immediate = true)
40 +public class LinkCollectionIntentInstaller implements IntentInstaller<LinkCollectionIntent> {
41 +
42 + private final Logger log = getLogger(getClass());
43 +
44 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
45 + protected IntentExtensionService intentManager;
46 +
47 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
48 + protected FlowRuleService flowRuleService;
49 +
50 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 + protected CoreService coreService;
52 +
53 + private ApplicationId appId;
54 +
55 + @Activate
56 + public void activate() {
57 + appId = coreService.registerApplication("org.onlab.onos.net.intent");
58 + intentManager.registerInstaller(LinkCollectionIntent.class, this);
59 + }
60 +
61 + @Deactivate
62 + public void deactivate() {
63 + intentManager.unregisterInstaller(PathIntent.class);
64 + }
65 +
66 + /**
67 + * Apply a list of FlowRules.
68 + *
69 + * @param rules rules to apply
70 + */
71 + private Future<CompletedBatchOperation> applyBatch(List<FlowRuleBatchEntry> rules) {
72 + FlowRuleBatchOperation batch = new FlowRuleBatchOperation(rules);
73 + return flowRuleService.applyBatch(batch);
74 + }
75 +
76 + @Override
77 + public Future<CompletedBatchOperation> install(LinkCollectionIntent intent) {
78 + TrafficSelector.Builder builder =
79 + DefaultTrafficSelector.builder(intent.selector());
80 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
81 + for (Link link : intent.links()) {
82 + TrafficTreatment treatment = builder()
83 + .setOutput(link.src().port()).build();
84 +
85 + FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
86 + builder.build(), treatment,
87 + 123, appId, 600);
88 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
89 + }
90 +
91 + return applyBatch(rules);
92 + }
93 +
94 + @Override
95 + public Future<CompletedBatchOperation> uninstall(LinkCollectionIntent intent) {
96 + TrafficSelector.Builder builder =
97 + DefaultTrafficSelector.builder(intent.selector());
98 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
99 +
100 + for (Link link : intent.links()) {
101 + TrafficTreatment treatment = builder()
102 + .setOutput(link.src().port()).build();
103 + FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
104 + builder.build(), treatment,
105 + 123, appId, 600);
106 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, rule));
107 + }
108 + return applyBatch(rules);
109 + }
110 +}
1 +package org.onlab.onos.net.intent.impl;
2 +
3 +import java.util.Arrays;
4 +import java.util.HashSet;
5 +import java.util.List;
6 +import java.util.Set;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Reference;
12 +import org.apache.felix.scr.annotations.ReferenceCardinality;
13 +import org.onlab.onos.net.ConnectPoint;
14 +import org.onlab.onos.net.Link;
15 +import org.onlab.onos.net.Path;
16 +import org.onlab.onos.net.intent.IdGenerator;
17 +import org.onlab.onos.net.intent.Intent;
18 +import org.onlab.onos.net.intent.IntentCompiler;
19 +import org.onlab.onos.net.intent.IntentExtensionService;
20 +import org.onlab.onos.net.intent.IntentId;
21 +import org.onlab.onos.net.intent.LinkCollectionIntent;
22 +import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
23 +import org.onlab.onos.net.intent.PointToPointIntent;
24 +import org.onlab.onos.net.topology.PathService;
25 +
26 +/**
27 + * An intent compiler for
28 + * {@link org.onlab.onos.net.intent.MultiPointToSinglePointIntent}.
29 + */
30 +@Component(immediate = true)
31 +public class MultiPointToSinglePointIntentCompiler
32 + implements IntentCompiler<MultiPointToSinglePointIntent> {
33 +
34 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 + protected IntentExtensionService intentManager;
36 +
37 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
38 + protected PathService pathService;
39 +
40 + private IdGenerator<IntentId> intentIdGenerator;
41 +
42 + @Activate
43 + public void activate() {
44 + IdBlockAllocator idBlockAllocator = new DummyIdBlockAllocator();
45 + intentIdGenerator = new IdBlockAllocatorBasedIntentIdGenerator(idBlockAllocator);
46 + intentManager.registerCompiler(MultiPointToSinglePointIntent.class, this);
47 + }
48 +
49 + @Deactivate
50 + public void deactivate() {
51 + intentManager.unregisterCompiler(PointToPointIntent.class);
52 + }
53 +
54 + @Override
55 + public List<Intent> compile(MultiPointToSinglePointIntent intent) {
56 + Set<Link> links = new HashSet<>();
57 +
58 + for (ConnectPoint ingressPoint : intent.ingressPoints()) {
59 + Path path = getPath(ingressPoint, intent.egressPoint());
60 + links.addAll(path.links());
61 + }
62 +
63 + Intent result = new LinkCollectionIntent(intentIdGenerator.getNewId(),
64 + intent.selector(), intent.treatment(),
65 + links);
66 + return Arrays.asList(result);
67 + }
68 +
69 + /**
70 + * Computes a path between two ConnectPoints.
71 + *
72 + * @param one start of the path
73 + * @param two end of the path
74 + * @return Path between the two
75 + * @throws org.onlab.onos.net.intent.impl.PathNotFoundException if a path cannot be found
76 + */
77 + private Path getPath(ConnectPoint one, ConnectPoint two) {
78 + Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
79 + if (paths.isEmpty()) {
80 + throw new PathNotFoundException("No path from " + one + " to " + two);
81 + }
82 + // TODO: let's be more intelligent about this eventually
83 + return paths.iterator().next();
84 + }
85 +}
...@@ -10,14 +10,16 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -10,14 +10,16 @@ import org.onlab.onos.cluster.ClusterService;
10 import org.onlab.onos.cluster.ControllerNode; 10 import org.onlab.onos.cluster.ControllerNode;
11 import org.onlab.onos.cluster.ControllerNode.State; 11 import org.onlab.onos.cluster.ControllerNode.State;
12 import org.onlab.onos.cluster.DefaultControllerNode; 12 import org.onlab.onos.cluster.DefaultControllerNode;
13 -import org.onlab.onos.cluster.MastershipService;
14 -import org.onlab.onos.cluster.MastershipTermService;
15 import org.onlab.onos.cluster.NodeId; 13 import org.onlab.onos.cluster.NodeId;
16 import org.onlab.onos.event.impl.TestEventDispatcher; 14 import org.onlab.onos.event.impl.TestEventDispatcher;
15 +import org.onlab.onos.mastership.MastershipService;
16 +import org.onlab.onos.mastership.MastershipTermService;
17 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
18 import org.onlab.onos.store.trivial.impl.SimpleMastershipStore; 18 import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
19 import org.onlab.packet.IpPrefix; 19 import org.onlab.packet.IpPrefix;
20 20
21 +import com.google.common.collect.Sets;
22 +
21 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNull; 24 import static org.junit.Assert.assertNull;
23 import static org.onlab.onos.net.MastershipRole.*; 25 import static org.onlab.onos.net.MastershipRole.*;
...@@ -143,7 +145,7 @@ public class MastershipManagerTest { ...@@ -143,7 +145,7 @@ public class MastershipManagerTest {
143 145
144 @Override 146 @Override
145 public Set<ControllerNode> getNodes() { 147 public Set<ControllerNode> getNodes() {
146 - return null; 148 + return Sets.newHashSet();
147 } 149 }
148 150
149 @Override 151 @Override
......
...@@ -10,13 +10,13 @@ import org.onlab.onos.cluster.ClusterEventListener; ...@@ -10,13 +10,13 @@ import org.onlab.onos.cluster.ClusterEventListener;
10 import org.onlab.onos.cluster.ClusterService; 10 import org.onlab.onos.cluster.ClusterService;
11 import org.onlab.onos.cluster.ControllerNode; 11 import org.onlab.onos.cluster.ControllerNode;
12 import org.onlab.onos.cluster.DefaultControllerNode; 12 import org.onlab.onos.cluster.DefaultControllerNode;
13 -import org.onlab.onos.cluster.MastershipServiceAdapter;
14 -import org.onlab.onos.cluster.MastershipTerm;
15 -import org.onlab.onos.cluster.MastershipTermService;
16 import org.onlab.onos.cluster.NodeId; 13 import org.onlab.onos.cluster.NodeId;
17 import org.onlab.onos.cluster.ControllerNode.State; 14 import org.onlab.onos.cluster.ControllerNode.State;
18 import org.onlab.onos.event.Event; 15 import org.onlab.onos.event.Event;
19 import org.onlab.onos.event.impl.TestEventDispatcher; 16 import org.onlab.onos.event.impl.TestEventDispatcher;
17 +import org.onlab.onos.mastership.MastershipServiceAdapter;
18 +import org.onlab.onos.mastership.MastershipTerm;
19 +import org.onlab.onos.mastership.MastershipTermService;
20 import org.onlab.onos.net.Device; 20 import org.onlab.onos.net.Device;
21 import org.onlab.onos.net.DeviceId; 21 import org.onlab.onos.net.DeviceId;
22 import org.onlab.onos.net.MastershipRole; 22 import org.onlab.onos.net.MastershipRole;
...@@ -25,6 +25,7 @@ import org.onlab.onos.net.PortNumber; ...@@ -25,6 +25,7 @@ import org.onlab.onos.net.PortNumber;
25 import org.onlab.onos.net.device.DefaultDeviceDescription; 25 import org.onlab.onos.net.device.DefaultDeviceDescription;
26 import org.onlab.onos.net.device.DefaultPortDescription; 26 import org.onlab.onos.net.device.DefaultPortDescription;
27 import org.onlab.onos.net.device.DeviceAdminService; 27 import org.onlab.onos.net.device.DeviceAdminService;
28 +import org.onlab.onos.net.device.DeviceClockProviderService;
28 import org.onlab.onos.net.device.DeviceDescription; 29 import org.onlab.onos.net.device.DeviceDescription;
29 import org.onlab.onos.net.device.DeviceEvent; 30 import org.onlab.onos.net.device.DeviceEvent;
30 import org.onlab.onos.net.device.DeviceListener; 31 import org.onlab.onos.net.device.DeviceListener;
...@@ -35,7 +36,6 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -35,7 +36,6 @@ import org.onlab.onos.net.device.DeviceService;
35 import org.onlab.onos.net.device.PortDescription; 36 import org.onlab.onos.net.device.PortDescription;
36 import org.onlab.onos.net.provider.AbstractProvider; 37 import org.onlab.onos.net.provider.AbstractProvider;
37 import org.onlab.onos.net.provider.ProviderId; 38 import org.onlab.onos.net.provider.ProviderId;
38 -import org.onlab.onos.store.ClockProviderService;
39 import org.onlab.onos.store.trivial.impl.SimpleDeviceStore; 39 import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
40 import org.onlab.packet.IpPrefix; 40 import org.onlab.packet.IpPrefix;
41 41
...@@ -88,7 +88,7 @@ public class DeviceManagerTest { ...@@ -88,7 +88,7 @@ public class DeviceManagerTest {
88 mgr.eventDispatcher = new TestEventDispatcher(); 88 mgr.eventDispatcher = new TestEventDispatcher();
89 mgr.mastershipService = new TestMastershipService(); 89 mgr.mastershipService = new TestMastershipService();
90 mgr.clusterService = new TestClusterService(); 90 mgr.clusterService = new TestClusterService();
91 - mgr.clockProviderService = new TestClockProviderService(); 91 + mgr.deviceClockProviderService = new TestClockProviderService();
92 mgr.activate(); 92 mgr.activate();
93 93
94 service.addListener(listener); 94 service.addListener(listener);
...@@ -336,7 +336,7 @@ public class DeviceManagerTest { ...@@ -336,7 +336,7 @@ public class DeviceManagerTest {
336 } 336 }
337 337
338 private final class TestClockProviderService implements 338 private final class TestClockProviderService implements
339 - ClockProviderService { 339 + DeviceClockProviderService {
340 340
341 @Override 341 @Override
342 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 342 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
......
1 +package org.onlab.onos.net.intent;
2 +
3 +import java.util.ArrayList;
4 +import java.util.HashSet;
5 +import java.util.List;
6 +import java.util.Set;
7 +
8 +import org.junit.Test;
9 +import org.onlab.onos.net.Link;
10 +import org.onlab.onos.net.flow.TrafficSelector;
11 +import org.onlab.onos.net.flow.TrafficTreatment;
12 +import org.onlab.onos.net.flow.criteria.Criterion;
13 +import org.onlab.onos.net.flow.instructions.Instruction;
14 +
15 +import static org.hamcrest.MatcherAssert.assertThat;
16 +import static org.hamcrest.Matchers.is;
17 +
18 +public class TestLinkCollectionIntent {
19 +
20 + private static class MockSelector implements TrafficSelector {
21 + @Override
22 + public Set<Criterion> criteria() {
23 + return new HashSet<Criterion>();
24 + }
25 + }
26 +
27 + private static class MockTreatment implements TrafficTreatment {
28 + @Override
29 + public List<Instruction> instructions() {
30 + return new ArrayList<>();
31 + }
32 + }
33 +
34 + @Test
35 + public void testComparison() {
36 + TrafficSelector selector = new MockSelector();
37 + TrafficTreatment treatment = new MockTreatment();
38 + Set<Link> links = new HashSet<>();
39 + LinkCollectionIntent i1 = new LinkCollectionIntent(new IntentId(12),
40 + selector, treatment, links);
41 + LinkCollectionIntent i2 = new LinkCollectionIntent(new IntentId(12),
42 + selector, treatment, links);
43 +
44 + assertThat(i1.equals(i2), is(true));
45 + }
46 +
47 +}
...@@ -62,6 +62,11 @@ ...@@ -62,6 +62,11 @@
62 <groupId>org.apache.commons</groupId> 62 <groupId>org.apache.commons</groupId>
63 <artifactId>commons-lang3</artifactId> 63 <artifactId>commons-lang3</artifactId>
64 </dependency> 64 </dependency>
65 + <dependency>
66 + <groupId>org.easymock</groupId>
67 + <artifactId>easymock</artifactId>
68 + <scope>test</scope>
69 + </dependency>
65 </dependencies> 70 </dependencies>
66 71
67 <build> 72 <build>
......
1 package org.onlab.onos.store.cluster.messaging; 1 package org.onlab.onos.store.cluster.messaging;
2 2
3 +// FIXME: not used any more? remove
3 /** 4 /**
4 * Service for encoding &amp; decoding intra-cluster message payload. 5 * Service for encoding &amp; decoding intra-cluster message payload.
5 */ 6 */
......
...@@ -11,6 +11,7 @@ import org.onlab.util.KryoPool; ...@@ -11,6 +11,7 @@ import org.onlab.util.KryoPool;
11 import org.slf4j.Logger; 11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory; 12 import org.slf4j.LoggerFactory;
13 13
14 +//FIXME: not used any more? remove
14 /** 15 /**
15 * Factory for parsing messages sent between cluster members. 16 * Factory for parsing messages sent between cluster members.
16 */ 17 */
......
...@@ -10,7 +10,8 @@ import com.google.common.base.MoreObjects; ...@@ -10,7 +10,8 @@ import com.google.common.base.MoreObjects;
10 10
11 /** 11 /**
12 * Wrapper class to store Timestamped value. 12 * Wrapper class to store Timestamped value.
13 - * @param <T> 13 + *
14 + * @param <T> Timestamped value type
14 */ 15 */
15 public final class Timestamped<T> { 16 public final class Timestamped<T> {
16 17
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import static com.google.common.base.Preconditions.checkNotNull; 3 import static com.google.common.base.Preconditions.checkNotNull;
4 4
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import static com.google.common.base.Preconditions.checkNotNull; 3 import static com.google.common.base.Preconditions.checkNotNull;
4 4
......
...@@ -10,12 +10,12 @@ import org.apache.felix.scr.annotations.Activate; ...@@ -10,12 +10,12 @@ import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
11 import org.apache.felix.scr.annotations.Deactivate; 11 import org.apache.felix.scr.annotations.Deactivate;
12 import org.apache.felix.scr.annotations.Service; 12 import org.apache.felix.scr.annotations.Service;
13 -import org.onlab.onos.cluster.MastershipTerm; 13 +import org.onlab.onos.mastership.MastershipTerm;
14 import org.onlab.onos.net.DeviceId; 14 import org.onlab.onos.net.DeviceId;
15 -import org.onlab.onos.store.ClockProviderService; 15 +import org.onlab.onos.net.device.DeviceClockProviderService;
16 -import org.onlab.onos.store.ClockService; 16 +import org.onlab.onos.net.device.DeviceClockService;
17 import org.onlab.onos.store.Timestamp; 17 import org.onlab.onos.store.Timestamp;
18 -import org.onlab.onos.store.common.impl.MastershipBasedTimestamp; 18 +import org.onlab.onos.store.impl.MastershipBasedTimestamp;
19 import org.slf4j.Logger; 19 import org.slf4j.Logger;
20 20
21 /** 21 /**
...@@ -23,7 +23,7 @@ import org.slf4j.Logger; ...@@ -23,7 +23,7 @@ import org.slf4j.Logger;
23 */ 23 */
24 @Component(immediate = true) 24 @Component(immediate = true)
25 @Service 25 @Service
26 -public class DeviceClockManager implements ClockService, ClockProviderService { 26 +public class DeviceClockManager implements DeviceClockService, DeviceClockProviderService {
27 27
28 private final Logger log = getLogger(getClass()); 28 private final Logger log = getLogger(getClass());
29 29
......
...@@ -58,7 +58,7 @@ class DeviceDescriptions { ...@@ -58,7 +58,7 @@ class DeviceDescriptions {
58 * 58 *
59 * @param newDesc new DeviceDescription 59 * @param newDesc new DeviceDescription
60 */ 60 */
61 - public synchronized void putDeviceDesc(Timestamped<DeviceDescription> newDesc) { 61 + public void putDeviceDesc(Timestamped<DeviceDescription> newDesc) {
62 Timestamped<DeviceDescription> oldOne = deviceDesc; 62 Timestamped<DeviceDescription> oldOne = deviceDesc;
63 Timestamped<DeviceDescription> newOne = newDesc; 63 Timestamped<DeviceDescription> newOne = newDesc;
64 if (oldOne != null) { 64 if (oldOne != null) {
...@@ -76,7 +76,7 @@ class DeviceDescriptions { ...@@ -76,7 +76,7 @@ class DeviceDescriptions {
76 * 76 *
77 * @param newDesc new PortDescription 77 * @param newDesc new PortDescription
78 */ 78 */
79 - public synchronized void putPortDesc(Timestamped<PortDescription> newDesc) { 79 + public void putPortDesc(Timestamped<PortDescription> newDesc) {
80 Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber()); 80 Timestamped<PortDescription> oldOne = portDescs.get(newDesc.value().portNumber());
81 Timestamped<PortDescription> newOne = newDesc; 81 Timestamped<PortDescription> newOne = newDesc;
82 if (oldOne != null) { 82 if (oldOne != null) {
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import java.util.Objects; 3 import java.util.Objects;
4 4
......
1 package org.onlab.onos.store.device.impl; 1 package org.onlab.onos.store.device.impl;
2 2
3 +import com.google.common.base.Function;
3 import com.google.common.collect.FluentIterable; 4 import com.google.common.collect.FluentIterable;
4 import com.google.common.collect.ImmutableList; 5 import com.google.common.collect.ImmutableList;
5 import com.google.common.collect.Maps; 6 import com.google.common.collect.Maps;
...@@ -24,6 +25,7 @@ import org.onlab.onos.net.Device.Type; ...@@ -24,6 +25,7 @@ import org.onlab.onos.net.Device.Type;
24 import org.onlab.onos.net.DeviceId; 25 import org.onlab.onos.net.DeviceId;
25 import org.onlab.onos.net.Port; 26 import org.onlab.onos.net.Port;
26 import org.onlab.onos.net.PortNumber; 27 import org.onlab.onos.net.PortNumber;
28 +import org.onlab.onos.net.device.DeviceClockService;
27 import org.onlab.onos.net.device.DeviceDescription; 29 import org.onlab.onos.net.device.DeviceDescription;
28 import org.onlab.onos.net.device.DeviceEvent; 30 import org.onlab.onos.net.device.DeviceEvent;
29 import org.onlab.onos.net.device.DeviceStore; 31 import org.onlab.onos.net.device.DeviceStore;
...@@ -31,16 +33,12 @@ import org.onlab.onos.net.device.DeviceStoreDelegate; ...@@ -31,16 +33,12 @@ import org.onlab.onos.net.device.DeviceStoreDelegate;
31 import org.onlab.onos.net.device.PortDescription; 33 import org.onlab.onos.net.device.PortDescription;
32 import org.onlab.onos.net.provider.ProviderId; 34 import org.onlab.onos.net.provider.ProviderId;
33 import org.onlab.onos.store.AbstractStore; 35 import org.onlab.onos.store.AbstractStore;
34 -import org.onlab.onos.store.ClockService;
35 import org.onlab.onos.store.Timestamp; 36 import org.onlab.onos.store.Timestamp;
36 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; 37 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
37 import org.onlab.onos.store.cluster.messaging.ClusterMessage; 38 import org.onlab.onos.store.cluster.messaging.ClusterMessage;
38 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; 39 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
39 import org.onlab.onos.store.cluster.messaging.MessageSubject; 40 import org.onlab.onos.store.cluster.messaging.MessageSubject;
40 import org.onlab.onos.store.common.impl.Timestamped; 41 import org.onlab.onos.store.common.impl.Timestamped;
41 -import org.onlab.onos.store.device.impl.peermsg.DeviceAntiEntropyAdvertisement;
42 -import org.onlab.onos.store.device.impl.peermsg.DeviceFragmentId;
43 -import org.onlab.onos.store.device.impl.peermsg.PortFragmentId;
44 import org.onlab.onos.store.serializers.KryoSerializer; 42 import org.onlab.onos.store.serializers.KryoSerializer;
45 import org.onlab.onos.store.serializers.DistributedStoreSerializers; 43 import org.onlab.onos.store.serializers.DistributedStoreSerializers;
46 import org.onlab.util.KryoPool; 44 import org.onlab.util.KryoPool;
...@@ -110,7 +108,7 @@ public class GossipDeviceStore ...@@ -110,7 +108,7 @@ public class GossipDeviceStore
110 private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); 108 private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet();
111 109
112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 - protected ClockService clockService; 111 + protected DeviceClockService deviceClockService;
114 112
115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
116 protected ClusterCommunicationService clusterCommunicator; 114 protected ClusterCommunicationService clusterCommunicator;
...@@ -118,7 +116,7 @@ public class GossipDeviceStore ...@@ -118,7 +116,7 @@ public class GossipDeviceStore
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected ClusterService clusterService; 117 protected ClusterService clusterService;
120 118
121 - private static final KryoSerializer SERIALIZER = new KryoSerializer() { 119 + protected static final KryoSerializer SERIALIZER = new KryoSerializer() {
122 @Override 120 @Override
123 protected void setupKryoPool() { 121 protected void setupKryoPool() {
124 serializerPool = KryoPool.newBuilder() 122 serializerPool = KryoPool.newBuilder()
...@@ -206,14 +204,19 @@ public class GossipDeviceStore ...@@ -206,14 +204,19 @@ public class GossipDeviceStore
206 public synchronized DeviceEvent createOrUpdateDevice(ProviderId providerId, 204 public synchronized DeviceEvent createOrUpdateDevice(ProviderId providerId,
207 DeviceId deviceId, 205 DeviceId deviceId,
208 DeviceDescription deviceDescription) { 206 DeviceDescription deviceDescription) {
209 - Timestamp newTimestamp = clockService.getTimestamp(deviceId); 207 + final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
210 final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp); 208 final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp);
211 - DeviceEvent event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc); 209 + final DeviceEvent event;
210 + final Timestamped<DeviceDescription> mergedDesc;
211 + synchronized (getDeviceDescriptions(deviceId)) {
212 + event = createOrUpdateDeviceInternal(providerId, deviceId, deltaDesc);
213 + mergedDesc = getDeviceDescriptions(deviceId).get(providerId).getDeviceDesc();
214 + }
212 if (event != null) { 215 if (event != null) {
213 log.info("Notifying peers of a device update topology event for providerId: {} and deviceId: {}", 216 log.info("Notifying peers of a device update topology event for providerId: {} and deviceId: {}",
214 providerId, deviceId); 217 providerId, deviceId);
215 try { 218 try {
216 - notifyPeers(new InternalDeviceEvent(providerId, deviceId, deltaDesc)); 219 + notifyPeers(new InternalDeviceEvent(providerId, deviceId, mergedDesc));
217 } catch (IOException e) { 220 } catch (IOException e) {
218 log.error("Failed to notify peers of a device update topology event for providerId: " 221 log.error("Failed to notify peers of a device update topology event for providerId: "
219 + providerId + " and deviceId: " + deviceId, e); 222 + providerId + " and deviceId: " + deviceId, e);
...@@ -317,8 +320,8 @@ public class GossipDeviceStore ...@@ -317,8 +320,8 @@ public class GossipDeviceStore
317 320
318 @Override 321 @Override
319 public DeviceEvent markOffline(DeviceId deviceId) { 322 public DeviceEvent markOffline(DeviceId deviceId) {
320 - Timestamp timestamp = clockService.getTimestamp(deviceId); 323 + final Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
321 - DeviceEvent event = markOfflineInternal(deviceId, timestamp); 324 + final DeviceEvent event = markOfflineInternal(deviceId, timestamp);
322 if (event != null) { 325 if (event != null) {
323 log.info("Notifying peers of a device offline topology event for deviceId: {}", 326 log.info("Notifying peers of a device offline topology event for deviceId: {}",
324 deviceId); 327 deviceId);
...@@ -390,17 +393,33 @@ public class GossipDeviceStore ...@@ -390,17 +393,33 @@ public class GossipDeviceStore
390 public synchronized List<DeviceEvent> updatePorts(ProviderId providerId, 393 public synchronized List<DeviceEvent> updatePorts(ProviderId providerId,
391 DeviceId deviceId, 394 DeviceId deviceId,
392 List<PortDescription> portDescriptions) { 395 List<PortDescription> portDescriptions) {
393 - Timestamp newTimestamp = clockService.getTimestamp(deviceId);
394 396
395 - Timestamped<List<PortDescription>> timestampedPortDescriptions = 397 + final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
396 - new Timestamped<>(portDescriptions, newTimestamp); 398 +
399 + final Timestamped<List<PortDescription>> timestampedInput
400 + = new Timestamped<>(portDescriptions, newTimestamp);
401 + final List<DeviceEvent> events;
402 + final Timestamped<List<PortDescription>> merged;
397 403
398 - List<DeviceEvent> events = updatePortsInternal(providerId, deviceId, timestampedPortDescriptions); 404 + synchronized (getDeviceDescriptions(deviceId)) {
405 + events = updatePortsInternal(providerId, deviceId, timestampedInput);
406 + final DeviceDescriptions descs = getDeviceDescriptions(deviceId).get(providerId);
407 + List<PortDescription> mergedList =
408 + FluentIterable.from(portDescriptions)
409 + .transform(new Function<PortDescription, PortDescription>() {
410 + @Override
411 + public PortDescription apply(PortDescription input) {
412 + // lookup merged port description
413 + return descs.getPortDesc(input.portNumber()).value();
414 + }
415 + }).toList();
416 + merged = new Timestamped<List<PortDescription>>(mergedList, newTimestamp);
417 + }
399 if (!events.isEmpty()) { 418 if (!events.isEmpty()) {
400 log.info("Notifying peers of a port update topology event for providerId: {} and deviceId: {}", 419 log.info("Notifying peers of a port update topology event for providerId: {} and deviceId: {}",
401 providerId, deviceId); 420 providerId, deviceId);
402 try { 421 try {
403 - notifyPeers(new InternalPortEvent(providerId, deviceId, timestampedPortDescriptions)); 422 + notifyPeers(new InternalPortEvent(providerId, deviceId, merged));
404 } catch (IOException e) { 423 } catch (IOException e) {
405 log.error("Failed to notify peers of a port update topology event or providerId: " 424 log.error("Failed to notify peers of a port update topology event or providerId: "
406 + providerId + " and deviceId: " + deviceId, e); 425 + providerId + " and deviceId: " + deviceId, e);
...@@ -527,16 +546,25 @@ public class GossipDeviceStore ...@@ -527,16 +546,25 @@ public class GossipDeviceStore
527 } 546 }
528 547
529 @Override 548 @Override
530 - public synchronized DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId, 549 + public synchronized DeviceEvent updatePortStatus(ProviderId providerId,
550 + DeviceId deviceId,
531 PortDescription portDescription) { 551 PortDescription portDescription) {
532 - Timestamp newTimestamp = clockService.getTimestamp(deviceId); 552 +
533 - final Timestamped<PortDescription> deltaDesc = new Timestamped<>(portDescription, newTimestamp); 553 + final Timestamp newTimestamp = deviceClockService.getTimestamp(deviceId);
534 - DeviceEvent event = updatePortStatusInternal(providerId, deviceId, deltaDesc); 554 + final Timestamped<PortDescription> deltaDesc
555 + = new Timestamped<>(portDescription, newTimestamp);
556 + final DeviceEvent event;
557 + final Timestamped<PortDescription> mergedDesc;
558 + synchronized (getDeviceDescriptions(deviceId)) {
559 + event = updatePortStatusInternal(providerId, deviceId, deltaDesc);
560 + mergedDesc = getDeviceDescriptions(deviceId).get(providerId)
561 + .getPortDesc(portDescription.portNumber());
562 + }
535 if (event != null) { 563 if (event != null) {
536 log.info("Notifying peers of a port status update topology event for providerId: {} and deviceId: {}", 564 log.info("Notifying peers of a port status update topology event for providerId: {} and deviceId: {}",
537 providerId, deviceId); 565 providerId, deviceId);
538 try { 566 try {
539 - notifyPeers(new InternalPortStatusEvent(providerId, deviceId, deltaDesc)); 567 + notifyPeers(new InternalPortStatusEvent(providerId, deviceId, mergedDesc));
540 } catch (IOException e) { 568 } catch (IOException e) {
541 log.error("Failed to notify peers of a port status update topology event or providerId: " 569 log.error("Failed to notify peers of a port status update topology event or providerId: "
542 + providerId + " and deviceId: " + deviceId, e); 570 + providerId + " and deviceId: " + deviceId, e);
...@@ -615,7 +643,7 @@ public class GossipDeviceStore ...@@ -615,7 +643,7 @@ public class GossipDeviceStore
615 643
616 @Override 644 @Override
617 public synchronized DeviceEvent removeDevice(DeviceId deviceId) { 645 public synchronized DeviceEvent removeDevice(DeviceId deviceId) {
618 - Timestamp timestamp = clockService.getTimestamp(deviceId); 646 + Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
619 DeviceEvent event = removeDeviceInternal(deviceId, timestamp); 647 DeviceEvent event = removeDeviceInternal(deviceId, timestamp);
620 if (event != null) { 648 if (event != null) {
621 log.info("Notifying peers of a device removed topology event for deviceId: {}", 649 log.info("Notifying peers of a device removed topology event for deviceId: {}",
...@@ -684,7 +712,7 @@ public class GossipDeviceStore ...@@ -684,7 +712,7 @@ public class GossipDeviceStore
684 * @return Device instance 712 * @return Device instance
685 */ 713 */
686 private Device composeDevice(DeviceId deviceId, 714 private Device composeDevice(DeviceId deviceId,
687 - ConcurrentMap<ProviderId, DeviceDescriptions> providerDescs) { 715 + Map<ProviderId, DeviceDescriptions> providerDescs) {
688 716
689 checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied"); 717 checkArgument(!providerDescs.isEmpty(), "No Device descriptions supplied");
690 718
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import java.util.Objects; 3 import java.util.Objects;
4 4
......
1 -package org.onlab.onos.store.common.impl; 1 +package org.onlab.onos.store.impl;
2 2
3 import static com.google.common.base.Preconditions.checkArgument; 3 import static com.google.common.base.Preconditions.checkArgument;
4 4
......
...@@ -29,6 +29,7 @@ import org.onlab.onos.net.SparseAnnotations; ...@@ -29,6 +29,7 @@ import org.onlab.onos.net.SparseAnnotations;
29 import org.onlab.onos.net.Link.Type; 29 import org.onlab.onos.net.Link.Type;
30 import org.onlab.onos.net.LinkKey; 30 import org.onlab.onos.net.LinkKey;
31 import org.onlab.onos.net.Provided; 31 import org.onlab.onos.net.Provided;
32 +import org.onlab.onos.net.device.DeviceClockService;
32 import org.onlab.onos.net.link.DefaultLinkDescription; 33 import org.onlab.onos.net.link.DefaultLinkDescription;
33 import org.onlab.onos.net.link.LinkDescription; 34 import org.onlab.onos.net.link.LinkDescription;
34 import org.onlab.onos.net.link.LinkEvent; 35 import org.onlab.onos.net.link.LinkEvent;
...@@ -36,7 +37,6 @@ import org.onlab.onos.net.link.LinkStore; ...@@ -36,7 +37,6 @@ import org.onlab.onos.net.link.LinkStore;
36 import org.onlab.onos.net.link.LinkStoreDelegate; 37 import org.onlab.onos.net.link.LinkStoreDelegate;
37 import org.onlab.onos.net.provider.ProviderId; 38 import org.onlab.onos.net.provider.ProviderId;
38 import org.onlab.onos.store.AbstractStore; 39 import org.onlab.onos.store.AbstractStore;
39 -import org.onlab.onos.store.ClockService;
40 import org.onlab.onos.store.Timestamp; 40 import org.onlab.onos.store.Timestamp;
41 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; 41 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
42 import org.onlab.onos.store.cluster.messaging.ClusterMessage; 42 import org.onlab.onos.store.cluster.messaging.ClusterMessage;
...@@ -100,7 +100,7 @@ public class GossipLinkStore ...@@ -100,7 +100,7 @@ public class GossipLinkStore
100 private final Map<LinkKey, Timestamp> removedLinks = Maps.newHashMap(); 100 private final Map<LinkKey, Timestamp> removedLinks = Maps.newHashMap();
101 101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 - protected ClockService clockService; 103 + protected DeviceClockService deviceClockService;
104 104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected ClusterCommunicationService clusterCommunicator; 106 protected ClusterCommunicationService clusterCommunicator;
...@@ -223,7 +223,7 @@ public class GossipLinkStore ...@@ -223,7 +223,7 @@ public class GossipLinkStore
223 LinkDescription linkDescription) { 223 LinkDescription linkDescription) {
224 224
225 DeviceId dstDeviceId = linkDescription.dst().deviceId(); 225 DeviceId dstDeviceId = linkDescription.dst().deviceId();
226 - Timestamp newTimestamp = clockService.getTimestamp(dstDeviceId); 226 + Timestamp newTimestamp = deviceClockService.getTimestamp(dstDeviceId);
227 227
228 final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp); 228 final Timestamped<LinkDescription> deltaDesc = new Timestamped<>(linkDescription, newTimestamp);
229 229
...@@ -344,7 +344,7 @@ public class GossipLinkStore ...@@ -344,7 +344,7 @@ public class GossipLinkStore
344 final LinkKey key = new LinkKey(src, dst); 344 final LinkKey key = new LinkKey(src, dst);
345 345
346 DeviceId dstDeviceId = dst.deviceId(); 346 DeviceId dstDeviceId = dst.deviceId();
347 - Timestamp timestamp = clockService.getTimestamp(dstDeviceId); 347 + Timestamp timestamp = deviceClockService.getTimestamp(dstDeviceId);
348 348
349 LinkEvent event = removeLinkInternal(key, timestamp); 349 LinkEvent event = removeLinkInternal(key, timestamp);
350 350
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import org.onlab.onos.store.common.impl.MastershipBasedTimestamp;
4 import org.onlab.onos.store.common.impl.Timestamped; 3 import org.onlab.onos.store.common.impl.Timestamped;
4 +import org.onlab.onos.store.impl.MastershipBasedTimestamp;
5 import org.onlab.util.KryoPool; 5 import org.onlab.util.KryoPool;
6 6
7 public final class DistributedStoreSerializers { 7 public final class DistributedStoreSerializers {
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import org.onlab.onos.store.common.impl.MastershipBasedTimestamp; 3 +import org.onlab.onos.store.impl.MastershipBasedTimestamp;
4 4
5 import com.esotericsoftware.kryo.Kryo; 5 import com.esotericsoftware.kryo.Kryo;
6 import com.esotericsoftware.kryo.Serializer; 6 import com.esotericsoftware.kryo.Serializer;
......
1 -package org.onlab.onos.store.cluster.impl; 1 +package org.onlab.onos.store.cluster.messaging.impl;
2 2
3 import org.junit.After; 3 import org.junit.After;
4 import org.junit.Before; 4 import org.junit.Before;
...@@ -6,8 +6,7 @@ import org.junit.Ignore; ...@@ -6,8 +6,7 @@ import org.junit.Ignore;
6 import org.junit.Test; 6 import org.junit.Test;
7 import org.onlab.onos.cluster.DefaultControllerNode; 7 import org.onlab.onos.cluster.DefaultControllerNode;
8 import org.onlab.onos.cluster.NodeId; 8 import org.onlab.onos.cluster.NodeId;
9 -import org.onlab.onos.store.cluster.messaging.impl.ClusterCommunicationManager; 9 +import org.onlab.onos.store.cluster.impl.ClusterNodesDelegate;
10 -import org.onlab.onos.store.cluster.messaging.impl.MessageSerializer;
11 import org.onlab.netty.NettyMessagingService; 10 import org.onlab.netty.NettyMessagingService;
12 import org.onlab.packet.IpPrefix; 11 import org.onlab.packet.IpPrefix;
13 12
......
...@@ -6,6 +6,7 @@ import java.nio.ByteBuffer; ...@@ -6,6 +6,7 @@ import java.nio.ByteBuffer;
6 6
7 import org.junit.Test; 7 import org.junit.Test;
8 import org.onlab.onos.store.Timestamp; 8 import org.onlab.onos.store.Timestamp;
9 +import org.onlab.onos.store.impl.MastershipBasedTimestamp;
9 import org.onlab.util.KryoPool; 10 import org.onlab.util.KryoPool;
10 11
11 import com.google.common.testing.EqualsTester; 12 import com.google.common.testing.EqualsTester;
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import static org.onlab.onos.net.DeviceId.deviceId; 3 import static org.onlab.onos.net.DeviceId.deviceId;
4 4
......
1 package org.onlab.onos.store.device.impl; 1 package org.onlab.onos.store.device.impl;
2 2
3 +import static org.easymock.EasyMock.*;
3 import static org.junit.Assert.*; 4 import static org.junit.Assert.*;
4 import static org.onlab.onos.net.Device.Type.SWITCH; 5 import static org.onlab.onos.net.Device.Type.SWITCH;
5 import static org.onlab.onos.net.DeviceId.deviceId; 6 import static org.onlab.onos.net.DeviceId.deviceId;
6 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 7 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
8 +import static org.onlab.onos.cluster.ControllerNode.State.*;
9 +import static org.onlab.onos.net.DefaultAnnotations.union;
10 +import static java.util.Arrays.asList;
7 11
8 import java.io.IOException; 12 import java.io.IOException;
9 import java.util.Arrays; 13 import java.util.Arrays;
14 +import java.util.Collections;
10 import java.util.HashMap; 15 import java.util.HashMap;
11 import java.util.List; 16 import java.util.List;
12 import java.util.Map; 17 import java.util.Map;
...@@ -14,6 +19,7 @@ import java.util.Set; ...@@ -14,6 +19,7 @@ import java.util.Set;
14 import java.util.concurrent.CountDownLatch; 19 import java.util.concurrent.CountDownLatch;
15 import java.util.concurrent.TimeUnit; 20 import java.util.concurrent.TimeUnit;
16 21
22 +import org.easymock.Capture;
17 import org.junit.After; 23 import org.junit.After;
18 import org.junit.AfterClass; 24 import org.junit.AfterClass;
19 import org.junit.Before; 25 import org.junit.Before;
...@@ -25,8 +31,8 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -25,8 +31,8 @@ import org.onlab.onos.cluster.ClusterService;
25 import org.onlab.onos.cluster.ControllerNode; 31 import org.onlab.onos.cluster.ControllerNode;
26 import org.onlab.onos.cluster.ControllerNode.State; 32 import org.onlab.onos.cluster.ControllerNode.State;
27 import org.onlab.onos.cluster.DefaultControllerNode; 33 import org.onlab.onos.cluster.DefaultControllerNode;
28 -import org.onlab.onos.cluster.MastershipTerm;
29 import org.onlab.onos.cluster.NodeId; 34 import org.onlab.onos.cluster.NodeId;
35 +import org.onlab.onos.mastership.MastershipTerm;
30 import org.onlab.onos.net.Annotations; 36 import org.onlab.onos.net.Annotations;
31 import org.onlab.onos.net.DefaultAnnotations; 37 import org.onlab.onos.net.DefaultAnnotations;
32 import org.onlab.onos.net.Device; 38 import org.onlab.onos.net.Device;
...@@ -36,13 +42,13 @@ import org.onlab.onos.net.PortNumber; ...@@ -36,13 +42,13 @@ import org.onlab.onos.net.PortNumber;
36 import org.onlab.onos.net.SparseAnnotations; 42 import org.onlab.onos.net.SparseAnnotations;
37 import org.onlab.onos.net.device.DefaultDeviceDescription; 43 import org.onlab.onos.net.device.DefaultDeviceDescription;
38 import org.onlab.onos.net.device.DefaultPortDescription; 44 import org.onlab.onos.net.device.DefaultPortDescription;
45 +import org.onlab.onos.net.device.DeviceClockService;
39 import org.onlab.onos.net.device.DeviceDescription; 46 import org.onlab.onos.net.device.DeviceDescription;
40 import org.onlab.onos.net.device.DeviceEvent; 47 import org.onlab.onos.net.device.DeviceEvent;
41 import org.onlab.onos.net.device.DeviceStore; 48 import org.onlab.onos.net.device.DeviceStore;
42 import org.onlab.onos.net.device.DeviceStoreDelegate; 49 import org.onlab.onos.net.device.DeviceStoreDelegate;
43 import org.onlab.onos.net.device.PortDescription; 50 import org.onlab.onos.net.device.PortDescription;
44 import org.onlab.onos.net.provider.ProviderId; 51 import org.onlab.onos.net.provider.ProviderId;
45 -import org.onlab.onos.store.ClockService;
46 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService; 52 import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
47 import org.onlab.onos.store.cluster.messaging.ClusterMessage; 53 import org.onlab.onos.store.cluster.messaging.ClusterMessage;
48 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler; 54 import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
...@@ -90,14 +96,25 @@ public class GossipDeviceStoreTest { ...@@ -90,14 +96,25 @@ public class GossipDeviceStoreTest {
90 .set("B4", "b4") 96 .set("B4", "b4")
91 .build(); 97 .build();
92 98
93 - private static final NodeId MYSELF = new NodeId("myself"); 99 + // local node
100 + private static final NodeId NID1 = new NodeId("local");
101 + private static final ControllerNode ONOS1 =
102 + new DefaultControllerNode(NID1, IpPrefix.valueOf("127.0.0.1"));
103 +
104 + // remote node
105 + private static final NodeId NID2 = new NodeId("remote");
106 + private static final ControllerNode ONOS2 =
107 + new DefaultControllerNode(NID2, IpPrefix.valueOf("127.0.0.2"));
108 + private static final List<SparseAnnotations> NO_ANNOTATION = Collections.<SparseAnnotations>emptyList();
94 109
110 +
111 + private TestGossipDeviceStore testGossipDeviceStore;
95 private GossipDeviceStore gossipDeviceStore; 112 private GossipDeviceStore gossipDeviceStore;
96 private DeviceStore deviceStore; 113 private DeviceStore deviceStore;
97 114
98 private DeviceClockManager deviceClockManager; 115 private DeviceClockManager deviceClockManager;
99 - private ClockService clockService; 116 + private DeviceClockService deviceClockService;
100 - 117 + private ClusterCommunicationService clusterCommunicator;
101 @BeforeClass 118 @BeforeClass
102 public static void setUpBeforeClass() throws Exception { 119 public static void setUpBeforeClass() throws Exception {
103 } 120 }
...@@ -111,17 +128,24 @@ public class GossipDeviceStoreTest { ...@@ -111,17 +128,24 @@ public class GossipDeviceStoreTest {
111 public void setUp() throws Exception { 128 public void setUp() throws Exception {
112 deviceClockManager = new DeviceClockManager(); 129 deviceClockManager = new DeviceClockManager();
113 deviceClockManager.activate(); 130 deviceClockManager.activate();
114 - clockService = deviceClockManager; 131 + deviceClockService = deviceClockManager;
115 132
116 - deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(MYSELF, 1)); 133 + deviceClockManager.setMastershipTerm(DID1, MastershipTerm.of(NID1, 1));
117 - deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(MYSELF, 2)); 134 + deviceClockManager.setMastershipTerm(DID2, MastershipTerm.of(NID1, 2));
118 135
119 - ClusterCommunicationService clusterCommunicator = new TestClusterCommunicationService(); 136 + clusterCommunicator = createNiceMock(ClusterCommunicationService.class);
137 + clusterCommunicator.addSubscriber(anyObject(MessageSubject.class),
138 + anyObject(ClusterMessageHandler.class));
139 + expectLastCall().anyTimes();
140 + replay(clusterCommunicator);
120 ClusterService clusterService = new TestClusterService(); 141 ClusterService clusterService = new TestClusterService();
121 142
122 - gossipDeviceStore = new TestGossipDeviceStore(clockService, clusterService, clusterCommunicator); 143 + testGossipDeviceStore = new TestGossipDeviceStore(deviceClockService, clusterService, clusterCommunicator);
144 + gossipDeviceStore = testGossipDeviceStore;
123 gossipDeviceStore.activate(); 145 gossipDeviceStore.activate();
124 deviceStore = gossipDeviceStore; 146 deviceStore = gossipDeviceStore;
147 + verify(clusterCommunicator);
148 + reset(clusterCommunicator);
125 } 149 }
126 150
127 @After 151 @After
...@@ -135,7 +159,16 @@ public class GossipDeviceStoreTest { ...@@ -135,7 +159,16 @@ public class GossipDeviceStoreTest {
135 DeviceDescription description = 159 DeviceDescription description =
136 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR, 160 new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
137 HW, swVersion, SN, annotations); 161 HW, swVersion, SN, annotations);
162 + reset(clusterCommunicator);
163 + try {
164 + expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class)))
165 + .andReturn(true).anyTimes();
166 + } catch (IOException e) {
167 + fail("Should never reach here");
168 + }
169 + replay(clusterCommunicator);
138 deviceStore.createOrUpdateDevice(PID, deviceId, description); 170 deviceStore.createOrUpdateDevice(PID, deviceId, description);
171 + verify(clusterCommunicator);
139 } 172 }
140 173
141 private void putDeviceAncillary(DeviceId deviceId, String swVersion, 174 private void putDeviceAncillary(DeviceId deviceId, String swVersion,
...@@ -163,9 +196,9 @@ public class GossipDeviceStoreTest { ...@@ -163,9 +196,9 @@ public class GossipDeviceStoreTest {
163 * @param annotations 196 * @param annotations
164 */ 197 */
165 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) { 198 private static void assertAnnotationsEquals(Annotations actual, SparseAnnotations... annotations) {
166 - DefaultAnnotations expected = DefaultAnnotations.builder().build(); 199 + SparseAnnotations expected = DefaultAnnotations.builder().build();
167 for (SparseAnnotations a : annotations) { 200 for (SparseAnnotations a : annotations) {
168 - expected = DefaultAnnotations.merge(expected, a); 201 + expected = DefaultAnnotations.union(expected, a);
169 } 202 }
170 assertEquals(expected.keys(), actual.keys()); 203 assertEquals(expected.keys(), actual.keys());
171 for (String key : expected.keys()) { 204 for (String key : expected.keys()) {
...@@ -173,6 +206,36 @@ public class GossipDeviceStoreTest { ...@@ -173,6 +206,36 @@ public class GossipDeviceStoreTest {
173 } 206 }
174 } 207 }
175 208
209 + private static void assertDeviceDescriptionEquals(DeviceDescription expected,
210 + DeviceDescription actual) {
211 + if (expected == actual) {
212 + return;
213 + }
214 + assertEquals(expected.deviceURI(), actual.deviceURI());
215 + assertEquals(expected.hwVersion(), actual.hwVersion());
216 + assertEquals(expected.manufacturer(), actual.manufacturer());
217 + assertEquals(expected.serialNumber(), actual.serialNumber());
218 + assertEquals(expected.swVersion(), actual.swVersion());
219 +
220 + assertAnnotationsEquals(actual.annotations(), expected.annotations());
221 + }
222 +
223 + private static void assertDeviceDescriptionEquals(DeviceDescription expected,
224 + List<SparseAnnotations> expectedAnnotations,
225 + DeviceDescription actual) {
226 + if (expected == actual) {
227 + return;
228 + }
229 + assertEquals(expected.deviceURI(), actual.deviceURI());
230 + assertEquals(expected.hwVersion(), actual.hwVersion());
231 + assertEquals(expected.manufacturer(), actual.manufacturer());
232 + assertEquals(expected.serialNumber(), actual.serialNumber());
233 + assertEquals(expected.swVersion(), actual.swVersion());
234 +
235 + assertAnnotationsEquals(actual.annotations(),
236 + expectedAnnotations.toArray(new SparseAnnotations[0]));
237 + }
238 +
176 @Test 239 @Test
177 public final void testGetDeviceCount() { 240 public final void testGetDeviceCount() {
178 assertEquals("initialy empty", 0, deviceStore.getDeviceCount()); 241 assertEquals("initialy empty", 0, deviceStore.getDeviceCount());
...@@ -215,56 +278,123 @@ public class GossipDeviceStoreTest { ...@@ -215,56 +278,123 @@ public class GossipDeviceStoreTest {
215 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2)); 278 assertNull("DID2 shouldn't be there", deviceStore.getDevice(DID2));
216 } 279 }
217 280
281 + private void assertInternalDeviceEvent(NodeId sender,
282 + DeviceId deviceId,
283 + ProviderId providerId,
284 + DeviceDescription expectedDesc,
285 + Capture<ClusterMessage> actualMsg) {
286 + assertTrue(actualMsg.hasCaptured());
287 + assertEquals(sender, actualMsg.getValue().sender());
288 + assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
289 + actualMsg.getValue().subject());
290 + InternalDeviceEvent addEvent
291 + = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
292 + assertEquals(deviceId, addEvent.deviceId());
293 + assertEquals(providerId, addEvent.providerId());
294 + assertDeviceDescriptionEquals(expectedDesc, addEvent.deviceDescription().value());
295 + }
296 +
297 + private void assertInternalDeviceEvent(NodeId sender,
298 + DeviceId deviceId,
299 + ProviderId providerId,
300 + DeviceDescription expectedDesc,
301 + List<SparseAnnotations> expectedAnnotations,
302 + Capture<ClusterMessage> actualMsg) {
303 + assertTrue(actualMsg.hasCaptured());
304 + assertEquals(sender, actualMsg.getValue().sender());
305 + assertEquals(GossipDeviceStoreMessageSubjects.DEVICE_UPDATE,
306 + actualMsg.getValue().subject());
307 + InternalDeviceEvent addEvent
308 + = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
309 + assertEquals(deviceId, addEvent.deviceId());
310 + assertEquals(providerId, addEvent.providerId());
311 + assertDeviceDescriptionEquals(expectedDesc, expectedAnnotations, addEvent.deviceDescription().value());
312 + }
313 +
218 @Test 314 @Test
219 - public final void testCreateOrUpdateDevice() { 315 + public final void testCreateOrUpdateDevice() throws IOException {
220 DeviceDescription description = 316 DeviceDescription description =
221 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, 317 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
222 HW, SW1, SN); 318 HW, SW1, SN);
319 + Capture<ClusterMessage> bcast = new Capture<>();
320 +
321 + resetCommunicatorExpectingSingleBroadcast(bcast);
223 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description); 322 DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
224 assertEquals(DEVICE_ADDED, event.type()); 323 assertEquals(DEVICE_ADDED, event.type());
225 assertDevice(DID1, SW1, event.subject()); 324 assertDevice(DID1, SW1, event.subject());
325 + verify(clusterCommunicator);
326 + assertInternalDeviceEvent(NID1, DID1, PID, description, bcast);
327 +
226 328
227 DeviceDescription description2 = 329 DeviceDescription description2 =
228 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, 330 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
229 HW, SW2, SN); 331 HW, SW2, SN);
332 + resetCommunicatorExpectingSingleBroadcast(bcast);
230 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2); 333 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
231 assertEquals(DEVICE_UPDATED, event2.type()); 334 assertEquals(DEVICE_UPDATED, event2.type());
232 assertDevice(DID1, SW2, event2.subject()); 335 assertDevice(DID1, SW2, event2.subject());
233 336
337 + verify(clusterCommunicator);
338 + assertInternalDeviceEvent(NID1, DID1, PID, description2, bcast);
339 + reset(clusterCommunicator);
340 +
234 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2)); 341 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
235 } 342 }
236 343
237 @Test 344 @Test
238 - public final void testCreateOrUpdateDeviceAncillary() { 345 + public final void testCreateOrUpdateDeviceAncillary() throws IOException {
346 + // add
239 DeviceDescription description = 347 DeviceDescription description =
240 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, 348 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
241 HW, SW1, SN, A2); 349 HW, SW1, SN, A2);
350 + Capture<ClusterMessage> bcast = new Capture<>();
351 +
352 + resetCommunicatorExpectingSingleBroadcast(bcast);
242 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description); 353 DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
243 assertEquals(DEVICE_ADDED, event.type()); 354 assertEquals(DEVICE_ADDED, event.type());
244 assertDevice(DID1, SW1, event.subject()); 355 assertDevice(DID1, SW1, event.subject());
245 assertEquals(PIDA, event.subject().providerId()); 356 assertEquals(PIDA, event.subject().providerId());
246 assertAnnotationsEquals(event.subject().annotations(), A2); 357 assertAnnotationsEquals(event.subject().annotations(), A2);
247 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1)); 358 assertFalse("Ancillary will not bring device up", deviceStore.isAvailable(DID1));
359 + verify(clusterCommunicator);
360 + assertInternalDeviceEvent(NID1, DID1, PIDA, description, bcast);
248 361
362 + // update from primary
249 DeviceDescription description2 = 363 DeviceDescription description2 =
250 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, 364 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
251 HW, SW2, SN, A1); 365 HW, SW2, SN, A1);
366 + resetCommunicatorExpectingSingleBroadcast(bcast);
367 +
252 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2); 368 DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
253 assertEquals(DEVICE_UPDATED, event2.type()); 369 assertEquals(DEVICE_UPDATED, event2.type());
254 assertDevice(DID1, SW2, event2.subject()); 370 assertDevice(DID1, SW2, event2.subject());
255 assertEquals(PID, event2.subject().providerId()); 371 assertEquals(PID, event2.subject().providerId());
256 assertAnnotationsEquals(event2.subject().annotations(), A1, A2); 372 assertAnnotationsEquals(event2.subject().annotations(), A1, A2);
257 assertTrue(deviceStore.isAvailable(DID1)); 373 assertTrue(deviceStore.isAvailable(DID1));
374 + verify(clusterCommunicator);
375 + assertInternalDeviceEvent(NID1, DID1, PID, description2, bcast);
258 376
377 + // no-op update from primary
378 + resetCommunicatorExpectingNoBroadcast(bcast);
259 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2)); 379 assertNull("No change expected", deviceStore.createOrUpdateDevice(PID, DID1, description2));
260 380
381 + verify(clusterCommunicator);
382 + assertFalse("no broadcast expected", bcast.hasCaptured());
383 +
261 // For now, Ancillary is ignored once primary appears 384 // For now, Ancillary is ignored once primary appears
385 + resetCommunicatorExpectingNoBroadcast(bcast);
386 +
262 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description)); 387 assertNull("No change expected", deviceStore.createOrUpdateDevice(PIDA, DID1, description));
263 388
389 + verify(clusterCommunicator);
390 + assertFalse("no broadcast expected", bcast.hasCaptured());
391 +
264 // But, Ancillary annotations will be in effect 392 // But, Ancillary annotations will be in effect
265 DeviceDescription description3 = 393 DeviceDescription description3 =
266 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR, 394 new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
267 HW, SW1, SN, A2_2); 395 HW, SW1, SN, A2_2);
396 + resetCommunicatorExpectingSingleBroadcast(bcast);
397 +
268 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3); 398 DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
269 assertEquals(DEVICE_UPDATED, event3.type()); 399 assertEquals(DEVICE_UPDATED, event3.type());
270 // basic information will be the one from Primary 400 // basic information will be the one from Primary
...@@ -273,6 +403,11 @@ public class GossipDeviceStoreTest { ...@@ -273,6 +403,11 @@ public class GossipDeviceStoreTest {
273 // but annotation from Ancillary will be merged 403 // but annotation from Ancillary will be merged
274 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2); 404 assertAnnotationsEquals(event3.subject().annotations(), A1, A2, A2_2);
275 assertTrue(deviceStore.isAvailable(DID1)); 405 assertTrue(deviceStore.isAvailable(DID1));
406 + verify(clusterCommunicator);
407 + // note: only annotation from PIDA is sent over the wire
408 + assertInternalDeviceEvent(NID1, DID1, PIDA, description3,
409 + asList(union(A2, A2_2)), bcast);
410 +
276 } 411 }
277 412
278 413
...@@ -282,14 +417,24 @@ public class GossipDeviceStoreTest { ...@@ -282,14 +417,24 @@ public class GossipDeviceStoreTest {
282 putDevice(DID1, SW1); 417 putDevice(DID1, SW1);
283 assertTrue(deviceStore.isAvailable(DID1)); 418 assertTrue(deviceStore.isAvailable(DID1));
284 419
420 + Capture<ClusterMessage> bcast = new Capture<>();
421 +
422 + resetCommunicatorExpectingSingleBroadcast(bcast);
285 DeviceEvent event = deviceStore.markOffline(DID1); 423 DeviceEvent event = deviceStore.markOffline(DID1);
286 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type()); 424 assertEquals(DEVICE_AVAILABILITY_CHANGED, event.type());
287 assertDevice(DID1, SW1, event.subject()); 425 assertDevice(DID1, SW1, event.subject());
288 assertFalse(deviceStore.isAvailable(DID1)); 426 assertFalse(deviceStore.isAvailable(DID1));
427 + verify(clusterCommunicator);
428 + // TODO: verify broadcast message
429 + assertTrue(bcast.hasCaptured());
430 +
289 431
432 + resetCommunicatorExpectingNoBroadcast(bcast);
290 DeviceEvent event2 = deviceStore.markOffline(DID1); 433 DeviceEvent event2 = deviceStore.markOffline(DID1);
291 assertNull("No change, no event", event2); 434 assertNull("No change, no event", event2);
292 -} 435 + verify(clusterCommunicator);
436 + assertFalse(bcast.hasCaptured());
437 + }
293 438
294 @Test 439 @Test
295 public final void testUpdatePorts() { 440 public final void testUpdatePorts() {
...@@ -298,8 +443,13 @@ public class GossipDeviceStoreTest { ...@@ -298,8 +443,13 @@ public class GossipDeviceStoreTest {
298 new DefaultPortDescription(P1, true), 443 new DefaultPortDescription(P1, true),
299 new DefaultPortDescription(P2, true) 444 new DefaultPortDescription(P2, true)
300 ); 445 );
446 + Capture<ClusterMessage> bcast = new Capture<>();
301 447
448 + resetCommunicatorExpectingSingleBroadcast(bcast);
302 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds); 449 List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
450 + verify(clusterCommunicator);
451 + // TODO: verify broadcast message
452 + assertTrue(bcast.hasCaptured());
303 453
304 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 454 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
305 for (DeviceEvent event : events) { 455 for (DeviceEvent event : events) {
...@@ -318,7 +468,12 @@ public class GossipDeviceStoreTest { ...@@ -318,7 +468,12 @@ public class GossipDeviceStoreTest {
318 new DefaultPortDescription(P3, true) 468 new DefaultPortDescription(P3, true)
319 ); 469 );
320 470
471 + resetCommunicatorExpectingSingleBroadcast(bcast);
321 events = deviceStore.updatePorts(PID, DID1, pds2); 472 events = deviceStore.updatePorts(PID, DID1, pds2);
473 + verify(clusterCommunicator);
474 + // TODO: verify broadcast message
475 + assertTrue(bcast.hasCaptured());
476 +
322 assertFalse("event should be triggered", events.isEmpty()); 477 assertFalse("event should be triggered", events.isEmpty());
323 for (DeviceEvent event : events) { 478 for (DeviceEvent event : events) {
324 PortNumber num = event.port().number(); 479 PortNumber num = event.port().number();
...@@ -341,7 +496,12 @@ public class GossipDeviceStoreTest { ...@@ -341,7 +496,12 @@ public class GossipDeviceStoreTest {
341 new DefaultPortDescription(P1, false), 496 new DefaultPortDescription(P1, false),
342 new DefaultPortDescription(P2, true) 497 new DefaultPortDescription(P2, true)
343 ); 498 );
499 + resetCommunicatorExpectingSingleBroadcast(bcast);
344 events = deviceStore.updatePorts(PID, DID1, pds3); 500 events = deviceStore.updatePorts(PID, DID1, pds3);
501 + verify(clusterCommunicator);
502 + // TODO: verify broadcast message
503 + assertTrue(bcast.hasCaptured());
504 +
345 assertFalse("event should be triggered", events.isEmpty()); 505 assertFalse("event should be triggered", events.isEmpty());
346 for (DeviceEvent event : events) { 506 for (DeviceEvent event : events) {
347 PortNumber num = event.port().number(); 507 PortNumber num = event.port().number();
...@@ -357,7 +517,6 @@ public class GossipDeviceStoreTest { ...@@ -357,7 +517,6 @@ public class GossipDeviceStoreTest {
357 fail("Unknown port number encountered: " + num); 517 fail("Unknown port number encountered: " + num);
358 } 518 }
359 } 519 }
360 -
361 } 520 }
362 521
363 @Test 522 @Test
...@@ -368,16 +527,22 @@ public class GossipDeviceStoreTest { ...@@ -368,16 +527,22 @@ public class GossipDeviceStoreTest {
368 ); 527 );
369 deviceStore.updatePorts(PID, DID1, pds); 528 deviceStore.updatePorts(PID, DID1, pds);
370 529
371 - DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, 530 + Capture<ClusterMessage> bcast = new Capture<>();
372 - new DefaultPortDescription(P1, false)); 531 +
532 + resetCommunicatorExpectingSingleBroadcast(bcast);
533 + final DefaultPortDescription desc = new DefaultPortDescription(P1, false);
534 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc);
373 assertEquals(PORT_UPDATED, event.type()); 535 assertEquals(PORT_UPDATED, event.type());
374 assertDevice(DID1, SW1, event.subject()); 536 assertDevice(DID1, SW1, event.subject());
375 assertEquals(P1, event.port().number()); 537 assertEquals(P1, event.port().number());
376 assertFalse("Port is disabled", event.port().isEnabled()); 538 assertFalse("Port is disabled", event.port().isEnabled());
377 - 539 + verify(clusterCommunicator);
540 + assertInternalPortStatusEvent(NID1, DID1, PID, desc, NO_ANNOTATION, bcast);
541 + assertTrue(bcast.hasCaptured());
378 } 542 }
543 +
379 @Test 544 @Test
380 - public final void testUpdatePortStatusAncillary() { 545 + public final void testUpdatePortStatusAncillary() throws IOException {
381 putDeviceAncillary(DID1, SW1); 546 putDeviceAncillary(DID1, SW1);
382 putDevice(DID1, SW1); 547 putDevice(DID1, SW1);
383 List<PortDescription> pds = Arrays.<PortDescription>asList( 548 List<PortDescription> pds = Arrays.<PortDescription>asList(
...@@ -385,36 +550,106 @@ public class GossipDeviceStoreTest { ...@@ -385,36 +550,106 @@ public class GossipDeviceStoreTest {
385 ); 550 );
386 deviceStore.updatePorts(PID, DID1, pds); 551 deviceStore.updatePorts(PID, DID1, pds);
387 552
388 - DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, 553 + Capture<ClusterMessage> bcast = new Capture<>();
389 - new DefaultPortDescription(P1, false, A1_2)); 554 +
555 +
556 + // update port from primary
557 + resetCommunicatorExpectingSingleBroadcast(bcast);
558 + final DefaultPortDescription desc1 = new DefaultPortDescription(P1, false, A1_2);
559 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1, desc1);
390 assertEquals(PORT_UPDATED, event.type()); 560 assertEquals(PORT_UPDATED, event.type());
391 assertDevice(DID1, SW1, event.subject()); 561 assertDevice(DID1, SW1, event.subject());
392 assertEquals(P1, event.port().number()); 562 assertEquals(P1, event.port().number());
393 assertAnnotationsEquals(event.port().annotations(), A1, A1_2); 563 assertAnnotationsEquals(event.port().annotations(), A1, A1_2);
394 assertFalse("Port is disabled", event.port().isEnabled()); 564 assertFalse("Port is disabled", event.port().isEnabled());
395 - 565 + verify(clusterCommunicator);
396 - DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, 566 + assertInternalPortStatusEvent(NID1, DID1, PID, desc1, asList(A1, A1_2), bcast);
397 - new DefaultPortDescription(P1, true)); 567 + assertTrue(bcast.hasCaptured());
568 +
569 + // update port from ancillary with no attributes
570 + resetCommunicatorExpectingNoBroadcast(bcast);
571 + final DefaultPortDescription desc2 = new DefaultPortDescription(P1, true);
572 + DeviceEvent event2 = deviceStore.updatePortStatus(PIDA, DID1, desc2);
398 assertNull("Ancillary is ignored if primary exists", event2); 573 assertNull("Ancillary is ignored if primary exists", event2);
574 + verify(clusterCommunicator);
575 + assertFalse(bcast.hasCaptured());
399 576
400 // but, Ancillary annotation update will be notified 577 // but, Ancillary annotation update will be notified
401 - DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, 578 + resetCommunicatorExpectingSingleBroadcast(bcast);
402 - new DefaultPortDescription(P1, true, A2)); 579 + final DefaultPortDescription desc3 = new DefaultPortDescription(P1, true, A2);
580 + DeviceEvent event3 = deviceStore.updatePortStatus(PIDA, DID1, desc3);
403 assertEquals(PORT_UPDATED, event3.type()); 581 assertEquals(PORT_UPDATED, event3.type());
404 assertDevice(DID1, SW1, event3.subject()); 582 assertDevice(DID1, SW1, event3.subject());
405 assertEquals(P1, event3.port().number()); 583 assertEquals(P1, event3.port().number());
406 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2); 584 assertAnnotationsEquals(event3.port().annotations(), A1, A1_2, A2);
407 assertFalse("Port is disabled", event3.port().isEnabled()); 585 assertFalse("Port is disabled", event3.port().isEnabled());
586 + verify(clusterCommunicator);
587 + assertInternalPortStatusEvent(NID1, DID1, PIDA, desc3, asList(A2), bcast);
588 + assertTrue(bcast.hasCaptured());
408 589
409 // port only reported from Ancillary will be notified as down 590 // port only reported from Ancillary will be notified as down
410 - DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, 591 + resetCommunicatorExpectingSingleBroadcast(bcast);
411 - new DefaultPortDescription(P2, true)); 592 + final DefaultPortDescription desc4 = new DefaultPortDescription(P2, true);
593 + DeviceEvent event4 = deviceStore.updatePortStatus(PIDA, DID1, desc4);
412 assertEquals(PORT_ADDED, event4.type()); 594 assertEquals(PORT_ADDED, event4.type());
413 assertDevice(DID1, SW1, event4.subject()); 595 assertDevice(DID1, SW1, event4.subject());
414 assertEquals(P2, event4.port().number()); 596 assertEquals(P2, event4.port().number());
415 assertAnnotationsEquals(event4.port().annotations()); 597 assertAnnotationsEquals(event4.port().annotations());
416 assertFalse("Port is disabled if not given from primary provider", 598 assertFalse("Port is disabled if not given from primary provider",
417 event4.port().isEnabled()); 599 event4.port().isEnabled());
600 + verify(clusterCommunicator);
601 + // TODO: verify broadcast message content
602 + assertInternalPortStatusEvent(NID1, DID1, PIDA, desc4, NO_ANNOTATION, bcast);
603 + assertTrue(bcast.hasCaptured());
604 + }
605 +
606 + private void assertInternalPortStatusEvent(NodeId sender, DeviceId did,
607 + ProviderId pid, DefaultPortDescription expectedDesc,
608 + List<SparseAnnotations> expectedAnnotations, Capture<ClusterMessage> actualMsg) {
609 +
610 + assertTrue(actualMsg.hasCaptured());
611 + assertEquals(sender, actualMsg.getValue().sender());
612 + assertEquals(GossipDeviceStoreMessageSubjects.PORT_STATUS_UPDATE,
613 + actualMsg.getValue().subject());
614 + InternalPortStatusEvent addEvent
615 + = testGossipDeviceStore.deserialize(actualMsg.getValue().payload());
616 + assertEquals(did, addEvent.deviceId());
617 + assertEquals(pid, addEvent.providerId());
618 + assertPortDescriptionEquals(expectedDesc, expectedAnnotations,
619 + addEvent.portDescription().value());
620 +
621 + }
622 +
623 + private void assertPortDescriptionEquals(
624 + PortDescription expectedDesc,
625 + List<SparseAnnotations> expectedAnnotations,
626 + PortDescription actual) {
627 +
628 + assertEquals(expectedDesc.portNumber(), actual.portNumber());
629 + assertEquals(expectedDesc.isEnabled(), actual.isEnabled());
630 +
631 + assertAnnotationsEquals(actual.annotations(),
632 + expectedAnnotations.toArray(new SparseAnnotations[0]));
633 + }
634 +
635 + private void resetCommunicatorExpectingNoBroadcast(
636 + Capture<ClusterMessage> bcast) {
637 + bcast.reset();
638 + reset(clusterCommunicator);
639 + replay(clusterCommunicator);
640 + }
641 +
642 + private void resetCommunicatorExpectingSingleBroadcast(
643 + Capture<ClusterMessage> bcast) {
644 +
645 + bcast.reset();
646 + reset(clusterCommunicator);
647 + try {
648 + expect(clusterCommunicator.broadcast(capture(bcast))).andReturn(true).once();
649 + } catch (IOException e) {
650 + fail("Should never reach here");
651 + }
652 + replay(clusterCommunicator);
418 } 653 }
419 654
420 @Test 655 @Test
...@@ -476,12 +711,19 @@ public class GossipDeviceStoreTest { ...@@ -476,12 +711,19 @@ public class GossipDeviceStoreTest {
476 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1); 711 assertAnnotationsEquals(deviceStore.getDevice(DID1).annotations(), A1);
477 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2); 712 assertAnnotationsEquals(deviceStore.getPort(DID1, P1).annotations(), A2);
478 713
714 + Capture<ClusterMessage> bcast = new Capture<>();
715 +
716 + resetCommunicatorExpectingSingleBroadcast(bcast);
717 +
479 DeviceEvent event = deviceStore.removeDevice(DID1); 718 DeviceEvent event = deviceStore.removeDevice(DID1);
480 assertEquals(DEVICE_REMOVED, event.type()); 719 assertEquals(DEVICE_REMOVED, event.type());
481 assertDevice(DID1, SW1, event.subject()); 720 assertDevice(DID1, SW1, event.subject());
482 721
483 assertEquals(1, deviceStore.getDeviceCount()); 722 assertEquals(1, deviceStore.getDeviceCount());
484 assertEquals(0, deviceStore.getPorts(DID1).size()); 723 assertEquals(0, deviceStore.getPorts(DID1).size());
724 + verify(clusterCommunicator);
725 + // TODO: verify broadcast message
726 + assertTrue(bcast.hasCaptured());
485 727
486 // putBack Device, Port w/o annotation 728 // putBack Device, Port w/o annotation
487 putDevice(DID1, SW1); 729 putDevice(DID1, SW1);
...@@ -556,41 +798,35 @@ public class GossipDeviceStoreTest { ...@@ -556,41 +798,35 @@ public class GossipDeviceStoreTest {
556 private static final class TestGossipDeviceStore extends GossipDeviceStore { 798 private static final class TestGossipDeviceStore extends GossipDeviceStore {
557 799
558 public TestGossipDeviceStore( 800 public TestGossipDeviceStore(
559 - ClockService clockService, 801 + DeviceClockService deviceClockService,
560 ClusterService clusterService, 802 ClusterService clusterService,
561 ClusterCommunicationService clusterCommunicator) { 803 ClusterCommunicationService clusterCommunicator) {
562 - this.clockService = clockService; 804 + this.deviceClockService = deviceClockService;
563 this.clusterService = clusterService; 805 this.clusterService = clusterService;
564 this.clusterCommunicator = clusterCommunicator; 806 this.clusterCommunicator = clusterCommunicator;
565 } 807 }
566 - }
567 808
568 - private static final class TestClusterCommunicationService implements ClusterCommunicationService { 809 + public <T> T deserialize(byte[] bytes) {
569 - @Override 810 + return SERIALIZER.decode(bytes);
570 - public boolean broadcast(ClusterMessage message) throws IOException { return true; } 811 + }
571 - @Override
572 - public boolean unicast(ClusterMessage message, NodeId nodeId) throws IOException { return true; }
573 - @Override
574 - public boolean multicast(ClusterMessage message, Set<NodeId> nodeIds) throws IOException { return true; }
575 - @Override
576 - public void addSubscriber(MessageSubject subject, ClusterMessageHandler subscriber) {}
577 } 812 }
578 813
579 private static final class TestClusterService implements ClusterService { 814 private static final class TestClusterService implements ClusterService {
580 815
581 - private static final ControllerNode ONOS1 =
582 - new DefaultControllerNode(new NodeId("N1"), IpPrefix.valueOf("127.0.0.1"));
583 private final Map<NodeId, ControllerNode> nodes = new HashMap<>(); 816 private final Map<NodeId, ControllerNode> nodes = new HashMap<>();
584 private final Map<NodeId, ControllerNode.State> nodeStates = new HashMap<>(); 817 private final Map<NodeId, ControllerNode.State> nodeStates = new HashMap<>();
585 818
586 public TestClusterService() { 819 public TestClusterService() {
587 - nodes.put(new NodeId("N1"), ONOS1); 820 + nodes.put(NID1, ONOS1);
588 - nodeStates.put(new NodeId("N1"), ControllerNode.State.ACTIVE); 821 + nodeStates.put(NID1, ACTIVE);
822 +
823 + nodes.put(NID2, ONOS2);
824 + nodeStates.put(NID2, ACTIVE);
589 } 825 }
590 826
591 @Override 827 @Override
592 public ControllerNode getLocalNode() { 828 public ControllerNode getLocalNode() {
593 - return ONOS1; 829 + return GossipDeviceStoreTest.ONOS1;
594 } 830 }
595 831
596 @Override 832 @Override
......
1 -package org.onlab.onos.store.device.impl.peermsg; 1 +package org.onlab.onos.store.device.impl;
2 2
3 import static org.onlab.onos.net.DeviceId.deviceId; 3 import static org.onlab.onos.net.DeviceId.deviceId;
4 4
......
1 -package org.onlab.onos.store.common.impl; 1 +package org.onlab.onos.store.impl;
2 2
3 import static org.junit.Assert.*; 3 import static org.junit.Assert.*;
4 4
......
1 -package org.onlab.onos.store.cluster.impl; 1 +package org.onlab.onos.store.mastership.impl;
2 2
3 -import static org.onlab.onos.cluster.MastershipEvent.Type.MASTER_CHANGED; 3 +import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED;
4 4
5 import java.util.Map; 5 import java.util.Map;
6 import java.util.Set; 6 import java.util.Set;
...@@ -12,11 +12,11 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -12,11 +12,11 @@ import org.apache.felix.scr.annotations.Reference;
12 import org.apache.felix.scr.annotations.ReferenceCardinality; 12 import org.apache.felix.scr.annotations.ReferenceCardinality;
13 import org.apache.felix.scr.annotations.Service; 13 import org.apache.felix.scr.annotations.Service;
14 import org.onlab.onos.cluster.ClusterService; 14 import org.onlab.onos.cluster.ClusterService;
15 -import org.onlab.onos.cluster.MastershipEvent;
16 -import org.onlab.onos.cluster.MastershipStore;
17 -import org.onlab.onos.cluster.MastershipStoreDelegate;
18 -import org.onlab.onos.cluster.MastershipTerm;
19 import org.onlab.onos.cluster.NodeId; 15 import org.onlab.onos.cluster.NodeId;
16 +import org.onlab.onos.mastership.MastershipEvent;
17 +import org.onlab.onos.mastership.MastershipStore;
18 +import org.onlab.onos.mastership.MastershipStoreDelegate;
19 +import org.onlab.onos.mastership.MastershipTerm;
20 import org.onlab.onos.net.DeviceId; 20 import org.onlab.onos.net.DeviceId;
21 import org.onlab.onos.net.MastershipRole; 21 import org.onlab.onos.net.MastershipRole;
22 import org.onlab.onos.store.common.AbstractHazelcastStore; 22 import org.onlab.onos.store.common.AbstractHazelcastStore;
......
1 /** 1 /**
2 - * Structure and utilities used for inter-Node messaging. 2 + * Implementation of a distributed mastership store using Hazelcast.
3 */ 3 */
4 -package org.onlab.onos.store.device.impl.peermsg; 4 +package org.onlab.onos.store.mastership.impl;
......
1 -package org.onlab.onos.store.cluster.impl; 1 +package org.onlab.onos.store.mastership.impl;
2 2
3 import static org.junit.Assert.assertEquals; 3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertNull; 4 import static org.junit.Assert.assertNull;
...@@ -21,11 +21,11 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -21,11 +21,11 @@ import org.onlab.onos.cluster.ClusterService;
21 import org.onlab.onos.cluster.ControllerNode; 21 import org.onlab.onos.cluster.ControllerNode;
22 import org.onlab.onos.cluster.ControllerNode.State; 22 import org.onlab.onos.cluster.ControllerNode.State;
23 import org.onlab.onos.cluster.DefaultControllerNode; 23 import org.onlab.onos.cluster.DefaultControllerNode;
24 -import org.onlab.onos.cluster.MastershipEvent;
25 -import org.onlab.onos.cluster.MastershipEvent.Type;
26 -import org.onlab.onos.cluster.MastershipStoreDelegate;
27 -import org.onlab.onos.cluster.MastershipTerm;
28 import org.onlab.onos.cluster.NodeId; 24 import org.onlab.onos.cluster.NodeId;
25 +import org.onlab.onos.mastership.MastershipEvent;
26 +import org.onlab.onos.mastership.MastershipStoreDelegate;
27 +import org.onlab.onos.mastership.MastershipTerm;
28 +import org.onlab.onos.mastership.MastershipEvent.Type;
29 import org.onlab.onos.net.DeviceId; 29 import org.onlab.onos.net.DeviceId;
30 import org.onlab.onos.store.common.StoreManager; 30 import org.onlab.onos.store.common.StoreManager;
31 import org.onlab.onos.store.common.StoreService; 31 import org.onlab.onos.store.common.StoreService;
......
...@@ -2,17 +2,17 @@ package org.onlab.onos.store.device.impl; ...@@ -2,17 +2,17 @@ package org.onlab.onos.store.device.impl;
2 2
3 import org.apache.felix.scr.annotations.Component; 3 import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
5 -import org.onlab.onos.cluster.MastershipTerm; 5 +import org.onlab.onos.mastership.MastershipTerm;
6 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
7 -import org.onlab.onos.store.ClockProviderService; 7 +import org.onlab.onos.net.device.DeviceClockProviderService;
8 8
9 // FIXME: Code clone in onos-core-trivial, onos-core-hz-net 9 // FIXME: Code clone in onos-core-trivial, onos-core-hz-net
10 /** 10 /**
11 - * Dummy implementation of {@link ClockProviderService}. 11 + * Dummy implementation of {@link DeviceClockProviderService}.
12 */ 12 */
13 @Component(immediate = true) 13 @Component(immediate = true)
14 @Service 14 @Service
15 -public class NoOpClockProviderService implements ClockProviderService { 15 +public class NoOpClockProviderService implements DeviceClockProviderService {
16 16
17 @Override 17 @Override
18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
......
1 -/**
2 - * Implementation of flow store using Hazelcast distributed structures.
3 - */
4 -package org.onlab.onos.store.flow.impl;
1 -/**
2 - * Implementation of host store using Hazelcast distributed structures.
3 - */
4 -package org.onlab.onos.store.host.impl;
1 -/**
2 - * Implementation of link store using Hazelcast distributed structures.
3 - */
4 -package org.onlab.onos.store.link.impl;
1 -/**
2 - * Implementation of topology store using Hazelcast distributed structures.
3 - */
4 -package org.onlab.onos.store.topology.impl;
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.util.KryoPool.FamilySerializer;
4 +
5 +import com.esotericsoftware.kryo.Kryo;
6 +import com.esotericsoftware.kryo.io.Input;
7 +import com.esotericsoftware.kryo.io.Output;
8 +import com.google.common.collect.ImmutableList;
9 +import com.google.common.collect.ImmutableList.Builder;
10 +
11 +/**
12 + * Creates {@link ImmutableList} serializer instance.
13 + */
14 +public class ImmutableListSerializer extends FamilySerializer<ImmutableList<?>> {
15 +
16 + /**
17 + * Creates {@link ImmutableList} serializer instance.
18 + */
19 + public ImmutableListSerializer() {
20 + // non-null, immutable
21 + super(false, true);
22 + }
23 + @Override
24 + public void write(Kryo kryo, Output output, ImmutableList<?> object) {
25 + output.writeInt(object.size());
26 + for (Object e : object) {
27 + kryo.writeClassAndObject(output, e);
28 + }
29 + }
30 +
31 + @Override
32 + public ImmutableList<?> read(Kryo kryo, Input input,
33 + Class<ImmutableList<?>> type) {
34 + final int size = input.readInt();
35 + Builder<Object> builder = ImmutableList.builder();
36 + for (int i = 0; i < size; ++i) {
37 + builder.add(kryo.readClassAndObject(input));
38 + }
39 + return builder.build();
40 + }
41 +
42 + @Override
43 + public void registerFamilies(Kryo kryo) {
44 + kryo.register(ImmutableList.of(1).getClass(), this);
45 + kryo.register(ImmutableList.of(1, 2).getClass(), this);
46 + // TODO register required ImmutableList variants
47 + }
48 +
49 +}
...@@ -7,8 +7,8 @@ import java.util.HashMap; ...@@ -7,8 +7,8 @@ import java.util.HashMap;
7 7
8 import org.onlab.onos.cluster.ControllerNode; 8 import org.onlab.onos.cluster.ControllerNode;
9 import org.onlab.onos.cluster.DefaultControllerNode; 9 import org.onlab.onos.cluster.DefaultControllerNode;
10 -import org.onlab.onos.cluster.MastershipTerm;
11 import org.onlab.onos.cluster.NodeId; 10 import org.onlab.onos.cluster.NodeId;
11 +import org.onlab.onos.mastership.MastershipTerm;
12 import org.onlab.onos.net.ConnectPoint; 12 import org.onlab.onos.net.ConnectPoint;
13 import org.onlab.onos.net.DefaultAnnotations; 13 import org.onlab.onos.net.DefaultAnnotations;
14 import org.onlab.onos.net.DefaultDevice; 14 import org.onlab.onos.net.DefaultDevice;
...@@ -31,6 +31,9 @@ import org.onlab.packet.IpAddress; ...@@ -31,6 +31,9 @@ import org.onlab.packet.IpAddress;
31 import org.onlab.packet.IpPrefix; 31 import org.onlab.packet.IpPrefix;
32 import org.onlab.util.KryoPool; 32 import org.onlab.util.KryoPool;
33 33
34 +import com.google.common.collect.ImmutableList;
35 +import com.google.common.collect.ImmutableMap;
36 +
34 public final class KryoPoolUtil { 37 public final class KryoPoolUtil {
35 38
36 /** 39 /**
...@@ -47,12 +50,15 @@ public final class KryoPoolUtil { ...@@ -47,12 +50,15 @@ public final class KryoPoolUtil {
47 */ 50 */
48 public static final KryoPool API = KryoPool.newBuilder() 51 public static final KryoPool API = KryoPool.newBuilder()
49 .register(MISC) 52 .register(MISC)
53 + .register(ImmutableMap.class, new ImmutableMapSerializer())
54 + .register(ImmutableList.class, new ImmutableListSerializer())
50 .register( 55 .register(
51 // 56 //
52 ArrayList.class, 57 ArrayList.class,
53 Arrays.asList().getClass(), 58 Arrays.asList().getClass(),
54 HashMap.class, 59 HashMap.class,
55 // 60 //
61 + //
56 ControllerNode.State.class, 62 ControllerNode.State.class,
57 Device.Type.class, 63 Device.Type.class,
58 DefaultAnnotations.class, 64 DefaultAnnotations.class,
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import org.onlab.onos.cluster.MastershipTerm;
4 import org.onlab.onos.cluster.NodeId; 3 import org.onlab.onos.cluster.NodeId;
4 +import org.onlab.onos.mastership.MastershipTerm;
5 +
5 import com.esotericsoftware.kryo.Kryo; 6 import com.esotericsoftware.kryo.Kryo;
6 import com.esotericsoftware.kryo.Serializer; 7 import com.esotericsoftware.kryo.Serializer;
7 import com.esotericsoftware.kryo.io.Input; 8 import com.esotericsoftware.kryo.io.Input;
8 import com.esotericsoftware.kryo.io.Output; 9 import com.esotericsoftware.kryo.io.Output;
9 10
10 /** 11 /**
11 - * Kryo Serializer for {@link org.onlab.onos.cluster.MastershipTerm}. 12 + * Kryo Serializer for {@link org.onlab.onos.mastership.MastershipTerm}.
12 */ 13 */
13 public class MastershipTermSerializer extends Serializer<MastershipTerm> { 14 public class MastershipTermSerializer extends Serializer<MastershipTerm> {
14 15
......
...@@ -10,8 +10,8 @@ import org.junit.After; ...@@ -10,8 +10,8 @@ import org.junit.After;
10 import org.junit.Before; 10 import org.junit.Before;
11 import org.junit.BeforeClass; 11 import org.junit.BeforeClass;
12 import org.junit.Test; 12 import org.junit.Test;
13 -import org.onlab.onos.cluster.MastershipTerm;
14 import org.onlab.onos.cluster.NodeId; 13 import org.onlab.onos.cluster.NodeId;
14 +import org.onlab.onos.mastership.MastershipTerm;
15 import org.onlab.onos.net.Annotations; 15 import org.onlab.onos.net.Annotations;
16 import org.onlab.onos.net.ConnectPoint; 16 import org.onlab.onos.net.ConnectPoint;
17 import org.onlab.onos.net.DefaultAnnotations; 17 import org.onlab.onos.net.DefaultAnnotations;
......
...@@ -2,17 +2,17 @@ package org.onlab.onos.store.trivial.impl; ...@@ -2,17 +2,17 @@ package org.onlab.onos.store.trivial.impl;
2 2
3 import org.apache.felix.scr.annotations.Component; 3 import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
5 -import org.onlab.onos.cluster.MastershipTerm; 5 +import org.onlab.onos.mastership.MastershipTerm;
6 import org.onlab.onos.net.DeviceId; 6 import org.onlab.onos.net.DeviceId;
7 -import org.onlab.onos.store.ClockProviderService; 7 +import org.onlab.onos.net.device.DeviceClockProviderService;
8 8
9 //FIXME: Code clone in onos-core-trivial, onos-core-hz-net 9 //FIXME: Code clone in onos-core-trivial, onos-core-hz-net
10 /** 10 /**
11 - * Dummy implementation of {@link ClockProviderService}. 11 + * Dummy implementation of {@link DeviceClockProviderService}.
12 */ 12 */
13 @Component(immediate = true) 13 @Component(immediate = true)
14 @Service 14 @Service
15 -public class NoOpClockProviderService implements ClockProviderService { 15 +public class NoOpClockProviderService implements DeviceClockProviderService {
16 16
17 @Override 17 @Override
18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) { 18 public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
......
...@@ -15,18 +15,18 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -15,18 +15,18 @@ import org.apache.felix.scr.annotations.Deactivate;
15 import org.apache.felix.scr.annotations.Service; 15 import org.apache.felix.scr.annotations.Service;
16 import org.onlab.onos.cluster.ControllerNode; 16 import org.onlab.onos.cluster.ControllerNode;
17 import org.onlab.onos.cluster.DefaultControllerNode; 17 import org.onlab.onos.cluster.DefaultControllerNode;
18 -import org.onlab.onos.cluster.MastershipEvent;
19 -import org.onlab.onos.cluster.MastershipStore;
20 -import org.onlab.onos.cluster.MastershipStoreDelegate;
21 -import org.onlab.onos.cluster.MastershipTerm;
22 import org.onlab.onos.cluster.NodeId; 18 import org.onlab.onos.cluster.NodeId;
19 +import org.onlab.onos.mastership.MastershipEvent;
20 +import org.onlab.onos.mastership.MastershipStore;
21 +import org.onlab.onos.mastership.MastershipStoreDelegate;
22 +import org.onlab.onos.mastership.MastershipTerm;
23 import org.onlab.onos.net.DeviceId; 23 import org.onlab.onos.net.DeviceId;
24 import org.onlab.onos.net.MastershipRole; 24 import org.onlab.onos.net.MastershipRole;
25 import org.onlab.onos.store.AbstractStore; 25 import org.onlab.onos.store.AbstractStore;
26 import org.onlab.packet.IpPrefix; 26 import org.onlab.packet.IpPrefix;
27 import org.slf4j.Logger; 27 import org.slf4j.Logger;
28 28
29 -import static org.onlab.onos.cluster.MastershipEvent.Type.*; 29 +import static org.onlab.onos.mastership.MastershipEvent.Type.*;
30 30
31 /** 31 /**
32 * Manages inventory of controller mastership over devices using 32 * Manages inventory of controller mastership over devices using
......
...@@ -6,8 +6,8 @@ import java.util.concurrent.atomic.AtomicInteger; ...@@ -6,8 +6,8 @@ import java.util.concurrent.atomic.AtomicInteger;
6 import org.junit.After; 6 import org.junit.After;
7 import org.junit.Before; 7 import org.junit.Before;
8 import org.junit.Test; 8 import org.junit.Test;
9 -import org.onlab.onos.cluster.MastershipTerm;
10 import org.onlab.onos.cluster.NodeId; 9 import org.onlab.onos.cluster.NodeId;
10 +import org.onlab.onos.mastership.MastershipTerm;
11 import org.onlab.onos.net.DeviceId; 11 import org.onlab.onos.net.DeviceId;
12 12
13 import com.google.common.collect.Sets; 13 import com.google.common.collect.Sets;
...@@ -15,8 +15,8 @@ import com.google.common.collect.Sets; ...@@ -15,8 +15,8 @@ import com.google.common.collect.Sets;
15 import static org.junit.Assert.assertEquals; 15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertNull; 16 import static org.junit.Assert.assertNull;
17 import static org.junit.Assert.assertTrue; 17 import static org.junit.Assert.assertTrue;
18 +import static org.onlab.onos.mastership.MastershipEvent.Type.*;
18 import static org.onlab.onos.net.MastershipRole.*; 19 import static org.onlab.onos.net.MastershipRole.*;
19 -import static org.onlab.onos.cluster.MastershipEvent.Type.*;
20 20
21 /** 21 /**
22 * Test for the simple MastershipStore implementation. 22 * Test for the simple MastershipStore implementation.
......
...@@ -500,7 +500,7 @@ ...@@ -500,7 +500,7 @@
500 <group> 500 <group>
501 <title>Core Subsystems</title> 501 <title>Core Subsystems</title>
502 <packages> 502 <packages>
503 - 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 503 + 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
504 </packages> 504 </packages>
505 </group> 505 </group>
506 <group> 506 <group>
......
1 +#!/bin/bash
2 +#-------------------------------------------------------------------------------
3 +# Update bundle on locally running karaf.
4 +#-------------------------------------------------------------------------------
5 +
6 +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
7 +. $ONOS_ROOT/tools/build/envDefaults
8 +
9 +cd ~/.m2/repository
10 +jar=$(find org/onlab -type f -name '*.jar' | grep -e $1 | grep -v -e -tests | head -n 1)
11 +
12 +[ -z "$jar" ] && echo "No bundle $1 found for" && exit 1
13 +
14 +bundle=$(echo $(basename $jar .jar) | sed 's/-[0-9].*//g')
15 +
16 +client "bundle:update -f $bundle" 2>/dev/null