list mastership roles CLI command

Change-Id: I54dc296f90c4b8ceebe4e86816c3796da4d2d714
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index a0b9f50..101cc82 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -13,6 +13,10 @@
         <command>
             <action class="org.onlab.onos.cli.NodeRemoveCommand"/>
         </command>
+
+        <command>
+            <action class="org.onlab.onos.cli.RolesCommand"/>
+        </command>
         <command>
             <action class="org.onlab.onos.cli.MastersListCommand"/>
             <completers>
diff --git a/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
index 029e357..224bc05 100644
--- a/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipService.java
@@ -1,5 +1,6 @@
 package org.onlab.onos.mastership;
 
+import java.util.List;
 import java.util.Set;
 
 import org.onlab.onos.cluster.NodeId;
@@ -50,6 +51,15 @@
     NodeId getMasterFor(DeviceId deviceId);
 
     /**
+     * Returns controllers connected to a given device, in order of
+     * preference. The first entry in the list is the current master.
+     *
+     * @param deviceId the identifier of the device
+     * @return a list of controller IDs
+     */
+    List<NodeId> getNodesFor(DeviceId deviceId);
+
+    /**
      * Returns the devices for which a controller is master.
      *
      * @param nodeId the ID of the controller
diff --git a/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
index 0117d0d..5e7b0e4 100644
--- a/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipStore.java
@@ -1,5 +1,6 @@
 package org.onlab.onos.mastership;
 
+import java.util.List;
 import java.util.Set;
 
 import org.onlab.onos.cluster.NodeId;
@@ -41,6 +42,15 @@
     NodeId getMaster(DeviceId deviceId);
 
     /**
+     * Returns the controllers connected to a device, in mastership-
+     * preference order.
+     *
+     * @param deviceId the device identifier
+     * @return an ordered list of controller IDs
+     */
+    List<NodeId> getNodes(DeviceId deviceId);
+
+    /**
      * Returns the devices that a controller instance is master of.
      *
      * @param nodeId the instance identifier
@@ -48,6 +58,7 @@
      */
     Set<DeviceId> getDevices(NodeId nodeId);
 
+
     /**
      * Sets a device's role for a specified controller instance.
      *
diff --git a/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java b/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
index 97b57e5..af376e8 100644
--- a/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
+++ b/core/api/src/test/java/org/onlab/onos/mastership/MastershipServiceAdapter.java
@@ -4,6 +4,7 @@
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.MastershipRole;
 
+import java.util.List;
 import java.util.Set;
 
 /**
@@ -46,4 +47,9 @@
     public MastershipTermService requestTermService() {
         return null;
     }
+
+    @Override
+    public List<NodeId> getNodesFor(DeviceId deviceId) {
+        return null;
+    }
 }
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 59614da..4bcaff4a 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
@@ -3,6 +3,7 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.slf4j.LoggerFactory.getLogger;
 
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
@@ -127,6 +128,11 @@
         return store.getDevices(nodeId);
     }
 
+    @Override
+    public List<NodeId> getNodesFor(DeviceId deviceId) {
+        checkNotNull(deviceId, DEVICE_ID_NULL);
+        return store.getNodes(deviceId);
+    }
 
     @Override
     public MastershipTermService requestTermService() {
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
index 5e64a39..8f48890 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
@@ -54,7 +54,7 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     private ClusterCommunicationAdminService clusterCommunicationAdminService;
 
-    private final ClusterNodesDelegate nodesDelegate = new InnerNodesDelegate();
+    private final ClusterNodesDelegate nodesDelegate = new InternalNodesDelegate();
 
     @Activate
     public void activate() throws IOException {
@@ -151,7 +151,7 @@
     }
 
     // Entity to handle back calls from the connection manager.
-    private class InnerNodesDelegate implements ClusterNodesDelegate {
+    private class InternalNodesDelegate implements ClusterNodesDelegate {
         @Override
         public DefaultControllerNode nodeDetected(NodeId nodeId, IpPrefix ip, int tcpPort) {
             DefaultControllerNode node = nodes.get(nodeId);
diff --git a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
index e073b63..1def9f9 100644
--- a/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
+++ b/core/store/hz/cluster/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
@@ -2,6 +2,8 @@
 
 import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED;
 
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -143,6 +145,30 @@
         return deserialize(masters.get(serialize(deviceId)));
     }
 
+
+    @Override
+    public List<NodeId> getNodes(DeviceId deviceId) {
+        byte [] did = serialize(deviceId);
+        List<NodeId> nodes = new LinkedList<>();
+
+        //add current master to head - if there is one
+        ILock lock = theInstance.getLock(LOCK);
+        lock.lock();
+        try {
+            byte [] master = masters.get(did);
+            if (master != null) {
+                nodes.add((NodeId) deserialize(master));
+            }
+
+            for (byte [] el : standbys.get(serialize(deviceId))) {
+                nodes.add((NodeId) deserialize(el));
+            }
+            return nodes;
+        } finally {
+            lock.unlock();
+        }
+    }
+
     @Override
     public Set<DeviceId> getDevices(NodeId nodeId) {
         ImmutableSet.Builder<DeviceId> builder = ImmutableSet.builder();
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
index aba77d0..a6cfe8b 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleMastershipStore.java
@@ -5,6 +5,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -95,6 +96,11 @@
     }
 
     @Override
+    public List<NodeId> getNodes(DeviceId deviceId) {
+        return null;
+    }
+
+    @Override
     public Set<DeviceId> getDevices(NodeId nodeId) {
         Set<DeviceId> ids = new HashSet<>();
         for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {