use of org.onosproject.cluster.NodeId in project onos by opennetworkinglab.
the class GeneralDeviceProvider method roleChanged.
@Override
public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
final MastershipInfo mastershipInfo = mastershipService.getMastershipFor(deviceId);
final NodeId localNodeId = clusterService.getLocalNode().id();
if (!mastershipInfo.getRole(localNodeId).equals(newRole)) {
log.warn("Inconsistent mastership info for {}! Requested {}, but " + "mastership service reports {}, will apply the latter...", deviceId, newRole, mastershipInfo.getRole(localNodeId));
newRole = mastershipInfo.getRole(localNodeId);
}
final DeviceHandshaker handshaker = getBehaviour(deviceId, DeviceHandshaker.class);
if (handshaker == null) {
log.error("Null handshaker. Unable to notify role {} to {}", newRole, deviceId);
return;
}
// Derive preference value.
final int preference;
switch(newRole) {
case MASTER:
preference = 0;
break;
case STANDBY:
preference = mastershipInfo.backups().indexOf(localNodeId) + 1;
if (preference == 0) {
// Not found in list.
log.error("Unable to derive mastership preference for {}, " + "requested role {} but local node ID was " + "not found among list of backup nodes " + "reported by mastership service", deviceId, newRole);
return;
}
break;
case NONE:
// No preference for NONE, apply as is.
Pair<MastershipRole, Integer> pairRolePref = Pair.of(newRole, -1);
if (log.isDebugEnabled()) {
log.debug("Notifying role {} to {}", newRole, deviceId);
} else if (!pairRolePref.equals(lastRoleRequest.get(deviceId))) {
log.info("Notifying role {} to {}", newRole, deviceId);
}
lastRoleRequest.put(deviceId, pairRolePref);
handshaker.roleChanged(newRole);
return;
default:
log.error("Unrecognized mastership role {}", newRole);
return;
}
Pair<MastershipRole, Integer> pairRolePref = Pair.of(newRole, preference);
if (log.isDebugEnabled()) {
log.debug("Notifying role {} (preference {}) for term {} to {}", newRole, preference, mastershipInfo.term(), deviceId);
} else if (!pairRolePref.equals(lastRoleRequest.get(deviceId))) {
log.info("Notifying role {} (preference {}) for term {} to {}", newRole, preference, mastershipInfo.term(), deviceId);
}
lastRoleRequest.put(deviceId, pairRolePref);
try {
handshaker.roleChanged(preference, mastershipInfo.term());
} catch (UnsupportedOperationException e) {
// Preference-based method not supported.
handshaker.roleChanged(newRole);
}
}
use of org.onosproject.cluster.NodeId in project onos by opennetworkinglab.
the class MastershipWebResource method getMasterFor.
/**
* Returns the current master for a given device.
*
* @param deviceId device identifier
* @return 200 OK with the identifier of the master controller for the device
* @onos.rsModel NodeId
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{deviceId}/master")
public Response getMasterFor(@PathParam("deviceId") String deviceId) {
MastershipService mastershipService = get(MastershipService.class);
NodeId id = nullIsNotFound(mastershipService.getMasterFor(DeviceId.deviceId(deviceId)), NODE_ID_NOT_FOUND);
ObjectNode root = mapper().createObjectNode();
root.put(NODE_ID, id.id());
return ok(root).build();
}
use of org.onosproject.cluster.NodeId in project onos by opennetworkinglab.
the class ProxyTestCommand method doExecute.
@Override
protected void doExecute() {
ProxyTest proxyTest = get(ProxyTest.class);
TestProxy proxy;
if ("node".equals(type)) {
NodeId nodeId = NodeId.nodeId(arg1);
proxy = proxyTest.getProxyFor(nodeId);
} else if ("master".equals(type)) {
DeviceId deviceId = DeviceId.deviceId(arg1);
proxy = proxyTest.getProxyFor(deviceId);
} else {
throw new IllegalArgumentException("Unknown operation type " + type);
}
if ("sync".equals(operation)) {
print("%s", proxy.testSync(arg2));
} else if ("async".equals(operation)) {
try {
print("%s", proxy.testAsync(arg2).get(10, TimeUnit.SECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
throw new IllegalStateException(e);
}
} else {
throw new IllegalArgumentException("Unknown operation " + operation);
}
}
use of org.onosproject.cluster.NodeId 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.NodeId in project onos by opennetworkinglab.
the class DeviceManager method updateMastershipFor.
/**
* Update the mastership for this device. If there is a node able
* to reach the device and this node is the master move the
* mastership to the next node still connected to this device.
* If the current node is a backup, it demotes itself to the bottom
* of the candidates list
*
* @param deviceId the device for which we have to update the mastership
* @return the NodeId of any node that can reach the device, or null if
* none of the ONOS instances can reach the device
*/
private NodeId updateMastershipFor(DeviceId deviceId) {
Map<NodeId, CompletableFuture<Boolean>> probes = Maps.newHashMap();
// Request a probe only if the node is ready
for (ControllerNode onosNode : clusterService.getNodes()) {
if (!clusterService.getState(onosNode.id()).isReady() || localNodeId.equals(onosNode.id())) {
continue;
}
probes.put(onosNode.id(), communicationService.sendAndReceive(deviceId, PROBE_SUBJECT, SERIALIZER::encode, SERIALIZER::decode, onosNode.id()));
}
// Returns the first node able to reach the device
// FIXME [SDFAB-935] optimize by looking at the MastershipInfo
boolean isReachable;
NodeId nextMaster = null;
// FIXME Should we expose timeout? Understand if there is need to signal to the caller
for (Map.Entry<NodeId, CompletableFuture<Boolean>> probe : probes.entrySet()) {
isReachable = Tools.futureGetOrElse(probe.getValue(), PROBE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS, Boolean.FALSE);
if (isReachable) {
nextMaster = probe.getKey();
}
}
// FIXME [SDFAB-935] optimize demote by looking at the MastershipInfo;
if (nextMaster != null) {
log.info("Device {} is still connected to {}", deviceId, nextMaster);
MastershipRole myRole = mastershipService.getLocalRole(deviceId);
if (myRole == MASTER) {
log.info("Handing over the mastership of {} to next master {}", deviceId, nextMaster);
mastershipAdminService.setRole(nextMaster, deviceId, MASTER);
// Do not demote here because setRole can return before the mastership has been passed.
// Current implementation promotes first the nextMaster as top of candidate list and then
// transfer the leadership. We can use the BACKUP events to do demote or leverage periodic
// checks.
} else if (myRole == STANDBY) {
log.info("Demote current instance to the bottom of the candidates list for {}", deviceId);
mastershipAdminService.demote(localNodeId, deviceId);
} else {
log.debug("No valid role for {}", deviceId);
}
}
return nextMaster;
}
Aggregations