blob: 57c0774c9fab4c869c778cd36b917002d36daf54 [file] [log] [blame]
Yoonseon Hana578d762017-05-08 13:42:02 -07001/*
Thomas Vachuska52f2cd12018-11-08 21:20:04 -08002 * Copyright 2018-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;
Jordan Halterman0a2bd452018-06-13 17:24:58 -070034import org.onosproject.mastership.MastershipInfo;
Yoonseon Hana578d762017-05-08 13:42:02 -070035import org.onosproject.mastership.MastershipListener;
36import org.onosproject.mastership.MastershipService;
37import org.onosproject.mastership.MastershipStoreDelegate;
38import org.onosproject.mastership.MastershipTerm;
39import org.onosproject.mastership.MastershipTermService;
40import org.onosproject.net.DeviceId;
41import org.onosproject.net.MastershipRole;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070042import org.slf4j.Logger;
43import com.codahale.metrics.Timer;
Yoonseon Hana578d762017-05-08 13:42:02 -070044
Yoonseon Hanaea0f332017-05-23 10:31:11 -070045import java.util.Comparator;
46import java.util.List;
Yoonseon Hana578d762017-05-08 13:42:02 -070047import java.util.Set;
48import java.util.concurrent.CompletableFuture;
Yoonseon Hanea8ac722017-05-24 17:25:01 -070049import java.util.stream.Collectors;
Yoonseon Hana578d762017-05-08 13:42:02 -070050
Yoonseon Hanaea0f332017-05-23 10:31:11 -070051import static com.google.common.base.Preconditions.checkNotNull;
Yoonseon Hanaea0f332017-05-23 10:31:11 -070052import static org.onlab.metrics.MetricsUtil.startTimer;
53import static org.onlab.metrics.MetricsUtil.stopTimer;
54import static org.slf4j.LoggerFactory.getLogger;
55
Yoonseon Hana578d762017-05-08 13:42:02 -070056public class VirtualNetworkMastershipManager
57 extends AbstractVirtualListenerManager<MastershipEvent, MastershipListener>
58 implements MastershipService, MastershipAdminService, MastershipTermService,
59 MetricsHelper {
60
Yoonseon Hanaea0f332017-05-23 10:31:11 -070061 private static final String NODE_ID_NULL = "Node ID cannot be null";
62 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
63 private static final String ROLE_NULL = "Mastership role cannot be null";
64
65 private final Logger log = getLogger(getClass());
66
67 protected ClusterService clusterService;
68
Yoonseon Hana578d762017-05-08 13:42:02 -070069 VirtualNetworkMastershipStore store;
70 MastershipStoreDelegate storeDelegate;
71
Yoonseon Hanaea0f332017-05-23 10:31:11 -070072 private NodeId localNodeId;
73 private Timer requestRoleTimer;
74
Yoonseon Hana578d762017-05-08 13:42:02 -070075 /**
76 * Creates a new VirtualNetworkMastershipManager object.
77 *
78 * @param manager virtual network manager service
79 * @param networkId virtual network identifier
80 */
81 public VirtualNetworkMastershipManager(VirtualNetworkService manager, NetworkId networkId) {
82 super(manager, networkId, MastershipEvent.class);
83
Yoonseon Hanaea0f332017-05-23 10:31:11 -070084 clusterService = serviceDirectory.get(ClusterService.class);
85
Yoonseon Hana578d762017-05-08 13:42:02 -070086 store = serviceDirectory.get(VirtualNetworkMastershipStore.class);
87 this.storeDelegate = new InternalDelegate();
88 store.setDelegate(networkId, this.storeDelegate);
Yoonseon Hanaea0f332017-05-23 10:31:11 -070089
90 requestRoleTimer = createTimer("Virtual-mastership", "requestRole", "responseTime");
91 localNodeId = clusterService.getLocalNode().id();
Yoonseon Hana578d762017-05-08 13:42:02 -070092 }
93
94 @Override
Yoonseon Hanaea0f332017-05-23 10:31:11 -070095 public CompletableFuture<Void> setRole(NodeId nodeId, DeviceId deviceId,
96 MastershipRole role) {
97 checkNotNull(nodeId, NODE_ID_NULL);
98 checkNotNull(deviceId, DEVICE_ID_NULL);
99 checkNotNull(role, ROLE_NULL);
100
101 CompletableFuture<MastershipEvent> eventFuture = null;
102
103 switch (role) {
104 case MASTER:
105 eventFuture = store.setMaster(networkId, nodeId, deviceId);
106 break;
107 case STANDBY:
108 eventFuture = store.setStandby(networkId, nodeId, deviceId);
109 break;
110 case NONE:
111 eventFuture = store.relinquishRole(networkId, nodeId, deviceId);
112 break;
113 default:
114 log.info("Unknown role; ignoring");
115 return CompletableFuture.completedFuture(null);
116 }
117
118 return eventFuture.thenAccept(this::post).thenApply(v -> null);
119 }
120
121 @Override
122 public MastershipRole getLocalRole(DeviceId deviceId) {
123 checkNotNull(deviceId, DEVICE_ID_NULL);
124
125 return store.getRole(networkId, localNodeId, deviceId);
126 }
127
128 @Override
129 public CompletableFuture<MastershipRole> requestRoleFor(DeviceId deviceId) {
130 checkNotNull(deviceId, DEVICE_ID_NULL);
131
132 final Timer.Context timer = startTimer(requestRoleTimer);
133 return store.requestRole(networkId, deviceId)
134 .whenComplete((result, error) -> stopTimer(timer));
135 }
136
137 @Override
138 public CompletableFuture<Void> relinquishMastership(DeviceId deviceId) {
139 return store.relinquishRole(networkId, localNodeId, deviceId)
140 .thenAccept(this::post)
141 .thenApply(v -> null);
142 }
143
144 @Override
145 public NodeId getMasterFor(DeviceId deviceId) {
146 checkNotNull(deviceId, DEVICE_ID_NULL);
147
148 return store.getMaster(networkId, deviceId);
149 }
150
151 @Override
152 public RoleInfo getNodesFor(DeviceId deviceId) {
153 checkNotNull(deviceId, DEVICE_ID_NULL);
154
155 return store.getNodes(networkId, deviceId);
156 }
157
158 @Override
Jordan Halterman0a2bd452018-06-13 17:24:58 -0700159 public MastershipInfo getMastershipFor(DeviceId deviceId) {
160 checkNotNull(deviceId, DEVICE_ID_NULL);
161 return store.getMastership(networkId, deviceId);
162 }
163
164 @Override
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700165 public Set<DeviceId> getDevicesOf(NodeId nodeId) {
166 checkNotNull(nodeId, NODE_ID_NULL);
167
168 return store.getDevices(networkId, nodeId);
Yoonseon Hana578d762017-05-08 13:42:02 -0700169 }
170
171 @Override
172 public MastershipTerm getMastershipTerm(DeviceId deviceId) {
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700173 return store.getTermFor(networkId, deviceId);
Yoonseon Hana578d762017-05-08 13:42:02 -0700174 }
175
176 @Override
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700177 public MetricsService metricsService() {
178 //TODO: support metric service for virtual network
179 log.warn("Currently, virtual network does not support metric service.");
Yoonseon Hana578d762017-05-08 13:42:02 -0700180 return null;
181 }
182
183 @Override
184 public void balanceRoles() {
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700185 //FIXME: More advanced logic for balancing virtual network roles.
Yoonseon Hanea8ac722017-05-24 17:25:01 -0700186 List<ControllerNode> nodes = clusterService.getNodes().stream()
187 .filter(n -> clusterService.getState(n.id())
188 .equals(ControllerNode.State.ACTIVE))
189 .collect(Collectors.toList());
190
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700191 nodes.sort(Comparator.comparing(ControllerNode::id));
Yoonseon Hana578d762017-05-08 13:42:02 -0700192
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700193 //Pick a node using network Id,
Yoonseon Hanea8ac722017-05-24 17:25:01 -0700194 NodeId masterNode = nodes.get((int) ((networkId.id() - 1) % nodes.size())).id();
Yoonseon Hana578d762017-05-08 13:42:02 -0700195
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700196 List<CompletableFuture<Void>> setRoleFutures = Lists.newLinkedList();
197 for (VirtualDevice device : manager.getVirtualDevices(networkId)) {
198 setRoleFutures.add(setRole(masterNode, device.id(), MastershipRole.MASTER));
199 }
Yoonseon Hana578d762017-05-08 13:42:02 -0700200
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700201 CompletableFuture<Void> balanceRolesFuture = CompletableFuture.allOf(
202 setRoleFutures.toArray(new CompletableFuture[setRoleFutures.size()]));
Yoonseon Hana578d762017-05-08 13:42:02 -0700203
Yoonseon Hanaea0f332017-05-23 10:31:11 -0700204 Futures.getUnchecked(balanceRolesFuture);
Yoonseon Hana578d762017-05-08 13:42:02 -0700205 }
206
207 public class InternalDelegate implements MastershipStoreDelegate {
208 @Override
209 public void notify(MastershipEvent event) {
210 post(event);
211 }
212 }
Yoonseon Hana578d762017-05-08 13:42:02 -0700213}