Committed by
Gerrit Code Review
[ONOS-4681] Enables device registration in GossipDeviceStore,
exposes availability, and polls NETCONF device reachability. Change-Id: I5492c7b6109c3431d71555a9104c7e97fc6e75be
Showing
12 changed files
with
236 additions
and
38 deletions
| ... | @@ -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); |
| 363 | - log.info("Device {} connected", deviceId); | 374 | + if (deviceDescription.isDefaultAvailable()) { |
| 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,8 +393,13 @@ public class ECDeviceStore | ... | @@ -392,8 +393,13 @@ 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? |
| 396 | - return availableDevices.add(deviceId); | 397 | + public boolean markOnline(DeviceId deviceId) { |
| 398 | + if (devices.containsKey(deviceId)) { | ||
| 399 | + return availableDevices.add(deviceId); | ||
| 400 | + } | ||
| 401 | + log.warn("Device {} does not exist in store", deviceId); | ||
| 402 | + return false; | ||
| 397 | } | 403 | } |
| 398 | 404 | ||
| 399 | @Override | 405 | @Override | ... | ... |
| ... | @@ -341,7 +341,7 @@ public class GossipDeviceStore | ... | @@ -341,7 +341,7 @@ public class GossipDeviceStore |
| 341 | 341 | ||
| 342 | if (deviceEvent != null) { | 342 | if (deviceEvent != null) { |
| 343 | log.debug("Notifying peers of a device update topology event for providerId: {} and deviceId: {}", | 343 | log.debug("Notifying peers of a device update topology event for providerId: {} and deviceId: {}", |
| 344 | - providerId, deviceId); | 344 | + providerId, deviceId); |
| 345 | notifyPeers(new InternalDeviceEvent(providerId, deviceId, mergedDesc)); | 345 | notifyPeers(new InternalDeviceEvent(providerId, deviceId, mergedDesc)); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| ... | @@ -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 | + |
| 274 | - providerService.deviceDisconnected(deviceId); | 292 | + if (deviceService.getDevice(deviceId) != null) { |
| 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, |
| 323 | + annotations); | ||
| 324 | + deviceKeyAdminService.addKey( | ||
| 325 | + DeviceKey.createDeviceKeyUsingUsernamePassword( | ||
| 326 | + DeviceKeyId.deviceKeyId(deviceId.toString()), | ||
| 327 | + null, addr.name(), addr.password())); | ||
| 328 | + if (deviceService.getDevice(deviceId) == null) { | ||
| 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, | ||
| 299 | annotations); | 377 | annotations); |
| 300 | deviceKeyAdminService.addKey( | 378 | deviceKeyAdminService.addKey( |
| 301 | DeviceKey.createDeviceKeyUsingUsernamePassword( | 379 | DeviceKey.createDeviceKeyUsingUsernamePassword( |
| 302 | DeviceKeyId.deviceKeyId(deviceId.toString()), | 380 | DeviceKeyId.deviceKeyId(deviceId.toString()), |
| 303 | null, addr.name(), addr.password())); | 381 | null, addr.name(), addr.password())); |
| 304 | - providerService.deviceConnected(deviceId, deviceDescription); | 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); | ... | ... |
-
Please register or login to post a comment