blob: 8e5d005172872fc154be173e337c625034ba47eb [file] [log] [blame]
Yoonseon Hana578d762017-05-08 13:42:02 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yoonseon Hana578d762017-05-08 13:42:02 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.incubator.net.virtual.impl;
18
Yoonseon Hanaea0f332017-05-23 10:31:11 -070019import com.google.common.collect.Lists;
20import com.google.common.util.concurrent.Futures;
Yoonseon Hana578d762017-05-08 13:42:02 -070021import org.onlab.metrics.MetricsService;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070022import org.onosproject.cluster.ClusterService;
23import org.onosproject.cluster.ControllerNode;
Yoonseon Hana578d762017-05-08 13:42:02 -070024import org.onosproject.cluster.NodeId;
25import org.onosproject.cluster.RoleInfo;
26import org.onosproject.core.MetricsHelper;
27import org.onosproject.incubator.net.virtual.NetworkId;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070028import org.onosproject.incubator.net.virtual.VirtualDevice;
Yoonseon Hana578d762017-05-08 13:42:02 -070029import org.onosproject.incubator.net.virtual.VirtualNetworkMastershipStore;
30import org.onosproject.incubator.net.virtual.VirtualNetworkService;
31import org.onosproject.incubator.net.virtual.event.AbstractVirtualListenerManager;
32import org.onosproject.mastership.MastershipAdminService;
33import org.onosproject.mastership.MastershipEvent;
34import org.onosproject.mastership.MastershipListener;
35import org.onosproject.mastership.MastershipService;
36import org.onosproject.mastership.MastershipStoreDelegate;
37import org.onosproject.mastership.MastershipTerm;
38import org.onosproject.mastership.MastershipTermService;
39import org.onosproject.net.DeviceId;
40import org.onosproject.net.MastershipRole;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070041import org.slf4j.Logger;
42import com.codahale.metrics.Timer;
Yoonseon Hana578d762017-05-08 13:42:02 -070043
Yoonseon Hanaea0f332017-05-23 10:31:11 -070044import java.util.Comparator;
45import java.util.List;
Yoonseon Hana578d762017-05-08 13:42:02 -070046import java.util.Set;
47import java.util.concurrent.CompletableFuture;
Yoonseon Hanea8ac722017-05-24 17:25:01 -070048import java.util.stream.Collectors;
Yoonseon Hana578d762017-05-08 13:42:02 -070049
Yoonseon Hanaea0f332017-05-23 10:31:11 -070050import static com.google.common.base.Preconditions.checkNotNull;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070051import static org.onlab.metrics.MetricsUtil.startTimer;
52import static org.onlab.metrics.MetricsUtil.stopTimer;
53import static org.slf4j.LoggerFactory.getLogger;
54
Yoonseon Hana578d762017-05-08 13:42:02 -070055public class VirtualNetworkMastershipManager
56 extends AbstractVirtualListenerManager<MastershipEvent, MastershipListener>
57 implements MastershipService, MastershipAdminService, MastershipTermService,
58 MetricsHelper {
59
Yoonseon Hanaea0f332017-05-23 10:31:11 -070060 private static final String NODE_ID_NULL = "Node ID cannot be null";
61 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
62 private static final String ROLE_NULL = "Mastership role cannot be null";
63
64 private final Logger log = getLogger(getClass());
65
66 protected ClusterService clusterService;
67
Yoonseon Hana578d762017-05-08 13:42:02 -070068 VirtualNetworkMastershipStore store;
69 MastershipStoreDelegate storeDelegate;
70
Yoonseon Hanaea0f332017-05-23 10:31:11 -070071 private NodeId localNodeId;
72 private Timer requestRoleTimer;
73
Yoonseon Hana578d762017-05-08 13:42:02 -070074 /**
75 * Creates a new VirtualNetworkMastershipManager object.
76 *
77 * @param manager virtual network manager service
78 * @param networkId virtual network identifier
79 */
80 public VirtualNetworkMastershipManager(VirtualNetworkService manager, NetworkId networkId) {
81 super(manager, networkId, MastershipEvent.class);
82
Yoonseon Hanaea0f332017-05-23 10:31:11 -070083 clusterService = serviceDirectory.get(ClusterService.class);
84
Yoonseon Hana578d762017-05-08 13:42:02 -070085 store = serviceDirectory.get(VirtualNetworkMastershipStore.class);
86 this.storeDelegate = new InternalDelegate();
87 store.setDelegate(networkId, this.storeDelegate);
Yoonseon Hanaea0f332017-05-23 10:31:11 -070088
89 requestRoleTimer = createTimer("Virtual-mastership", "requestRole", "responseTime");
90 localNodeId = clusterService.getLocalNode().id();
Yoonseon Hana578d762017-05-08 13:42:02 -070091 }
92
93 @Override
Yoonseon Hanaea0f332017-05-23 10:31:11 -070094 public CompletableFuture<Void> setRole(NodeId nodeId, DeviceId deviceId,
95 MastershipRole role) {
96 checkNotNull(nodeId, NODE_ID_NULL);
97 checkNotNull(deviceId, DEVICE_ID_NULL);
98 checkNotNull(role, ROLE_NULL);
99
100 CompletableFuture<MastershipEvent> eventFuture = null;
101
102 switch (role) {
103 case MASTER:
104 eventFuture = store.setMaster(networkId, nodeId, deviceId);
105 break;
106 case STANDBY:
107 eventFuture = store.setStandby(networkId, nodeId, deviceId);
108 break;
109 case NONE:
110 eventFuture = store.relinquishRole(networkId, nodeId, deviceId);
111 break;
112 default:
113 log.info("Unknown role; ignoring");
114 return CompletableFuture.completedFuture(null);
115 }
116
117 return eventFuture.thenAccept(this::post).thenApply(v -> null);
118 }
119
120 @Override
121 public MastershipRole getLocalRole(DeviceId deviceId) {
122 checkNotNull(deviceId, DEVICE_ID_NULL);
123
124 return store.getRole(networkId, localNodeId, deviceId);
125 }
126
127 @Override
128 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
129 checkNotNull(deviceId, DEVICE_ID_NULL);
130
131 final Timer.Context timer = startTimer(requestRoleTimer);
132 return store.requestRole(networkId, deviceId)
133 .whenComplete((result, error) -> stopTimer(timer));
134 }
135
136 @Override
137 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
138 return store.relinquishRole(networkId, localNodeId, deviceId)
139 .thenAccept(this::post)
140 .thenApply(v -> null);
141 }
142
143 @Override
144 public NodeId getMasterFor(DeviceId deviceId) {
145 checkNotNull(deviceId, DEVICE_ID_NULL);
146
147 return store.getMaster(networkId, deviceId);
148 }
149
150 @Override
151 public RoleInfo getNodesFor(DeviceId deviceId) {
152 checkNotNull(deviceId, DEVICE_ID_NULL);
153
154 return store.getNodes(networkId, deviceId);
155 }
156
157 @Override
158 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
159 checkNotNull(nodeId, NODE_ID_NULL);
160
161 return store.getDevices(networkId, nodeId);
Yoonseon Hana578d762017-05-08 13:42:02 -0700162 }
163
164 @Override
165 public MastershipTerm getMastershipTerm(DeviceId deviceId) {
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700166 return store.getTermFor(networkId, deviceId);
Yoonseon Hana578d762017-05-08 13:42:02 -0700167 }
168
169 @Override
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700170 public MetricsService metricsService() {
171 //TODO: support metric service for virtual network
172 log.warn("Currently, virtual network does not support metric service.");
Yoonseon Hana578d762017-05-08 13:42:02 -0700173 return null;
174 }
175
176 @Override
177 public void balanceRoles() {
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700178 //FIXME: More advanced logic for balancing virtual network roles.
Yoonseon Hanea8ac722017-05-24 17:25:01 -0700179 List<ControllerNode> nodes = clusterService.getNodes().stream()
180 .filter(n -> clusterService.getState(n.id())
181 .equals(ControllerNode.State.ACTIVE))
182 .collect(Collectors.toList());
183
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700184 nodes.sort(Comparator.comparing(ControllerNode::id));
Yoonseon Hana578d762017-05-08 13:42:02 -0700185
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700186 //Pick a node using network Id,
Yoonseon Hanea8ac722017-05-24 17:25:01 -0700187 NodeId masterNode = nodes.get((int) ((networkId.id() - 1) % nodes.size())).id();
Yoonseon Hana578d762017-05-08 13:42:02 -0700188
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700189 List<CompletableFuture<Void>> setRoleFutures = Lists.newLinkedList();
190 for (VirtualDevice device : manager.getVirtualDevices(networkId)) {
191 setRoleFutures.add(setRole(masterNode, device.id(), MastershipRole.MASTER));
192 }
Yoonseon Hana578d762017-05-08 13:42:02 -0700193
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700194 CompletableFuture<Void> balanceRolesFuture = CompletableFuture.allOf(
195 setRoleFutures.toArray(new CompletableFuture[setRoleFutures.size()]));
Yoonseon Hana578d762017-05-08 13:42:02 -0700196
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700197 Futures.getUnchecked(balanceRolesFuture);
Yoonseon Hana578d762017-05-08 13:42:02 -0700198 }
199
200 public class InternalDelegate implements MastershipStoreDelegate {
201 @Override
202 public void notify(MastershipEvent event) {
203 post(event);
204 }
205 }
Yoonseon Hana578d762017-05-08 13:42:02 -0700206}