RestDevice connection/disconnection identification-ONOS-7655, Issue - when device is rebooted/shutdown, device information - 'available' & 'local-status' was not getting changed.In our project with same changes many testcases excuted and working fine.Submitting to onos

Change-Id: I778ef9ac6d6651bde570f997c2acd36858635990
diff --git a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
index e6d8b7b..f289dc9 100644
--- a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
+++ b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
@@ -110,6 +110,7 @@
     private static final String POLL_FREQUENCY = "pollFrequency";
     private static final int REST_TIMEOUT_SEC = 5;
     private static final int EXECUTOR_THREAD_POOL_SIZE = 8;
+    private static final int DEVICE_POLL_SEC = 30;
     private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -146,6 +147,9 @@
     private final SharedScheduledExecutorService portStatisticsExecutor =
             SharedScheduledExecutors.getPoolThreadExecutor();
 
+    private final SharedScheduledExecutorService deviceConnectionExecutor =
+            SharedScheduledExecutors.getPoolThreadExecutor();
+    private ScheduledFuture<?> devicePollTask;
     private final List<ConfigFactory> factories = ImmutableList.of(
             new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
                                                           RestDeviceConfig.class,
@@ -173,6 +177,7 @@
         netCfgService.addListener(configListener);
         executor.execute(RestDeviceProvider.this::createAndConnectDevices);
         scheduledTask = schedulePolling();
+        devicePollTask = scheduleDevicePolling();
         log.info("Started");
     }
 
@@ -204,6 +209,7 @@
         factories.forEach(netCfgService::unregisterConfigFactory);
         scheduledTask.cancel(true);
         executor.shutdown();
+        devicePollTask.cancel(true);
         log.info("Stopped");
     }
 
@@ -219,23 +225,91 @@
 
     @Override
     public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
-        // TODO: This will be implemented later.
+        log.debug("Received role {} request for device {}", newRole, deviceId);
+        RestSBDevice device = controller.getDevice(deviceId);
+        if (device != null && testDeviceConnection(device)) {
+            providerService.receivedRoleReply(deviceId, newRole, newRole);
+        } else {
+            log.warn("Device not present or available {}", deviceId);
+            providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
+        }
     }
 
     @Override
     public boolean isReachable(DeviceId deviceId) {
         RestSBDevice restDevice = controller.getDevice(deviceId);
-        if (restDevice == null) {
-            restDevice = controller.getProxySBDevice(deviceId);
-            if (restDevice == null) {
-                log.debug("the requested device id: " +
-                                  deviceId.toString() +
-                                  "  is not associated to any REST or REST " +
-                                  "proxy Device");
-                return false;
+        return restDevice != null ? restDevice.isActive() : false;
+    }
+
+    private ScheduledFuture scheduleDevicePolling() {
+        return deviceConnectionExecutor.scheduleWithFixedDelay(() -> {
+            try {
+                controller.getDevices().values().stream().forEach(restSBDevice -> {
+                            DeviceId deviceId = restSBDevice.deviceId();
+                            if (deviceService.getDevice(deviceId) != null) {
+                                boolean connected = testDeviceConnection(restSBDevice);
+                                restSBDevice.setActive(connected);
+                                if (deviceService.isAvailable(deviceId) && (!connected)) {
+                                    providerService.deviceDisconnected(deviceId);
+                                } else if (!deviceService.isAvailable(deviceId) && connected) {
+                                    DeviceDescription devDesc = getDesc(restSBDevice);
+                                    checkNotNull(devDesc, "deviceDescription cannot be null");
+                                    providerService.deviceConnected(
+                                            deviceId, mergeAnn(deviceId, devDesc));
+                                }
+                            }
+                        }
+                );
+            } catch (Exception e) {
+                log.error("Exception at schedule Device polling", e);
+            }
+        }, 1, DEVICE_POLL_SEC, TimeUnit.SECONDS);
+    }
+
+    private DeviceDescription getDesc(RestSBDevice restSBDev) {
+        DeviceId deviceId = restSBDev.deviceId();
+        if (restSBDev.isProxy()) {
+            Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
+                    restSBDev.hwVersion().get(),
+                    restSBDev.swVersion().get());
+
+            if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
+
+                //Creates the driver to communicate with the server
+                DevicesDiscovery devicesDiscovery =
+                        devicesDiscovery(restSBDev, driver);
+                return devicesDiscovery.deviceDetails(deviceId);
+            } else {
+                log.warn("Driver not found for {}", restSBDev);
+                return null;
             }
         }
-        return restDevice.isActive();
+        ChassisId cid = new ChassisId();
+        String ipAddress = restSBDev.ip().toString();
+        SparseAnnotations annotations = DefaultAnnotations.builder()
+                .set(IPADDRESS, ipAddress)
+                .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
+                .build();
+        String manufacturer = UNKNOWN;
+        String hwVersion = UNKNOWN;
+        String swVersion = UNKNOWN;
+        String serialNumber = UNKNOWN;
+
+        Device device = deviceService.getDevice(deviceId);
+        if (device != null) {
+            manufacturer = device.manufacturer();
+            hwVersion = device.hwVersion();
+            swVersion = device.swVersion();
+            serialNumber = device.serialNumber();
+        }
+
+        return new DefaultDeviceDescription(
+                deviceId.uri(),
+                Device.Type.SWITCH,
+                manufacturer, hwVersion,
+                swVersion, serialNumber,
+                cid,
+                annotations);
     }
 
     private void deviceAdded(RestSBDevice restSBDev) {
@@ -270,6 +344,7 @@
             }
         } else {
             DeviceId deviceId = restSBDev.deviceId();
+
             if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
                 restSBDev.setActive(true);
                 DevicesDiscovery devicesDiscovery = devicesDiscovery(restSBDev, driver);
@@ -283,23 +358,10 @@
                     providerService.updatePorts(deviceId, deviceDiscovery.discoverPortDetails());
                 }
             } else {
-                ChassisId cid = new ChassisId();
-                String ipAddress = restSBDev.ip().toString();
-                SparseAnnotations annotations = DefaultAnnotations.builder()
-                        .set(IPADDRESS, ipAddress)
-                        .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
-                        .build();
-                DeviceDescription deviceDescription = new DefaultDeviceDescription(
-                        deviceId.uri(),
-                        Device.Type.SWITCH,
-                        UNKNOWN, UNKNOWN,
-                        UNKNOWN, UNKNOWN,
-                        cid,
-                        annotations);
+                DeviceDescription deviceDescription = getDesc(restSBDev);
                 restSBDev.setActive(true);
                 providerService.deviceConnected(deviceId, deviceDescription);
             }
-
             checkAndUpdateDevice(deviceId);
         }
     }
@@ -369,6 +431,7 @@
 
     private void deviceRemoved(DeviceId deviceId) {
         checkNotNull(deviceId, ISNOTNULL);
+        log.debug("Device removed called for {}", deviceId);
         providerService.deviceDisconnected(deviceId);
         controller.getProxiedDevices(deviceId).forEach(device -> {
             controller.removeProxiedDevice(device);
@@ -381,6 +444,8 @@
     private void createAndConnectDevices() {
         Set<DeviceId> deviceSubjects =
                 netCfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
+        log.debug("Connecting and configuring devices with received configuration:{}",
+                deviceSubjects);
         connectDevices(deviceSubjects.stream()
                 .filter(deviceId -> deviceService.getDevice(deviceId) == null)
                 .map(deviceId -> {
@@ -508,10 +573,14 @@
 
             ExecutorService bg = SharedExecutors.getSingleThreadExecutor();
             if (event.type() == CONFIG_REMOVED) {
+                log.debug("Config {} event for rest device provider for {}",
+                        event.type(), event.prevConfig().get().subject());
                 DeviceId did = (DeviceId) event.subject();
                 bg.execute(() -> deviceRemoved(did));
             } else {
-                // CONFIG_ADDED or CONFIG_UPDATED
+                //CONFIG_ADDED or CONFIG_UPDATED
+                log.debug("Config {} event for rest device provider for {}",
+                        event.type(), event.config().get().subject());
                 RestDeviceConfig cfg = (RestDeviceConfig) event.config().get();
                 RestSBDevice restSBDevice = toInactiveRestSBDevice(cfg);
                 bg.execute(() -> connectDevice(restSBDevice));