Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java b/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
index eae664d..08fa57b 100644
--- a/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
+++ b/core/api/src/main/java/org/onlab/onos/cluster/MastershipStore.java
@@ -55,6 +55,5 @@
* @param role new role
* @return a mastership event
*/
- MastershipEvent setRole(NodeId nodeId, DeviceId deviceId,
- MastershipRole role);
+ MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId);
}
diff --git a/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java b/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
index 4ac6052..255830c 100644
--- a/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
+++ b/core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
@@ -64,9 +64,12 @@
checkNotNull(nodeId, NODE_ID_NULL);
checkNotNull(deviceId, DEVICE_ID_NULL);
checkNotNull(role, ROLE_NULL);
- MastershipEvent event = store.setRole(nodeId, deviceId, role);
- if (event != null) {
- post(event);
+ //TODO figure out appropriate action for non-MASTER roles, if we even set those
+ if (role.equals(MastershipRole.MASTER)) {
+ MastershipEvent event = store.setMaster(nodeId, deviceId);
+ if (event != null) {
+ post(event);
+ }
}
}
diff --git a/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java b/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java
new file mode 100644
index 0000000..40902f2
--- /dev/null
+++ b/core/net/src/test/java/org/onlab/onos/cluster/impl/MastershipManagerTest.java
@@ -0,0 +1,136 @@
+package org.onlab.onos.cluster.impl;
+
+import java.util.Set;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.onos.cluster.ClusterEventListener;
+import org.onlab.onos.cluster.ClusterService;
+import org.onlab.onos.cluster.ControllerNode;
+import org.onlab.onos.cluster.ControllerNode.State;
+import org.onlab.onos.cluster.DefaultControllerNode;
+import org.onlab.onos.cluster.MastershipService;
+import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.event.impl.TestEventDispatcher;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.trivial.impl.SimpleMastershipStore;
+import org.onlab.packet.IpPrefix;
+
+import static org.junit.Assert.assertEquals;
+import static org.onlab.onos.net.MastershipRole.*;
+
+/**
+ * Test codifying the mastership service contracts.
+ */
+public class MastershipManagerTest {
+
+ private static final NodeId NID_LOCAL = new NodeId("local");
+ private static final NodeId NID_OTHER = new NodeId("foo");
+ private static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
+ private static final DeviceId DEV_MASTER = DeviceId.deviceId("of:1");
+ private static final DeviceId DEV_OTHER = DeviceId.deviceId("of:2");
+
+ private MastershipManager mgr;
+ protected MastershipService service;
+
+ @Before
+ public void setUp() {
+ mgr = new MastershipManager();
+ service = mgr;
+ mgr.store = new SimpleMastershipStore();
+ mgr.eventDispatcher = new TestEventDispatcher();
+ mgr.clusterService = new TestClusterService();
+ mgr.activate();
+ }
+
+ @After
+ public void tearDown() {
+ mgr.deactivate();
+ mgr.clusterService = null;
+ mgr.eventDispatcher = null;
+ mgr.store = null;
+ }
+
+ @Test
+ public void setRole() {
+ mgr.setRole(NID_OTHER, DEV_MASTER, MASTER);
+ assertEquals("wrong local role:", STANDBY, mgr.getLocalRole(DEV_MASTER));
+
+ //set to master
+ mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
+ assertEquals("wrong local role:", MASTER, mgr.getLocalRole(DEV_MASTER));
+ }
+
+ @Test
+ public void relinquishMastership() {
+ //TODO
+ }
+
+ @Test
+ public void requestRoleFor() {
+ mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
+ mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);
+
+ //local should be master for one but standby for other
+ assertEquals("wrong role:", MASTER, mgr.requestRoleFor(DEV_MASTER));
+ assertEquals("wrong role:", STANDBY, mgr.requestRoleFor(DEV_OTHER));
+ }
+
+ @Test
+ public void getMasterFor() {
+ mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
+ mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);
+ assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
+ assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_OTHER));
+
+ //have NID_OTHER hand over DEV_OTHER to NID_LOCAL
+ mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
+ assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_OTHER));
+ }
+
+ @Test
+ public void getDevicesOf() {
+ mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
+ mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
+ assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size());
+
+ //hand both devices to NID_LOCAL
+ mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
+ assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size());
+ }
+
+ private final class TestClusterService implements ClusterService {
+
+ ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);
+
+ @Override
+ public ControllerNode getLocalNode() {
+ return local;
+ }
+
+ @Override
+ public Set<ControllerNode> getNodes() {
+ return null;
+ }
+
+ @Override
+ public ControllerNode getNode(NodeId nodeId) {
+ return null;
+ }
+
+ @Override
+ public State getState(NodeId nodeId) {
+ return null;
+ }
+
+ @Override
+ public void addListener(ClusterEventListener listener) {
+ }
+
+ @Override
+ public void removeListener(ClusterEventListener listener) {
+ }
+
+ }
+}
diff --git a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
index 2a7f67a..10c116b 100644
--- a/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
@@ -42,6 +42,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
+ @Override
@Activate
public void activate() {
super.activate();
@@ -61,10 +62,10 @@
}
@Override
- public MastershipEvent setRole(NodeId nodeId, DeviceId deviceId, MastershipRole role) {
+ public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
synchronized (this) {
NodeId currentMaster = getMaster(deviceId);
- if (role == MastershipRole.MASTER && Objects.equals(currentMaster, nodeId)) {
+ if (Objects.equals(currentMaster, nodeId)) {
return null;
}
@@ -94,7 +95,7 @@
@Override
public MastershipRole requestRole(DeviceId deviceId) {
// FIXME: for now we are 'selecting' as master whoever asks
- setRole(clusterService.getLocalNode().id(), deviceId, MastershipRole.MASTER);
+ setMaster(clusterService.getLocalNode().id(), deviceId);
return MastershipRole.MASTER;
}
diff --git a/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleMastershipStore.java b/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleMastershipStore.java
index feea6ee..da691fe 100644
--- a/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleMastershipStore.java
+++ b/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleMastershipStore.java
@@ -3,6 +3,8 @@
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -27,7 +29,7 @@
/**
* Manages inventory of controller mastership over devices using
- * trivial in-memory structures implementation.
+ * trivial, non-distributed in-memory structures implementation.
*/
@Component(immediate = true)
@Service
@@ -35,18 +37,19 @@
extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
implements MastershipStore {
- public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
-
private final Logger log = getLogger(getClass());
- private ControllerNode instance;
+ public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
- protected final ConcurrentMap<DeviceId, MastershipRole> roleMap =
+ private ControllerNode instance =
+ new DefaultControllerNode(new NodeId("local"), LOCALHOST);
+
+ //devices mapped to their masters, to emulate multiple nodes
+ protected final ConcurrentMap<DeviceId, NodeId> masterMap =
new ConcurrentHashMap<>();
@Activate
public void activate() {
- instance = new DefaultControllerNode(new NodeId("local"), LOCALHOST);
log.info("Started");
}
@@ -56,23 +59,36 @@
}
@Override
- public MastershipEvent setRole(NodeId nodeId, DeviceId deviceId,
- MastershipRole role) {
- if (roleMap.get(deviceId) == null) {
- return null;
+ public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
+
+ NodeId node = masterMap.get(deviceId);
+ if (node == null) {
+ masterMap.put(deviceId, nodeId);
+ return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
}
- roleMap.put(deviceId, role);
- return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
+
+ if (node.equals(nodeId)) {
+ return null;
+ } else {
+ masterMap.put(deviceId, nodeId);
+ return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
+ }
}
@Override
public NodeId getMaster(DeviceId deviceId) {
- return instance.id();
+ return masterMap.get(deviceId);
}
@Override
public Set<DeviceId> getDevices(NodeId nodeId) {
- return Collections.unmodifiableSet(roleMap.keySet());
+ Set<DeviceId> ids = new HashSet<>();
+ for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {
+ if (d.getValue().equals(nodeId)) {
+ ids.add(d.getKey());
+ }
+ }
+ return Collections.unmodifiableSet(ids);
}
@Override
@@ -82,11 +98,18 @@
@Override
public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
- MastershipRole role = roleMap.get(deviceId);
- if (role == null) {
- //say MASTER. If clustered, we'd figure out if anyone's got dibs here.
+ NodeId node = masterMap.get(deviceId);
+ MastershipRole role;
+ if (node != null) {
+ if (node.equals(nodeId)) {
+ role = MastershipRole.MASTER;
+ } else {
+ role = MastershipRole.STANDBY;
+ }
+ } else {
+ //masterMap doesn't contain it.
role = MastershipRole.MASTER;
- roleMap.put(deviceId, role);
+ masterMap.put(deviceId, nodeId);
}
return role;
}