connect netconf devices through ssh key

Change-Id: I1a0961ffffd33559f903ead0634dbb5492e9a154
diff --git a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
index 9e68636..b950b9f 100644
--- a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
+++ b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
@@ -161,6 +161,11 @@
     public static final String REST_SERVER = "restServer";
 
     /**
+     * Annotation key for the sshkey.
+     */
+    public static final String SSHKEY = "sshkey";
+
+    /**
      * Returns the value annotated object for the specified annotation key.
      * The annotated value is expected to be String that can be parsed as double.
      * If parsing fails, the returned value will be 1.0.
diff --git a/core/api/src/main/java/org/onosproject/net/key/DeviceKey.java b/core/api/src/main/java/org/onosproject/net/key/DeviceKey.java
index 971a233..7511735 100644
--- a/core/api/src/main/java/org/onosproject/net/key/DeviceKey.java
+++ b/core/api/src/main/java/org/onosproject/net/key/DeviceKey.java
@@ -144,6 +144,25 @@
     }
 
     /**
+     * Method to create a device key of type SSL_KEY.
+     *
+     * @param id    device key identifier
+     * @param label optional label for this device key
+     * @param username username for this device key
+     * @param password password for this device key
+     * @param sshkey sshkey for this device key
+     * @return device key
+     */
+    public static DeviceKey createDeviceKeyUsingSshKey(DeviceKeyId id, String label,
+                                                                 String username, String password, String sshkey) {
+        DefaultAnnotations annotations = builder().set(AnnotationKeys.USERNAME, username)
+                .set(AnnotationKeys.PASSWORD, password)
+                .set(AnnotationKeys.SSHKEY, sshkey).build();
+
+        return new DeviceKey(id, label, Type.SSL_KEY, annotations);
+    }
+
+    /**
      * Returns a username and password object from the device key.
      *
      * @return username and password
diff --git a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
index 4c900ea..2468562 100644
--- a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
+++ b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
@@ -22,7 +22,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Objects;
@@ -39,7 +38,7 @@
     private String password;
     private IpAddress ipAddress;
     private int port;
-    private File keyFile;
+    private char[] key;
     private DeviceId deviceId;
 
 
@@ -80,7 +79,7 @@
         this.password = password;
         this.ipAddress = ipAddress;
         this.port = port;
-        this.keyFile = new File(keyString);
+        this.key = keyString.toCharArray();
     }
 
     /**
@@ -120,12 +119,12 @@
     }
 
     /**
-     * Exposes the keyFile of the controller.
+     * Exposes the key of the controller.
      *
      * @return int port address
      */
-    public File getKeyFile() {
-        return keyFile;
+    public char[] getKey() {
+        return key;
     }
 
     /**
diff --git a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java
index 00178bc..afe791c 100644
--- a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java
+++ b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfControllerImpl.java
@@ -26,9 +26,11 @@
 import org.apache.felix.scr.annotations.Service;
 import org.onlab.packet.IpAddress;
 import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.net.AnnotationKeys;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.key.DeviceKey;
 import org.onosproject.net.key.DeviceKeyId;
 import org.onosproject.net.key.DeviceKeyService;
 import org.onosproject.net.key.UsernamePassword;
@@ -201,15 +203,31 @@
                 }
             }
             try {
-                UsernamePassword deviceKey = deviceKeyService.getDeviceKey(
-                        DeviceKeyId.deviceKeyId(deviceId.toString())).asUsernamePassword();
+                DeviceKey deviceKey = deviceKeyService.getDeviceKey(
+                                DeviceKeyId.deviceKeyId(deviceId.toString()));
+                NetconfDeviceInfo deviceInfo = null;
+                if (deviceKey.type() == DeviceKey.Type.USERNAME_PASSWORD) {
+                    UsernamePassword usernamepasswd = deviceKey.asUsernamePassword();
 
-                NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo(deviceKey.username(),
-                                                                     deviceKey.password(),
-                                                                     IpAddress.valueOf(ip),
-                                                                     port);
+                    deviceInfo = new NetconfDeviceInfo(usernamepasswd.username(),
+                            usernamepasswd.password(),
+                            IpAddress.valueOf(ip),
+                            port);
+
+                } else if (deviceKey.type() == DeviceKey.Type.SSL_KEY) {
+                    String username = deviceKey.annotations().value(AnnotationKeys.USERNAME);
+                    String password = deviceKey.annotations().value(AnnotationKeys.PASSWORD);
+                    String sshkey =   deviceKey.annotations().value(AnnotationKeys.SSHKEY);
+
+                    deviceInfo = new NetconfDeviceInfo(username,
+                            password,
+                            IpAddress.valueOf(ip),
+                            port,
+                            sshkey);
+                } else {
+                    log.error("Unknown device key for device {}", deviceId);
+                }
                 NetconfDevice netconfDevicedevice = createDevice(deviceInfo);
-
                 netconfDevicedevice.getSession().addDeviceOutputListener(downListener);
                 return netconfDevicedevice;
             } catch (NullPointerException e) {
diff --git a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java
index 59cc125..451a2a1 100644
--- a/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java
+++ b/protocols/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/NetconfSessionImpl.java
@@ -118,12 +118,14 @@
             }
             boolean isAuthenticated;
             try {
-                if (deviceInfo.getKeyFile() != null) {
+                if (deviceInfo.getKey() != null) {
+                    log.debug("Authenticating with key to device {} with username {}",
+                            deviceInfo.getDeviceId(), deviceInfo.name());
                     isAuthenticated = netconfConnection.authenticateWithPublicKey(
-                            deviceInfo.name(), deviceInfo.getKeyFile(),
-                            deviceInfo.password());
+                            deviceInfo.name(), deviceInfo.getKey(),
+                            deviceInfo.password().equals("") ? null : deviceInfo.password());
                 } else {
-                    log.debug("Authenticating to device {} with username {}",
+                    log.debug("Authenticating to device {} with username {} with password",
                               deviceInfo.getDeviceId(), deviceInfo.name());
                     isAuthenticated = netconfConnection.authenticateWithPassword(
                             deviceInfo.name(), deviceInfo.password());
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 c04e23e..3ddc4ff 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
@@ -318,10 +318,8 @@
                             UNKNOWN, UNKNOWN,
                             cid, false,
                             annotations);
-                    deviceKeyAdminService.addKey(
-                            DeviceKey.createDeviceKeyUsingUsernamePassword(
-                                    DeviceKeyId.deviceKeyId(deviceId.toString()),
-                                    null, addr.name(), addr.password()));
+                    storeDeviceKey(addr, deviceId);
+
                     if (deviceService.getDevice(deviceId) == null) {
                         providerService.deviceConnected(deviceId, deviceDescription);
                     }
@@ -408,10 +406,7 @@
                             UNKNOWN, UNKNOWN,
                             cid, false,
                             annotations);
-                    deviceKeyAdminService.addKey(
-                            DeviceKey.createDeviceKeyUsingUsernamePassword(
-                                    DeviceKeyId.deviceKeyId(deviceId.toString()),
-                                    null, addr.name(), addr.password()));
+                    storeDeviceKey(addr, deviceId);
                     checkAndUpdateDevice(deviceId, deviceDescription);
                 });
             } catch (ConfigException e) {
@@ -420,6 +415,20 @@
         }
     }
 
+    private void storeDeviceKey(NetconfProviderConfig.NetconfDeviceAddress addr, DeviceId deviceId) {
+        if (addr.sshkey().equals("")) {
+            deviceKeyAdminService.addKey(
+                    DeviceKey.createDeviceKeyUsingUsernamePassword(
+                            DeviceKeyId.deviceKeyId(deviceId.toString()),
+                            null, addr.name(), addr.password()));
+        } else {
+            deviceKeyAdminService.addKey(
+                    DeviceKey.createDeviceKeyUsingSshKey(
+                            DeviceKeyId.deviceKeyId(deviceId.toString()),
+                            null, addr.name(), addr.password(), addr.sshkey()));
+        }
+    }
+
     private void initiateConnection(DeviceId deviceId, MastershipRole newRole) {
         try {
             if (isReachable(deviceId)) {
diff --git a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
index 625322f..2cdeb53 100644
--- a/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
+++ b/providers/netconf/device/src/main/java/org/onosproject/provider/netconf/device/impl/NetconfProviderConfig.java
@@ -38,6 +38,7 @@
     private static final String PORT = "port";
     private static final String NAME = "username";
     private static final String PASSWORD = "password";
+    private static final String SSHKEY = "sshkey";
 
     public Set<NetconfDeviceAddress> getDevicesAddresses() throws ConfigException {
         Set<NetconfDeviceAddress> devicesAddresses = Sets.newHashSet();
@@ -49,7 +50,8 @@
                 int port = node.path(PORT).asInt(DEFAULT_TCP_PORT);
                 String name = node.path(NAME).asText();
                 String password = node.path(PASSWORD).asText();
-                devicesAddresses.add(new NetconfDeviceAddress(ipAddr, port, name, password));
+                String sshkey = node.path(SSHKEY).asText();
+                devicesAddresses.add(new NetconfDeviceAddress(ipAddr, port, name, password, sshkey));
 
             }
         } catch (IllegalArgumentException e) {
@@ -64,12 +66,22 @@
         private final int port;
         private final String name;
         private final String password;
+        private final String sshkey;
 
         public NetconfDeviceAddress(IpAddress ip, int port, String name, String password) {
             this.ip = ip;
             this.port = port;
             this.name = name;
             this.password = password;
+            this.sshkey = "";
+        }
+
+        public NetconfDeviceAddress(IpAddress ip, int port, String name, String password, String sshkey) {
+            this.ip = ip;
+            this.port = port;
+            this.name = name;
+            this.password = password;
+            this.sshkey = sshkey;
         }
 
         public IpAddress ip() {
@@ -87,6 +99,10 @@
         public String password() {
             return password;
         }
+
+        public String sshkey() {
+            return sshkey;
+        }
     }
 
 }