handle devices agreed to be inactive during master re-election
Change-Id: Ia193d7210a8319f04ce957f2bd4a0479b88d15a8
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceService.java
index 8364935..54b9d72 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceService.java
@@ -42,6 +42,7 @@
* @param deviceId device identifier
* @return designated mastership role
*/
+ //XXX do we want this method here when MastershipService already does?
MastershipRole getRole(DeviceId deviceId);
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
index 6a96c01..04833e6 100644
--- a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java
@@ -10,6 +10,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.MastershipEvent;
@@ -19,6 +20,7 @@
import org.onlab.onos.cluster.NodeId;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
+import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.store.common.AbstractHazelcastStore;
import com.google.common.collect.ImmutableSet;
@@ -51,6 +53,10 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
+ //FIXME: need to guarantee that this will be met, sans circular dependencies
+ @Reference(policy = ReferencePolicy.DYNAMIC)
+ protected DeviceService deviceService;
+
@Override
@Activate
public void activate() {
@@ -230,9 +236,11 @@
//helper for "re-electing" a new master for a given device
private NodeId reelect(NodeId current, DeviceId deviceId) {
+
for (byte [] node : backups.keySet()) {
NodeId nid = deserialize(node);
- if (!current.equals(nid)) {
+ //if a device dies we shouldn't pick another master for it.
+ if (!current.equals(nid) && (deviceService.isAvailable(deviceId))) {
return nid;
}
}
diff --git a/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java b/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
index b2c0e2e..c3efdfe 100644
--- a/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
+++ b/core/store/hz/cluster/src/test/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStoreTest.java
@@ -5,6 +5,7 @@
import static org.junit.Assert.assertTrue;
import static org.onlab.onos.net.MastershipRole.*;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -25,7 +26,13 @@
import org.onlab.onos.cluster.MastershipStoreDelegate;
import org.onlab.onos.cluster.MastershipTerm;
import org.onlab.onos.cluster.NodeId;
+import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.MastershipRole;
+import org.onlab.onos.net.Port;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.device.DeviceListener;
+import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.store.common.StoreManager;
import org.onlab.onos.store.common.StoreService;
import org.onlab.onos.store.common.TestStoreManager;
@@ -80,6 +87,7 @@
dms = new TestDistributedMastershipStore(storeMgr, serializationMgr);
dms.clusterService = new TestClusterService();
+ dms.deviceService = new TestDeviceService();
dms.activate();
testStore = (TestDistributedMastershipStore) dms;
@@ -179,8 +187,11 @@
assertEquals("wrong role for NONE:", MASTER, dms.requestRole(DID1));
//no backup, no new MASTER/event
assertNull("wrong event:", dms.unsetMaster(N1, DID1));
- //add backup CN2, get it elected MASTER
+
dms.requestRole(DID1);
+ ((TestDeviceService) dms.deviceService).active.add(DID1);
+
+ //add backup CN2, get it elected MASTER by relinquishing
testStore.setCurrent(CN2);
dms.requestRole(DID1);
assertEquals("wrong event:", Type.MASTER_CHANGED, dms.unsetMaster(N1, DID1).type());
@@ -193,6 +204,12 @@
//NONE - nothing happens
assertNull("wrong event:", dms.unsetMaster(N1, DID2));
assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID2));
+
+ //for a device that turned off (not active) - status to NONE
+ ((TestDeviceService) dms.deviceService).active.clear();
+ assertNull("extraneous event:", dms.unsetMaster(N2, DID1));
+ assertEquals("wrong role", NONE, dms.getRole(N2, DID1));
+
}
@Ignore("Ignore until Delegate spec. is clear.")
@@ -299,4 +316,53 @@
}
}
+
+ private class TestDeviceService implements DeviceService {
+
+ Set<DeviceId> active = Sets.newHashSet();
+
+ @Override
+ public int getDeviceCount() {
+ return 0;
+ }
+
+ @Override
+ public Iterable<Device> getDevices() {
+ return null;
+ }
+
+ @Override
+ public Device getDevice(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public MastershipRole getRole(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public List<Port> getPorts(DeviceId deviceId) {
+ return null;
+ }
+
+ @Override
+ public Port getPort(DeviceId deviceId, PortNumber portNumber) {
+ return null;
+ }
+
+ @Override
+ public boolean isAvailable(DeviceId deviceId) {
+ return active.contains(deviceId);
+ }
+
+ @Override
+ public void addListener(DeviceListener listener) {
+ }
+
+ @Override
+ public void removeListener(DeviceListener listener) {
+ }
+
+ }
}