blob: 61d1625cb9cde70cb2ab56762336f86001e68569 [file] [log] [blame]
Andrea Campanella945ded22016-01-07 13:17:43 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
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;
Andrea Campanella945ded22016-01-07 13:17:43 -0800105 private final Logger log = getLogger(getClass());
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected DeviceProviderRegistry providerRegistry;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected RestSBController controller;
112
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected NetworkConfigRegistry cfgService;
115
116 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected CoreService coreService;
118
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella6c71a052016-04-22 11:56:31 -0700120 protected DeviceService deviceService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800121
Michele Santuaric372c222017-01-12 09:41:25 +0100122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected DriverService driverService;
124
Andrea Campanella945ded22016-01-07 13:17:43 -0800125 private DeviceProviderService providerService;
Michele Santuaric372c222017-01-12 09:41:25 +0100126 private ApplicationId appId;
Andrea Campanella945ded22016-01-07 13:17:43 -0800127
Michal Mach13072e22017-06-21 09:12:24 +0200128 private ExecutorService executor;
Michal Mach67acb692017-06-21 12:05:36 +0200129 private final SharedScheduledExecutorService portStatisticsExecutor =
130 SharedScheduledExecutors.getPoolThreadExecutor();
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800131
Michal Mach67acb692017-06-21 12:05:36 +0200132 private final List<ConfigFactory> factories = ImmutableList.of(
Andrea Campanella945ded22016-01-07 13:17:43 -0800133 new ConfigFactory<ApplicationId, RestProviderConfig>(APP_SUBJECT_FACTORY,
134 RestProviderConfig.class,
Palash Kalac3ffad92017-06-09 21:18:19 +0900135 "rest_devices",
Andrea Campanella945ded22016-01-07 13:17:43 -0800136 true) {
137 @Override
138 public RestProviderConfig createConfig() {
139 return new RestProviderConfig();
140 }
Andrea Campanella59b549d2017-04-14 21:58:16 +0200141 },
142 new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
143 RestDeviceConfig.class,
144 REST) {
145 @Override
146 public RestDeviceConfig createConfig() {
147 return new RestDeviceConfig();
148 }
149 });
150
Michal Mach67acb692017-06-21 12:05:36 +0200151 private final NetworkConfigListener configListener = new InternalNetworkConfigListener();
Andrea Campanella945ded22016-01-07 13:17:43 -0800152
Michal Machd8099742017-06-19 14:32:35 +0200153 private ScheduledFuture<?> scheduledTask;
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800154
Andrea Campanella945ded22016-01-07 13:17:43 -0800155
156 @Activate
157 public void activate() {
158 appId = coreService.registerApplication(APP_NAME);
159 providerService = providerRegistry.register(this);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200160 factories.forEach(cfgService::registerConfigFactory);
Michal Mach13072e22017-06-21 09:12:24 +0200161 executor = Executors.newFixedThreadPool(5, groupedThreads("onos/restsbprovider", "device-installer-%d", log));
Michal Mach67acb692017-06-21 12:05:36 +0200162 cfgService.addListener(configListener);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200163 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
164 executor.execute(RestDeviceProvider.this::createDevices);
Michal Machd8099742017-06-19 14:32:35 +0200165 scheduledTask = schedulePolling();
Andrea Campanella945ded22016-01-07 13:17:43 -0800166 log.info("Started");
167 }
168
Andrea Campanella945ded22016-01-07 13:17:43 -0800169 @Deactivate
170 public void deactivate() {
Michal Mach67acb692017-06-21 12:05:36 +0200171 cfgService.removeListener(configListener);
Andrea Campanella86294db2016-03-07 11:42:49 -0800172 controller.getDevices().keySet().forEach(this::deviceRemoved);
Andrea Campanella945ded22016-01-07 13:17:43 -0800173 providerRegistry.unregister(this);
174 providerService = null;
Andrea Campanella59b549d2017-04-14 21:58:16 +0200175 factories.forEach(cfgService::unregisterConfigFactory);
Michal Machd8099742017-06-19 14:32:35 +0200176 scheduledTask.cancel(true);
Lukasz Ryba4da35c52017-06-20 09:14:11 +0200177 executor.shutdown();
Andrea Campanella945ded22016-01-07 13:17:43 -0800178 log.info("Stopped");
179 }
180
181 public RestDeviceProvider() {
182 super(new ProviderId(REST, PROVIDER));
183 }
184
185 @Override
186 public void triggerProbe(DeviceId deviceId) {
187 // TODO: This will be implemented later.
188 log.info("Triggering probe on device {}", deviceId);
189 }
190
191 @Override
192 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
193 // TODO: This will be implemented later.
194 }
195
Andrea Campanella945ded22016-01-07 13:17:43 -0800196 @Override
197 public boolean isReachable(DeviceId deviceId) {
198 RestSBDevice restDevice = controller.getDevice(deviceId);
199 if (restDevice == null) {
Michele Santuaric372c222017-01-12 09:41:25 +0100200 restDevice = controller.getProxySBDevice(deviceId);
201 if (restDevice == null) {
202 log.debug("the requested device id: " +
203 deviceId.toString() +
204 " is not associated to any REST or REST " +
205 "proxy Device");
206 return false;
207 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800208 }
209 return restDevice.isActive();
210 }
211
Michele Santuaric372c222017-01-12 09:41:25 +0100212 private void deviceAdded(RestSBDevice restSBDev) {
213 checkNotNull(restSBDev, ISNOTNULL);
214
215 //check if the server is controlling a single or multiple devices
216 if (restSBDev.isProxy()) {
217
218 Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
219 restSBDev.hwVersion().get(),
220 restSBDev.swVersion().get());
221
222 if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
223
224 //Creates the driver to communicate with the server
225 DevicesDiscovery devicesDiscovery =
226 devicesDiscovery(restSBDev, driver);
227 Set<DeviceId> deviceIds = devicesDiscovery.deviceIds();
228 restSBDev.setActive(true);
Michal Mach67acb692017-06-21 12:05:36 +0200229 deviceIds.forEach(deviceId -> {
Michele Santuaric372c222017-01-12 09:41:25 +0100230 controller.addProxiedDevice(deviceId, restSBDev);
231 DeviceDescription devDesc =
232 devicesDiscovery.deviceDetails(deviceId);
233 checkNotNull(devDesc,
234 "deviceDescription cannot be null");
235 providerService.deviceConnected(
236 deviceId, mergeAnn(restSBDev.deviceId(), devDesc));
237
238 if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
239 DriverHandler h = driverService.createHandler(deviceId);
240 DeviceDescriptionDiscovery devDisc =
241 h.behaviour(DeviceDescriptionDiscovery.class);
242 providerService.updatePorts(deviceId,
243 devDisc.discoverPortDetails());
244 }
245
246 checkAndUpdateDevice(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100247 });
248 } else {
249 log.warn("Driver not found for {}", restSBDev);
250 }
251 } else {
252 DeviceId deviceId = restSBDev.deviceId();
253 ChassisId cid = new ChassisId();
254 String ipAddress = restSBDev.ip().toString();
255 SparseAnnotations annotations = DefaultAnnotations.builder()
256 .set(IPADDRESS, ipAddress)
257 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
258 .build();
259 DeviceDescription deviceDescription = new DefaultDeviceDescription(
260 deviceId.uri(),
261 Device.Type.SWITCH,
262 UNKNOWN, UNKNOWN,
263 UNKNOWN, UNKNOWN,
264 cid,
265 annotations);
266 restSBDev.setActive(true);
267 providerService.deviceConnected(deviceId, deviceDescription);
268 checkAndUpdateDevice(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100269 }
270 }
271
272 private DefaultDeviceDescription mergeAnn(DeviceId devId, DeviceDescription desc) {
273 return new DefaultDeviceDescription(
274 desc,
275 DefaultAnnotations.merge(
276 DefaultAnnotations.builder()
277 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
278 // The rest server added as annotation to the device
279 .set(AnnotationKeys.REST_SERVER, devId.toString())
280 .build(),
281 desc.annotations()));
282 }
283
284 private DevicesDiscovery devicesDiscovery(RestSBDevice restSBDevice, Driver driver) {
285 DriverData driverData = new DefaultDriverData(driver, restSBDevice.deviceId());
286 DevicesDiscovery devicesDiscovery = driver.createBehaviour(driverData,
287 DevicesDiscovery.class);
288 devicesDiscovery.setHandler(new DefaultDriverHandler(driverData));
289 return devicesDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -0800290 }
291
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600292 private void checkAndUpdateDevice(DeviceId deviceId) {
293 if (deviceService.getDevice(deviceId) == null) {
294 log.warn("Device {} has not been added to store, " +
295 "maybe due to a problem in connectivity", deviceId);
296 } else {
297 boolean isReachable = isReachable(deviceId);
298 if (isReachable && deviceService.isAvailable(deviceId)) {
299 Device device = deviceService.getDevice(deviceId);
300 if (device.is(DeviceDescriptionDiscovery.class)) {
Michele Santuaric372c222017-01-12 09:41:25 +0100301 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
302 device.as(DeviceDescriptionDiscovery.class);
303 DeviceDescription updatedDeviceDescription =
304 deviceDescriptionDiscovery.discoverDeviceDetails();
305 if (updatedDeviceDescription != null &&
306 !descriptionEquals(device, updatedDeviceDescription)) {
307 providerService.deviceConnected(
308 deviceId,
309 new DefaultDeviceDescription(
310 updatedDeviceDescription, true,
311 updatedDeviceDescription.annotations()));
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600312 //if ports are not discovered, retry the discovery
313 if (deviceService.getPorts(deviceId).isEmpty()) {
314 discoverPorts(deviceId);
315 }
316 }
317 } else {
318 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
319 }
320 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
321 providerService.deviceDisconnected(deviceId);
322 }
323 }
324 }
325
326 private boolean descriptionEquals(Device device, DeviceDescription updatedDeviceDescription) {
Michele Santuarid2c8f212017-01-09 18:23:45 +0100327 return Objects.equal(device.id().uri(), updatedDeviceDescription.deviceUri())
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600328 && Objects.equal(device.type(), updatedDeviceDescription.type())
329 && Objects.equal(device.manufacturer(), updatedDeviceDescription.manufacturer())
330 && Objects.equal(device.hwVersion(), updatedDeviceDescription.hwVersion())
331 && Objects.equal(device.swVersion(), updatedDeviceDescription.swVersion())
332 && Objects.equal(device.serialNumber(), updatedDeviceDescription.serialNumber())
333 && Objects.equal(device.chassisId(), updatedDeviceDescription.chassisId())
334 && Objects.equal(device.annotations(), updatedDeviceDescription.annotations());
335 }
336
Andrea Campanella86294db2016-03-07 11:42:49 -0800337 private void deviceRemoved(DeviceId deviceId) {
Michele Santuaric372c222017-01-12 09:41:25 +0100338 checkNotNull(deviceId, ISNOTNULL);
Andrea Campanella945ded22016-01-07 13:17:43 -0800339 providerService.deviceDisconnected(deviceId);
Michal Mach67acb692017-06-21 12:05:36 +0200340 controller.getProxiedDevices(deviceId).forEach(device -> {
Michele Santuaric372c222017-01-12 09:41:25 +0100341 controller.removeProxiedDevice(device);
342 providerService.deviceDisconnected(device);
343 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800344 controller.removeDevice(deviceId);
Andrea Campanella945ded22016-01-07 13:17:43 -0800345 }
346
Andrea Campanella59b549d2017-04-14 21:58:16 +0200347 //Method to connect devices provided via net-cfg under devices/ tree
348 private void createAndConnectDevices() {
349 Set<DeviceId> deviceSubjects =
350 cfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
351 connectDevices(deviceSubjects.stream()
352 .filter(deviceId -> deviceService.getDevice(deviceId) == null)
353 .map(deviceId -> {
354 RestDeviceConfig config =
355 cfgService.getConfig(deviceId, RestDeviceConfig.class);
Michal Mach67acb692017-06-21 12:05:36 +0200356 return new DefaultRestSBDevice(config.ip(),
357 config.port(),
358 config.username(),
359 config.password(),
360 config.protocol(),
361 config.url(),
362 false,
363 config.testUrl(),
364 config.manufacturer(),
365 config.hwVersion(),
366 config.swVersion());
Andrea Campanella59b549d2017-04-14 21:58:16 +0200367 }).collect(Collectors.toSet()));
368 }
369
370 //Old method to register devices provided via net-cfg under apps/rest/ tree
371 private void createDevices() {
Andrea Campanella945ded22016-01-07 13:17:43 -0800372 RestProviderConfig cfg = cfgService.getConfig(appId, RestProviderConfig.class);
373 try {
374 if (cfg != null && cfg.getDevicesAddresses() != null) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200375 connectDevices(cfg.getDevicesAddresses());
376
Andrea Campanella945ded22016-01-07 13:17:43 -0800377 }
378 } catch (ConfigException e) {
379 log.error("Configuration error {}", e);
380 }
Andrea Campanella2947e622016-01-27 09:23:46 -0800381 log.debug("REST Devices {}", controller.getDevices());
Andrea Campanella945ded22016-01-07 13:17:43 -0800382 }
383
Andrea Campanella59b549d2017-04-14 21:58:16 +0200384 private void connectDevices(Set<RestSBDevice> devices) {
385 //Precomputing the devices to be removed
386 Set<RestSBDevice> toBeRemoved = new HashSet<>(controller.getDevices().values());
387 toBeRemoved.removeAll(devices);
388 //Adding new devices
389 devices.stream()
390 .filter(device -> {
391 device.setActive(false);
392 controller.addDevice(device);
393 return testDeviceConnection(device);
394 })
Michal Mach67acb692017-06-21 12:05:36 +0200395 .forEach(this::deviceAdded);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200396 //Removing devices not wanted anymore
397 toBeRemoved.forEach(device -> deviceRemoved(device.deviceId()));
398 }
399
Michal Machd8099742017-06-19 14:32:35 +0200400 private ScheduledFuture schedulePolling() {
401 return portStatisticsExecutor.scheduleAtFixedRate(this::executePortStatisticsUpdate,
402 DEFAULT_POLL_FREQUENCY_SECONDS / 2,
403 DEFAULT_POLL_FREQUENCY_SECONDS,
404 TimeUnit.SECONDS);
405 }
406
407 private void executePortStatisticsUpdate() {
408 controller.getDevices().keySet().forEach(this::updatePortStatistics);
409 }
410
411 private void updatePortStatistics(DeviceId deviceId) {
412 Device device = deviceService.getDevice(deviceId);
413 checkNotNull(device, "device cannot be null");
414
415 if (device.is(PortStatisticsDiscovery.class)) {
416 PortStatisticsDiscovery portStatisticsDiscovery = device.as(PortStatisticsDiscovery.class);
417 Collection<PortStatistics> portStatistics = portStatisticsDiscovery.discoverPortStatistics();
418 if (portStatistics != null && !portStatistics.isEmpty()) {
419 providerService.updatePortStatistics(deviceId, portStatistics);
420 }
421 } else {
422 log.debug("No port statistics getter behaviour for device {}", deviceId);
423 }
424 }
425
Andrea Campanella6c71a052016-04-22 11:56:31 -0700426 private void discoverPorts(DeviceId deviceId) {
427 Device device = deviceService.getDevice(deviceId);
428 //TODO remove when PortDiscovery is removed from master
429 if (device.is(PortDiscovery.class)) {
430 PortDiscovery portConfig = device.as(PortDiscovery.class);
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600431 providerService.updatePorts(deviceId, portConfig.getPorts());
432 } else {
Andrea Campanella6c71a052016-04-22 11:56:31 -0700433 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
434 device.as(DeviceDescriptionDiscovery.class);
435 providerService.updatePorts(deviceId, deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700436 }
437 }
438
Michele Santuaric372c222017-01-12 09:41:25 +0100439 private boolean testDeviceConnection(RestSBDevice dev) {
Andrea Campanella945ded22016-01-07 13:17:43 -0800440 try {
Palash Kala4c71ee72017-05-24 17:43:59 +0900441 Callable<Boolean> connectionSuccess;
442
Michele Santuaric372c222017-01-12 09:41:25 +0100443 if (dev.testUrl().isPresent()) {
Michal Mach67acb692017-06-21 12:05:36 +0200444 connectionSuccess = () ->
445 controller.get(dev.deviceId(), dev.testUrl().get(), MediaType.APPLICATION_JSON_TYPE) != null;
Palash Kala4c71ee72017-05-24 17:43:59 +0900446 } else {
Michal Mach67acb692017-06-21 12:05:36 +0200447 connectionSuccess = () ->
448 controller.get(dev.deviceId(), "", MediaType.APPLICATION_JSON_TYPE) != null;
Michele Santuaric372c222017-01-12 09:41:25 +0100449 }
Palash Kala4c71ee72017-05-24 17:43:59 +0900450
451 Future<Boolean> future = executor.submit(connectionSuccess);
452 try {
Michal Mach67acb692017-06-21 12:05:36 +0200453 return future.get(REST_TIMEOUT_SEC, TimeUnit.SECONDS);
Palash Kala4c71ee72017-05-24 17:43:59 +0900454 } catch (TimeoutException ex) {
455 log.warn("Connection to device {} timed out", dev.deviceId());
456 return false;
457 } catch (InterruptedException ex) {
458 log.warn("Connection to device {} interrupted", dev.deviceId());
459 return false;
460 } catch (ExecutionException ex) {
461 log.warn("Connection to device {} had a execution exception", dev.deviceId());
462 return false;
463 }
Michele Santuaric372c222017-01-12 09:41:25 +0100464
Andrea Campanellac6ecc632016-03-10 17:57:06 -0800465 } catch (ProcessingException e) {
Michele Santuaric372c222017-01-12 09:41:25 +0100466 log.warn("Cannot connect to device {}", dev, e);
Andrea Campanella945ded22016-01-07 13:17:43 -0800467 }
468 return false;
469 }
470
471 private class InternalNetworkConfigListener implements NetworkConfigListener {
Andrea Campanella945ded22016-01-07 13:17:43 -0800472 @Override
473 public void event(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200474 if (event.configClass().equals(RestDeviceConfig.class)) {
475 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
476 } else {
477 log.warn("Injecting device via this Json is deprecated, " +
478 "please put configuration under devices/");
479 executor.execute(RestDeviceProvider.this::createDevices);
480 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800481 }
482
483 @Override
484 public boolean isRelevant(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200485 return (event.configClass().equals(RestDeviceConfig.class) ||
486 event.configClass().equals(RestProviderConfig.class)) &&
Andrea Campanella945ded22016-01-07 13:17:43 -0800487 (event.type() == CONFIG_ADDED ||
488 event.type() == CONFIG_UPDATED);
489 }
490 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700491
492 @Override
493 public void changePortState(DeviceId deviceId, PortNumber portNumber,
494 boolean enable) {
495 // TODO if required
496 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800497}