helenyrwu
Committed by Gerrit Code Review

[ONOS-4681] Enables device registration in GossipDeviceStore,

exposes availability, and polls NETCONF device reachability.

Change-Id: I5492c7b6109c3431d71555a9104c7e97fc6e75be
...@@ -38,6 +38,7 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -38,6 +38,7 @@ public class DefaultDeviceDescription extends AbstractDescription
38 private final String swVersion; 38 private final String swVersion;
39 private final String serialNumber; 39 private final String serialNumber;
40 private final ChassisId chassisId; 40 private final ChassisId chassisId;
41 + private final boolean defaultAvailable;
41 42
42 /** 43 /**
43 * Creates a device description using the supplied information. 44 * Creates a device description using the supplied information.
...@@ -55,6 +56,28 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -55,6 +56,28 @@ public class DefaultDeviceDescription extends AbstractDescription
55 String hwVersion, String swVersion, 56 String hwVersion, String swVersion,
56 String serialNumber, ChassisId chassis, 57 String serialNumber, ChassisId chassis,
57 SparseAnnotations... annotations) { 58 SparseAnnotations... annotations) {
59 + this(uri, type, manufacturer, hwVersion, swVersion, serialNumber,
60 + chassis, true, annotations);
61 + }
62 +
63 + /**
64 + * Creates a device description using the supplied information.
65 + *
66 + * @param uri device URI
67 + * @param type device type
68 + * @param manufacturer device manufacturer
69 + * @param hwVersion device HW version
70 + * @param swVersion device SW version
71 + * @param serialNumber device serial number
72 + * @param chassis chassis id
73 + * @param defaultAvailable optional whether device is by default available
74 + * @param annotations optional key/value annotations map
75 + */
76 + public DefaultDeviceDescription(URI uri, Type type, String manufacturer,
77 + String hwVersion, String swVersion,
78 + String serialNumber, ChassisId chassis,
79 + boolean defaultAvailable,
80 + SparseAnnotations... annotations) {
58 super(annotations); 81 super(annotations);
59 this.uri = checkNotNull(uri, "Device URI cannot be null"); 82 this.uri = checkNotNull(uri, "Device URI cannot be null");
60 this.type = checkNotNull(type, "Device type cannot be null"); 83 this.type = checkNotNull(type, "Device type cannot be null");
...@@ -63,6 +86,7 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -63,6 +86,7 @@ public class DefaultDeviceDescription extends AbstractDescription
63 this.swVersion = swVersion; 86 this.swVersion = swVersion;
64 this.serialNumber = serialNumber; 87 this.serialNumber = serialNumber;
65 this.chassisId = chassis; 88 this.chassisId = chassis;
89 + this.defaultAvailable = defaultAvailable;
66 } 90 }
67 91
68 /** 92 /**
...@@ -74,7 +98,7 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -74,7 +98,7 @@ public class DefaultDeviceDescription extends AbstractDescription
74 SparseAnnotations... annotations) { 98 SparseAnnotations... annotations) {
75 this(base.deviceUri(), base.type(), base.manufacturer(), 99 this(base.deviceUri(), base.type(), base.manufacturer(),
76 base.hwVersion(), base.swVersion(), base.serialNumber(), 100 base.hwVersion(), base.swVersion(), base.serialNumber(),
77 - base.chassisId(), annotations); 101 + base.chassisId(), base.isDefaultAvailable(), annotations);
78 } 102 }
79 103
80 /** 104 /**
...@@ -83,10 +107,26 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -83,10 +107,26 @@ public class DefaultDeviceDescription extends AbstractDescription
83 * @param type device type 107 * @param type device type
84 * @param annotations Annotations to use. 108 * @param annotations Annotations to use.
85 */ 109 */
86 - public DefaultDeviceDescription(DeviceDescription base, Type type, SparseAnnotations... annotations) { 110 + public DefaultDeviceDescription(DeviceDescription base, Type type,
111 + SparseAnnotations... annotations) {
87 this(base.deviceUri(), type, base.manufacturer(), 112 this(base.deviceUri(), type, base.manufacturer(),
88 base.hwVersion(), base.swVersion(), base.serialNumber(), 113 base.hwVersion(), base.swVersion(), base.serialNumber(),
89 - base.chassisId(), annotations); 114 + base.chassisId(), base.isDefaultAvailable(), annotations);
115 + }
116 +
117 + /**
118 + * Creates a device description using the supplied information.
119 + *
120 + * @param base DeviceDescription to basic information (except for defaultAvailable)
121 + * @param defaultAvailable whether device should be made available by default
122 + * @param annotations Annotations to use.
123 + */
124 + public DefaultDeviceDescription(DeviceDescription base,
125 + boolean defaultAvailable,
126 + SparseAnnotations... annotations) {
127 + this(base.deviceUri(), base.type(), base.manufacturer(),
128 + base.hwVersion(), base.swVersion(), base.serialNumber(),
129 + base.chassisId(), defaultAvailable, annotations);
90 } 130 }
91 131
92 @Override 132 @Override
...@@ -125,6 +165,11 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -125,6 +165,11 @@ public class DefaultDeviceDescription extends AbstractDescription
125 } 165 }
126 166
127 @Override 167 @Override
168 + public boolean isDefaultAvailable() {
169 + return defaultAvailable;
170 + }
171 +
172 + @Override
128 public String toString() { 173 public String toString() {
129 return toStringHelper(this) 174 return toStringHelper(this)
130 .add("uri", uri).add("type", type).add("mfr", manufacturer) 175 .add("uri", uri).add("type", type).add("mfr", manufacturer)
...@@ -137,7 +182,8 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -137,7 +182,8 @@ public class DefaultDeviceDescription extends AbstractDescription
137 @Override 182 @Override
138 public int hashCode() { 183 public int hashCode() {
139 return Objects.hashCode(super.hashCode(), uri, type, manufacturer, 184 return Objects.hashCode(super.hashCode(), uri, type, manufacturer,
140 - hwVersion, swVersion, serialNumber, chassisId); 185 + hwVersion, swVersion, serialNumber, chassisId,
186 + defaultAvailable);
141 } 187 }
142 188
143 @Override 189 @Override
...@@ -153,7 +199,8 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -153,7 +199,8 @@ public class DefaultDeviceDescription extends AbstractDescription
153 && Objects.equal(this.hwVersion, that.hwVersion) 199 && Objects.equal(this.hwVersion, that.hwVersion)
154 && Objects.equal(this.swVersion, that.swVersion) 200 && Objects.equal(this.swVersion, that.swVersion)
155 && Objects.equal(this.serialNumber, that.serialNumber) 201 && Objects.equal(this.serialNumber, that.serialNumber)
156 - && Objects.equal(this.chassisId, that.chassisId); 202 + && Objects.equal(this.chassisId, that.chassisId)
203 + && Objects.equal(this.defaultAvailable, that.defaultAvailable);
157 } 204 }
158 return false; 205 return false;
159 } 206 }
...@@ -167,5 +214,6 @@ public class DefaultDeviceDescription extends AbstractDescription ...@@ -167,5 +214,6 @@ public class DefaultDeviceDescription extends AbstractDescription
167 this.swVersion = null; 214 this.swVersion = null;
168 this.serialNumber = null; 215 this.serialNumber = null;
169 this.chassisId = null; 216 this.chassisId = null;
217 + this.defaultAvailable = true;
170 } 218 }
171 } 219 }
......
...@@ -77,4 +77,11 @@ public interface DeviceDescription extends Description { ...@@ -77,4 +77,11 @@ public interface DeviceDescription extends Description {
77 */ 77 */
78 ChassisId chassisId(); 78 ChassisId chassisId();
79 79
80 + /**
81 + * Return whether device should be made available by default.
82 + *
83 + * @return default availability
84 + */
85 + boolean isDefaultAvailable();
86 +
80 } 87 }
......
...@@ -52,8 +52,6 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -52,8 +52,6 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
52 */ 52 */
53 Iterable<Device> getAvailableDevices(); 53 Iterable<Device> getAvailableDevices();
54 54
55 -
56 -
57 /** 55 /**
58 * Returns the device with the specified identifier. 56 * Returns the device with the specified identifier.
59 * 57 *
...@@ -74,6 +72,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -74,6 +72,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
74 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId, 72 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
75 DeviceDescription deviceDescription); 73 DeviceDescription deviceDescription);
76 74
75 +
77 // TODO: We may need to enforce that ancillary cannot interfere this state 76 // TODO: We may need to enforce that ancillary cannot interfere this state
78 /** 77 /**
79 * Removes the specified infrastructure device. 78 * Removes the specified infrastructure device.
...@@ -84,6 +83,14 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -84,6 +83,14 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
84 DeviceEvent markOffline(DeviceId deviceId); 83 DeviceEvent markOffline(DeviceId deviceId);
85 84
86 /** 85 /**
86 + * Marks the device as available.
87 + *
88 + * @param deviceId device identifier
89 + * @return true if availability change request was accepted and changed the state
90 + */
91 + boolean markOnline(DeviceId deviceId);
92 +
93 + /**
87 * Updates the ports of the specified infrastructure device using the given 94 * Updates the ports of the specified infrastructure device using the given
88 * list of port descriptions. The list is assumed to be comprehensive. 95 * list of port descriptions. The list is assumed to be comprehensive.
89 * 96 *
......
...@@ -57,6 +57,11 @@ public class DeviceStoreAdapter implements DeviceStore { ...@@ -57,6 +57,11 @@ public class DeviceStoreAdapter implements DeviceStore {
57 } 57 }
58 58
59 @Override 59 @Override
60 + public boolean markOnline(DeviceId deviceId) {
61 + return false;
62 + }
63 +
64 + @Override
60 public DeviceEvent markOffline(DeviceId deviceId) { 65 public DeviceEvent markOffline(DeviceId deviceId) {
61 return null; 66 return null;
62 } 67 }
......
...@@ -245,6 +245,13 @@ public class SimpleDeviceStore ...@@ -245,6 +245,13 @@ public class SimpleDeviceStore
245 } 245 }
246 } 246 }
247 247
248 + // implement differently if desired
249 + @Override
250 + public boolean markOnline(DeviceId deviceId) {
251 + log.warn("Mark online not supported");
252 + return false;
253 + }
254 +
248 @Override 255 @Override
249 public List<DeviceEvent> updatePorts(ProviderId providerId, 256 public List<DeviceEvent> updatePorts(ProviderId providerId,
250 DeviceId deviceId, 257 DeviceId deviceId,
......
...@@ -79,7 +79,8 @@ public final class BasicDeviceOperator implements ConfigOperator { ...@@ -79,7 +79,8 @@ public final class BasicDeviceOperator implements ConfigOperator {
79 SparseAnnotations sa = combine(bdc, descr.annotations()); 79 SparseAnnotations sa = combine(bdc, descr.annotations());
80 return new DefaultDeviceDescription(descr.deviceUri(), type, manufacturer, 80 return new DefaultDeviceDescription(descr.deviceUri(), type, manufacturer,
81 hwVersion, swVersion, 81 hwVersion, swVersion,
82 - serial, descr.chassisId(), sa); 82 + serial, descr.chassisId(),
83 + descr.isDefaultAvailable(), sa);
83 } 84 }
84 85
85 /** 86 /**
......
...@@ -64,7 +64,6 @@ import org.onosproject.net.config.NetworkConfigListener; ...@@ -64,7 +64,6 @@ import org.onosproject.net.config.NetworkConfigListener;
64 import org.onosproject.net.config.NetworkConfigService; 64 import org.onosproject.net.config.NetworkConfigService;
65 import org.onosproject.net.config.basics.BasicDeviceConfig; 65 import org.onosproject.net.config.basics.BasicDeviceConfig;
66 import org.onosproject.net.config.basics.OpticalPortConfig; 66 import org.onosproject.net.config.basics.OpticalPortConfig;
67 -import org.onosproject.net.device.DefaultDeviceDescription;
68 import org.onosproject.net.device.DefaultPortDescription; 67 import org.onosproject.net.device.DefaultPortDescription;
69 import org.onosproject.net.device.DeviceAdminService; 68 import org.onosproject.net.device.DeviceAdminService;
70 import org.onosproject.net.device.DeviceDescription; 69 import org.onosproject.net.device.DeviceDescription;
...@@ -288,6 +287,19 @@ public class DeviceManager ...@@ -288,6 +287,19 @@ public class DeviceManager
288 log.trace("Checking device {}", deviceId); 287 log.trace("Checking device {}", deviceId);
289 288
290 if (!isReachable(deviceId)) { 289 if (!isReachable(deviceId)) {
290 + if (mastershipService.getLocalRole(deviceId) != NONE) {
291 + // can't be master if device is not reachable
292 + try {
293 + post(store.markOffline(deviceId));
294 + //relinquish master role and ability to be backup.
295 + mastershipService.relinquishMastership(deviceId).get();
296 + } catch (InterruptedException e) {
297 + log.warn("Interrupted while reliquishing role for {}", deviceId);
298 + Thread.currentThread().interrupt();
299 + } catch (ExecutionException e) {
300 + log.error("Exception thrown while relinquishing role for {}", deviceId, e);
301 + }
302 + }
291 continue; 303 continue;
292 } 304 }
293 305
...@@ -334,7 +346,6 @@ public class DeviceManager ...@@ -334,7 +346,6 @@ public class DeviceManager
334 } 346 }
335 provider.roleChanged(deviceId, newRole); 347 provider.roleChanged(deviceId, newRole);
336 // not triggering probe when triggered by provider service event 348 // not triggering probe when triggered by provider service event
337 -
338 return true; 349 return true;
339 } 350 }
340 351
...@@ -360,12 +371,15 @@ public class DeviceManager ...@@ -360,12 +371,15 @@ public class DeviceManager
360 371
361 DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId, 372 DeviceEvent event = store.createOrUpdateDevice(provider().id(), deviceId,
362 deviceDescription); 373 deviceDescription);
374 + if (deviceDescription.isDefaultAvailable()) {
363 log.info("Device {} connected", deviceId); 375 log.info("Device {} connected", deviceId);
376 + } else {
377 + log.info("Device {} registered", deviceId);
378 + }
364 if (event != null) { 379 if (event != null) {
365 log.trace("event: {} {}", event.type(), event); 380 log.trace("event: {} {}", event.type(), event);
366 post(event); 381 post(event);
367 } 382 }
368 -
369 } 383 }
370 384
371 private PortDescription ensurePortEnabledState(PortDescription desc, boolean enabled) { 385 private PortDescription ensurePortEnabledState(PortDescription desc, boolean enabled) {
...@@ -684,19 +698,7 @@ public class DeviceManager ...@@ -684,19 +698,7 @@ public class DeviceManager
684 case MASTER: 698 case MASTER:
685 final Device device = getDevice(did); 699 final Device device = getDevice(did);
686 if ((device != null) && !isAvailable(did)) { 700 if ((device != null) && !isAvailable(did)) {
687 - //flag the device as online. Is there a better way to do this? 701 + store.markOnline(did);
688 - DefaultDeviceDescription deviceDescription
689 - = new DefaultDeviceDescription(did.uri(),
690 - device.type(),
691 - device.manufacturer(),
692 - device.hwVersion(),
693 - device.swVersion(),
694 - device.serialNumber(),
695 - device.chassisId());
696 - DeviceEvent devEvent =
697 - store.createOrUpdateDevice(device.providerId(), did,
698 - deviceDescription);
699 - post(devEvent);
700 } 702 }
701 // TODO: should apply role only if there is mismatch 703 // TODO: should apply role only if there is mismatch
702 log.debug("Applying role {} to {}", myNextRole, did); 704 log.debug("Applying role {} to {}", myNextRole, did);
......
...@@ -275,6 +275,7 @@ public class ECDeviceStore ...@@ -275,6 +275,7 @@ public class ECDeviceStore
275 return devices.get(deviceId); 275 return devices.get(deviceId);
276 } 276 }
277 277
278 + // FIXME handle deviceDescription.isDefaultAvailable()=false case properly.
278 @Override 279 @Override
279 public DeviceEvent createOrUpdateDevice(ProviderId providerId, 280 public DeviceEvent createOrUpdateDevice(ProviderId providerId,
280 DeviceId deviceId, 281 DeviceId deviceId,
...@@ -392,9 +393,14 @@ public class ECDeviceStore ...@@ -392,9 +393,14 @@ public class ECDeviceStore
392 return null; 393 return null;
393 } 394 }
394 395
395 - private boolean markOnline(DeviceId deviceId) { 396 + // FIXME publicization of markOnline -- trigger some action independently?
397 + public boolean markOnline(DeviceId deviceId) {
398 + if (devices.containsKey(deviceId)) {
396 return availableDevices.add(deviceId); 399 return availableDevices.add(deviceId);
397 } 400 }
401 + log.warn("Device {} does not exist in store", deviceId);
402 + return false;
403 + }
398 404
399 @Override 405 @Override
400 public DeviceEvent markOffline(DeviceId deviceId) { 406 public DeviceEvent markOffline(DeviceId deviceId) {
......
...@@ -406,11 +406,16 @@ public class GossipDeviceStore ...@@ -406,11 +406,16 @@ public class GossipDeviceStore
406 return null; 406 return null;
407 } 407 }
408 if (oldDevice == null) { 408 if (oldDevice == null) {
409 + // REGISTER
410 + if (!deltaDesc.value().isDefaultAvailable()) {
411 + return registerDevice(providerId, newDevice);
412 + }
409 // ADD 413 // ADD
410 return createDevice(providerId, newDevice, deltaDesc.timestamp()); 414 return createDevice(providerId, newDevice, deltaDesc.timestamp());
411 } else { 415 } else {
412 // UPDATE or ignore (no change or stale) 416 // UPDATE or ignore (no change or stale)
413 - return updateDevice(providerId, oldDevice, newDevice, deltaDesc.timestamp()); 417 + return updateDevice(providerId, oldDevice, newDevice, deltaDesc.timestamp(),
418 + deltaDesc.value().isDefaultAvailable());
414 } 419 }
415 } 420 }
416 } 421 }
...@@ -437,7 +442,8 @@ public class GossipDeviceStore ...@@ -437,7 +442,8 @@ public class GossipDeviceStore
437 // Guarded by deviceDescs value (=Device lock) 442 // Guarded by deviceDescs value (=Device lock)
438 private DeviceEvent updateDevice(ProviderId providerId, 443 private DeviceEvent updateDevice(ProviderId providerId,
439 Device oldDevice, 444 Device oldDevice,
440 - Device newDevice, Timestamp newTimestamp) { 445 + Device newDevice, Timestamp newTimestamp,
446 + boolean forceAvailable) {
441 // We allow only certain attributes to trigger update 447 // We allow only certain attributes to trigger update
442 boolean propertiesChanged = 448 boolean propertiesChanged =
443 !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || 449 !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) ||
...@@ -461,7 +467,7 @@ public class GossipDeviceStore ...@@ -461,7 +467,7 @@ public class GossipDeviceStore
461 event = new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null); 467 event = new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
462 } 468 }
463 469
464 - if (!providerId.isAncillary()) { 470 + if (!providerId.isAncillary() && forceAvailable) {
465 boolean wasOnline = availableDevices.contains(newDevice.id()); 471 boolean wasOnline = availableDevices.contains(newDevice.id());
466 markOnline(newDevice.id(), newTimestamp); 472 markOnline(newDevice.id(), newTimestamp);
467 if (!wasOnline) { 473 if (!wasOnline) {
...@@ -471,6 +477,20 @@ public class GossipDeviceStore ...@@ -471,6 +477,20 @@ public class GossipDeviceStore
471 return event; 477 return event;
472 } 478 }
473 479
480 + private DeviceEvent registerDevice(ProviderId providerId, Device newDevice) {
481 + // update composed device cache
482 + Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice);
483 + verify(oldDevice == null,
484 + "Unexpected Device in cache. PID:%s [old=%s, new=%s]",
485 + providerId, oldDevice, newDevice);
486 +
487 + if (!providerId.isAncillary()) {
488 + markOffline(newDevice.id());
489 + }
490 +
491 + return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, newDevice, null);
492 + }
493 +
474 @Override 494 @Override
475 public DeviceEvent markOffline(DeviceId deviceId) { 495 public DeviceEvent markOffline(DeviceId deviceId) {
476 final Timestamp timestamp = deviceClockService.getTimestamp(deviceId); 496 final Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
...@@ -514,6 +534,24 @@ public class GossipDeviceStore ...@@ -514,6 +534,24 @@ public class GossipDeviceStore
514 } 534 }
515 } 535 }
516 536
537 + public boolean markOnline(DeviceId deviceId) {
538 + if (devices.containsKey(deviceId)) {
539 + final Timestamp timestamp = deviceClockService.getTimestamp(deviceId);
540 + Map<?, ?> deviceLock = getOrCreateDeviceDescriptionsMap(deviceId);
541 + synchronized (deviceLock) {
542 + if (markOnline(deviceId, timestamp)) {
543 + notifyDelegate(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, getDevice(deviceId), null));
544 + return true;
545 + } else {
546 + return false;
547 + }
548 + }
549 + }
550 + log.warn("Device {} does not exist in store", deviceId);
551 + return false;
552 +
553 + }
554 +
517 /** 555 /**
518 * Marks the device as available if the given timestamp is not outdated, 556 * Marks the device as available if the given timestamp is not outdated,
519 * compared to the time the device has been marked offline. 557 * compared to the time the device has been marked offline.
...@@ -1576,7 +1614,8 @@ public class GossipDeviceStore ...@@ -1576,7 +1614,8 @@ public class GossipDeviceStore
1576 Timestamped<DeviceDescription> deviceDescription = event.deviceDescription(); 1614 Timestamped<DeviceDescription> deviceDescription = event.deviceDescription();
1577 1615
1578 try { 1616 try {
1579 - notifyDelegateIfNotNull(createOrUpdateDeviceInternal(providerId, deviceId, deviceDescription)); 1617 + notifyDelegateIfNotNull(createOrUpdateDeviceInternal(providerId, deviceId,
1618 + deviceDescription));
1580 } catch (Exception e) { 1619 } catch (Exception e) {
1581 log.warn("Exception thrown handling device update", e); 1620 log.warn("Exception thrown handling device update", e);
1582 } 1621 }
......
...@@ -450,7 +450,6 @@ public class GrpcRemoteServiceTest { ...@@ -450,7 +450,6 @@ public class GrpcRemoteServiceTest {
450 deviceConnected.countDown(); 450 deviceConnected.countDown();
451 } 451 }
452 452
453 -
454 final CountDownLatch updatePorts = new CountDownLatch(1); 453 final CountDownLatch updatePorts = new CountDownLatch(1);
455 DeviceId updatePortsDid; 454 DeviceId updatePortsDid;
456 List<PortDescription> updatePortsDescs; 455 List<PortDescription> updatePortsDescs;
......
...@@ -258,7 +258,6 @@ public class IsisTopologyProviderTest { ...@@ -258,7 +258,6 @@ public class IsisTopologyProviderTest {
258 258
259 } 259 }
260 260
261 -
262 @Override 261 @Override
263 public void deviceDisconnected(DeviceId deviceId) { 262 public void deviceDisconnected(DeviceId deviceId) {
264 263
......
...@@ -67,6 +67,9 @@ import java.net.URISyntaxException; ...@@ -67,6 +67,9 @@ import java.net.URISyntaxException;
67 import java.util.Arrays; 67 import java.util.Arrays;
68 import java.util.concurrent.ExecutorService; 68 import java.util.concurrent.ExecutorService;
69 import java.util.concurrent.Executors; 69 import java.util.concurrent.Executors;
70 +import java.util.concurrent.ScheduledExecutorService;
71 +import java.util.concurrent.ScheduledFuture;
72 +import java.util.concurrent.TimeUnit;
70 73
71 import static org.onlab.util.Tools.groupedThreads; 74 import static org.onlab.util.Tools.groupedThreads;
72 import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY; 75 import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
...@@ -114,17 +117,21 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -114,17 +117,21 @@ public class NetconfDeviceProvider extends AbstractProvider
114 private static final String IPADDRESS = "ipaddress"; 117 private static final String IPADDRESS = "ipaddress";
115 private static final String NETCONF = "netconf"; 118 private static final String NETCONF = "netconf";
116 private static final String PORT = "port"; 119 private static final String PORT = "port";
120 + private static final int CORE_POOL_SIZE = 10;
117 //FIXME eventually a property 121 //FIXME eventually a property
118 private static final int ISREACHABLE_TIMEOUT = 2000; 122 private static final int ISREACHABLE_TIMEOUT = 2000;
123 + private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 30;
119 124
120 private final ExecutorService executor = 125 private final ExecutorService executor =
121 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider", 126 Executors.newFixedThreadPool(5, groupedThreads("onos/netconfdeviceprovider",
122 "device-installer-%d", log)); 127 "device-installer-%d", log));
128 + protected ScheduledExecutorService connectionExecutor = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
123 129
124 private DeviceProviderService providerService; 130 private DeviceProviderService providerService;
125 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener(); 131 private NetconfDeviceListener innerNodeListener = new InnerNetconfDeviceListener();
126 private InternalDeviceListener deviceListener = new InternalDeviceListener(); 132 private InternalDeviceListener deviceListener = new InternalDeviceListener();
127 private NodeId localNodeId; 133 private NodeId localNodeId;
134 + private ScheduledFuture<?> scheduledTask;
128 135
129 private final ConfigFactory factory = 136 private final ConfigFactory factory =
130 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY, 137 new ConfigFactory<ApplicationId, NetconfProviderConfig>(APP_SUBJECT_FACTORY,
...@@ -152,6 +159,7 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -152,6 +159,7 @@ public class NetconfDeviceProvider extends AbstractProvider
152 deviceService.addListener(deviceListener); 159 deviceService.addListener(deviceListener);
153 executor.execute(NetconfDeviceProvider.this::connectDevices); 160 executor.execute(NetconfDeviceProvider.this::connectDevices);
154 localNodeId = clusterService.getLocalNode().id(); 161 localNodeId = clusterService.getLocalNode().id();
162 + scheduledTask = schedulePolling();
155 log.info("Started"); 163 log.info("Started");
156 } 164 }
157 165
...@@ -169,6 +177,7 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -169,6 +177,7 @@ public class NetconfDeviceProvider extends AbstractProvider
169 providerRegistry.unregister(this); 177 providerRegistry.unregister(this);
170 providerService = null; 178 providerService = null;
171 cfgService.unregisterConfigFactory(factory); 179 cfgService.unregisterConfigFactory(factory);
180 + scheduledTask.cancel(true);
172 executor.shutdown(); 181 executor.shutdown();
173 log.info("Stopped"); 182 log.info("Stopped");
174 } 183 }
...@@ -177,6 +186,15 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -177,6 +186,15 @@ public class NetconfDeviceProvider extends AbstractProvider
177 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE)); 186 super(new ProviderId(SCHEME_NAME, DEVICE_PROVIDER_PACKAGE));
178 } 187 }
179 188
189 + // Checks connection to devices in the config file
190 + // every DEFAULT_POLL_FREQUENCY_SECONDS seconds.
191 + private ScheduledFuture schedulePolling() {
192 + return connectionExecutor.scheduleAtFixedRate(this::checkAndUpdateDevices,
193 + DEFAULT_POLL_FREQUENCY_SECONDS / 10,
194 + DEFAULT_POLL_FREQUENCY_SECONDS,
195 + TimeUnit.SECONDS);
196 + }
197 +
180 @Override 198 @Override
181 public void triggerProbe(DeviceId deviceId) { 199 public void triggerProbe(DeviceId deviceId) {
182 // TODO: This will be implemented later. 200 // TODO: This will be implemented later.
...@@ -270,8 +288,14 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -270,8 +288,14 @@ public class NetconfDeviceProvider extends AbstractProvider
270 @Override 288 @Override
271 public void deviceRemoved(DeviceId deviceId) { 289 public void deviceRemoved(DeviceId deviceId) {
272 Preconditions.checkNotNull(deviceId, ISNULL); 290 Preconditions.checkNotNull(deviceId, ISNULL);
273 - log.debug("Netconf device {} removed from Netconf subController", deviceId); 291 +
292 + if (deviceService.getDevice(deviceId) != null) {
274 providerService.deviceDisconnected(deviceId); 293 providerService.deviceDisconnected(deviceId);
294 + log.debug("Netconf device {} removed from Netconf subController", deviceId);
295 + } else {
296 + log.warn("Netconf device {} does not exist in the store, " +
297 + "it may already have been removed", deviceId);
298 + }
275 } 299 }
276 } 300 }
277 301
...@@ -295,13 +319,67 @@ public class NetconfDeviceProvider extends AbstractProvider ...@@ -295,13 +319,67 @@ public class NetconfDeviceProvider extends AbstractProvider
295 Device.Type.SWITCH, 319 Device.Type.SWITCH,
296 UNKNOWN, UNKNOWN, 320 UNKNOWN, UNKNOWN,
297 UNKNOWN, UNKNOWN, 321 UNKNOWN, UNKNOWN,
298 - cid, 322 + cid, false,
299 annotations); 323 annotations);
300 deviceKeyAdminService.addKey( 324 deviceKeyAdminService.addKey(
301 DeviceKey.createDeviceKeyUsingUsernamePassword( 325 DeviceKey.createDeviceKeyUsingUsernamePassword(
302 DeviceKeyId.deviceKeyId(deviceId.toString()), 326 DeviceKeyId.deviceKeyId(deviceId.toString()),
303 null, addr.name(), addr.password())); 327 null, addr.name(), addr.password()));
328 + if (deviceService.getDevice(deviceId) == null) {
304 providerService.deviceConnected(deviceId, deviceDescription); 329 providerService.deviceConnected(deviceId, deviceDescription);
330 + }
331 + checkAndUpdateDevice(deviceId, deviceDescription);
332 + });
333 + } catch (ConfigException e) {
334 + log.error("Cannot read config error " + e);
335 + }
336 + }
337 + }
338 +
339 + private void checkAndUpdateDevice(DeviceId deviceId, DeviceDescription deviceDescription) {
340 + if (deviceService.getDevice(deviceId) == null) {
341 + log.warn("Device {} has not been added to store, " +
342 + "maybe due to a problem in connectivity", deviceId);
343 + } else {
344 + boolean isReachable = isReachable(deviceId);
345 + if (isReachable && !deviceService.isAvailable(deviceId)) {
346 + providerService.deviceConnected(
347 + deviceId, new DefaultDeviceDescription(
348 + deviceDescription, true, deviceDescription.annotations()));
349 + } else if (!isReachable && deviceService.isAvailable(deviceId)) {
350 + providerService.deviceDisconnected(deviceId);
351 + }
352 + }
353 + }
354 +
355 + private void checkAndUpdateDevices() {
356 + NetconfProviderConfig cfg = cfgService.getConfig(appId, NetconfProviderConfig.class);
357 + if (cfg != null) {
358 + log.info("Checking connection to devices in configuration");
359 + try {
360 + cfg.getDevicesAddresses().stream().forEach(addr -> {
361 + DeviceId deviceId = getDeviceId(addr.ip().toString(), addr.port());
362 + Preconditions.checkNotNull(deviceId, ISNULL);
363 + //Netconf configuration object
364 + ChassisId cid = new ChassisId();
365 + String ipAddress = addr.ip().toString();
366 + SparseAnnotations annotations = DefaultAnnotations.builder()
367 + .set(IPADDRESS, ipAddress)
368 + .set(PORT, String.valueOf(addr.port()))
369 + .set(AnnotationKeys.PROTOCOL, SCHEME_NAME.toUpperCase())
370 + .build();
371 + DeviceDescription deviceDescription = new DefaultDeviceDescription(
372 + deviceId.uri(),
373 + Device.Type.SWITCH,
374 + UNKNOWN, UNKNOWN,
375 + UNKNOWN, UNKNOWN,
376 + cid, false,
377 + annotations);
378 + deviceKeyAdminService.addKey(
379 + DeviceKey.createDeviceKeyUsingUsernamePassword(
380 + DeviceKeyId.deviceKeyId(deviceId.toString()),
381 + null, addr.name(), addr.password()));
382 + checkAndUpdateDevice(deviceId, deviceDescription);
305 }); 383 });
306 } catch (ConfigException e) { 384 } catch (ConfigException e) {
307 log.error("Cannot read config error " + e); 385 log.error("Cannot read config error " + e);
......