tom

Merge remote-tracking branch 'origin/master'

...@@ -55,6 +55,5 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD ...@@ -55,6 +55,5 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD
55 * @param role new role 55 * @param role new role
56 * @return a mastership event 56 * @return a mastership event
57 */ 57 */
58 - MastershipEvent setRole(NodeId nodeId, DeviceId deviceId, 58 + MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId);
59 - MastershipRole role);
60 } 59 }
......
...@@ -64,9 +64,12 @@ public class MastershipManager ...@@ -64,9 +64,12 @@ public class MastershipManager
64 checkNotNull(nodeId, NODE_ID_NULL); 64 checkNotNull(nodeId, NODE_ID_NULL);
65 checkNotNull(deviceId, DEVICE_ID_NULL); 65 checkNotNull(deviceId, DEVICE_ID_NULL);
66 checkNotNull(role, ROLE_NULL); 66 checkNotNull(role, ROLE_NULL);
67 - MastershipEvent event = store.setRole(nodeId, deviceId, role); 67 + //TODO figure out appropriate action for non-MASTER roles, if we even set those
68 - if (event != null) { 68 + if (role.equals(MastershipRole.MASTER)) {
69 - post(event); 69 + MastershipEvent event = store.setMaster(nodeId, deviceId);
70 + if (event != null) {
71 + post(event);
72 + }
70 } 73 }
71 } 74 }
72 75
......
1 +package org.onlab.onos.cluster.impl;
2 +
3 +import java.util.Set;
4 +
5 +import org.junit.After;
6 +import org.junit.Before;
7 +import org.junit.Test;
8 +import org.onlab.onos.cluster.ClusterEventListener;
9 +import org.onlab.onos.cluster.ClusterService;
10 +import org.onlab.onos.cluster.ControllerNode;
11 +import org.onlab.onos.cluster.ControllerNode.State;
12 +import org.onlab.onos.cluster.DefaultControllerNode;
13 +import org.onlab.onos.cluster.MastershipService;
14 +import org.onlab.onos.cluster.NodeId;
15 +import org.onlab.onos.event.impl.TestEventDispatcher;
16 +import org.onlab.onos.net.DeviceId;
17 +import org.onlab.onos.net.trivial.impl.SimpleMastershipStore;
18 +import org.onlab.packet.IpPrefix;
19 +
20 +import static org.junit.Assert.assertEquals;
21 +import static org.onlab.onos.net.MastershipRole.*;
22 +
23 +/**
24 + * Test codifying the mastership service contracts.
25 + */
26 +public class MastershipManagerTest {
27 +
28 + private static final NodeId NID_LOCAL = new NodeId("local");
29 + private static final NodeId NID_OTHER = new NodeId("foo");
30 + private static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
31 + private static final DeviceId DEV_MASTER = DeviceId.deviceId("of:1");
32 + private static final DeviceId DEV_OTHER = DeviceId.deviceId("of:2");
33 +
34 + private MastershipManager mgr;
35 + protected MastershipService service;
36 +
37 + @Before
38 + public void setUp() {
39 + mgr = new MastershipManager();
40 + service = mgr;
41 + mgr.store = new SimpleMastershipStore();
42 + mgr.eventDispatcher = new TestEventDispatcher();
43 + mgr.clusterService = new TestClusterService();
44 + mgr.activate();
45 + }
46 +
47 + @After
48 + public void tearDown() {
49 + mgr.deactivate();
50 + mgr.clusterService = null;
51 + mgr.eventDispatcher = null;
52 + mgr.store = null;
53 + }
54 +
55 + @Test
56 + public void setRole() {
57 + mgr.setRole(NID_OTHER, DEV_MASTER, MASTER);
58 + assertEquals("wrong local role:", STANDBY, mgr.getLocalRole(DEV_MASTER));
59 +
60 + //set to master
61 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
62 + assertEquals("wrong local role:", MASTER, mgr.getLocalRole(DEV_MASTER));
63 + }
64 +
65 + @Test
66 + public void relinquishMastership() {
67 + //TODO
68 + }
69 +
70 + @Test
71 + public void requestRoleFor() {
72 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
73 + mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);
74 +
75 + //local should be master for one but standby for other
76 + assertEquals("wrong role:", MASTER, mgr.requestRoleFor(DEV_MASTER));
77 + assertEquals("wrong role:", STANDBY, mgr.requestRoleFor(DEV_OTHER));
78 + }
79 +
80 + @Test
81 + public void getMasterFor() {
82 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
83 + mgr.setRole(NID_OTHER, DEV_OTHER, MASTER);
84 + assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
85 + assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_OTHER));
86 +
87 + //have NID_OTHER hand over DEV_OTHER to NID_LOCAL
88 + mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
89 + assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_OTHER));
90 + }
91 +
92 + @Test
93 + public void getDevicesOf() {
94 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
95 + mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
96 + assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size());
97 +
98 + //hand both devices to NID_LOCAL
99 + mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
100 + assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size());
101 + }
102 +
103 + private final class TestClusterService implements ClusterService {
104 +
105 + ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);
106 +
107 + @Override
108 + public ControllerNode getLocalNode() {
109 + return local;
110 + }
111 +
112 + @Override
113 + public Set<ControllerNode> getNodes() {
114 + return null;
115 + }
116 +
117 + @Override
118 + public ControllerNode getNode(NodeId nodeId) {
119 + return null;
120 + }
121 +
122 + @Override
123 + public State getState(NodeId nodeId) {
124 + return null;
125 + }
126 +
127 + @Override
128 + public void addListener(ClusterEventListener listener) {
129 + }
130 +
131 + @Override
132 + public void removeListener(ClusterEventListener listener) {
133 + }
134 +
135 + }
136 +}
...@@ -42,6 +42,7 @@ public class DistributedMastershipStore ...@@ -42,6 +42,7 @@ public class DistributedMastershipStore
42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 protected ClusterService clusterService; 43 protected ClusterService clusterService;
44 44
45 + @Override
45 @Activate 46 @Activate
46 public void activate() { 47 public void activate() {
47 super.activate(); 48 super.activate();
...@@ -61,10 +62,10 @@ public class DistributedMastershipStore ...@@ -61,10 +62,10 @@ public class DistributedMastershipStore
61 } 62 }
62 63
63 @Override 64 @Override
64 - public MastershipEvent setRole(NodeId nodeId, DeviceId deviceId, MastershipRole role) { 65 + public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
65 synchronized (this) { 66 synchronized (this) {
66 NodeId currentMaster = getMaster(deviceId); 67 NodeId currentMaster = getMaster(deviceId);
67 - if (role == MastershipRole.MASTER && Objects.equals(currentMaster, nodeId)) { 68 + if (Objects.equals(currentMaster, nodeId)) {
68 return null; 69 return null;
69 } 70 }
70 71
...@@ -94,7 +95,7 @@ public class DistributedMastershipStore ...@@ -94,7 +95,7 @@ public class DistributedMastershipStore
94 @Override 95 @Override
95 public MastershipRole requestRole(DeviceId deviceId) { 96 public MastershipRole requestRole(DeviceId deviceId) {
96 // FIXME: for now we are 'selecting' as master whoever asks 97 // FIXME: for now we are 'selecting' as master whoever asks
97 - setRole(clusterService.getLocalNode().id(), deviceId, MastershipRole.MASTER); 98 + setMaster(clusterService.getLocalNode().id(), deviceId);
98 return MastershipRole.MASTER; 99 return MastershipRole.MASTER;
99 } 100 }
100 101
......
...@@ -3,6 +3,8 @@ package org.onlab.onos.net.trivial.impl; ...@@ -3,6 +3,8 @@ package org.onlab.onos.net.trivial.impl;
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
5 import java.util.Collections; 5 import java.util.Collections;
6 +import java.util.HashSet;
7 +import java.util.Map;
6 import java.util.Set; 8 import java.util.Set;
7 import java.util.concurrent.ConcurrentHashMap; 9 import java.util.concurrent.ConcurrentHashMap;
8 import java.util.concurrent.ConcurrentMap; 10 import java.util.concurrent.ConcurrentMap;
...@@ -27,7 +29,7 @@ import static org.onlab.onos.cluster.MastershipEvent.Type.*; ...@@ -27,7 +29,7 @@ import static org.onlab.onos.cluster.MastershipEvent.Type.*;
27 29
28 /** 30 /**
29 * Manages inventory of controller mastership over devices using 31 * Manages inventory of controller mastership over devices using
30 - * trivial in-memory structures implementation. 32 + * trivial, non-distributed in-memory structures implementation.
31 */ 33 */
32 @Component(immediate = true) 34 @Component(immediate = true)
33 @Service 35 @Service
...@@ -35,18 +37,19 @@ public class SimpleMastershipStore ...@@ -35,18 +37,19 @@ public class SimpleMastershipStore
35 extends AbstractStore<MastershipEvent, MastershipStoreDelegate> 37 extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
36 implements MastershipStore { 38 implements MastershipStore {
37 39
38 - public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
39 -
40 private final Logger log = getLogger(getClass()); 40 private final Logger log = getLogger(getClass());
41 41
42 - private ControllerNode instance; 42 + public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
43 +
44 + private ControllerNode instance =
45 + new DefaultControllerNode(new NodeId("local"), LOCALHOST);
43 46
44 - protected final ConcurrentMap<DeviceId, MastershipRole> roleMap = 47 + //devices mapped to their masters, to emulate multiple nodes
48 + protected final ConcurrentMap<DeviceId, NodeId> masterMap =
45 new ConcurrentHashMap<>(); 49 new ConcurrentHashMap<>();
46 50
47 @Activate 51 @Activate
48 public void activate() { 52 public void activate() {
49 - instance = new DefaultControllerNode(new NodeId("local"), LOCALHOST);
50 log.info("Started"); 53 log.info("Started");
51 } 54 }
52 55
...@@ -56,23 +59,36 @@ public class SimpleMastershipStore ...@@ -56,23 +59,36 @@ public class SimpleMastershipStore
56 } 59 }
57 60
58 @Override 61 @Override
59 - public MastershipEvent setRole(NodeId nodeId, DeviceId deviceId, 62 + public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
60 - MastershipRole role) { 63 +
61 - if (roleMap.get(deviceId) == null) { 64 + NodeId node = masterMap.get(deviceId);
65 + if (node == null) {
66 + masterMap.put(deviceId, nodeId);
67 + return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
68 + }
69 +
70 + if (node.equals(nodeId)) {
62 return null; 71 return null;
72 + } else {
73 + masterMap.put(deviceId, nodeId);
74 + return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
63 } 75 }
64 - roleMap.put(deviceId, role);
65 - return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
66 } 76 }
67 77
68 @Override 78 @Override
69 public NodeId getMaster(DeviceId deviceId) { 79 public NodeId getMaster(DeviceId deviceId) {
70 - return instance.id(); 80 + return masterMap.get(deviceId);
71 } 81 }
72 82
73 @Override 83 @Override
74 public Set<DeviceId> getDevices(NodeId nodeId) { 84 public Set<DeviceId> getDevices(NodeId nodeId) {
75 - return Collections.unmodifiableSet(roleMap.keySet()); 85 + Set<DeviceId> ids = new HashSet<>();
86 + for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {
87 + if (d.getValue().equals(nodeId)) {
88 + ids.add(d.getKey());
89 + }
90 + }
91 + return Collections.unmodifiableSet(ids);
76 } 92 }
77 93
78 @Override 94 @Override
...@@ -82,11 +98,18 @@ public class SimpleMastershipStore ...@@ -82,11 +98,18 @@ public class SimpleMastershipStore
82 98
83 @Override 99 @Override
84 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) { 100 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
85 - MastershipRole role = roleMap.get(deviceId); 101 + NodeId node = masterMap.get(deviceId);
86 - if (role == null) { 102 + MastershipRole role;
87 - //say MASTER. If clustered, we'd figure out if anyone's got dibs here. 103 + if (node != null) {
104 + if (node.equals(nodeId)) {
105 + role = MastershipRole.MASTER;
106 + } else {
107 + role = MastershipRole.STANDBY;
108 + }
109 + } else {
110 + //masterMap doesn't contain it.
88 role = MastershipRole.MASTER; 111 role = MastershipRole.MASTER;
89 - roleMap.put(deviceId, role); 112 + masterMap.put(deviceId, nodeId);
90 } 113 }
91 return role; 114 return role;
92 } 115 }
......