blob: 2bf4ee89bb04cc7c1eacb00e165919e01ab0ed42 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.device.impl;
tomd3097b02014-08-26 10:40:29 -070017
Yafit Hadara9a73de2015-09-06 13:52:52 +030018import static com.google.common.base.Preconditions.checkNotNull;
19import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
20import static org.onlab.util.Tools.groupedThreads;
Thomas Vachuskafa8aa2f2015-10-13 11:56:59 -070021import static org.onlab.util.Tools.nullIsNotFound;
Yafit Hadara9a73de2015-09-06 13:52:52 +030022import static org.onosproject.net.MastershipRole.MASTER;
23import static org.onosproject.net.MastershipRole.NONE;
24import static org.onosproject.net.MastershipRole.STANDBY;
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -070025import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
26import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
Yafit Hadara9a73de2015-09-06 13:52:52 +030027import static org.onosproject.security.AppGuard.checkPermission;
28import static org.onosproject.security.AppPermission.Type.DEVICE_READ;
29import static org.slf4j.LoggerFactory.getLogger;
30
31import java.util.Collection;
32import java.util.HashSet;
33import java.util.List;
34import java.util.Objects;
35import java.util.Set;
36import java.util.concurrent.CompletableFuture;
37import java.util.concurrent.ExecutionException;
38import java.util.concurrent.ScheduledExecutorService;
39import java.util.concurrent.TimeUnit;
40import java.util.stream.Collectors;
Madan Jampani565a66a2015-07-25 17:01:13 -070041
tomd3097b02014-08-26 10:40:29 -070042import org.apache.felix.scr.annotations.Activate;
43import org.apache.felix.scr.annotations.Component;
44import org.apache.felix.scr.annotations.Deactivate;
tom5f38b3a2014-08-27 23:50:54 -070045import org.apache.felix.scr.annotations.Reference;
46import org.apache.felix.scr.annotations.ReferenceCardinality;
tomd3097b02014-08-26 10:40:29 -070047import org.apache.felix.scr.annotations.Service;
Brian O'Connorabafb502014-12-02 22:26:20 -080048import org.onosproject.cluster.ClusterService;
49import org.onosproject.cluster.NodeId;
Brian O'Connorabafb502014-12-02 22:26:20 -080050import org.onosproject.mastership.MastershipEvent;
51import org.onosproject.mastership.MastershipListener;
52import org.onosproject.mastership.MastershipService;
53import org.onosproject.mastership.MastershipTerm;
54import org.onosproject.mastership.MastershipTermService;
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -070055import org.onosproject.net.ConnectPoint;
Brian O'Connorabafb502014-12-02 22:26:20 -080056import org.onosproject.net.Device;
samuel738dfaf2015-07-11 11:08:57 +080057import org.onosproject.net.Device.Type;
Brian O'Connorabafb502014-12-02 22:26:20 -080058import org.onosproject.net.DeviceId;
59import org.onosproject.net.MastershipRole;
60import org.onosproject.net.Port;
61import org.onosproject.net.PortNumber;
Yafit Hadara9a73de2015-09-06 13:52:52 +030062import org.onosproject.net.config.NetworkConfigEvent;
63import org.onosproject.net.config.NetworkConfigListener;
64import org.onosproject.net.config.NetworkConfigService;
65import org.onosproject.net.config.basics.BasicDeviceConfig;
66import org.onosproject.net.config.basics.OpticalPortConfig;
Brian O'Connorabafb502014-12-02 22:26:20 -080067import org.onosproject.net.device.DefaultDeviceDescription;
68import org.onosproject.net.device.DefaultPortDescription;
69import org.onosproject.net.device.DeviceAdminService;
Brian O'Connorabafb502014-12-02 22:26:20 -080070import org.onosproject.net.device.DeviceDescription;
71import org.onosproject.net.device.DeviceEvent;
72import org.onosproject.net.device.DeviceListener;
73import org.onosproject.net.device.DeviceProvider;
74import org.onosproject.net.device.DeviceProviderRegistry;
75import org.onosproject.net.device.DeviceProviderService;
76import org.onosproject.net.device.DeviceService;
77import org.onosproject.net.device.DeviceStore;
78import org.onosproject.net.device.DeviceStoreDelegate;
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -070079import org.onosproject.net.device.OchPortDescription;
80import org.onosproject.net.device.OduCltPortDescription;
81import org.onosproject.net.device.OmsPortDescription;
82import org.onosproject.net.device.OtuPortDescription;
Brian O'Connorabafb502014-12-02 22:26:20 -080083import org.onosproject.net.device.PortDescription;
sangho538108b2015-04-08 14:29:20 -070084import org.onosproject.net.device.PortStatistics;
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -070085import org.onosproject.net.optical.device.OmsPortHelper;
86import org.onosproject.net.optical.device.OtuPortHelper;
Yafit Hadara9a73de2015-09-06 13:52:52 +030087import org.onosproject.net.provider.AbstractListenerProviderRegistry;
Brian O'Connorabafb502014-12-02 22:26:20 -080088import org.onosproject.net.provider.AbstractProviderService;
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -070089import org.onosproject.net.provider.Provider;
tomd3097b02014-08-26 10:40:29 -070090import org.slf4j.Logger;
tomd3097b02014-08-26 10:40:29 -070091
Yafit Hadara9a73de2015-09-06 13:52:52 +030092import com.google.common.util.concurrent.Futures;
Jonathan Hart2f669362015-02-11 16:19:20 -080093
tomd3097b02014-08-26 10:40:29 -070094/**
tome4729872014-09-23 00:37:37 -070095 * Provides implementation of the device SB & NB APIs.
tomd3097b02014-08-26 10:40:29 -070096 */
97@Component(immediate = true)
98@Service
tom41a2c5f2014-09-19 09:20:35 -070099public class DeviceManager
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700100 extends AbstractListenerProviderRegistry<DeviceEvent, DeviceListener, DeviceProvider, DeviceProviderService>
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700101 implements DeviceService, DeviceAdminService, DeviceProviderRegistry {
tom32f66842014-08-27 19:27:47 -0700102
tome5ec3fd2014-09-04 15:18:06 -0700103 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
104 private static final String PORT_NUMBER_NULL = "Port number cannot be null";
105 private static final String DEVICE_DESCRIPTION_NULL = "Device description cannot be null";
106 private static final String PORT_DESCRIPTION_NULL = "Port description cannot be null";
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700107 private static final String PORT_DESC_LIST_NULL = "Port description list cannot be null";
tomd3097b02014-08-26 10:40:29 -0700108
tom5f38b3a2014-08-27 23:50:54 -0700109 private final Logger log = getLogger(getClass());
tomd3097b02014-08-26 10:40:29 -0700110
alshabib339a3d92014-09-26 17:54:32 -0700111 private final DeviceStoreDelegate delegate = new InternalStoreDelegate();
tomf80c9722014-09-24 14:49:18 -0700112
tomc78acee2014-09-24 15:16:55 -0700113 private final MastershipListener mastershipListener = new InternalMastershipListener();
Madan Jampanide003d92015-05-11 17:14:20 -0700114 private NodeId localNodeId;
tomb41d1ac2014-09-24 01:51:24 -0700115
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800116 private ScheduledExecutorService backgroundService;
117
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700118 private final NetworkConfigListener networkConfigListener = new InternalNetworkConfigListener();
119
tom41a2c5f2014-09-19 09:20:35 -0700120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected DeviceStore store;
tomd3097b02014-08-26 10:40:29 -0700122
tom5f38b3a2014-08-27 23:50:54 -0700123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
tomb41d1ac2014-09-24 01:51:24 -0700124 protected ClusterService clusterService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700127 protected MastershipService mastershipService;
128
Yuta HIGUCHIbcac4992014-11-22 19:27:57 -0800129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Ayaka Koshibe3de43ca2014-09-26 16:40:23 -0700130 protected MastershipTermService termService;
131
Madan Jampani61056bc2014-09-27 09:07:26 -0700132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700133 protected NetworkConfigService networkConfigService;
134
tomd3097b02014-08-26 10:40:29 -0700135 @Activate
136 public void activate() {
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800137 backgroundService = newSingleThreadScheduledExecutor(
138 groupedThreads("onos/device", "manager-background", log));
Madan Jampanide003d92015-05-11 17:14:20 -0700139 localNodeId = clusterService.getLocalNode().id();
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800140
tomf80c9722014-09-24 14:49:18 -0700141 store.setDelegate(delegate);
tom96dfcab2014-08-28 09:26:03 -0700142 eventDispatcher.addSink(DeviceEvent.class, listenerRegistry);
tomb41d1ac2014-09-24 01:51:24 -0700143 mastershipService.addListener(mastershipListener);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700144 networkConfigService.addListener(networkConfigListener);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800145
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700146 backgroundService.scheduleWithFixedDelay(() -> {
147 try {
148 mastershipCheck();
149 } catch (Exception e) {
150 log.error("Exception thrown during integrity check", e);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800151 }
152 }, 1, 1, TimeUnit.MINUTES);
tomd3097b02014-08-26 10:40:29 -0700153 log.info("Started");
154 }
155
156 @Deactivate
157 public void deactivate() {
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800158 backgroundService.shutdown();
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700159 networkConfigService.removeListener(networkConfigListener);
tomf80c9722014-09-24 14:49:18 -0700160 store.unsetDelegate(delegate);
tomb41d1ac2014-09-24 01:51:24 -0700161 mastershipService.removeListener(mastershipListener);
tom5f38b3a2014-08-27 23:50:54 -0700162 eventDispatcher.removeSink(DeviceEvent.class);
tomd3097b02014-08-26 10:40:29 -0700163 log.info("Stopped");
164 }
165
166 @Override
tomad2d2092014-09-06 23:24:20 -0700167 public int getDeviceCount() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900168 checkPermission(DEVICE_READ);
tomad2d2092014-09-06 23:24:20 -0700169 return store.getDeviceCount();
tomd3097b02014-08-26 10:40:29 -0700170 }
171
172 @Override
tom32f66842014-08-27 19:27:47 -0700173 public Iterable<Device> getDevices() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900174 checkPermission(DEVICE_READ);
tome5ec3fd2014-09-04 15:18:06 -0700175 return store.getDevices();
tomd3097b02014-08-26 10:40:29 -0700176 }
177
tom32f66842014-08-27 19:27:47 -0700178 @Override
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800179 public Iterable<Device> getAvailableDevices() {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900180 checkPermission(DEVICE_READ);
Yuta HIGUCHIf1f2ac02014-11-26 14:02:22 -0800181 return store.getAvailableDevices();
182 }
183
184 @Override
tom32f66842014-08-27 19:27:47 -0700185 public Device getDevice(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900186 checkPermission(DEVICE_READ);
tom32f66842014-08-27 19:27:47 -0700187 checkNotNull(deviceId, DEVICE_ID_NULL);
tom132b58a2014-08-28 16:11:28 -0700188 return store.getDevice(deviceId);
tom32f66842014-08-27 19:27:47 -0700189 }
190
191 @Override
tomad2d2092014-09-06 23:24:20 -0700192 public MastershipRole getRole(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900193 checkPermission(DEVICE_READ);
tomad2d2092014-09-06 23:24:20 -0700194 checkNotNull(deviceId, DEVICE_ID_NULL);
tomb41d1ac2014-09-24 01:51:24 -0700195 return mastershipService.getLocalRole(deviceId);
tomad2d2092014-09-06 23:24:20 -0700196 }
197
198 @Override
tom32f66842014-08-27 19:27:47 -0700199 public List<Port> getPorts(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900200 checkPermission(DEVICE_READ);
tom32f66842014-08-27 19:27:47 -0700201 checkNotNull(deviceId, DEVICE_ID_NULL);
tom132b58a2014-08-28 16:11:28 -0700202 return store.getPorts(deviceId);
tom32f66842014-08-27 19:27:47 -0700203 }
204
205 @Override
sangho538108b2015-04-08 14:29:20 -0700206 public List<PortStatistics> getPortStatistics(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900207 checkPermission(DEVICE_READ);
sangho538108b2015-04-08 14:29:20 -0700208 checkNotNull(deviceId, DEVICE_ID_NULL);
209 return store.getPortStatistics(deviceId);
210 }
211
212 @Override
Dusan Pajin11ff4a82015-08-20 18:03:05 +0200213 public List<PortStatistics> getPortDeltaStatistics(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900214 checkPermission(DEVICE_READ);
Dusan Pajin11ff4a82015-08-20 18:03:05 +0200215 checkNotNull(deviceId, DEVICE_ID_NULL);
216 return store.getPortDeltaStatistics(deviceId);
217 }
218
219 @Override
tom32f66842014-08-27 19:27:47 -0700220 public Port getPort(DeviceId deviceId, PortNumber portNumber) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900221 checkPermission(DEVICE_READ);
tom32f66842014-08-27 19:27:47 -0700222 checkNotNull(deviceId, DEVICE_ID_NULL);
223 checkNotNull(portNumber, PORT_NUMBER_NULL);
tom132b58a2014-08-28 16:11:28 -0700224 return store.getPort(deviceId, portNumber);
tom32f66842014-08-27 19:27:47 -0700225 }
226
227 @Override
tomff7eb7c2014-09-08 12:49:03 -0700228 public boolean isAvailable(DeviceId deviceId) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900229 checkPermission(DEVICE_READ);
Changhoon Yoon541ef712015-05-23 17:18:34 +0900230
tomff7eb7c2014-09-08 12:49:03 -0700231 checkNotNull(deviceId, DEVICE_ID_NULL);
232 return store.isAvailable(deviceId);
233 }
234
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700235 // Check a device for control channel connectivity.
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700236 private boolean isReachable(DeviceId deviceId) {
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800237 if (deviceId == null) {
238 return false;
239 }
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700240 DeviceProvider provider = getProvider(deviceId);
241 if (provider != null) {
242 return provider.isReachable(deviceId);
243 } else {
Yuta HIGUCHI72669c42014-11-13 14:48:17 -0800244 log.debug("Provider not found for {}", deviceId);
Ayaka Koshibee60d4522014-10-28 15:07:00 -0700245 return false;
246 }
Ayaka Koshibee8708e32014-10-22 13:40:18 -0700247 }
248
tome5ec3fd2014-09-04 15:18:06 -0700249 @Override
250 public void removeDevice(DeviceId deviceId) {
251 checkNotNull(deviceId, DEVICE_ID_NULL);
252 DeviceEvent event = store.removeDevice(deviceId);
tom0efbb1d2014-09-09 11:54:28 -0700253 if (event != null) {
254 log.info("Device {} administratively removed", deviceId);
255 post(event);
256 }
tome5ec3fd2014-09-04 15:18:06 -0700257 }
258
tom7869ad92014-09-09 14:32:08 -0700259 @Override
Saurav Dasa2d37502016-03-25 17:50:40 -0700260 public void changePortState(DeviceId deviceId, PortNumber portNumber,
261 boolean enable) {
262 checkNotNull(deviceId, DEVICE_ID_NULL);
263 checkNotNull(deviceId, PORT_NUMBER_NULL);
264 DeviceProvider provider = getProvider(deviceId);
265 if (provider != null) {
266 log.warn("Port {} on device {} being administratively brought {}",
267 portNumber, deviceId,
268 (enable) ? "UP" : "DOWN");
269 provider.changePortState(deviceId, portNumber, enable);
270 } else {
271 log.warn("Provider not found for {}", deviceId);
272 }
273 }
274
275 @Override
samuele1fa7322015-07-14 16:35:16 +0800276 protected DeviceProviderService createProviderService(
277 DeviceProvider provider) {
tom7869ad92014-09-09 14:32:08 -0700278 return new InternalDeviceProviderService(provider);
279 }
280
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800281 /**
282 * Checks if all the reachable devices have a valid mastership role.
283 */
284 private void mastershipCheck() {
285 log.debug("Checking mastership");
286 for (Device device : getDevices()) {
287 final DeviceId deviceId = device.id();
Jonathan Hart2f669362015-02-11 16:19:20 -0800288 log.trace("Checking device {}", deviceId);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800289
290 if (!isReachable(deviceId)) {
291 continue;
292 }
293
294 if (mastershipService.getLocalRole(deviceId) != NONE) {
295 continue;
296 }
297
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700298 log.info("{} is reachable but did not have a valid role, reasserting", deviceId);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800299
300 // isReachable but was not MASTER or STANDBY, get a role and apply
301 // Note: NONE triggers request to MastershipService
302 reassertRole(deviceId, NONE);
303 }
304 }
305
tomd3097b02014-08-26 10:40:29 -0700306 // Personalized device provider service issued to the supplied provider.
tomdc361b62014-09-09 20:36:52 -0700307 private class InternalDeviceProviderService
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700308 extends AbstractProviderService<DeviceProvider>
309 implements DeviceProviderService {
tomd3097b02014-08-26 10:40:29 -0700310
tomcfde0622014-09-09 11:02:42 -0700311 InternalDeviceProviderService(DeviceProvider provider) {
tomd3097b02014-08-26 10:40:29 -0700312 super(provider);
313 }
314
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700315 /**
316 * Apply role in reaction to provider event.
317 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700318 * @param deviceId device identifier
319 * @param newRole new role to apply to the device
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700320 * @return true if the request was sent to provider
321 */
322 private boolean applyRole(DeviceId deviceId, MastershipRole newRole) {
323
324 if (newRole.equals(MastershipRole.NONE)) {
samuele1fa7322015-07-14 16:35:16 +0800325 //no-op
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700326 return true;
327 }
328
329 DeviceProvider provider = provider();
330 if (provider == null) {
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700331 log.warn("Provider for {} was not found. Cannot apply role {}",
332 deviceId, newRole);
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700333 return false;
334 }
Yuta HIGUCHI54815322014-10-31 23:17:08 -0700335 provider.roleChanged(deviceId, newRole);
336 // not triggering probe when triggered by provider service event
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700337
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700338 return true;
339 }
340
tomd3097b02014-08-26 10:40:29 -0700341 @Override
alshabibb7b40632014-09-28 21:30:00 -0700342 public void deviceConnected(DeviceId deviceId,
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700343 DeviceDescription deviceDescription) {
tom32f66842014-08-27 19:27:47 -0700344 checkNotNull(deviceId, DEVICE_ID_NULL);
345 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
tomeadbb462014-09-07 16:10:19 -0700346 checkValidity();
Yuta HIGUCHI24b2e2a2014-10-07 15:53:57 -0700347
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700348 BasicDeviceConfig cfg = networkConfigService.getConfig(deviceId, BasicDeviceConfig.class);
349 if (!isAllowed(cfg)) {
350 log.warn("Device {} is not allowed", deviceId);
351 return;
352 }
353 // Generate updated description and establish my Role
354 deviceDescription = BasicDeviceOperator.combine(cfg, deviceDescription);
Madan Jampani565a66a2015-07-25 17:01:13 -0700355 Futures.getUnchecked(mastershipService.requestRoleFor(deviceId)
356 .thenAccept(role -> {
357 log.info("Local role is {} for {}", role, deviceId);
358 applyRole(deviceId, role);
359 }));
HIGUCHI Yuta11530fb2015-05-27 13:10:20 -0700360
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700361 DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId,
362 deviceDescription);
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700363 log.info("Device {} connected", deviceId);
tom80c0e5e2014-09-08 18:08:58 -0700364 if (event != null) {
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700365 log.trace("event: {} {}", event.type(), event);
tom568581d2014-09-08 20:13:36 -0700366 post(event);
tom80c0e5e2014-09-08 18:08:58 -0700367 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700368
tomd3097b02014-08-26 10:40:29 -0700369 }
370
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700371 private PortDescription ensurePortEnabledState(PortDescription desc, boolean enabled) {
372 if (desc.isEnabled() != enabled) {
373 return new DefaultPortDescription(desc.portNumber(),
374 enabled,
375 desc.type(),
376 desc.portSpeed(),
377 desc.annotations());
378 }
379 return desc;
380 }
381
tomd3097b02014-08-26 10:40:29 -0700382 @Override
383 public void deviceDisconnected(DeviceId deviceId) {
tom32f66842014-08-27 19:27:47 -0700384 checkNotNull(deviceId, DEVICE_ID_NULL);
tomeadbb462014-09-07 16:10:19 -0700385 checkValidity();
Yuta HIGUCHIcf603902014-10-07 23:04:32 -0700386
Yuta HIGUCHI2d3cd312014-10-31 11:38:04 -0700387 log.info("Device {} disconnected from this node", deviceId);
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700388
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700389 List<PortDescription> descs = store.getPortDescriptions(provider().id(), deviceId)
390 .map(desc -> ensurePortEnabledState(desc, false))
391 .collect(Collectors.toList());
Yafit Hadara9a73de2015-09-06 13:52:52 +0300392
alshabibafc514a2014-12-01 14:44:05 -0800393 store.updatePorts(this.provider().id(), deviceId, descs);
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700394 try {
Madan Jampani565a66a2015-07-25 17:01:13 -0700395 if (mastershipService.isLocalMaster(deviceId)) {
Thomas Vachuska5f429d62015-05-28 15:34:36 -0700396 post(store.markOffline(deviceId));
397 }
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700398 } catch (IllegalStateException e) {
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700399 log.warn("Failed to mark {} offline", deviceId);
400 // only the MASTER should be marking off-line in normal cases,
samuele1fa7322015-07-14 16:35:16 +0800401 // but if I was the last STANDBY connection, etc. and no one else
402 // was there to mark the device offline, this instance may need to
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700403 // temporarily request for Master Role and mark offline.
404
samuele1fa7322015-07-14 16:35:16 +0800405 //there are times when this node will correctly have mastership, BUT
406 //that isn't reflected in the ClockManager before the device disconnects.
407 //we want to let go of the device anyways, so make sure this happens.
Yuta HIGUCHI0722fb22014-10-19 01:16:33 -0700408
Yuta HIGUCHIeb24e9d2014-10-26 19:34:20 -0700409 // FIXME: Store semantics leaking out as IllegalStateException.
samuele1fa7322015-07-14 16:35:16 +0800410 // Consider revising store API to handle this scenario.
411 CompletableFuture<MastershipRole> roleFuture = mastershipService.requestRoleFor(deviceId);
Madan Jampanide003d92015-05-11 17:14:20 -0700412 roleFuture.whenComplete((role, error) -> {
samuele1fa7322015-07-14 16:35:16 +0800413 MastershipTerm term = termService.getMastershipTerm(deviceId);
414 // TODO: Move this type of check inside device clock manager, etc.
415 if (term != null && localNodeId.equals(term.master())) {
416 log.info("Retry marking {} offline", deviceId);
samuele1fa7322015-07-14 16:35:16 +0800417 post(store.markOffline(deviceId));
418 } else {
419 log.info("Failed again marking {} offline. {}", deviceId, role);
420 }
421 });
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700422 } finally {
Madan Jampanic6e574f2015-05-29 13:41:52 -0700423 try {
samuele1fa7322015-07-14 16:35:16 +0800424 //relinquish master role and ability to be backup.
Madan Jampanic6e574f2015-05-29 13:41:52 -0700425 mastershipService.relinquishMastership(deviceId).get();
426 } catch (InterruptedException e) {
samuele1fa7322015-07-14 16:35:16 +0800427 log.warn("Interrupted while reliquishing role for {}", deviceId);
Madan Jampanic6e574f2015-05-29 13:41:52 -0700428 Thread.currentThread().interrupt();
429 } catch (ExecutionException e) {
samuele1fa7322015-07-14 16:35:16 +0800430 log.error("Exception thrown while relinquishing role for {}", deviceId, e);
Madan Jampanic6e574f2015-05-29 13:41:52 -0700431 }
tom0efbb1d2014-09-09 11:54:28 -0700432 }
tomd3097b02014-08-26 10:40:29 -0700433 }
434
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -0700435 /**
436 * Transforms optical specific PortDescription to generic PortDescription.
437 *
438 * @param descr PortDescription
439 * @return generic PortDescription
440 * @deprecated in Goldeneye (1.6.0)
441 */
442 @Deprecated
443 private PortDescription ensureGeneric(PortDescription descr) {
444 switch (descr.type()) {
445 case OCH:
446 if (descr instanceof OchPortDescription) {
447 OchPortDescription och = (OchPortDescription) descr;
448 return ochPortDescription(och,
449 och.signalType(),
450 och.isTunable(),
451 och.lambda(),
452 och.annotations());
453 }
454 break;
455 case ODUCLT:
456 if (descr instanceof OduCltPortDescription) {
457 OduCltPortDescription clt = (OduCltPortDescription) descr;
458 return oduCltPortDescription(clt,
459 clt.signalType(),
460 clt.annotations());
461 }
462 break;
463 case OMS:
464 if (descr instanceof OmsPortDescription) {
465 OmsPortDescription oms = (OmsPortDescription) descr;
466 return OmsPortHelper.omsPortDescription(oms,
467 oms.minFrequency(),
468 oms.maxFrequency(),
469 oms.grid(),
470 oms.annotations());
471 }
472 break;
473 case OTU:
474 if (descr instanceof OtuPortDescription) {
475 OtuPortDescription otu = (OtuPortDescription) descr;
476 return OtuPortHelper.otuPortDescription(otu,
477 otu.signalType(),
478 otu.annotations());
479 }
480 break;
481
482 default:
483 // no-op
484 break;
485 }
486 return descr;
487 }
488
tomd3097b02014-08-26 10:40:29 -0700489 @Override
alshabibb7b40632014-09-28 21:30:00 -0700490 public void updatePorts(DeviceId deviceId,
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700491 List<PortDescription> portDescriptions) {
tom32f66842014-08-27 19:27:47 -0700492 checkNotNull(deviceId, DEVICE_ID_NULL);
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700493 checkNotNull(portDescriptions, PORT_DESC_LIST_NULL);
tomeadbb462014-09-07 16:10:19 -0700494 checkValidity();
Madan Jampani565a66a2015-07-25 17:01:13 -0700495 if (!mastershipService.isLocalMaster(deviceId)) {
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700496 // Never been a master for this device
497 // any update will be ignored.
samuele1fa7322015-07-14 16:35:16 +0800498 log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions);
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700499 return;
500 }
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700501 portDescriptions = portDescriptions.stream()
502 .map(e -> consolidate(deviceId, e))
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -0700503 .map(this::ensureGeneric)
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700504 .collect(Collectors.toList());
Yuta HIGUCHI5f6739c2014-10-01 14:04:01 -0700505 List<DeviceEvent> events = store.updatePorts(this.provider().id(),
samuele1fa7322015-07-14 16:35:16 +0800506 deviceId, portDescriptions);
Thomas Vachuska5923b9a2016-01-26 10:52:57 -0800507 if (events != null) {
508 for (DeviceEvent event : events) {
509 post(event);
510 }
tom32f66842014-08-27 19:27:47 -0700511 }
tomd3097b02014-08-26 10:40:29 -0700512 }
513
514 @Override
alshabibb7b40632014-09-28 21:30:00 -0700515 public void portStatusChanged(DeviceId deviceId,
Thomas Vachuskad16ce182014-10-29 17:25:29 -0700516 PortDescription portDescription) {
tom32f66842014-08-27 19:27:47 -0700517 checkNotNull(deviceId, DEVICE_ID_NULL);
518 checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
tomeadbb462014-09-07 16:10:19 -0700519 checkValidity();
Ayaka Koshibeb5c63a02014-10-18 18:42:27 -0700520
Madan Jampani565a66a2015-07-25 17:01:13 -0700521 if (!mastershipService.isLocalMaster(deviceId)) {
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700522 // Never been a master for this device
523 // any update will be ignored.
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700524 log.trace("Ignoring {} port update on standby node. {}", deviceId,
525 portDescription);
Yuta HIGUCHI13c0b872014-10-30 18:09:22 -0700526 return;
527 }
Thomas Vachuskafa8aa2f2015-10-13 11:56:59 -0700528 Device device = nullIsNotFound(getDevice(deviceId), "Device not found");
Rimon Ashkenazy8ebfff02016-02-01 11:56:36 +0200529 if ((Device.Type.ROADM.equals(device.type())) ||
530 (Device.Type.OTN.equals(device.type()))) {
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -0700531 // FIXME This is ignoring all other info in portDescription given as input??
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700532 PortDescription storedPortDesc = store.getPortDescription(provider().id(),
533 deviceId,
534 portDescription.portNumber());
535 portDescription = ensurePortEnabledState(storedPortDesc,
536 portDescription.isEnabled());
Yafit Hadara9a73de2015-09-06 13:52:52 +0300537 }
538
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700539 portDescription = consolidate(deviceId, portDescription);
samuele1fa7322015-07-14 16:35:16 +0800540 final DeviceEvent event = store.updatePortStatus(this.provider().id(),
HIGUCHI Yuta6972ae62016-05-12 19:57:46 -0700541 deviceId,
542 ensureGeneric(portDescription));
tomff7eb7c2014-09-08 12:49:03 -0700543 if (event != null) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700544 log.info("Device {} port {} status changed", deviceId, event.port().number());
tom0efbb1d2014-09-09 11:54:28 -0700545 post(event);
tomff7eb7c2014-09-08 12:49:03 -0700546 }
tomd3097b02014-08-26 10:40:29 -0700547 }
tom3f2bbd72014-09-24 12:07:58 -0700548
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700549 // merges the appropriate PortConfig with the description.
550 private PortDescription consolidate(DeviceId did, PortDescription desc) {
551 switch (desc.type()) {
552 case COPPER:
553 case VIRTUAL:
554 return desc;
555 default:
556 OpticalPortConfig opc = networkConfigService.getConfig(
557 new ConnectPoint(did, desc.portNumber()), OpticalPortConfig.class);
558 return OpticalPortOperator.combine(opc, desc);
559 }
560 }
561
tom3f2bbd72014-09-24 12:07:58 -0700562 @Override
samuele1fa7322015-07-14 16:35:16 +0800563 public void receivedRoleReply(DeviceId deviceId, MastershipRole requested,
Thomas Vachuskab17c41f2015-05-19 11:16:05 -0700564 MastershipRole response) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700565 // Several things can happen here:
566 // 1. request and response match
567 // 2. request and response don't match
568 // 3. MastershipRole and requested match (and 1 or 2 are true)
569 // 4. MastershipRole and requested don't match (and 1 or 2 are true)
570 //
571 // 2, 4, and 3 with case 2 are failure modes.
572
tom3f2bbd72014-09-24 12:07:58 -0700573 // FIXME: implement response to this notification
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700574
Madan Jampanif2af7712015-05-29 18:43:52 -0700575 log.debug("got reply to a role request for {}: asked for {}, and got {}",
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700576 deviceId, requested, response);
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700577
578 if (requested == null && response == null) {
samuele1fa7322015-07-14 16:35:16 +0800579 // something was off with DeviceProvider, maybe check channel too?
Shashikanth VH387a1ca2016-02-09 20:35:21 +0530580 log.warn("Failed to assert role onto Device {}", deviceId);
Yuta HIGUCHIcf603902014-10-07 23:04:32 -0700581 mastershipService.relinquishMastership(deviceId);
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700582 return;
Yuta HIGUCHIcf603902014-10-07 23:04:32 -0700583 }
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700584
Thomas Vachuskab17c41f2015-05-19 11:16:05 -0700585 if (Objects.equals(requested, response)) {
samuele1fa7322015-07-14 16:35:16 +0800586 if (Objects.equals(requested, mastershipService.getLocalRole(deviceId))) {
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700587 return;
588 } else {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800589 log.warn("Role mismatch on {}. set to {}, but store demands {}",
590 deviceId, response, mastershipService.getLocalRole(deviceId));
591 // roleManager got the device to comply, but doesn't agree with
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700592 // the store; use the store's view, then try to reassert.
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800593 backgroundService.execute(() -> reassertRole(deviceId, mastershipService.getLocalRole(deviceId)));
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800594 return;
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700595 }
596 } else {
597 // we didn't get back what we asked for. Reelect someone else.
samuele1fa7322015-07-14 16:35:16 +0800598 log.warn("Failed to assert role [{}] onto Device {}", response, deviceId);
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700599 if (response == MastershipRole.MASTER) {
600 mastershipService.relinquishMastership(deviceId);
601 // TODO: Shouldn't we be triggering event?
samuele1fa7322015-07-14 16:35:16 +0800602 //final Device device = getDevice(deviceId);
603 //post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device));
Ayaka Koshibe3ef2b0d2014-10-31 13:58:27 -0700604 }
605 }
tom3f2bbd72014-09-24 12:07:58 -0700606 }
sangho538108b2015-04-08 14:29:20 -0700607
608 @Override
samuele1fa7322015-07-14 16:35:16 +0800609 public void updatePortStatistics(DeviceId deviceId, Collection<PortStatistics> portStatistics) {
sangho538108b2015-04-08 14:29:20 -0700610 checkNotNull(deviceId, DEVICE_ID_NULL);
Thomas Vachuskab17c41f2015-05-19 11:16:05 -0700611 checkNotNull(portStatistics, "Port statistics list cannot be null");
sangho538108b2015-04-08 14:29:20 -0700612 checkValidity();
613
samuele1fa7322015-07-14 16:35:16 +0800614 DeviceEvent event = store.updatePortStatistics(this.provider().id(),
615 deviceId, portStatistics);
sangho538108b2015-04-08 14:29:20 -0700616 post(event);
617 }
tomd3097b02014-08-26 10:40:29 -0700618 }
tom32f66842014-08-27 19:27:47 -0700619
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700620 // by default allowed, otherwise check flag
621 private boolean isAllowed(BasicDeviceConfig cfg) {
622 return (cfg == null || cfg.isAllowed());
623 }
624
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800625 // Applies the specified role to the device; ignores NONE
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700626
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800627 /**
628 * Apply role to device and send probe if MASTER.
629 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700630 * @param deviceId device identifier
631 * @param newRole new role to apply to the device
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800632 * @return true if the request was sent to provider
633 */
634 private boolean applyRoleAndProbe(DeviceId deviceId, MastershipRole newRole) {
635 if (newRole.equals(MastershipRole.NONE)) {
samuele1fa7322015-07-14 16:35:16 +0800636 //no-op
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700637 return true;
638 }
Ayaka Koshibe317245a2014-10-29 00:34:43 -0700639
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800640 DeviceProvider provider = getProvider(deviceId);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800641 if (provider == null) {
samuele1fa7322015-07-14 16:35:16 +0800642 log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800643 return false;
644 }
645 provider.roleChanged(deviceId, newRole);
646
647 if (newRole.equals(MastershipRole.MASTER)) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800648 log.debug("sent TriggerProbe({})", deviceId);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800649 // only trigger event when request was sent to provider
Ayaka Koshibe78bcbc12014-11-19 14:28:58 -0800650 provider.triggerProbe(deviceId);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800651 }
652 return true;
653 }
654
655 /**
656 * Reaasert role for specified device connected to this node.
657 *
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700658 * @param did device identifier
659 * @param nextRole role to apply. If NONE is specified,
660 * it will ask mastership service for a role and apply it.
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800661 */
samuele1fa7322015-07-14 16:35:16 +0800662 private void reassertRole(final DeviceId did,
663 final MastershipRole nextRole) {
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800664
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800665 MastershipRole myNextRole = nextRole;
666 if (myNextRole == NONE) {
HIGUCHI Yuta1979f552015-12-28 21:24:26 -0800667 try {
668 mastershipService.requestRoleFor(did).get();
669 MastershipTerm term = termService.getMastershipTerm(did);
670 if (term != null && localNodeId.equals(term.master())) {
671 myNextRole = MASTER;
672 } else {
673 myNextRole = STANDBY;
674 }
675 } catch (InterruptedException e) {
676 Thread.currentThread().interrupt();
677 log.error("Interrupted waiting for Mastership", e);
678 } catch (ExecutionException e) {
679 log.error("Encountered an error waiting for Mastership", e);
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800680 }
681 }
682
683 switch (myNextRole) {
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700684 case MASTER:
685 final Device device = getDevice(did);
686 if ((device != null) && !isAvailable(did)) {
687 //flag the device as online. Is there a better way to do this?
688 DefaultDeviceDescription deviceDescription
689 = new DefaultDeviceDescription(did.uri(),
690 device.type(),
691 device.manufacturer(),
692 device.hwVersion(),
693 device.swVersion(),
694 device.serialNumber(),
695 device.chassisId());
696 DeviceEvent devEvent =
697 store.createOrUpdateDevice(device.providerId(), did,
698 deviceDescription);
699 post(devEvent);
700 }
701 // TODO: should apply role only if there is mismatch
702 log.debug("Applying role {} to {}", myNextRole, did);
703 if (!applyRoleAndProbe(did, MASTER)) {
704 log.warn("Unsuccessful applying role {} to {}", myNextRole, did);
705 // immediately failed to apply role
706 mastershipService.relinquishMastership(did);
707 // FIXME disconnect?
708 }
709 break;
710 case STANDBY:
711 log.debug("Applying role {} to {}", myNextRole, did);
712 if (!applyRoleAndProbe(did, STANDBY)) {
713 log.warn("Unsuccessful applying role {} to {}", myNextRole, did);
714 // immediately failed to apply role
715 mastershipService.relinquishMastership(did);
716 // FIXME disconnect?
717 }
718 break;
719 case NONE:
720 default:
721 // should never reach here
722 log.error("You didn't see anything. I did not exist.");
723 break;
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800724 }
725 }
726
Madan Jampani328371d2015-05-29 14:06:27 -0700727 private void handleMastershipEvent(MastershipEvent event) {
728 if (event.type() != MastershipEvent.Type.MASTER_CHANGED) {
729 // Don't care if backup list changed.
730 return;
731 }
732
733 final DeviceId did = event.subject();
734
735 // myRole suggested by MastershipService
736 MastershipRole myNextRole;
737 if (localNodeId.equals(event.roleInfo().master())) {
738 // confirm latest info
739 MastershipTerm term = termService.getMastershipTerm(did);
samuele1fa7322015-07-14 16:35:16 +0800740 final boolean iHaveControl = term != null && localNodeId.equals(term.master());
Madan Jampani328371d2015-05-29 14:06:27 -0700741 if (iHaveControl) {
Madan Jampani328371d2015-05-29 14:06:27 -0700742 myNextRole = MASTER;
743 } else {
744 myNextRole = STANDBY;
745 }
746 } else if (event.roleInfo().backups().contains(localNodeId)) {
747 myNextRole = STANDBY;
748 } else {
749 myNextRole = NONE;
750 }
751
Madan Jampani328371d2015-05-29 14:06:27 -0700752 final boolean isReachable = isReachable(did);
753 if (!isReachable) {
754 // device is not connected to this node
755 if (myNextRole != NONE) {
756 log.warn("Node was instructed to be {} role for {}, "
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700757 + "but this node cannot reach the device. "
758 + "Relinquishing role. ",
samuele1fa7322015-07-14 16:35:16 +0800759 myNextRole, did);
Madan Jampani328371d2015-05-29 14:06:27 -0700760 mastershipService.relinquishMastership(did);
761 }
762 return;
763 }
764
765 // device is connected to this node:
766 if (store.getDevice(did) != null) {
767 reassertRole(did, myNextRole);
768 } else {
769 log.debug("Device is not yet/no longer in the store: {}", did);
770 }
771 }
772
Yuta HIGUCHI63323fd2014-11-11 12:16:58 -0800773 // Intercepts mastership events
774 private class InternalMastershipListener implements MastershipListener {
775
tomb41d1ac2014-09-24 01:51:24 -0700776 @Override
777 public void event(MastershipEvent event) {
HIGUCHI Yuta060da9a2016-03-11 19:16:35 -0800778 backgroundService.execute(() -> {
Madan Jampani328371d2015-05-29 14:06:27 -0700779 try {
780 handleMastershipEvent(event);
781 } catch (Exception e) {
782 log.warn("Failed to handle {}", event, e);
Yuta HIGUCHId26354d2014-10-31 14:14:38 -0700783 }
Madan Jampani328371d2015-05-29 14:06:27 -0700784 });
Ayaka Koshibe317245a2014-10-29 00:34:43 -0700785 }
tomb41d1ac2014-09-24 01:51:24 -0700786 }
tomf80c9722014-09-24 14:49:18 -0700787
788 // Store delegate to re-post events emitted from the store.
Thomas Vachuskab17c41f2015-05-19 11:16:05 -0700789 private class InternalStoreDelegate implements DeviceStoreDelegate {
tomf80c9722014-09-24 14:49:18 -0700790 @Override
791 public void notify(DeviceEvent event) {
792 post(event);
793 }
794 }
samuel738dfaf2015-07-11 11:08:57 +0800795
796 @Override
797 public Iterable<Device> getDevices(Type type) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900798 checkPermission(DEVICE_READ);
samuel738dfaf2015-07-11 11:08:57 +0800799 Set<Device> results = new HashSet<>();
800 Iterable<Device> devices = store.getDevices();
801 if (devices != null) {
802 devices.forEach(d -> {
803 if (type.equals(d.type())) {
804 results.add(d);
805 }
806 });
807 }
808 return results;
809 }
810
811 @Override
812 public Iterable<Device> getAvailableDevices(Type type) {
Changhoon Yoonb856b812015-08-10 03:47:19 +0900813 checkPermission(DEVICE_READ);
samuel738dfaf2015-07-11 11:08:57 +0800814 Set<Device> results = new HashSet<>();
815 Iterable<Device> availableDevices = store.getAvailableDevices();
816 if (availableDevices != null) {
817 availableDevices.forEach(d -> {
818 if (type.equals(d.type())) {
819 results.add(d);
820 }
821 });
822 }
823 return results;
824 }
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700825
826 private class InternalNetworkConfigListener implements NetworkConfigListener {
827 @Override
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700828 public boolean isRelevant(NetworkConfigEvent event) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700829 return (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
830 || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)
831 && (event.configClass().equals(BasicDeviceConfig.class)
832 || event.configClass().equals(OpticalPortConfig.class));
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700833 }
834
835 @Override
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700836 public void event(NetworkConfigEvent event) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700837 DeviceEvent de = null;
838 if (event.configClass().equals(BasicDeviceConfig.class)) {
Thomas Vachuska138de8b2016-01-11 21:31:38 -0800839 log.debug("Detected device network config event {}", event.type());
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700840 DeviceId did = (DeviceId) event.subject();
841 BasicDeviceConfig cfg = networkConfigService.getConfig(did, BasicDeviceConfig.class);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700842
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700843 if (!isAllowed(cfg)) {
844 kickOutBadDevice(did);
845 } else {
846 Device dev = getDevice(did);
847 DeviceDescription desc = (dev == null) ? null : BasicDeviceOperator.descriptionOf(dev);
848 desc = BasicDeviceOperator.combine(cfg, desc);
Thomas Vachuska1627dc82015-11-13 12:22:14 -0800849 if (desc != null && getProvider(did) != null) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700850 de = store.createOrUpdateDevice(getProvider(did).id(), did, desc);
851 }
852 }
853 }
854 if (event.configClass().equals(OpticalPortConfig.class)) {
855 ConnectPoint cpt = (ConnectPoint) event.subject();
856 DeviceId did = cpt.deviceId();
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700857 Provider provider = getProvider(did);
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700858 Port dpt = getPort(did, cpt.port());
859
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700860 if (dpt != null && provider != null) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700861 OpticalPortConfig opc = networkConfigService.getConfig(cpt, OpticalPortConfig.class);
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700862 PortDescription desc = store.getPortDescription(provider.id(), did, cpt.port());
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700863 desc = OpticalPortOperator.combine(opc, desc);
Yuta HIGUCHI6eb00cc2016-06-10 11:55:12 -0700864 if (desc != null) {
Ayaka Koshibed0ab3c02015-09-04 15:43:46 -0700865 de = store.updatePortStatus(getProvider(did).id(), did, desc);
866 }
867 }
868 }
869
870 if (de != null) {
871 post(de);
872 }
873 }
874
875 // checks if the specified device is allowed by the BasicDeviceConfig
876 // and if not, removes it
877 private void kickOutBadDevice(DeviceId deviceId) {
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700878 Device badDevice = getDevice(deviceId);
879 if (badDevice != null) {
880 removeDevice(deviceId);
Sahil Lele3a0cdd52015-07-21 14:16:31 -0700881 }
882 }
883 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700884
tomd3097b02014-08-26 10:40:29 -0700885}