blob: 478829e3b638b30df7dba69187865f3fc123f04a [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;
27import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.incubator.net.config.basics.ConfigException;
Marc De Leenheerb0d131c2016-03-01 20:34:59 -080030import org.onosproject.net.AnnotationKeys;
Andrea Campanella945ded22016-01-07 13:17:43 -080031import org.onosproject.net.DefaultAnnotations;
32import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
34import org.onosproject.net.MastershipRole;
Saurav Dasa2d37502016-03-25 17:50:40 -070035import org.onosproject.net.PortNumber;
Andrea Campanella945ded22016-01-07 13:17:43 -080036import org.onosproject.net.SparseAnnotations;
Michele Santuaric372c222017-01-12 09:41:25 +010037import org.onosproject.net.behaviour.DevicesDiscovery;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080038import org.onosproject.net.behaviour.PortDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -080039import org.onosproject.net.config.ConfigFactory;
40import org.onosproject.net.config.NetworkConfigEvent;
41import org.onosproject.net.config.NetworkConfigListener;
42import org.onosproject.net.config.NetworkConfigRegistry;
Andrea Campanella59b549d2017-04-14 21:58:16 +020043import org.onosproject.net.config.basics.SubjectFactories;
Andrea Campanella945ded22016-01-07 13:17:43 -080044import org.onosproject.net.device.DefaultDeviceDescription;
45import org.onosproject.net.device.DeviceDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070046import org.onosproject.net.device.DeviceDescriptionDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -080047import org.onosproject.net.device.DeviceProvider;
48import org.onosproject.net.device.DeviceProviderRegistry;
49import org.onosproject.net.device.DeviceProviderService;
Andrea Campanella6c71a052016-04-22 11:56:31 -070050import org.onosproject.net.device.DeviceService;
Michele Santuaric372c222017-01-12 09:41:25 +010051import org.onosproject.net.driver.DefaultDriverData;
52import org.onosproject.net.driver.DefaultDriverHandler;
53import org.onosproject.net.driver.Driver;
54import org.onosproject.net.driver.DriverData;
55import org.onosproject.net.driver.DriverHandler;
56import org.onosproject.net.driver.DriverService;
Andrea Campanella945ded22016-01-07 13:17:43 -080057import org.onosproject.net.provider.AbstractProvider;
58import org.onosproject.net.provider.ProviderId;
Andrea Campanella59b549d2017-04-14 21:58:16 +020059import org.onosproject.protocol.rest.DefaultRestSBDevice;
Andrea Campanella945ded22016-01-07 13:17:43 -080060import org.onosproject.protocol.rest.RestSBController;
61import org.onosproject.protocol.rest.RestSBDevice;
62import org.slf4j.Logger;
63
Andrea Campanellac6ecc632016-03-10 17:57:06 -080064import javax.ws.rs.ProcessingException;
Andrea Campanella945ded22016-01-07 13:17:43 -080065import java.util.HashSet;
Andrea Campanella59b549d2017-04-14 21:58:16 +020066import java.util.List;
Andrea Campanella945ded22016-01-07 13:17:43 -080067import java.util.Set;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080068import java.util.concurrent.ExecutorService;
69import java.util.concurrent.Executors;
Andrea Campanella59b549d2017-04-14 21:58:16 +020070import java.util.stream.Collectors;
Andrea Campanella945ded22016-01-07 13:17:43 -080071
Michele Santuaric372c222017-01-12 09:41:25 +010072import static com.google.common.base.Preconditions.checkNotNull;
Andrea Campanella784ee0f2016-02-17 15:50:59 -080073import static org.onlab.util.Tools.groupedThreads;
Andrea Campanella945ded22016-01-07 13:17:43 -080074import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
75import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
76import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
77import static org.slf4j.LoggerFactory.getLogger;
78
79/**
80 * Provider for devices that use REST as means of configuration communication.
81 */
82@Component(immediate = true)
83public class RestDeviceProvider extends AbstractProvider
84 implements DeviceProvider {
85 private static final String APP_NAME = "org.onosproject.restsb";
Andrea Campanella59b549d2017-04-14 21:58:16 +020086 protected static final String REST = "rest";
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -060087 private static final String JSON = "json";
Andrea Campanella945ded22016-01-07 13:17:43 -080088 private static final String PROVIDER = "org.onosproject.provider.rest.device";
89 private static final String IPADDRESS = "ipaddress";
Andrea Campanella2947e622016-01-27 09:23:46 -080090 private static final String HTTPS = "https";
91 private static final String AUTHORIZATION_PROPERTY = "authorization";
92 private static final String BASIC_AUTH_PREFIX = "Basic ";
93 private static final String URL_SEPARATOR = "://";
Michele Santuaric372c222017-01-12 09:41:25 +010094 protected static final String ISNOTNULL = "Rest device is not null";
95 private static final String UNKNOWN = "unknown";
Andrea Campanella945ded22016-01-07 13:17:43 -080096 private final Logger log = getLogger(getClass());
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected DeviceProviderRegistry providerRegistry;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected RestSBController controller;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected NetworkConfigRegistry cfgService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected CoreService coreService;
109
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Andrea Campanella6c71a052016-04-22 11:56:31 -0700111 protected DeviceService deviceService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800112
Michele Santuaric372c222017-01-12 09:41:25 +0100113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 protected DriverService driverService;
115
Andrea Campanella945ded22016-01-07 13:17:43 -0800116
117 private DeviceProviderService providerService;
Michele Santuaric372c222017-01-12 09:41:25 +0100118 private ApplicationId appId;
Andrea Campanella945ded22016-01-07 13:17:43 -0800119
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800120 private final ExecutorService executor =
Andrea Campanella90f044f2016-03-02 09:14:57 -0800121 Executors.newFixedThreadPool(5, groupedThreads("onos/restsbprovider", "device-installer-%d", log));
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800122
Andrea Campanella59b549d2017-04-14 21:58:16 +0200123 protected final List<ConfigFactory> factories = ImmutableList.of(
Andrea Campanella945ded22016-01-07 13:17:43 -0800124 new ConfigFactory<ApplicationId, RestProviderConfig>(APP_SUBJECT_FACTORY,
125 RestProviderConfig.class,
Konstantinos Kanonakisb3e97042016-11-15 11:33:07 -0600126 "devices",
Andrea Campanella945ded22016-01-07 13:17:43 -0800127 true) {
128 @Override
129 public RestProviderConfig createConfig() {
130 return new RestProviderConfig();
131 }
Andrea Campanella59b549d2017-04-14 21:58:16 +0200132 },
133 new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
134 RestDeviceConfig.class,
135 REST) {
136 @Override
137 public RestDeviceConfig createConfig() {
138 return new RestDeviceConfig();
139 }
140 });
141
Andrea Campanella945ded22016-01-07 13:17:43 -0800142 private final NetworkConfigListener cfgLister = new InternalNetworkConfigListener();
Andrea Campanella945ded22016-01-07 13:17:43 -0800143
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800144 private Set<DeviceId> addedDevices = new HashSet<>();
145
Andrea Campanella945ded22016-01-07 13:17:43 -0800146
147 @Activate
148 public void activate() {
149 appId = coreService.registerApplication(APP_NAME);
150 providerService = providerRegistry.register(this);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200151 factories.forEach(cfgService::registerConfigFactory);
Andrea Campanella945ded22016-01-07 13:17:43 -0800152 cfgService.addListener(cfgLister);
Andrea Campanella59b549d2017-04-14 21:58:16 +0200153 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
154 executor.execute(RestDeviceProvider.this::createDevices);
Andrea Campanella945ded22016-01-07 13:17:43 -0800155 log.info("Started");
156 }
157
Andrea Campanella945ded22016-01-07 13:17:43 -0800158 @Deactivate
159 public void deactivate() {
Andrea Campanella86294db2016-03-07 11:42:49 -0800160 cfgService.removeListener(cfgLister);
161 controller.getDevices().keySet().forEach(this::deviceRemoved);
Andrea Campanella945ded22016-01-07 13:17:43 -0800162 providerRegistry.unregister(this);
163 providerService = null;
Andrea Campanella59b549d2017-04-14 21:58:16 +0200164 factories.forEach(cfgService::unregisterConfigFactory);
Andrea Campanella945ded22016-01-07 13:17:43 -0800165 log.info("Stopped");
166 }
167
168 public RestDeviceProvider() {
169 super(new ProviderId(REST, PROVIDER));
170 }
171
172 @Override
173 public void triggerProbe(DeviceId deviceId) {
174 // TODO: This will be implemented later.
175 log.info("Triggering probe on device {}", deviceId);
176 }
177
178 @Override
179 public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
180 // TODO: This will be implemented later.
181 }
182
183
184 @Override
185 public boolean isReachable(DeviceId deviceId) {
186 RestSBDevice restDevice = controller.getDevice(deviceId);
187 if (restDevice == null) {
Michele Santuaric372c222017-01-12 09:41:25 +0100188 restDevice = controller.getProxySBDevice(deviceId);
189 if (restDevice == null) {
190 log.debug("the requested device id: " +
191 deviceId.toString() +
192 " is not associated to any REST or REST " +
193 "proxy Device");
194 return false;
195 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800196 }
197 return restDevice.isActive();
198 }
199
Michele Santuaric372c222017-01-12 09:41:25 +0100200 private void deviceAdded(RestSBDevice restSBDev) {
201 checkNotNull(restSBDev, ISNOTNULL);
202
203 //check if the server is controlling a single or multiple devices
204 if (restSBDev.isProxy()) {
205
206 Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
207 restSBDev.hwVersion().get(),
208 restSBDev.swVersion().get());
209
210 if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
211
212 //Creates the driver to communicate with the server
213 DevicesDiscovery devicesDiscovery =
214 devicesDiscovery(restSBDev, driver);
215 Set<DeviceId> deviceIds = devicesDiscovery.deviceIds();
216 restSBDev.setActive(true);
217 deviceIds.stream().forEach(deviceId -> {
218 controller.addProxiedDevice(deviceId, restSBDev);
219 DeviceDescription devDesc =
220 devicesDiscovery.deviceDetails(deviceId);
221 checkNotNull(devDesc,
222 "deviceDescription cannot be null");
223 providerService.deviceConnected(
224 deviceId, mergeAnn(restSBDev.deviceId(), devDesc));
225
226 if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
227 DriverHandler h = driverService.createHandler(deviceId);
228 DeviceDescriptionDiscovery devDisc =
229 h.behaviour(DeviceDescriptionDiscovery.class);
230 providerService.updatePorts(deviceId,
231 devDisc.discoverPortDetails());
232 }
233
234 checkAndUpdateDevice(deviceId);
235 addedDevices.add(deviceId);
236 });
237 } else {
238 log.warn("Driver not found for {}", restSBDev);
239 }
240 } else {
241 DeviceId deviceId = restSBDev.deviceId();
242 ChassisId cid = new ChassisId();
243 String ipAddress = restSBDev.ip().toString();
244 SparseAnnotations annotations = DefaultAnnotations.builder()
245 .set(IPADDRESS, ipAddress)
246 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
247 .build();
248 DeviceDescription deviceDescription = new DefaultDeviceDescription(
249 deviceId.uri(),
250 Device.Type.SWITCH,
251 UNKNOWN, UNKNOWN,
252 UNKNOWN, UNKNOWN,
253 cid,
254 annotations);
255 restSBDev.setActive(true);
256 providerService.deviceConnected(deviceId, deviceDescription);
257 checkAndUpdateDevice(deviceId);
258 addedDevices.add(deviceId);
259 }
260 }
261
262 private DefaultDeviceDescription mergeAnn(DeviceId devId, DeviceDescription desc) {
263 return new DefaultDeviceDescription(
264 desc,
265 DefaultAnnotations.merge(
266 DefaultAnnotations.builder()
267 .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
268 // The rest server added as annotation to the device
269 .set(AnnotationKeys.REST_SERVER, devId.toString())
270 .build(),
271 desc.annotations()));
272 }
273
274 private DevicesDiscovery devicesDiscovery(RestSBDevice restSBDevice, Driver driver) {
275 DriverData driverData = new DefaultDriverData(driver, restSBDevice.deviceId());
276 DevicesDiscovery devicesDiscovery = driver.createBehaviour(driverData,
277 DevicesDiscovery.class);
278 devicesDiscovery.setHandler(new DefaultDriverHandler(driverData));
279 return devicesDiscovery;
Andrea Campanella945ded22016-01-07 13:17:43 -0800280 }
281
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600282 private void checkAndUpdateDevice(DeviceId deviceId) {
283 if (deviceService.getDevice(deviceId) == null) {
284 log.warn("Device {} has not been added to store, " +
285 "maybe due to a problem in connectivity", deviceId);
286 } else {
287 boolean isReachable = isReachable(deviceId);
288 if (isReachable && deviceService.isAvailable(deviceId)) {
289 Device device = deviceService.getDevice(deviceId);
290 if (device.is(DeviceDescriptionDiscovery.class)) {
Michele Santuaric372c222017-01-12 09:41:25 +0100291 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
292 device.as(DeviceDescriptionDiscovery.class);
293 DeviceDescription updatedDeviceDescription =
294 deviceDescriptionDiscovery.discoverDeviceDetails();
295 if (updatedDeviceDescription != null &&
296 !descriptionEquals(device, updatedDeviceDescription)) {
297 providerService.deviceConnected(
298 deviceId,
299 new DefaultDeviceDescription(
300 updatedDeviceDescription, true,
301 updatedDeviceDescription.annotations()));
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600302 //if ports are not discovered, retry the discovery
303 if (deviceService.getPorts(deviceId).isEmpty()) {
304 discoverPorts(deviceId);
305 }
306 }
307 } else {
308 log.warn("No DeviceDescriptionDiscovery behaviour for device {}", deviceId);
309 }
310 } else if (!isReachable && deviceService.isAvailable(deviceId)) {
311 providerService.deviceDisconnected(deviceId);
312 }
313 }
314 }
315
316 private boolean descriptionEquals(Device device, DeviceDescription updatedDeviceDescription) {
Michele Santuarid2c8f212017-01-09 18:23:45 +0100317 return Objects.equal(device.id().uri(), updatedDeviceDescription.deviceUri())
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600318 && Objects.equal(device.type(), updatedDeviceDescription.type())
319 && Objects.equal(device.manufacturer(), updatedDeviceDescription.manufacturer())
320 && Objects.equal(device.hwVersion(), updatedDeviceDescription.hwVersion())
321 && Objects.equal(device.swVersion(), updatedDeviceDescription.swVersion())
322 && Objects.equal(device.serialNumber(), updatedDeviceDescription.serialNumber())
323 && Objects.equal(device.chassisId(), updatedDeviceDescription.chassisId())
324 && Objects.equal(device.annotations(), updatedDeviceDescription.annotations());
325 }
326
Andrea Campanella86294db2016-03-07 11:42:49 -0800327 private void deviceRemoved(DeviceId deviceId) {
Michele Santuaric372c222017-01-12 09:41:25 +0100328 checkNotNull(deviceId, ISNOTNULL);
Andrea Campanella945ded22016-01-07 13:17:43 -0800329 providerService.deviceDisconnected(deviceId);
Michele Santuaric372c222017-01-12 09:41:25 +0100330 controller.getProxiedDevices(deviceId).stream().forEach(device -> {
331 controller.removeProxiedDevice(device);
332 providerService.deviceDisconnected(device);
333 });
Andrea Campanella86294db2016-03-07 11:42:49 -0800334 controller.removeDevice(deviceId);
Andrea Campanella945ded22016-01-07 13:17:43 -0800335 }
336
Andrea Campanella59b549d2017-04-14 21:58:16 +0200337 //Method to connect devices provided via net-cfg under devices/ tree
338 private void createAndConnectDevices() {
339 Set<DeviceId> deviceSubjects =
340 cfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
341 connectDevices(deviceSubjects.stream()
342 .filter(deviceId -> deviceService.getDevice(deviceId) == null)
343 .map(deviceId -> {
344 RestDeviceConfig config =
345 cfgService.getConfig(deviceId, RestDeviceConfig.class);
346 RestSBDevice device = new DefaultRestSBDevice(config.ip(),
347 config.port(),
348 config.username(),
349 config.password(),
350 config.protocol(),
351 config.url(),
352 false, config.testUrl(),
353 config.manufacturer(),
354 config.hwVersion(),
355 config.swVersion());
356 return device;
357
358 }).collect(Collectors.toSet()));
359 }
360
361 //Old method to register devices provided via net-cfg under apps/rest/ tree
362 private void createDevices() {
Andrea Campanella945ded22016-01-07 13:17:43 -0800363 RestProviderConfig cfg = cfgService.getConfig(appId, RestProviderConfig.class);
364 try {
365 if (cfg != null && cfg.getDevicesAddresses() != null) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200366 connectDevices(cfg.getDevicesAddresses());
367
Andrea Campanella945ded22016-01-07 13:17:43 -0800368 }
369 } catch (ConfigException e) {
370 log.error("Configuration error {}", e);
371 }
Andrea Campanella2947e622016-01-27 09:23:46 -0800372 log.debug("REST Devices {}", controller.getDevices());
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800373 addedDevices.clear();
Andrea Campanella945ded22016-01-07 13:17:43 -0800374 }
375
Andrea Campanella59b549d2017-04-14 21:58:16 +0200376 private void connectDevices(Set<RestSBDevice> devices) {
377 //Precomputing the devices to be removed
378 Set<RestSBDevice> toBeRemoved = new HashSet<>(controller.getDevices().values());
379 toBeRemoved.removeAll(devices);
380 //Adding new devices
381 devices.stream()
382 .filter(device -> {
383 device.setActive(false);
384 controller.addDevice(device);
385 return testDeviceConnection(device);
386 })
387 .forEach(device -> {
388 deviceAdded(device);
389 });
390 //Removing devices not wanted anymore
391 toBeRemoved.forEach(device -> deviceRemoved(device.deviceId()));
392 }
393
Andrea Campanella6c71a052016-04-22 11:56:31 -0700394 private void discoverPorts(DeviceId deviceId) {
395 Device device = deviceService.getDevice(deviceId);
396 //TODO remove when PortDiscovery is removed from master
397 if (device.is(PortDiscovery.class)) {
398 PortDiscovery portConfig = device.as(PortDiscovery.class);
Konstantinos Kanonakis3cd85552016-11-17 10:11:13 -0600399 providerService.updatePorts(deviceId, portConfig.getPorts());
400 } else {
Andrea Campanella6c71a052016-04-22 11:56:31 -0700401 DeviceDescriptionDiscovery deviceDescriptionDiscovery =
402 device.as(DeviceDescriptionDiscovery.class);
403 providerService.updatePorts(deviceId, deviceDescriptionDiscovery.discoverPortDetails());
Andrea Campanella6c71a052016-04-22 11:56:31 -0700404 }
405 }
406
Michele Santuaric372c222017-01-12 09:41:25 +0100407 private boolean testDeviceConnection(RestSBDevice dev) {
Andrea Campanella945ded22016-01-07 13:17:43 -0800408 try {
Michele Santuaric372c222017-01-12 09:41:25 +0100409 if (dev.testUrl().isPresent()) {
410 return controller
411 .get(dev.deviceId(), dev.testUrl().get(), JSON) != null;
412 }
413 return controller.get(dev.deviceId(), "", JSON) != null;
414
Andrea Campanellac6ecc632016-03-10 17:57:06 -0800415 } catch (ProcessingException e) {
Michele Santuaric372c222017-01-12 09:41:25 +0100416 log.warn("Cannot connect to device {}", dev, e);
Andrea Campanella945ded22016-01-07 13:17:43 -0800417 }
418 return false;
419 }
420
421 private class InternalNetworkConfigListener implements NetworkConfigListener {
Andrea Campanella945ded22016-01-07 13:17:43 -0800422 @Override
423 public void event(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200424 if (event.configClass().equals(RestDeviceConfig.class)) {
425 executor.execute(RestDeviceProvider.this::createAndConnectDevices);
426 } else {
427 log.warn("Injecting device via this Json is deprecated, " +
428 "please put configuration under devices/");
429 executor.execute(RestDeviceProvider.this::createDevices);
430 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800431 }
432
433 @Override
434 public boolean isRelevant(NetworkConfigEvent event) {
Andrea Campanella59b549d2017-04-14 21:58:16 +0200435 return (event.configClass().equals(RestDeviceConfig.class) ||
436 event.configClass().equals(RestProviderConfig.class)) &&
Andrea Campanella945ded22016-01-07 13:17:43 -0800437 (event.type() == CONFIG_ADDED ||
438 event.type() == CONFIG_UPDATED);
439 }
440 }
Saurav Dasa2d37502016-03-25 17:50:40 -0700441
442 @Override
443 public void changePortState(DeviceId deviceId, PortNumber portNumber,
444 boolean enable) {
445 // TODO if required
446 }
Andrea Campanella945ded22016-01-07 13:17:43 -0800447}