[ONOS-7566] Implementation of NetconfProxySession

Change-Id: I01cbe0b10ac36cb6db53127555b551f405acdeb1
diff --git a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
index d8bb0c7..9b65f25 100644
--- a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
+++ b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
@@ -18,6 +18,7 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
+import org.onosproject.netconf.NetconfException;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -95,10 +96,16 @@
         providerService = providerRegistry.register(this);
         controller.getNetconfDevices().forEach(id -> {
             NetconfDevice device = controller.getNetconfDevice(id);
-            NetconfSession session = device.getSession();
-            InternalNotificationListener listener = new InternalNotificationListener(device.getDeviceInfo());
-            session.addDeviceOutputListener(listener);
-            idNotificationListenerMap.put(id, listener);
+            if (device.isMasterSession()) {
+                NetconfSession session = device.getSession();
+                InternalNotificationListener listener = new InternalNotificationListener(device.getDeviceInfo());
+                try {
+                    session.addDeviceOutputListener(listener);
+                } catch (NetconfException e) {
+                    log.error("addDeviceOutputListener Error {} ", e.getMessage());
+                }
+                idNotificationListenerMap.put(id, listener);
+            }
         });
         controller.addDeviceListener(deviceListener);
         log.info("NetconfAlarmProvider Started");
@@ -108,9 +115,14 @@
     public void deactivate() {
         providerRegistry.unregister(this);
         idNotificationListenerMap.forEach((id, listener) -> {
-            controller.getNetconfDevice(id)
-                    .getSession()
-                    .removeDeviceOutputListener(listener);
+            NetconfDevice device = controller.getNetconfDevice(id);
+            if (device.isMasterSession()) {
+                try {
+                    device.getSession().removeDeviceOutputListener(listener);
+                } catch (NetconfException e) {
+                    log.error("RemoveDeviceOutputListener Error {}", e.getMessage());
+                }
+            }
         });
         controller.removeDeviceListener(deviceListener);
         providerService = null;
@@ -161,11 +173,15 @@
 
         @Override
         public void deviceAdded(DeviceId deviceId) {
-            NetconfDevice device = controller.getNetconfDevice(deviceId);
-            NetconfSession session = device.getSession();
-            InternalNotificationListener listener = new InternalNotificationListener(device.getDeviceInfo());
-            session.addDeviceOutputListener(listener);
-            idNotificationListenerMap.put(deviceId, listener);
+            try {
+                NetconfDevice device = controller.getNetconfDevice(deviceId);
+                NetconfSession session = device.getSession();
+                InternalNotificationListener listener = new InternalNotificationListener(device.getDeviceInfo());
+                session.addDeviceOutputListener(listener);
+                idNotificationListenerMap.put(deviceId, listener);
+            } catch (NetconfException e) {
+                log.error("Device add fail {}", e.getMessage());
+            }
         }
 
         @Override
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
index 98d135f..80b9108 100644
--- a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProvider.java
@@ -274,6 +274,8 @@
                 case STANDBY:
                     //TODO this issue a warning on the first election/connection
                     controller.disconnectDevice(deviceId, false);
+                    withDeviceLock(
+                            () -> initiateConnection(deviceId, newRole), deviceId).run();
                     providerService.receivedRoleReply(deviceId, newRole, MastershipRole.STANDBY);
                     //else no-op
                     break;
@@ -531,6 +533,42 @@
                 UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, cid, true, annotations.build());
     }
 
+    /**
+     * Will appropriately create connections with the device.
+     * For Master role: will create secure transport and proxy sessions.
+     * For Standby role: will create only proxy session and disconnect secure transport session.
+     * For none role: will disconnect all sessions.
+     *
+     * @param deviceId device id
+     * @param newRole new role
+     */
+    private void initiateConnection(DeviceId deviceId, MastershipRole newRole) {
+        try {
+            if (isReachable(deviceId)) {
+                NetconfDevice device = null;
+                if (newRole.equals(MastershipRole.MASTER)) {
+                    device = controller.connectDevice(deviceId, true);
+                } else if (newRole.equals(MastershipRole.STANDBY)) {
+                    device = controller.connectDevice(deviceId, false);
+                }
+
+                if (device != null) {
+                    providerService.receivedRoleReply(deviceId, newRole, newRole);
+                } else {
+                    providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
+                }
+
+            }
+        } catch (Exception e) {
+            if (deviceService.getDevice(deviceId) != null) {
+                providerService.deviceDisconnected(deviceId);
+            }
+            deviceKeyAdminService.removeKey(DeviceKeyId.deviceKeyId(deviceId.toString()));
+            throw new IllegalStateException(new NetconfException(
+                    "Can't connect to NETCONF device " + deviceId, e));
+        }
+    }
+
 
     private void discoverOrUpdatePorts(DeviceId deviceId) {
         retriedPortDiscoveryMap.put(deviceId, new AtomicInteger(0));