Yuta HIGUCHI

Trigger MastershipEvent on no more master case

Change-Id: Iaac7b7d021802e7470df061dad719dcdf0e4b73e
...@@ -23,6 +23,10 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -23,6 +23,10 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.onlab.onos.cluster.ClusterEvent; 23 import org.onlab.onos.cluster.ClusterEvent;
24 import org.onlab.onos.cluster.ClusterEventListener; 24 import org.onlab.onos.cluster.ClusterEventListener;
25 import org.onlab.onos.cluster.ClusterService; 25 import org.onlab.onos.cluster.ClusterService;
26 +import org.onlab.onos.cluster.NodeId;
27 +import org.onlab.onos.mastership.MastershipEvent;
28 +import org.onlab.onos.mastership.MastershipListener;
29 +import org.onlab.onos.mastership.MastershipService;
26 import org.onlab.onos.net.device.DeviceEvent; 30 import org.onlab.onos.net.device.DeviceEvent;
27 import org.onlab.onos.net.device.DeviceListener; 31 import org.onlab.onos.net.device.DeviceListener;
28 import org.onlab.onos.net.device.DeviceService; 32 import org.onlab.onos.net.device.DeviceService;
...@@ -50,15 +54,20 @@ public class FooComponent { ...@@ -50,15 +54,20 @@ public class FooComponent {
50 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected IntentService intentService; 55 protected IntentService intentService;
52 56
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + protected MastershipService mastershipService;
59 +
53 private final ClusterEventListener clusterListener = new InnerClusterListener(); 60 private final ClusterEventListener clusterListener = new InnerClusterListener();
54 private final DeviceListener deviceListener = new InnerDeviceListener(); 61 private final DeviceListener deviceListener = new InnerDeviceListener();
55 private final IntentListener intentListener = new InnerIntentListener(); 62 private final IntentListener intentListener = new InnerIntentListener();
63 + private final MastershipListener mastershipListener = new InnerMastershipListener();
56 64
57 @Activate 65 @Activate
58 public void activate() { 66 public void activate() {
59 clusterService.addListener(clusterListener); 67 clusterService.addListener(clusterListener);
60 deviceService.addListener(deviceListener); 68 deviceService.addListener(deviceListener);
61 intentService.addListener(intentListener); 69 intentService.addListener(intentListener);
70 + mastershipService.addListener(mastershipListener);
62 log.info("Started"); 71 log.info("Started");
63 } 72 }
64 73
...@@ -67,6 +76,7 @@ public class FooComponent { ...@@ -67,6 +76,7 @@ public class FooComponent {
67 clusterService.removeListener(clusterListener); 76 clusterService.removeListener(clusterListener);
68 deviceService.removeListener(deviceListener); 77 deviceService.removeListener(deviceListener);
69 intentService.removeListener(intentListener); 78 intentService.removeListener(intentListener);
79 + mastershipService.removeListener(mastershipListener);
70 log.info("Stopped"); 80 log.info("Stopped");
71 } 81 }
72 82
...@@ -100,6 +110,18 @@ public class FooComponent { ...@@ -100,6 +110,18 @@ public class FooComponent {
100 log.info(message, event.subject()); 110 log.info(message, event.subject());
101 } 111 }
102 } 112 }
113 +
114 + private class InnerMastershipListener implements MastershipListener {
115 + @Override
116 + public void event(MastershipEvent event) {
117 + final NodeId myId = clusterService.getLocalNode().id();
118 + if (myId.equals(event.roleInfo().master())) {
119 + log.info("I have control/I wish you luck {}", event);
120 + } else {
121 + log.info("you have control {}", event);
122 + }
123 + }
124 + }
103 } 125 }
104 126
105 127
......
...@@ -28,6 +28,7 @@ import org.onlab.onos.cluster.DefaultControllerNode; ...@@ -28,6 +28,7 @@ import org.onlab.onos.cluster.DefaultControllerNode;
28 import org.onlab.onos.cluster.NodeId; 28 import org.onlab.onos.cluster.NodeId;
29 import org.onlab.onos.event.impl.TestEventDispatcher; 29 import org.onlab.onos.event.impl.TestEventDispatcher;
30 import org.onlab.onos.mastership.MastershipService; 30 import org.onlab.onos.mastership.MastershipService;
31 +import org.onlab.onos.mastership.MastershipStore;
31 import org.onlab.onos.mastership.MastershipTermService; 32 import org.onlab.onos.mastership.MastershipTermService;
32 import org.onlab.onos.net.DeviceId; 33 import org.onlab.onos.net.DeviceId;
33 import org.onlab.onos.store.trivial.impl.SimpleMastershipStore; 34 import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
...@@ -57,9 +58,9 @@ public class MastershipManagerTest { ...@@ -57,9 +58,9 @@ public class MastershipManagerTest {
57 public void setUp() { 58 public void setUp() {
58 mgr = new MastershipManager(); 59 mgr = new MastershipManager();
59 service = mgr; 60 service = mgr;
60 - mgr.store = new SimpleMastershipStore();
61 mgr.eventDispatcher = new TestEventDispatcher(); 61 mgr.eventDispatcher = new TestEventDispatcher();
62 mgr.clusterService = new TestClusterService(); 62 mgr.clusterService = new TestClusterService();
63 + mgr.store = new TestSimpleMastershipStore(mgr.clusterService);
63 mgr.activate(); 64 mgr.activate();
64 } 65 }
65 66
...@@ -74,7 +75,8 @@ public class MastershipManagerTest { ...@@ -74,7 +75,8 @@ public class MastershipManagerTest {
74 @Test 75 @Test
75 public void setRole() { 76 public void setRole() {
76 mgr.setRole(NID_OTHER, DEV_MASTER, MASTER); 77 mgr.setRole(NID_OTHER, DEV_MASTER, MASTER);
77 - assertEquals("wrong local role:", STANDBY, mgr.getLocalRole(DEV_MASTER)); 78 + assertEquals("wrong local role:", NONE, mgr.getLocalRole(DEV_MASTER));
79 + assertEquals("wrong obtained role:", STANDBY, mgr.requestRoleFor(DEV_MASTER));
78 80
79 //set to master 81 //set to master
80 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER); 82 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
...@@ -182,4 +184,12 @@ public class MastershipManagerTest { ...@@ -182,4 +184,12 @@ public class MastershipManagerTest {
182 } 184 }
183 185
184 } 186 }
187 +
188 + private final class TestSimpleMastershipStore extends SimpleMastershipStore
189 + implements MastershipStore {
190 +
191 + public TestSimpleMastershipStore(ClusterService clusterService) {
192 + super.clusterService = clusterService;
193 + }
194 + }
185 } 195 }
......
...@@ -283,16 +283,15 @@ implements MastershipStore { ...@@ -283,16 +283,15 @@ implements MastershipStore {
283 case MASTER: 283 case MASTER:
284 NodeId newMaster = reelect(nodeId, deviceId, rv); 284 NodeId newMaster = reelect(nodeId, deviceId, rv);
285 rv.reassign(nodeId, NONE, STANDBY); 285 rv.reassign(nodeId, NONE, STANDBY);
286 - if (newMaster != null) {
287 updateTerm(deviceId); 286 updateTerm(deviceId);
287 + if (newMaster != null) {
288 roleMap.put(deviceId, rv); 288 roleMap.put(deviceId, rv);
289 return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo()); 289 return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
290 } else { 290 } else {
291 // no master candidate 291 // no master candidate
292 roleMap.put(deviceId, rv); 292 roleMap.put(deviceId, rv);
293 - // FIXME: Should there be new event type? 293 + // TODO: Should there be new event type for no MASTER?
294 - // or should we issue null Master event? 294 + return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
295 - return null;
296 } 295 }
297 case STANDBY: 296 case STANDBY:
298 return null; 297 return null;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
15 */ 15 */
16 package org.onlab.onos.store.trivial.impl; 16 package org.onlab.onos.store.trivial.impl;
17 17
18 +import java.util.ArrayList;
19 +import java.util.List;
18 import java.util.Set; 20 import java.util.Set;
19 import java.util.concurrent.atomic.AtomicInteger; 21 import java.util.concurrent.atomic.AtomicInteger;
20 22
...@@ -22,6 +24,7 @@ import org.junit.After; ...@@ -22,6 +24,7 @@ import org.junit.After;
22 import org.junit.Before; 24 import org.junit.Before;
23 import org.junit.Test; 25 import org.junit.Test;
24 import org.onlab.onos.cluster.NodeId; 26 import org.onlab.onos.cluster.NodeId;
27 +import org.onlab.onos.mastership.MastershipEvent;
25 import org.onlab.onos.mastership.MastershipTerm; 28 import org.onlab.onos.mastership.MastershipTerm;
26 import org.onlab.onos.net.DeviceId; 29 import org.onlab.onos.net.DeviceId;
27 30
...@@ -74,6 +77,7 @@ public class SimpleMastershipStoreTest { ...@@ -74,6 +77,7 @@ public class SimpleMastershipStoreTest {
74 assertEquals("wrong role", MASTER, sms.getRole(N2, DID3)); 77 assertEquals("wrong role", MASTER, sms.getRole(N2, DID3));
75 78
76 //N2 is master but N1 is only in backups set 79 //N2 is master but N1 is only in backups set
80 + put(DID4, N1, false, true);
77 put(DID4, N2, true, false); 81 put(DID4, N2, true, false);
78 assertEquals("wrong role", STANDBY, sms.getRole(N1, DID4)); 82 assertEquals("wrong role", STANDBY, sms.getRole(N1, DID4));
79 } 83 }
...@@ -127,12 +131,12 @@ public class SimpleMastershipStoreTest { ...@@ -127,12 +131,12 @@ public class SimpleMastershipStoreTest {
127 put(DID1, N1, false, false); 131 put(DID1, N1, false, false);
128 assertEquals("wrong role", MASTER, sms.requestRole(DID1)); 132 assertEquals("wrong role", MASTER, sms.requestRole(DID1));
129 133
130 - //STANDBY without backup - become MASTER 134 + //was STANDBY - become MASTER
131 put(DID2, N1, false, true); 135 put(DID2, N1, false, true);
132 assertEquals("wrong role", MASTER, sms.requestRole(DID2)); 136 assertEquals("wrong role", MASTER, sms.requestRole(DID2));
133 137
134 - //STANDBY with backup - stay STANDBY 138 + //other MASTER - stay STANDBY
135 - put(DID3, N2, false, true); 139 + put(DID3, N2, true, false);
136 assertEquals("wrong role", STANDBY, sms.requestRole(DID3)); 140 assertEquals("wrong role", STANDBY, sms.requestRole(DID3));
137 141
138 //local (N1) is MASTER - stay MASTER 142 //local (N1) is MASTER - stay MASTER
...@@ -145,30 +149,34 @@ public class SimpleMastershipStoreTest { ...@@ -145,30 +149,34 @@ public class SimpleMastershipStoreTest {
145 //NONE - record backup but take no other action 149 //NONE - record backup but take no other action
146 put(DID1, N1, false, false); 150 put(DID1, N1, false, false);
147 sms.setStandby(N1, DID1); 151 sms.setStandby(N1, DID1);
148 - assertTrue("not backed up", sms.backups.contains(N1)); 152 + assertTrue("not backed up", sms.backups.get(DID1).contains(N1));
149 - sms.termMap.clear(); 153 + int prev = sms.termMap.get(DID1).get();
150 sms.setStandby(N1, DID1); 154 sms.setStandby(N1, DID1);
151 - assertTrue("term not set", sms.termMap.containsKey(DID1)); 155 + assertEquals("term should not change", prev, sms.termMap.get(DID1).get());
152 156
153 //no backup, MASTER 157 //no backup, MASTER
154 - put(DID1, N1, true, true); 158 + put(DID1, N1, true, false);
155 - assertNull("wrong event", sms.setStandby(N1, DID1)); 159 + assertNull("expect no MASTER event", sms.setStandby(N1, DID1).roleInfo().master());
156 assertNull("wrong node", sms.masterMap.get(DID1)); 160 assertNull("wrong node", sms.masterMap.get(DID1));
157 161
158 //backup, switch 162 //backup, switch
159 sms.masterMap.clear(); 163 sms.masterMap.clear();
160 put(DID1, N1, true, true); 164 put(DID1, N1, true, true);
165 + put(DID1, N2, false, true);
161 put(DID2, N2, true, true); 166 put(DID2, N2, true, true);
162 - assertEquals("wrong event", MASTER_CHANGED, sms.setStandby(N1, DID1).type()); 167 + MastershipEvent event = sms.setStandby(N1, DID1);
168 + assertEquals("wrong event", MASTER_CHANGED, event.type());
169 + assertEquals("wrong master", N2, event.roleInfo().master());
163 } 170 }
164 171
165 //helper to populate master/backup structures 172 //helper to populate master/backup structures
166 - private void put(DeviceId dev, NodeId node, boolean store, boolean backup) { 173 + private void put(DeviceId dev, NodeId node, boolean master, boolean backup) {
167 - if (store) { 174 + if (master) {
168 sms.masterMap.put(dev, node); 175 sms.masterMap.put(dev, node);
169 - } 176 + } else if (backup) {
170 - if (backup) { 177 + List<NodeId> stbys = sms.backups.getOrDefault(dev, new ArrayList<>());
171 - sms.backups.add(node); 178 + stbys.add(node);
179 + sms.backups.put(dev, stbys);
172 } 180 }
173 sms.termMap.put(dev, new AtomicInteger()); 181 sms.termMap.put(dev, new AtomicInteger());
174 } 182 }
......