blob: 86363484c1fd81c6761f3c2dbd1bc676efae7d7a [file] [log] [blame]
Andrea Campanella945ded22016-01-07 13:17:43 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Andrea Campanella945ded22016-01-07 13:17:43 -08003 *
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.provider.rest.device.impl;
18
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -060019import com.google.common.base.Objects;
Andrea Campanella59b549d2017-04-14 21:58:16 +020020import com.google.common.collect.ImmutableList;
Andrea Campanella945ded22016-01-07 13:17:43 -080021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onlab.packet.ChassisId;
Michal Machd8099742017-06-19 14:32:35 +020027import org.onlab.util.SharedScheduledExecutorService;
28import org.onlab.util.SharedScheduledExecutors;
Andrea Campanella945ded22016-01-07 13:17:43 -080029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.incubator.net.config.basics.ConfigException;
Marc De Leenheerb0d131c2016-03-01 20:34:59 -080032import org.onosproject.net.AnnotationKeys;
Andrea Campanella945ded22016-01-07 13:17:43 -080033import org.onosproject.net.DefaultAnnotations;
34import org.onosproject.net.Device;
35import org.onosproject.net.DeviceId;
36import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070037import org.onosproject.net.PortNumber;
Andrea Campanella945ded22016-01-07 13:17:43 -080038import org.onosproject.net.SparseAnnotations;
Michele Santuaric372c222017-01-12 09:41:25 +010039import org.onosproject.net.behaviour.DevicesDiscovery;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080040import org.onosproject.net.behaviour.PortDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -080041import org.onosproject.net.config.ConfigFactory;
42import org.onosproject.net.config.NetworkConfigEvent;
43import org.onosproject.net.config.NetworkConfigListener;
44import org.onosproject.net.config.NetworkConfigRegistry;
Andrea Campanella59b549d2017-04-14 21:58:16 +020045import org.onosproject.net.config.basics.SubjectFactories;
Andrea Campanella945ded22016-01-07 13:17:43 -080046import org.onosproject.net.device.DefaultDeviceDescription;
47import org.onosproject.net.device.DeviceDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070048import org.onosproject.net.device.DeviceDescriptionDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -080049import org.onosproject.net.device.DeviceProvider;
50import org.onosproject.net.device.DeviceProviderRegistry;
51import org.onosproject.net.device.DeviceProviderService;
Andrea Campanella6c71a052016-04-22 11:56:31 -070052import org.onosproject.net.device.DeviceService;
Michal Machd8099742017-06-19 14:32:35 +020053import org.onosproject.net.device.PortStatistics;
54import org.onosproject.net.device.PortStatisticsDiscovery;
Michele Santuaric372c222017-01-12 09:41:25 +010055import org.onosproject.net.driver.DefaultDriverData;
56import org.onosproject.net.driver.DefaultDriverHandler;
57import org.onosproject.net.driver.Driver;
58import org.onosproject.net.driver.DriverData;
59import org.onosproject.net.driver.DriverHandler;
60import org.onosproject.net.driver.DriverService;
Andrea Campanella945ded22016-01-07 13:17:43 -080061import org.onosproject.net.provider.AbstractProvider;
62import org.onosproject.net.provider.ProviderId;
Andrea Campanella59b549d2017-04-14 21:58:16 +020063import org.onosproject.protocol.rest.DefaultRestSBDevice;
Andrea Campanella945ded22016-01-07 13:17:43 -080064import org.onosproject.protocol.rest.RestSBController;
65import org.onosproject.protocol.rest.RestSBDevice;
66import org.slf4j.Logger;
67
Andrea Campanellac6ecc632016-03-10 17:57:06 -080068import javax.ws.rs.ProcessingException;
Michal Mach67acb692017-06-21 12:05:36 +020069import javax.ws.rs.core.MediaType;
Michal Machd8099742017-06-19 14:32:35 +020070import java.util.Collection;
Andrea Campanella945ded22016-01-07 13:17:43 -080071import java.util.HashSet;
Andrea Campanella59b549d2017-04-14 21:58:16 +020072import java.util.List;
Andrea Campanella945ded22016-01-07 13:17:43 -080073import java.util.Set;
Palash Kala4c71ee72017-05-24 17:43:59 +090074import java.util.concurrent.Callable;
75import java.util.concurrent.ExecutionException;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080076import java.util.concurrent.ExecutorService;
77import java.util.concurrent.Executors;
Palash Kala4c71ee72017-05-24 17:43:59 +090078import java.util.concurrent.Future;
Michal Machd8099742017-06-19 14:32:35 +020079import java.util.concurrent.ScheduledFuture;
Palash Kala4c71ee72017-05-24 17:43:59 +090080import java.util.concurrent.TimeUnit;
81import java.util.concurrent.TimeoutException;
Andrea Campanella59b549d2017-04-14 21:58:16 +020082import java.util.stream.Collectors;
Andrea Campanella945ded22016-01-07 13:17:43 -080083
Michele Santuaric372c222017-01-12 09:41:25 +010084import static com.google.common.base.Preconditions.checkNotNull;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080085import static org.onlab.util.Tools.groupedThreads;
Andrea Campanella945ded22016-01-07 13:17:43 -080086import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
87import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
88import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
89import static org.slf4j.LoggerFactory.getLogger;
90
91/**
92 * Provider for devices that use REST as means of configuration communication.
93 */
94@Component(immediate = true)
95public class RestDeviceProvider extends AbstractProvider
96 implements DeviceProvider {
97 private static final String APP_NAME = "org.onosproject.restsb";
Andrea Campanella59b549d2017-04-14 21:58:16 +020098 protected static final String REST = "rest";
Andrea Campanella945ded22016-01-07 13:17:43 -080099 private static final String PROVIDER = "org.onosproject.provider.rest.device";
100 private static final String IPADDRESS = "ipaddress";
Michal Mach67acb692017-06-21 12:05:36 +0200101 private static final String ISNOTNULL = "Rest device is not null";
Michele Santuaric372c222017-01-12 09:41:25 +0100102 private static final String UNKNOWN = "unknown";
Palash Kala4c71ee72017-05-24 17:43:59 +0900103 private static final int REST_TIMEOUT_SEC = 5;
Michal Machd8099742017-06-19 14:32:35 +0200104 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
Georgios Katsikas6a4d1662017-07-27 13:22:31 +0200105 private static final int EXECUTOR_THREAD_POOL_SIZE = 8;
Andrea Campanella945ded22016-01-07 13:17:43 -0800106 private final Logger log = getLogger(getClass());
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected DeviceProviderRegistry providerRegistry;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected RestSBController controller;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected NetworkConfigRegistry cfgService;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected CoreService coreService;
119
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella6c71a052016-04-22 11:56:31 -0700121 protected DeviceService deviceService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800122
Michele Santuaric372c222017-01-12 09:41:25 +0100123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected DriverService driverService;
125
Andrea Campanella945ded22016-01-07 13:17:43 -0800126 private DeviceProviderService providerService;
Michele Santuaric372c222017-01-12 09:41:25 +0100127 private ApplicationId appId;
Andrea Campanella945ded22016-01-07 13:17:43 -0800128
Michal Mach13072e22017-06-21 09:12:24 +0200129 private ExecutorService executor;
Michal Mach67acb692017-06-21 12:05:36 +0200130 private final SharedScheduledExecutorService portStatisticsExecutor =
131 SharedScheduledExecutors.getPoolThreadExecutor();
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800132
Michal Mach67acb692017-06-21 12:05:36 +0200133 private final List<ConfigFactory> factories = ImmutableList.of(
Andrea Campanella945ded22016-01-07 13:17:43 -0800134 new ConfigFactory<ApplicationId, RestProviderConfig>(APP_SUBJECT_FACTORY,
135 RestProviderConfig.class,
Palash Kalac3ffad92017-06-09 21:18:19 +0900136 "rest_devices",
Andrea Campanella945ded22016-01-07 13:17:43 -0800137 true) {
138 @Override
139 public RestProviderConfig createConfig() {
140 return new RestProviderConfig();
141 }
Andrea Campanella59b549d2017-04-14 21:58:16 +0200142 },
143 new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
144 RestDeviceConfig.class,
145 REST) {
146 @Override
147 public RestDeviceConfig createConfig() {
148 return new RestDeviceConfig();
149 }
150 });
151
Michal Mach67acb692017-06-21 12:05:36 +0200152 private final NetworkConfigListener configListener = new InternalNetworkConfigListener();
Andrea Campanella945ded22016-01-07 13:17:43 -0800153
Michal Machd8099742017-06-19 14:32:35 +0200154 private ScheduledFuture<?> scheduledTask;
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800155
Andrea Campanella945ded22016-01-07 13:17:43 -0800156
157 @Activate
158 public void activate() {
159 appId = coreService.registerApplication(APP_NAME);
160 providerService = providerRegistry.register(this);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200161 factories.forEach(cfgService::registerConfigFactory);
Georgios Katsikas6a4d1662017-07-27 13:22:31 +0200162 executor = Executors.newFixedThreadPool(
163 EXECUTOR_THREAD_POOL_SIZE, groupedThreads("onos/restsbprovider", "device-installer-%d", log)
164 );
Michal Mach67acb692017-06-21 12:05:36 +0200165 cfgService.addListener(configListener);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200166 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
167 executor.execute(RestDeviceProvider.this::createDevices);
Michal Machd8099742017-06-19 14:32:35 +0200168 scheduledTask = schedulePolling();
Andrea Campanella945ded22016-01-07 13:17:43 -0800169 log.info("Started");
170 }
171
Andrea Campanella945ded22016-01-07 13:17:43 -0800172 @Deactivate
173 public void deactivate() {
Michal Mach67acb692017-06-21 12:05:36 +0200174 cfgService.removeListener(configListener);
Andrea Campanella86294db2016-03-07 11:42:49 -0800175 controller.getDevices().keySet().forEach(this::deviceRemoved);
Andrea Campanella945ded22016-01-07 13:17:43 -0800176 providerRegistry.unregister(this);
177 providerService = null;
Andrea Campanella59b549d2017-04-14 21:58:16 +0200178 factories.forEach(cfgService::unregisterConfigFactory);
Michal Machd8099742017-06-19 14:32:35 +0200179 scheduledTask.cancel(true);
Lukasz Ryba4da35c52017-06-20 09:14:11 +0200180 executor.shutdown();
Andrea Campanella945ded22016-01-07 13:17:43 -0800181 log.info("Stopped");
182 }
183
184 public RestDeviceProvider() {
185 super(new ProviderId(REST, PROVIDER));
186 }
187
188 @Override
189 public void triggerProbe(DeviceId deviceId) {
190 // TODO: This will be implemented later.
191 log.info("Triggering probe on device {}", deviceId);
192 }
193
194 @Override
195 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
196 // TODO: This will be implemented later.
197 }
198
Andrea Campanella945ded22016-01-07 13:17:43 -0800199 @Override
200 public boolean isReachable(DeviceId deviceId) {
201 RestSBDevice restDevice = controller.getDevice(deviceId);
202 if (restDevice == null) {
Michele Santuaric372c222017-01-12 09:41:25 +0100203 restDevice = controller.getProxySBDevice(deviceId);
204 if (restDevice == null) {
205 log.debug("the requested device id: " +
206 deviceId.toString() +
207 " is not associated to any REST or REST " +
208 "proxy Device");
209 return false;
210 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800211 }
212 return restDevice.isActive();
213 }
214
Michele Santuaric372c222017-01-12 09:41:25 +0100215 private void deviceAdded(RestSBDevice restSBDev) {
216 checkNotNull(restSBDev, ISNOTNULL);
217
218 //check if the server is controlling a single or multiple devices
219 if (restSBDev.isProxy()) {
220
221 Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
222 restSBDev.hwVersion().get(),
223 restSBDev.swVersion().get());
224
225 if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
226
227 //Creates the driver to communicate with the server
228 DevicesDiscovery devicesDiscovery =
229 devicesDiscovery(restSBDev, driver);
230 Set<DeviceId> deviceIds = devicesDiscovery.deviceIds();
231 restSBDev.setActive(true);
Michal Mach67acb692017-06-21 12:05:36 +0200232 deviceIds.forEach(deviceId -> {
Michele Santuaric372c222017-01-12 09:41:25 +0100233 controller.addProxiedDevice(deviceId, restSBDev);
234 DeviceDescription devDesc =
235 devicesDiscovery.deviceDetails(deviceId);
236 checkNotNull(devDesc,
237 "deviceDescription cannot be null");
238 providerService.deviceConnected(
239 deviceId, mergeAnn(restSBDev.deviceId(), devDesc));
240
241 if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
242 DriverHandler h = driverService.createHandler(deviceId);
243 DeviceDescriptionDiscovery devDisc =
244 h.behaviour(DeviceDescriptionDiscovery.class);
245 providerService.updatePorts(deviceId,
246 devDisc.discoverPortDetails());
247 }
248
249 checkAndUpdateDevice(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100250 });
251 } else {
252 log.warn("Driver not found for {}", restSBDev);
253 }
254 } else {
255 DeviceId deviceId = restSBDev.deviceId();
256 ChassisId cid = new ChassisId();
257 String ipAddress = restSBDev.ip().toString();
258 SparseAnnotations annotations = DefaultAnnotations.builder()
259 .set(IPADDRESS, ipAddress)
260 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
261 .build();
262 DeviceDescription deviceDescription = new DefaultDeviceDescription(
263 deviceId.uri(),
264 Device.Type.SWITCH,
265 UNKNOWN, UNKNOWN,
266 UNKNOWN, UNKNOWN,
267 cid,
268 annotations);
269 restSBDev.setActive(true);
270 providerService.deviceConnected(deviceId, deviceDescription);
271 checkAndUpdateDevice(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100272 }
273 }
274
275 private DefaultDeviceDescription mergeAnn(DeviceId devId, DeviceDescription desc) {
276 return new DefaultDeviceDescription(
277 desc,
278 DefaultAnnotations.merge(
279 DefaultAnnotations.builder()
280 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
281 // The rest server added as annotation to the device
282 .set(AnnotationKeys.REST_SERVER, devId.toString())
283 .build(),
284 desc.annotations()));
285 }
286
287 private DevicesDiscovery devicesDiscovery(RestSBDevice restSBDevice, Driver driver) {
288 DriverData driverData = new DefaultDriverData(driver, restSBDevice.deviceId());
289 DevicesDiscovery devicesDiscovery = driver.createBehaviour(driverData,
290 DevicesDiscovery.class);
291 devicesDiscovery.setHandler(new DefaultDriverHandler(driverData));
292 return devicesDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -0800293 }
294
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600295 private void checkAndUpdateDevice(DeviceId deviceId) {
296 if (deviceService.getDevice(deviceId) == null) {
297 log.warn("Device {} has not been added to store, " +
298 "maybe due to a problem in connectivity", deviceId);
299 } else {
300 boolean isReachable = isReachable(deviceId);
301 if (isReachable && deviceService.isAvailable(deviceId)) {
302 Device device = deviceService.getDevice(deviceId);
303 if (device.is(DeviceDescriptionDiscovery.class)) {
Michele Santuaric372c222017-01-12 09:41:25 +0100304 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
305 device.as(DeviceDescriptionDiscovery.class);
306 DeviceDescription updatedDeviceDescription =
307 deviceDescriptionDiscovery.discoverDeviceDetails();
308 if (updatedDeviceDescription != null &&
309 !descriptionEquals(device, updatedDeviceDescription)) {
310 providerService.deviceConnected(
311 deviceId,
312 new DefaultDeviceDescription(
313 updatedDeviceDescription, true,
314 updatedDeviceDescription.annotations()));
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600315 //if ports are not discovered, retry the discovery
316 if (deviceService.getPorts(deviceId).isEmpty()) {
317 discoverPorts(deviceId);
318 }
319 }
320 } else {
321 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
322 }
323 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
324 providerService.deviceDisconnected(deviceId);
325 }
326 }
327 }
328
329 private boolean descriptionEquals(Device device, DeviceDescription updatedDeviceDescription) {
Michele Santuarid2c8f212017-01-09 18:23:45 +0100330 return Objects.equal(device.id().uri(), updatedDeviceDescription.deviceUri())
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600331 && Objects.equal(device.type(), updatedDeviceDescription.type())
332 && Objects.equal(device.manufacturer(), updatedDeviceDescription.manufacturer())
333 && Objects.equal(device.hwVersion(), updatedDeviceDescription.hwVersion())
334 && Objects.equal(device.swVersion(), updatedDeviceDescription.swVersion())
335 && Objects.equal(device.serialNumber(), updatedDeviceDescription.serialNumber())
336 && Objects.equal(device.chassisId(), updatedDeviceDescription.chassisId())
337 && Objects.equal(device.annotations(), updatedDeviceDescription.annotations());
338 }
339
Andrea Campanella86294db2016-03-07 11:42:49 -0800340 private void deviceRemoved(DeviceId deviceId) {
Michele Santuaric372c222017-01-12 09:41:25 +0100341 checkNotNull(deviceId, ISNOTNULL);
Andrea Campanella945ded22016-01-07 13:17:43 -0800342 providerService.deviceDisconnected(deviceId);
Michal Mach67acb692017-06-21 12:05:36 +0200343 controller.getProxiedDevices(deviceId).forEach(device -> {
Michele Santuaric372c222017-01-12 09:41:25 +0100344 controller.removeProxiedDevice(device);
345 providerService.deviceDisconnected(device);
346 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800347 controller.removeDevice(deviceId);
Andrea Campanella945ded22016-01-07 13:17:43 -0800348 }
349
Andrea Campanella59b549d2017-04-14 21:58:16 +0200350 //Method to connect devices provided via net-cfg under devices/ tree
351 private void createAndConnectDevices() {
352 Set<DeviceId> deviceSubjects =
353 cfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
354 connectDevices(deviceSubjects.stream()
355 .filter(deviceId -> deviceService.getDevice(deviceId) == null)
356 .map(deviceId -> {
357 RestDeviceConfig config =
358 cfgService.getConfig(deviceId, RestDeviceConfig.class);
Michal Mach67acb692017-06-21 12:05:36 +0200359 return new DefaultRestSBDevice(config.ip(),
360 config.port(),
361 config.username(),
362 config.password(),
363 config.protocol(),
364 config.url(),
365 false,
366 config.testUrl(),
367 config.manufacturer(),
368 config.hwVersion(),
369 config.swVersion());
Andrea Campanella59b549d2017-04-14 21:58:16 +0200370 }).collect(Collectors.toSet()));
371 }
372
373 //Old method to register devices provided via net-cfg under apps/rest/ tree
374 private void createDevices() {
Andrea Campanella945ded22016-01-07 13:17:43 -0800375 RestProviderConfig cfg = cfgService.getConfig(appId, RestProviderConfig.class);
376 try {
377 if (cfg != null && cfg.getDevicesAddresses() != null) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200378 connectDevices(cfg.getDevicesAddresses());
379
Andrea Campanella945ded22016-01-07 13:17:43 -0800380 }
381 } catch (ConfigException e) {
382 log.error("Configuration error {}", e);
383 }
Andrea Campanella2947e622016-01-27 09:23:46 -0800384 log.debug("REST Devices {}", controller.getDevices());
Andrea Campanella945ded22016-01-07 13:17:43 -0800385 }
386
Andrea Campanella59b549d2017-04-14 21:58:16 +0200387 private void connectDevices(Set<RestSBDevice> devices) {
388 //Precomputing the devices to be removed
389 Set<RestSBDevice> toBeRemoved = new HashSet<>(controller.getDevices().values());
390 toBeRemoved.removeAll(devices);
391 //Adding new devices
392 devices.stream()
393 .filter(device -> {
394 device.setActive(false);
395 controller.addDevice(device);
396 return testDeviceConnection(device);
397 })
Michal Mach67acb692017-06-21 12:05:36 +0200398 .forEach(this::deviceAdded);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200399 //Removing devices not wanted anymore
400 toBeRemoved.forEach(device -> deviceRemoved(device.deviceId()));
401 }
402
Michal Machd8099742017-06-19 14:32:35 +0200403 private ScheduledFuture schedulePolling() {
404 return portStatisticsExecutor.scheduleAtFixedRate(this::executePortStatisticsUpdate,
405 DEFAULT_POLL_FREQUENCY_SECONDS / 2,
406 DEFAULT_POLL_FREQUENCY_SECONDS,
407 TimeUnit.SECONDS);
408 }
409
410 private void executePortStatisticsUpdate() {
411 controller.getDevices().keySet().forEach(this::updatePortStatistics);
412 }
413
414 private void updatePortStatistics(DeviceId deviceId) {
415 Device device = deviceService.getDevice(deviceId);
416 checkNotNull(device, "device cannot be null");
417
418 if (device.is(PortStatisticsDiscovery.class)) {
419 PortStatisticsDiscovery portStatisticsDiscovery = device.as(PortStatisticsDiscovery.class);
420 Collection<PortStatistics> portStatistics = portStatisticsDiscovery.discoverPortStatistics();
421 if (portStatistics != null && !portStatistics.isEmpty()) {
422 providerService.updatePortStatistics(deviceId, portStatistics);
423 }
424 } else {
425 log.debug("No port statistics getter behaviour for device {}", deviceId);
426 }
427 }
428
Andrea Campanella6c71a052016-04-22 11:56:31 -0700429 private void discoverPorts(DeviceId deviceId) {
430 Device device = deviceService.getDevice(deviceId);
431 //TODO remove when PortDiscovery is removed from master
432 if (device.is(PortDiscovery.class)) {
433 PortDiscovery portConfig = device.as(PortDiscovery.class);
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600434 providerService.updatePorts(deviceId, portConfig.getPorts());
435 } else {
Andrea Campanella6c71a052016-04-22 11:56:31 -0700436 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
437 device.as(DeviceDescriptionDiscovery.class);
438 providerService.updatePorts(deviceId, deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700439 }
440 }
441
Michele Santuaric372c222017-01-12 09:41:25 +0100442 private boolean testDeviceConnection(RestSBDevice dev) {
Andrea Campanella945ded22016-01-07 13:17:43 -0800443 try {
Palash Kala4c71ee72017-05-24 17:43:59 +0900444 Callable<Boolean> connectionSuccess;
445
Michele Santuaric372c222017-01-12 09:41:25 +0100446 if (dev.testUrl().isPresent()) {
Michal Mach67acb692017-06-21 12:05:36 +0200447 connectionSuccess = () ->
448 controller.get(dev.deviceId(), dev.testUrl().get(), MediaType.APPLICATION_JSON_TYPE) != null;
Palash Kala4c71ee72017-05-24 17:43:59 +0900449 } else {
Michal Mach67acb692017-06-21 12:05:36 +0200450 connectionSuccess = () ->
451 controller.get(dev.deviceId(), "", MediaType.APPLICATION_JSON_TYPE) != null;
Michele Santuaric372c222017-01-12 09:41:25 +0100452 }
Palash Kala4c71ee72017-05-24 17:43:59 +0900453
454 Future<Boolean> future = executor.submit(connectionSuccess);
455 try {
Michal Mach67acb692017-06-21 12:05:36 +0200456 return future.get(REST_TIMEOUT_SEC, TimeUnit.SECONDS);
Palash Kala4c71ee72017-05-24 17:43:59 +0900457 } catch (TimeoutException ex) {
458 log.warn("Connection to device {} timed out", dev.deviceId());
459 return false;
460 } catch (InterruptedException ex) {
461 log.warn("Connection to device {} interrupted", dev.deviceId());
462 return false;
463 } catch (ExecutionException ex) {
464 log.warn("Connection to device {} had a execution exception", dev.deviceId());
465 return false;
466 }
Michele Santuaric372c222017-01-12 09:41:25 +0100467
Andrea Campanellac6ecc632016-03-10 17:57:06 -0800468 } catch (ProcessingException e) {
Michele Santuaric372c222017-01-12 09:41:25 +0100469 log.warn("Cannot connect to device {}", dev, e);
Andrea Campanella945ded22016-01-07 13:17:43 -0800470 }
471 return false;
472 }
473
474 private class InternalNetworkConfigListener implements NetworkConfigListener {
Andrea Campanella945ded22016-01-07 13:17:43 -0800475 @Override
476 public void event(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200477 if (event.configClass().equals(RestDeviceConfig.class)) {
478 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
479 } else {
480 log.warn("Injecting device via this Json is deprecated, " +
481 "please put configuration under devices/");
482 executor.execute(RestDeviceProvider.this::createDevices);
483 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800484 }
485
486 @Override
487 public boolean isRelevant(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200488 return (event.configClass().equals(RestDeviceConfig.class) ||
489 event.configClass().equals(RestProviderConfig.class)) &&
Andrea Campanella945ded22016-01-07 13:17:43 -0800490 (event.type() == CONFIG_ADDED ||
491 event.type() == CONFIG_UPDATED);
492 }
493 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700494
495 @Override
496 public void changePortState(DeviceId deviceId, PortNumber portNumber,
497 boolean enable) {
498 // TODO if required
499 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800500}