Added ability to force mastership re-balancing between instances from the GUI.

Change-Id: I98e56deb3e2b00df630ed85b596c8e35b3d6efab
diff --git a/cli/src/main/java/org/onlab/onos/cli/BalanceMastersCommand.java b/cli/src/main/java/org/onlab/onos/cli/BalanceMastersCommand.java
index 77d0c16..9b31715 100644
--- a/cli/src/main/java/org/onlab/onos/cli/BalanceMastersCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/BalanceMastersCommand.java
@@ -15,23 +15,8 @@
  */
 package org.onlab.onos.cli;
 
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
 import org.apache.karaf.shell.commands.Command;
-import org.onlab.onos.cluster.ClusterService;
-import org.onlab.onos.cluster.ControllerNode;
 import org.onlab.onos.mastership.MastershipAdminService;
-import org.onlab.onos.mastership.MastershipService;
-import org.onlab.onos.net.DeviceId;
-import org.onlab.onos.net.device.DeviceService;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.onlab.onos.net.MastershipRole.MASTER;
 
 /**
  * Forces device mastership rebalancing.
@@ -42,72 +27,7 @@
 
     @Override
     protected void execute() {
-        ClusterService service = get(ClusterService.class);
-        MastershipService mastershipService = get(MastershipService.class);
-        MastershipAdminService adminService = get(MastershipAdminService.class);
-
-        List<ControllerNode> nodes = newArrayList(service.getNodes());
-
-        Multimap<ControllerNode, DeviceId> controllerDevices = HashMultimap.create();
-
-        // Create buckets reflecting current ownership.
-        for (ControllerNode node : nodes) {
-            Set<DeviceId> devicesOf = mastershipService.getDevicesOf(node.id());
-            controllerDevices.putAll(node, devicesOf);
-            print("Node %s has %d devices.", node.id(), devicesOf.size());
-        }
-
-        int rounds = nodes.size();
-        for (int i = 0; i < rounds; i++) {
-            // Iterate over the buckets and find the smallest and the largest.
-            ControllerNode smallest = findBucket(true, nodes, controllerDevices);
-            ControllerNode largest = findBucket(false, nodes, controllerDevices);
-            balanceBuckets(smallest, largest, controllerDevices, adminService);
-        }
-    }
-
-    private ControllerNode findBucket(boolean min, Collection<ControllerNode> nodes,
-                                      Multimap<ControllerNode, DeviceId> controllerDevices) {
-        int xSize = min ? Integer.MAX_VALUE : -1;
-        ControllerNode xNode = null;
-        for (ControllerNode node : nodes) {
-            int size = controllerDevices.get(node).size();
-            if ((min && size < xSize) || (!min && size > xSize)) {
-                xSize = size;
-                xNode = node;
-            }
-        }
-        return xNode;
-    }
-
-    // FIXME: enhance to better handle cases where smallest cannot take any of the devices from largest
-
-    private void balanceBuckets(ControllerNode smallest, ControllerNode largest,
-                                Multimap<ControllerNode, DeviceId> controllerDevices,
-                                MastershipAdminService adminService) {
-        Collection<DeviceId> minBucket = controllerDevices.get(smallest);
-        Collection<DeviceId> maxBucket = controllerDevices.get(largest);
-        int bucketCount = controllerDevices.keySet().size();
-        int deviceCount = get(DeviceService.class).getDeviceCount();
-
-        int delta = (maxBucket.size() - minBucket.size()) / 2;
-        delta = Math.min(deviceCount / bucketCount, delta);
-
-        if (delta > 0) {
-            print("Attempting to move %d nodes from %s to %s...",
-                  delta, largest.id(), smallest.id());
-
-            int i = 0;
-            Iterator<DeviceId> it = maxBucket.iterator();
-            while (it.hasNext() && i < delta) {
-                DeviceId deviceId = it.next();
-                print("Setting %s as the master for %s", smallest.id(), deviceId);
-                adminService.setRole(smallest.id(), deviceId, MASTER);
-                controllerDevices.put(smallest, deviceId);
-                it.remove();
-                i++;
-            }
-        }
+        get(MastershipAdminService.class).balanceRoles();
     }
 
 }