blob: a4d9f56cbc2f4b60a5b506678a5f7e00e70365eb [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 Machd8099742017-06-19 14:32:35 +020069import java.util.Collection;
Andrea Campanella945ded22016-01-07 13:17:43 -080070import java.util.HashSet;
Andrea Campanella59b549d2017-04-14 21:58:16 +020071import java.util.List;
Andrea Campanella945ded22016-01-07 13:17:43 -080072import java.util.Set;
Palash Kala4c71ee72017-05-24 17:43:59 +090073import java.util.concurrent.Callable;
74import java.util.concurrent.ExecutionException;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080075import java.util.concurrent.ExecutorService;
76import java.util.concurrent.Executors;
Palash Kala4c71ee72017-05-24 17:43:59 +090077import java.util.concurrent.Future;
Michal Machd8099742017-06-19 14:32:35 +020078import java.util.concurrent.ScheduledFuture;
Palash Kala4c71ee72017-05-24 17:43:59 +090079import java.util.concurrent.TimeUnit;
80import java.util.concurrent.TimeoutException;
Andrea Campanella59b549d2017-04-14 21:58:16 +020081import java.util.stream.Collectors;
Andrea Campanella945ded22016-01-07 13:17:43 -080082
Michele Santuaric372c222017-01-12 09:41:25 +010083import static com.google.common.base.Preconditions.checkNotNull;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080084import static org.onlab.util.Tools.groupedThreads;
Andrea Campanella945ded22016-01-07 13:17:43 -080085import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
86import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
87import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
88import static org.slf4j.LoggerFactory.getLogger;
89
90/**
91 * Provider for devices that use REST as means of configuration communication.
92 */
93@Component(immediate = true)
94public class RestDeviceProvider extends AbstractProvider
95 implements DeviceProvider {
96 private static final String APP_NAME = "org.onosproject.restsb";
Andrea Campanella59b549d2017-04-14 21:58:16 +020097 protected static final String REST = "rest";
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -060098 private static final String JSON = "json";
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";
Andrea Campanella2947e622016-01-27 09:23:46 -0800101 private static final String HTTPS = "https";
102 private static final String AUTHORIZATION_PROPERTY = "authorization";
103 private static final String BASIC_AUTH_PREFIX = "Basic ";
104 private static final String URL_SEPARATOR = "://";
Michele Santuaric372c222017-01-12 09:41:25 +0100105 protected static final String ISNOTNULL = "Rest device is not null";
106 private static final String UNKNOWN = "unknown";
Palash Kala4c71ee72017-05-24 17:43:59 +0900107 private static final int REST_TIMEOUT_SEC = 5;
Michal Machd8099742017-06-19 14:32:35 +0200108 private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
Andrea Campanella945ded22016-01-07 13:17:43 -0800109 private final Logger log = getLogger(getClass());
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected DeviceProviderRegistry providerRegistry;
113
114 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
115 protected RestSBController controller;
116
117 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
118 protected NetworkConfigRegistry cfgService;
119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected CoreService coreService;
122
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella6c71a052016-04-22 11:56:31 -0700124 protected DeviceService deviceService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800125
Michele Santuaric372c222017-01-12 09:41:25 +0100126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected DriverService driverService;
128
Andrea Campanella945ded22016-01-07 13:17:43 -0800129
130 private DeviceProviderService providerService;
Michele Santuaric372c222017-01-12 09:41:25 +0100131 private ApplicationId appId;
Andrea Campanella945ded22016-01-07 13:17:43 -0800132
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800133 private final ExecutorService executor =
Andrea Campanella90f044f2016-03-02 09:14:57 -0800134 Executors.newFixedThreadPool(5, groupedThreads("onos/restsbprovider", "device-installer-%d", log));
Michal Machd8099742017-06-19 14:32:35 +0200135 private SharedScheduledExecutorService portStatisticsExecutor = SharedScheduledExecutors.getPoolThreadExecutor();
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800136
Andrea Campanella59b549d2017-04-14 21:58:16 +0200137 protected final List<ConfigFactory> factories = ImmutableList.of(
Andrea Campanella945ded22016-01-07 13:17:43 -0800138 new ConfigFactory<ApplicationId, RestProviderConfig>(APP_SUBJECT_FACTORY,
139 RestProviderConfig.class,
Palash Kalac3ffad92017-06-09 21:18:19 +0900140 "rest_devices",
Andrea Campanella945ded22016-01-07 13:17:43 -0800141 true) {
142 @Override
143 public RestProviderConfig createConfig() {
144 return new RestProviderConfig();
145 }
Andrea Campanella59b549d2017-04-14 21:58:16 +0200146 },
147 new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
148 RestDeviceConfig.class,
149 REST) {
150 @Override
151 public RestDeviceConfig createConfig() {
152 return new RestDeviceConfig();
153 }
154 });
155
Andrea Campanella945ded22016-01-07 13:17:43 -0800156 private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener();
Andrea Campanella945ded22016-01-07 13:17:43 -0800157
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800158 private Set<DeviceId> addedDevices = new HashSet<>();
Michal Machd8099742017-06-19 14:32:35 +0200159 private ScheduledFuture<?> scheduledTask;
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800160
Andrea Campanella945ded22016-01-07 13:17:43 -0800161
162 @Activate
163 public void activate() {
164 appId = coreService.registerApplication(APP_NAME);
165 providerService = providerRegistry.register(this);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200166 factories.forEach(cfgService::registerConfigFactory);
Andrea Campanella945ded22016-01-07 13:17:43 -0800167 cfgService.addListener(cfgLister);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200168 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
169 executor.execute(RestDeviceProvider.this::createDevices);
Michal Machd8099742017-06-19 14:32:35 +0200170 scheduledTask = schedulePolling();
Andrea Campanella945ded22016-01-07 13:17:43 -0800171 log.info("Started");
172 }
173
Andrea Campanella945ded22016-01-07 13:17:43 -0800174 @Deactivate
175 public void deactivate() {
Andrea Campanella86294db2016-03-07 11:42:49 -0800176 cfgService.removeListener(cfgLister);
177 controller.getDevices().keySet().forEach(this::deviceRemoved);
Andrea Campanella945ded22016-01-07 13:17:43 -0800178 providerRegistry.unregister(this);
179 providerService = null;
Andrea Campanella59b549d2017-04-14 21:58:16 +0200180 factories.forEach(cfgService::unregisterConfigFactory);
Michal Machd8099742017-06-19 14:32:35 +0200181 scheduledTask.cancel(true);
Lukasz Ryba4da35c52017-06-20 09:14:11 +0200182 executor.shutdown();
Andrea Campanella945ded22016-01-07 13:17:43 -0800183 log.info("Stopped");
184 }
185
186 public RestDeviceProvider() {
187 super(new ProviderId(REST, PROVIDER));
188 }
189
190 @Override
191 public void triggerProbe(DeviceId deviceId) {
192 // TODO: This will be implemented later.
193 log.info("Triggering probe on device {}", deviceId);
194 }
195
196 @Override
197 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
198 // TODO: This will be implemented later.
199 }
200
201
202 @Override
203 public boolean isReachable(DeviceId deviceId) {
204 RestSBDevice restDevice = controller.getDevice(deviceId);
205 if (restDevice == null) {
Michele Santuaric372c222017-01-12 09:41:25 +0100206 restDevice = controller.getProxySBDevice(deviceId);
207 if (restDevice == null) {
208 log.debug("the requested device id: " +
209 deviceId.toString() +
210 " is not associated to any REST or REST " +
211 "proxy Device");
212 return false;
213 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800214 }
215 return restDevice.isActive();
216 }
217
Michele Santuaric372c222017-01-12 09:41:25 +0100218 private void deviceAdded(RestSBDevice restSBDev) {
219 checkNotNull(restSBDev, ISNOTNULL);
220
221 //check if the server is controlling a single or multiple devices
222 if (restSBDev.isProxy()) {
223
224 Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
225 restSBDev.hwVersion().get(),
226 restSBDev.swVersion().get());
227
228 if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
229
230 //Creates the driver to communicate with the server
231 DevicesDiscovery devicesDiscovery =
232 devicesDiscovery(restSBDev, driver);
233 Set<DeviceId> deviceIds = devicesDiscovery.deviceIds();
234 restSBDev.setActive(true);
235 deviceIds.stream().forEach(deviceId -> {
236 controller.addProxiedDevice(deviceId, restSBDev);
237 DeviceDescription devDesc =
238 devicesDiscovery.deviceDetails(deviceId);
239 checkNotNull(devDesc,
240 "deviceDescription cannot be null");
241 providerService.deviceConnected(
242 deviceId, mergeAnn(restSBDev.deviceId(), devDesc));
243
244 if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
245 DriverHandler h = driverService.createHandler(deviceId);
246 DeviceDescriptionDiscovery devDisc =
247 h.behaviour(DeviceDescriptionDiscovery.class);
248 providerService.updatePorts(deviceId,
249 devDisc.discoverPortDetails());
250 }
251
252 checkAndUpdateDevice(deviceId);
253 addedDevices.add(deviceId);
254 });
255 } else {
256 log.warn("Driver not found for {}", restSBDev);
257 }
258 } else {
259 DeviceId deviceId = restSBDev.deviceId();
260 ChassisId cid = new ChassisId();
261 String ipAddress = restSBDev.ip().toString();
262 SparseAnnotations annotations = DefaultAnnotations.builder()
263 .set(IPADDRESS, ipAddress)
264 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
265 .build();
266 DeviceDescription deviceDescription = new DefaultDeviceDescription(
267 deviceId.uri(),
268 Device.Type.SWITCH,
269 UNKNOWN, UNKNOWN,
270 UNKNOWN, UNKNOWN,
271 cid,
272 annotations);
273 restSBDev.setActive(true);
274 providerService.deviceConnected(deviceId, deviceDescription);
275 checkAndUpdateDevice(deviceId);
276 addedDevices.add(deviceId);
277 }
278 }
279
280 private DefaultDeviceDescription mergeAnn(DeviceId devId, DeviceDescription desc) {
281 return new DefaultDeviceDescription(
282 desc,
283 DefaultAnnotations.merge(
284 DefaultAnnotations.builder()
285 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
286 // The rest server added as annotation to the device
287 .set(AnnotationKeys.REST_SERVER, devId.toString())
288 .build(),
289 desc.annotations()));
290 }
291
292 private DevicesDiscovery devicesDiscovery(RestSBDevice restSBDevice, Driver driver) {
293 DriverData driverData = new DefaultDriverData(driver, restSBDevice.deviceId());
294 DevicesDiscovery devicesDiscovery = driver.createBehaviour(driverData,
295 DevicesDiscovery.class);
296 devicesDiscovery.setHandler(new DefaultDriverHandler(driverData));
297 return devicesDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -0800298 }
299
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600300 private void checkAndUpdateDevice(DeviceId deviceId) {
301 if (deviceService.getDevice(deviceId) == null) {
302 log.warn("Device {} has not been added to store, " +
303 "maybe due to a problem in connectivity", deviceId);
304 } else {
305 boolean isReachable = isReachable(deviceId);
306 if (isReachable && deviceService.isAvailable(deviceId)) {
307 Device device = deviceService.getDevice(deviceId);
308 if (device.is(DeviceDescriptionDiscovery.class)) {
Michele Santuaric372c222017-01-12 09:41:25 +0100309 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
310 device.as(DeviceDescriptionDiscovery.class);
311 DeviceDescription updatedDeviceDescription =
312 deviceDescriptionDiscovery.discoverDeviceDetails();
313 if (updatedDeviceDescription != null &&
314 !descriptionEquals(device, updatedDeviceDescription)) {
315 providerService.deviceConnected(
316 deviceId,
317 new DefaultDeviceDescription(
318 updatedDeviceDescription, true,
319 updatedDeviceDescription.annotations()));
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600320 //if ports are not discovered, retry the discovery
321 if (deviceService.getPorts(deviceId).isEmpty()) {
322 discoverPorts(deviceId);
323 }
324 }
325 } else {
326 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
327 }
328 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
329 providerService.deviceDisconnected(deviceId);
330 }
331 }
332 }
333
334 private boolean descriptionEquals(Device device, DeviceDescription updatedDeviceDescription) {
Michele Santuarid2c8f212017-01-09 18:23:45 +0100335 return Objects.equal(device.id().uri(), updatedDeviceDescription.deviceUri())
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600336 && Objects.equal(device.type(), updatedDeviceDescription.type())
337 && Objects.equal(device.manufacturer(), updatedDeviceDescription.manufacturer())
338 && Objects.equal(device.hwVersion(), updatedDeviceDescription.hwVersion())
339 && Objects.equal(device.swVersion(), updatedDeviceDescription.swVersion())
340 && Objects.equal(device.serialNumber(), updatedDeviceDescription.serialNumber())
341 && Objects.equal(device.chassisId(), updatedDeviceDescription.chassisId())
342 && Objects.equal(device.annotations(), updatedDeviceDescription.annotations());
343 }
344
Andrea Campanella86294db2016-03-07 11:42:49 -0800345 private void deviceRemoved(DeviceId deviceId) {
Michele Santuaric372c222017-01-12 09:41:25 +0100346 checkNotNull(deviceId, ISNOTNULL);
Andrea Campanella945ded22016-01-07 13:17:43 -0800347 providerService.deviceDisconnected(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100348 controller.getProxiedDevices(deviceId).stream().forEach(device -> {
349 controller.removeProxiedDevice(device);
350 providerService.deviceDisconnected(device);
351 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800352 controller.removeDevice(deviceId);
Andrea Campanella945ded22016-01-07 13:17:43 -0800353 }
354
Andrea Campanella59b549d2017-04-14 21:58:16 +0200355 //Method to connect devices provided via net-cfg under devices/ tree
356 private void createAndConnectDevices() {
357 Set<DeviceId> deviceSubjects =
358 cfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
359 connectDevices(deviceSubjects.stream()
360 .filter(deviceId -> deviceService.getDevice(deviceId) == null)
361 .map(deviceId -> {
362 RestDeviceConfig config =
363 cfgService.getConfig(deviceId, RestDeviceConfig.class);
364 RestSBDevice device = new DefaultRestSBDevice(config.ip(),
365 config.port(),
366 config.username(),
367 config.password(),
368 config.protocol(),
369 config.url(),
370 false, config.testUrl(),
371 config.manufacturer(),
372 config.hwVersion(),
373 config.swVersion());
374 return device;
375
376 }).collect(Collectors.toSet()));
377 }
378
379 //Old method to register devices provided via net-cfg under apps/rest/ tree
380 private void createDevices() {
Andrea Campanella945ded22016-01-07 13:17:43 -0800381 RestProviderConfig cfg = cfgService.getConfig(appId, RestProviderConfig.class);
382 try {
383 if (cfg != null && cfg.getDevicesAddresses() != null) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200384 connectDevices(cfg.getDevicesAddresses());
385
Andrea Campanella945ded22016-01-07 13:17:43 -0800386 }
387 } catch (ConfigException e) {
388 log.error("Configuration error {}", e);
389 }
Andrea Campanella2947e622016-01-27 09:23:46 -0800390 log.debug("REST Devices {}", controller.getDevices());
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800391 addedDevices.clear();
Andrea Campanella945ded22016-01-07 13:17:43 -0800392 }
393
Andrea Campanella59b549d2017-04-14 21:58:16 +0200394 private void connectDevices(Set<RestSBDevice> devices) {
395 //Precomputing the devices to be removed
396 Set<RestSBDevice> toBeRemoved = new HashSet<>(controller.getDevices().values());
397 toBeRemoved.removeAll(devices);
398 //Adding new devices
399 devices.stream()
400 .filter(device -> {
401 device.setActive(false);
402 controller.addDevice(device);
403 return testDeviceConnection(device);
404 })
405 .forEach(device -> {
406 deviceAdded(device);
407 });
408 //Removing devices not wanted anymore
409 toBeRemoved.forEach(device -> deviceRemoved(device.deviceId()));
410 }
411
Michal Machd8099742017-06-19 14:32:35 +0200412 private ScheduledFuture schedulePolling() {
413 return portStatisticsExecutor.scheduleAtFixedRate(this::executePortStatisticsUpdate,
414 DEFAULT_POLL_FREQUENCY_SECONDS / 2,
415 DEFAULT_POLL_FREQUENCY_SECONDS,
416 TimeUnit.SECONDS);
417 }
418
419 private void executePortStatisticsUpdate() {
420 controller.getDevices().keySet().forEach(this::updatePortStatistics);
421 }
422
423 private void updatePortStatistics(DeviceId deviceId) {
424 Device device = deviceService.getDevice(deviceId);
425 checkNotNull(device, "device cannot be null");
426
427 if (device.is(PortStatisticsDiscovery.class)) {
428 PortStatisticsDiscovery portStatisticsDiscovery = device.as(PortStatisticsDiscovery.class);
429 Collection<PortStatistics> portStatistics = portStatisticsDiscovery.discoverPortStatistics();
430 if (portStatistics != null && !portStatistics.isEmpty()) {
431 providerService.updatePortStatistics(deviceId, portStatistics);
432 }
433 } else {
434 log.debug("No port statistics getter behaviour for device {}", deviceId);
435 }
436 }
437
Andrea Campanella6c71a052016-04-22 11:56:31 -0700438 private void discoverPorts(DeviceId deviceId) {
439 Device device = deviceService.getDevice(deviceId);
440 //TODO remove when PortDiscovery is removed from master
441 if (device.is(PortDiscovery.class)) {
442 PortDiscovery portConfig = device.as(PortDiscovery.class);
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600443 providerService.updatePorts(deviceId, portConfig.getPorts());
444 } else {
Andrea Campanella6c71a052016-04-22 11:56:31 -0700445 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
446 device.as(DeviceDescriptionDiscovery.class);
447 providerService.updatePorts(deviceId, deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700448 }
449 }
450
Michele Santuaric372c222017-01-12 09:41:25 +0100451 private boolean testDeviceConnection(RestSBDevice dev) {
Andrea Campanella945ded22016-01-07 13:17:43 -0800452 try {
Palash Kala4c71ee72017-05-24 17:43:59 +0900453 Callable<Boolean> connectionSuccess;
454
Michele Santuaric372c222017-01-12 09:41:25 +0100455 if (dev.testUrl().isPresent()) {
Palash Kala4c71ee72017-05-24 17:43:59 +0900456 connectionSuccess = new Callable<Boolean>() {
457 @Override
458 public Boolean call() throws Exception {
459 return controller
460 .get(dev.deviceId(), dev.testUrl().get(), JSON) != null;
461 }
462 };
463 } else {
464 connectionSuccess = new Callable<Boolean>() {
465 @Override
466 public Boolean call() throws Exception {
467 return controller.get(dev.deviceId(), "", JSON) != null;
468 }
469 };
Michele Santuaric372c222017-01-12 09:41:25 +0100470 }
Palash Kala4c71ee72017-05-24 17:43:59 +0900471
472 Future<Boolean> future = executor.submit(connectionSuccess);
473 try {
474 Boolean result = future.get(REST_TIMEOUT_SEC, TimeUnit.SECONDS);
475 return result;
476 } catch (TimeoutException ex) {
477 log.warn("Connection to device {} timed out", dev.deviceId());
478 return false;
479 } catch (InterruptedException ex) {
480 log.warn("Connection to device {} interrupted", dev.deviceId());
481 return false;
482 } catch (ExecutionException ex) {
483 log.warn("Connection to device {} had a execution exception", dev.deviceId());
484 return false;
485 }
Michele Santuaric372c222017-01-12 09:41:25 +0100486
Andrea Campanellac6ecc632016-03-10 17:57:06 -0800487 } catch (ProcessingException e) {
Michele Santuaric372c222017-01-12 09:41:25 +0100488 log.warn("Cannot connect to device {}", dev, e);
Andrea Campanella945ded22016-01-07 13:17:43 -0800489 }
490 return false;
491 }
492
493 private class InternalNetworkConfigListener implements NetworkConfigListener {
Andrea Campanella945ded22016-01-07 13:17:43 -0800494 @Override
495 public void event(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200496 if (event.configClass().equals(RestDeviceConfig.class)) {
497 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
498 } else {
499 log.warn("Injecting device via this Json is deprecated, " +
500 "please put configuration under devices/");
501 executor.execute(RestDeviceProvider.this::createDevices);
502 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800503 }
504
505 @Override
506 public boolean isRelevant(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200507 return (event.configClass().equals(RestDeviceConfig.class) ||
508 event.configClass().equals(RestProviderConfig.class)) &&
Andrea Campanella945ded22016-01-07 13:17:43 -0800509 (event.type() == CONFIG_ADDED ||
510 event.type() == CONFIG_UPDATED);
511 }
512 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700513
514 @Override
515 public void changePortState(DeviceId deviceId, PortNumber portNumber,
516 boolean enable) {
517 // TODO if required
518 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800519}