use of org.onosproject.cluster.ControllerNode in project onos by opennetworkinglab.
the class MastershipManager method distributeOrphanedDevices.
/**
* Uses the set of orphaned devices to even out the load among the controllers.
*
* @param controllerDevices controller nodes to devices map
* @param orphanedDevices set of orphaned devices without an active master
* @param futures list of completable future to track the progress of the balancing operation
*/
private void distributeOrphanedDevices(Map<ControllerNode, Set<DeviceId>> controllerDevices, Set<DeviceId> orphanedDevices, List<CompletableFuture<Void>> futures) {
// Now re-distribute the orphaned devices into buckets until they are roughly even.
while (!orphanedDevices.isEmpty()) {
// Iterate over the buckets and find the smallest bucket.
ControllerNode smallest = findBucket(true, controllerDevices);
changeMastership(smallest, controllerDevices.get(smallest), orphanedDevices, 1, futures);
}
}
use of org.onosproject.cluster.ControllerNode in project onos by opennetworkinglab.
the class MastershipManager method balanceRolesInRegion.
/**
* Balances the nodes in specified region.
*
* @param region region in which nodes are to be balanced
* @param allControllerDevices controller nodes to devices map
* @return controller nodes that were balanced
*/
private Map<ControllerNode, Set<DeviceId>> balanceRolesInRegion(Region region, Map<ControllerNode, Set<DeviceId>> allControllerDevices) {
// Retrieve all devices associated with specified region
Set<DeviceId> devicesInRegion = regionService.getRegionDevices(region.id());
log.info("Region {} has {} devices.", region.id(), devicesInRegion.size());
if (devicesInRegion.isEmpty()) {
// no devices in this region, so nothing to balance.
return new HashMap<>();
}
List<Set<NodeId>> mastersList = region.masters();
log.info("Region {} has {} sets of masters.", region.id(), mastersList.size());
if (mastersList.isEmpty()) {
// for now just leave devices alone
return new HashMap<>();
}
// Get the region's preferred set of masters
Set<DeviceId> devicesInMasters = Sets.newHashSet();
Map<ControllerNode, Set<DeviceId>> regionalControllerDevices = getRegionsPreferredMasters(region, devicesInMasters, allControllerDevices);
// Now re-balance the buckets until they are roughly even.
List<CompletableFuture<Void>> balanceBucketsFutures = Lists.newArrayList();
balanceControllerNodes(regionalControllerDevices, devicesInMasters.size(), balanceBucketsFutures);
// Handle devices that are not currently mastered by the master node set
Set<DeviceId> devicesNotMasteredWithControllers = Sets.difference(devicesInRegion, devicesInMasters);
if (!devicesNotMasteredWithControllers.isEmpty()) {
// active controllers in master node set are already balanced, just
// assign device mastership in sequence
List<ControllerNode> sorted = new ArrayList<>(regionalControllerDevices.keySet());
Collections.sort(sorted, Comparator.comparingInt(o -> (regionalControllerDevices.get(o)).size()));
int deviceIndex = 0;
for (DeviceId deviceId : devicesNotMasteredWithControllers) {
ControllerNode cnode = sorted.get(deviceIndex % sorted.size());
balanceBucketsFutures.add(setRole(cnode.id(), deviceId, MASTER));
regionalControllerDevices.get(cnode).add(deviceId);
deviceIndex++;
}
}
CompletableFuture<Void> balanceRolesFuture = allOf(balanceBucketsFutures.toArray(new CompletableFuture[balanceBucketsFutures.size()]));
Futures.getUnchecked(balanceRolesFuture);
// Update the map before returning
regionalControllerDevices.forEach((controllerNode, deviceIds) -> {
regionalControllerDevices.put(controllerNode, new HashSet<>(getDevicesOf(controllerNode.id())));
});
return regionalControllerDevices;
}
use of org.onosproject.cluster.ControllerNode in project onos by opennetworkinglab.
the class MastershipManager method balanceRoles.
@Override
public void balanceRoles() {
List<ControllerNode> nodes = newArrayList(clusterService.getNodes());
Map<ControllerNode, Set<DeviceId>> controllerDevices = new HashMap<>();
Set<DeviceId> orphanedDevices = Sets.newHashSet();
int deviceCount = 0;
// whether the node is active.
for (ControllerNode node : nodes) {
Set<DeviceId> devicesOf = new HashSet<>(getDevicesOf(node.id()));
if (clusterService.getState(node.id()).isActive()) {
log.info("Node {} has {} devices.", node.id(), devicesOf.size());
deviceCount += devicesOf.size();
controllerDevices.put(node, devicesOf);
} else if (!devicesOf.isEmpty()) {
log.warn("Inactive node {} has {} orphaned devices.", node.id(), devicesOf.size());
orphanedDevices.addAll(getDevicesOf(node.id()));
}
}
if (useRegionForBalanceRoles && balanceRolesUsingRegions(controllerDevices)) {
return;
}
List<CompletableFuture<Void>> balanceBucketsFutures = Lists.newLinkedList();
// First re-balance the buckets until they are roughly even.
balanceControllerNodes(controllerDevices, deviceCount, balanceBucketsFutures);
// Then attempt to distribute any orphaned devices among the buckets.
distributeOrphanedDevices(controllerDevices, orphanedDevices, balanceBucketsFutures);
CompletableFuture<Void> balanceRolesFuture = allOf(balanceBucketsFutures.toArray(new CompletableFuture[balanceBucketsFutures.size()]));
Futures.getUnchecked(balanceRolesFuture);
}
use of org.onosproject.cluster.ControllerNode in project onos by opennetworkinglab.
the class MastershipManager method getRegionsPreferredMasters.
/**
* Get region's preferred set of master nodes - the first master node set that has at
* least one active node.
*
* @param region region for which preferred set of master nodes is requested
* @param devicesInMasters device set to track devices in preferred set of master nodes
* @param allControllerDevices controller nodes to devices map
* @return region's preferred master nodes (and devices that use them as masters)
*/
private Map<ControllerNode, Set<DeviceId>> getRegionsPreferredMasters(Region region, Set<DeviceId> devicesInMasters, Map<ControllerNode, Set<DeviceId>> allControllerDevices) {
Map<ControllerNode, Set<DeviceId>> regionalControllerDevices = new HashMap<>();
int listIndex = 0;
for (Set<NodeId> masterSet : region.masters()) {
log.info("Region {} masters set {} has {} nodes.", region.id(), listIndex, masterSet.size());
if (masterSet.isEmpty()) {
// nothing on this level
listIndex++;
continue;
}
// Create buckets reflecting current ownership.
for (NodeId nodeId : masterSet) {
if (clusterService.getState(nodeId).isActive()) {
ControllerNode controllerNode = clusterService.getNode(nodeId);
Set<DeviceId> devicesOf = new HashSet<>(allControllerDevices.get(controllerNode));
regionalControllerDevices.put(controllerNode, devicesOf);
devicesInMasters.addAll(devicesOf);
log.info("Active Node {} has {} devices.", nodeId, devicesOf.size());
}
}
if (!regionalControllerDevices.isEmpty()) {
// now have a set of >0 active controllers
break;
}
// keep on looking
listIndex++;
}
return regionalControllerDevices;
}
use of org.onosproject.cluster.ControllerNode in project onos by opennetworkinglab.
the class SimpleMastershipStore method activate.
@Activate
public void activate() {
if (clusterService == null) {
// just for ease of unit test
final ControllerNode instance = new DefaultControllerNode(new NodeId("local"), IpAddress.valueOf("127.0.0.1"));
clusterService = new ClusterService() {
private final Instant creationTime = Instant.now();
@Override
public ControllerNode getLocalNode() {
return instance;
}
@Override
public Set<ControllerNode> getNodes() {
return ImmutableSet.of(instance);
}
@Override
public Set<Node> getConsensusNodes() {
return ImmutableSet.of();
}
@Override
public ControllerNode getNode(NodeId nodeId) {
if (instance.id().equals(nodeId)) {
return instance;
}
return null;
}
@Override
public State getState(NodeId nodeId) {
if (instance.id().equals(nodeId)) {
return State.ACTIVE;
} else {
return State.INACTIVE;
}
}
@Override
public Version getVersion(NodeId nodeId) {
if (instance.id().equals(nodeId)) {
return versionService.version();
}
return null;
}
@Override
public Instant getLastUpdatedInstant(NodeId nodeId) {
return creationTime;
}
@Override
public void addListener(ClusterEventListener listener) {
}
@Override
public void removeListener(ClusterEventListener listener) {
}
};
}
log.info("Started");
}
Aggregations