Add TLS option to NetonfConnectDeviceCommand. 09/70209/5
authorLiGuosheng <li.guosheng6@zte.com.cn>
Fri, 30 Mar 2018 06:07:25 +0000 (14:07 +0800)
committerJakubToth <jakub.toth@pantheon.tech>
Mon, 9 Apr 2018 14:21:33 +0000 (14:21 +0000)
Add parameter protocol to support connection to a netconf device via TLS.

Change-Id: I9744e2fad71886de1c4f1f8a2d020d96d7947828
Signed-off-by: Li guosheng <li.guosheng6@zte.com.cn>
netconf/netconf-console/src/main/java/org/opendaylight/netconf/console/commands/NetconfConnectDeviceCommand.java
netconf/netconf-console/src/test/java/org/opendaylight/netconf/console/commands/NetconfCommandsImplCallsTest.java

index b5c4c657065a41d590217093dd57f58ce743cf7d..be70b8155e473d28e95567129dcdd87ea97d9c08 100644 (file)
@@ -9,6 +9,10 @@
 package org.opendaylight.netconf.console.commands;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Strings;
+
+import java.util.Arrays;
+
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.AbstractAction;
@@ -17,8 +21,12 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.protocol.specification.TlsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.protocol.specification.TlsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.protocol.specification.tls._case.TlsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.Credentials;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
 
@@ -55,14 +63,14 @@ public class NetconfConnectDeviceCommand extends AbstractAction {
     @Option(name = "-U",
             aliases = { "--username" },
             description = "Username for netconf connection",
-            required = true,
+            required = false,
             multiValued = false)
     private String username;
 
     @Option(name = "-P",
             aliases = { "--password" },
             description = "Password for netconf connection",
-            required = true,
+            required = false,
             multiValued = false)
     private String password;
 
@@ -73,6 +81,20 @@ public class NetconfConnectDeviceCommand extends AbstractAction {
             multiValued = false)
     private String connectionType = "false";
 
+    @Option(name = "-pr",
+            aliases = { "--protocol" },
+            description = "Which protocol to be used, ssh or tls",
+            required = false,
+            multiValued = false)
+    private String protocol = "ssh";
+
+    @Option(name = "-ev",
+            aliases = { "--excluded-versions" },
+            description = "TLS versions not supported by target device",
+            required = false,
+            multiValued = false)
+    private String excludedTlsVersions;
+
     @Option(name = "-sl",
             aliases = { "--schemaless" },
             description = "Schemaless surpport, true for schemaless",
@@ -95,18 +117,41 @@ public class NetconfConnectDeviceCommand extends AbstractAction {
 
         final boolean isTcpOnly = connectionType.equals("true");
         final boolean isSchemaless = schemaless.equals("true");
-        final Credentials credentials =
-                new LoginPasswordBuilder().setPassword(password).setUsername(username).build();
-
-        final NetconfNode netconfNode = new NetconfNodeBuilder()
-                                        .setHost(new Host(new IpAddress(new Ipv4Address(deviceIp))))
-                                        .setPort(new PortNumber(Integer.decode(devicePort)))
-                                        .setTcpOnly(isTcpOnly)
-                                        .setSchemaless(isSchemaless)
-                                        .setCredentials(credentials)
-                                        .build();
-
-        service.connectDevice(netconfNode, deviceId);
+
+        final NetconfNodeBuilder netconfNodeBuilder = new NetconfNodeBuilder();
+        netconfNodeBuilder.setHost(new Host(new IpAddress(new Ipv4Address(deviceIp))))
+                          .setPort(new PortNumber(Integer.decode(devicePort)))
+                          .setTcpOnly(isTcpOnly)
+                          .setSchemaless(isSchemaless);
+
+        if (isTcpOnly || protocol.equalsIgnoreCase("ssh")) {
+            if (Strings.isNullOrEmpty(username) || Strings.isNullOrEmpty(password)) {
+                return "Empty Username:" + username + " or Password:" + password
+                        + ". In TCP or SSH mode, you must provide valid username and password.";
+            }
+            final Credentials credentials =
+                    new LoginPasswordBuilder().setPassword(password).setUsername(username).build();
+            netconfNodeBuilder.setCredentials(credentials);
+            if (!isTcpOnly) {
+                netconfNodeBuilder.setProtocol(new ProtocolBuilder().setName(Name.SSH).build());
+            }
+        } else if (protocol.equalsIgnoreCase("tls")) {
+            TlsCase tlsCase = null;
+            if (!Strings.isNullOrEmpty(excludedTlsVersions)) {
+                tlsCase = new TlsCaseBuilder()
+                            .setTls(new TlsBuilder()
+                                    .setExcludedVersions(Arrays.asList(excludedTlsVersions.split(","))).build())
+                            .build();
+            }
+            netconfNodeBuilder.setProtocol(new ProtocolBuilder()
+                                            .setName(Name.TLS)
+                                            .setSpecification(tlsCase)
+                                            .build());
+        } else {
+            return "Invalid protocol: " + protocol + ". Only SSH and TLS are supported.";
+        }
+
+        service.connectDevice(netconfNodeBuilder.build(), deviceId);
         final String message = "Netconf connector added succesfully";
         return message;
     }
index afedf3d5fc5142028b2b6ea68371e618263e022b..45cbb85fa1ba2e90bbeed96352914bf15e80ece8 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netconf.console.commands;
 
 import static junit.framework.TestCase.assertEquals;
 import static junit.framework.TestCase.assertTrue;
+import static org.mockito.BDDMockito.given;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doNothing;
@@ -18,17 +19,24 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.MockitoAnnotations.initMocks;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.opendaylight.netconf.console.api.NetconfCommands;
 import org.opendaylight.netconf.console.utils.NetconfConsoleConstants;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Strings.class)
 public class NetconfCommandsImplCallsTest {
 
     @Mock
@@ -48,6 +56,8 @@ public class NetconfCommandsImplCallsTest {
 
         netconfConnectDeviceCommand = new NetconfConnectDeviceCommand(netconfCommands, "192.168.1.1", "7777");
 
+        PowerMockito.mockStatic(Strings.class);
+        given(Strings.isNullOrEmpty(any())).willReturn(false);
         netconfConnectDeviceCommand.doExecute();
         doNothing().when(netconfCommands).connectDevice(any(), any());
         verify(netconfCommands, times(1)).connectDevice(any(), any());