[ONOS-6371] (vNet) mastership manager implementation
Implment a mastership manager for mastership service, mastership
admin service, and mastership term service for virtual network.
Moreover, a simple balancing roles method is included that balancing
accoridng to a virtual network identifier.
Change-Id: I68064775734438d59c576106c49d1ea72836caa8
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMastershipManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMastershipManager.java
index 273ecbb..b651fb1 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMastershipManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkMastershipManager.java
@@ -16,11 +16,16 @@
package org.onosproject.incubator.net.virtual.impl;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
import org.onlab.metrics.MetricsService;
+import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.core.MetricsHelper;
import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualDevice;
import org.onosproject.incubator.net.virtual.VirtualNetworkMastershipStore;
import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.incubator.net.virtual.event.AbstractVirtualListenerManager;
@@ -33,18 +38,39 @@
import org.onosproject.mastership.MastershipTermService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
+import org.slf4j.Logger;
+import com.codahale.metrics.Timer;
+import java.util.Comparator;
+import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.newArrayList;
+import static org.onlab.metrics.MetricsUtil.startTimer;
+import static org.onlab.metrics.MetricsUtil.stopTimer;
+import static org.slf4j.LoggerFactory.getLogger;
+
public class VirtualNetworkMastershipManager
extends AbstractVirtualListenerManager<MastershipEvent, MastershipListener>
implements MastershipService, MastershipAdminService, MastershipTermService,
MetricsHelper {
+ private static final String NODE_ID_NULL = "Node ID cannot be null";
+ private static final String DEVICE_ID_NULL = "Device ID cannot be null";
+ private static final String ROLE_NULL = "Mastership role cannot be null";
+
+ private final Logger log = getLogger(getClass());
+
+ protected ClusterService clusterService;
+
VirtualNetworkMastershipStore store;
MastershipStoreDelegate storeDelegate;
+ private NodeId localNodeId;
+ private Timer requestRoleTimer;
+
/**
* Creates a new VirtualNetworkMastershipManager object.
*
@@ -54,59 +80,117 @@
public VirtualNetworkMastershipManager(VirtualNetworkService manager, NetworkId networkId) {
super(manager, networkId, MastershipEvent.class);
+ clusterService = serviceDirectory.get(ClusterService.class);
+
store = serviceDirectory.get(VirtualNetworkMastershipStore.class);
this.storeDelegate = new InternalDelegate();
store.setDelegate(networkId, this.storeDelegate);
+
+ requestRoleTimer = createTimer("Virtual-mastership", "requestRole", "responseTime");
+ localNodeId = clusterService.getLocalNode().id();
}
@Override
- public MetricsService metricsService() {
- return null;
+ public CompletableFuture<Void> setRole(NodeId nodeId, DeviceId deviceId,
+ MastershipRole role) {
+ checkNotNull(nodeId, NODE_ID_NULL);
+ checkNotNull(deviceId, DEVICE_ID_NULL);
+ checkNotNull(role, ROLE_NULL);
+
+ CompletableFuture<MastershipEvent> eventFuture = null;
+
+ switch (role) {
+ case MASTER:
+ eventFuture = store.setMaster(networkId, nodeId, deviceId);
+ break;
+ case STANDBY:
+ eventFuture = store.setStandby(networkId, nodeId, deviceId);
+ break;
+ case NONE:
+ eventFuture = store.relinquishRole(networkId, nodeId, deviceId);
+ break;
+ default:
+ log.info("Unknown role; ignoring");
+ return CompletableFuture.completedFuture(null);
+ }
+
+ return eventFuture.thenAccept(this::post).thenApply(v -> null);
+ }
+
+ @Override
+ public MastershipRole getLocalRole(DeviceId deviceId) {
+ checkNotNull(deviceId, DEVICE_ID_NULL);
+
+ return store.getRole(networkId, localNodeId, deviceId);
+ }
+
+ @Override
+ public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
+ checkNotNull(deviceId, DEVICE_ID_NULL);
+
+ final Timer.Context timer = startTimer(requestRoleTimer);
+ return store.requestRole(networkId, deviceId)
+ .whenComplete((result, error) -> stopTimer(timer));
+ }
+
+ @Override
+ public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
+ return store.relinquishRole(networkId, localNodeId, deviceId)
+ .thenAccept(this::post)
+ .thenApply(v -> null);
+ }
+
+ @Override
+ public NodeId getMasterFor(DeviceId deviceId) {
+ checkNotNull(deviceId, DEVICE_ID_NULL);
+
+ return store.getMaster(networkId, deviceId);
+ }
+
+ @Override
+ public RoleInfo getNodesFor(DeviceId deviceId) {
+ checkNotNull(deviceId, DEVICE_ID_NULL);
+
+ return store.getNodes(networkId, deviceId);
+ }
+
+ @Override
+ public Set<DeviceId> getDevicesOf(NodeId nodeId) {
+ checkNotNull(nodeId, NODE_ID_NULL);
+
+ return store.getDevices(networkId, nodeId);
}
@Override
public MastershipTerm getMastershipTerm(DeviceId deviceId) {
- return null;
+ return store.getTermFor(networkId, deviceId);
}
@Override
- public CompletableFuture<Void> setRole(NodeId instance, DeviceId deviceId, MastershipRole role) {
+ public MetricsService metricsService() {
+ //TODO: support metric service for virtual network
+ log.warn("Currently, virtual network does not support metric service.");
return null;
}
@Override
public void balanceRoles() {
+ //FIXME: More advanced logic for balancing virtual network roles.
+ List<ControllerNode> nodes = newArrayList(clusterService.getNodes());
+ nodes.sort(Comparator.comparing(ControllerNode::id));
- }
+ //Pick a node using network Id,
+ NodeId masterNode = nodes.get((int) (networkId.id() % nodes.size())).id();
- @Override
- public MastershipRole getLocalRole(DeviceId deviceId) {
- return null;
- }
+ List<CompletableFuture<Void>> setRoleFutures = Lists.newLinkedList();
+ for (VirtualDevice device : manager.getVirtualDevices(networkId)) {
+ setRoleFutures.add(setRole(masterNode, device.id(), MastershipRole.MASTER));
+ }
- @Override
- public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
- return null;
- }
+ CompletableFuture<Void> balanceRolesFuture = CompletableFuture.allOf(
+ setRoleFutures.toArray(new CompletableFuture[setRoleFutures.size()]));
- @Override
- public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
- return null;
- }
-
- @Override
- public NodeId getMasterFor(DeviceId deviceId) {
- return null;
- }
-
- @Override
- public RoleInfo getNodesFor(DeviceId deviceId) {
- return null;
- }
-
- @Override
- public Set<DeviceId> getDevicesOf(NodeId nodeId) {
- return null;
+ Futures.getUnchecked(balanceRolesFuture);
}
public class InternalDelegate implements MastershipStoreDelegate {
@@ -115,4 +199,5 @@
post(event);
}
}
+
}