Merge "BUG-1568 Remove ganymed Ssh client adapter"
authorEd Warnicke <eaw@cisco.com>
Mon, 25 Aug 2014 11:15:10 +0000 (11:15 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 25 Aug 2014 11:15:10 +0000 (11:15 +0000)
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java [deleted file]
opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java [deleted file]
opendaylight/netconf/netconf-ssh/src/test/java/org/opendaylight/controller/netconf/netty/SSHTest.java

diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/Invoker.java
deleted file mode 100644 (file)
index eab2546..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import java.io.IOException;
-
-/**
- * Abstract class providing mechanism of invoking various SSH level services.
- * Class is not allowed to be extended, as it provides its own implementations via instance initiators.
- */
-abstract class Invoker {
-    private boolean invoked = false;
-
-    private Invoker() {
-    }
-
-    protected boolean isInvoked() {
-        return invoked;
-    }
-
-    public void setInvoked() {
-        this.invoked = true;
-    }
-
-    abstract void invoke(SshSession session) throws IOException;
-
-    public static Invoker netconfSubsystem(){
-        return subsystem("netconf");
-    }
-
-    public static Invoker subsystem(final String subsystem) {
-        return new Invoker() {
-            @Override
-            synchronized void invoke(SshSession session) throws IOException {
-                if (isInvoked()) {
-                    throw new IllegalStateException("Already invoked.");
-                }
-                try {
-                    session.startSubSystem(subsystem);
-                } finally {
-                    setInvoked();
-                }
-            }
-        };
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClient.java
deleted file mode 100644 (file)
index 271b781..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Connection;
-import ch.ethz.ssh2.Session;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-
-/**
- * Wrapper class around GANYMED SSH java library.
- */
-class SshClient {
-    private final VirtualSocket socket;
-    private final Map<Integer, SshSession> openSessions = new HashMap<>();
-    private final AuthenticationHandler authenticationHandler;
-    private Connection connection;
-
-    public SshClient(VirtualSocket socket, AuthenticationHandler authenticationHandler) throws IOException {
-        this.socket = socket;
-        this.authenticationHandler = authenticationHandler;
-    }
-
-    public SshSession openSession() throws IOException {
-        if (connection == null) {
-            connect();
-        }
-
-        Session session = connection.openSession();
-        SshSession sshSession = new SshSession(session);
-        openSessions.put(openSessions.size(), sshSession);
-
-        return sshSession;
-    }
-
-    private void connect() throws IOException {
-        connection = new Connection(socket);
-
-        connection.connect();
-        authenticationHandler.authenticate(connection);
-    }
-
-
-    public void close() {
-        for (SshSession session : openSessions.values()){
-            session.close();
-        }
-
-        openSessions.clear();
-
-        if (connection != null) {
-            connection.close();
-        }
-    }
-
-    @Override
-    public String toString() {
-        return "SshClient{" +
-                "socket=" + socket +
-                '}';
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshClientAdapter.java
deleted file mode 100644 (file)
index 4ca7bdf..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-/**
- * Worker thread class. Handles all downstream and upstream events in SSH Netty
- * pipeline.
- */
-class SshClientAdapter implements Runnable {
-    private static final Logger logger = LoggerFactory.getLogger(SshClientAdapter.class);
-
-    private static final int BUFFER_SIZE = 1024;
-
-    private final SshClient sshClient;
-    private final Invoker invoker;
-
-    private OutputStream stdIn;
-
-    private final Queue<ByteBuf> postponed = new LinkedList<>();
-
-    private ChannelHandlerContext ctx;
-    private ChannelPromise disconnectPromise;
-
-    private final AtomicBoolean stopRequested = new AtomicBoolean(false);
-
-    private final Object lock = new Object();
-
-    public SshClientAdapter(final SshClient sshClient, final Invoker invoker) {
-        this.sshClient = sshClient;
-        this.invoker = invoker;
-    }
-
-    // TODO ganymed spawns a Thread that receives the data from remote inside TransportManager
-    // Get rid of this thread and reuse Ganymed internal thread (not sure if its possible without modifications in ganymed)
-    public void run() {
-        try {
-            final SshSession session = sshClient.openSession();
-            invoker.invoke(session);
-            final InputStream stdOut = session.getStdout();
-
-            synchronized (lock) {
-                stdIn = session.getStdin();
-                while (postponed.peek() != null) {
-                    writeImpl(postponed.poll());
-                }
-            }
-
-            while (!stopRequested.get()) {
-                final byte[] readBuff = new byte[BUFFER_SIZE];
-                final int c = stdOut.read(readBuff);
-                if (c == -1) {
-                    continue;
-                }
-
-                ctx.fireChannelRead(Unpooled.copiedBuffer(readBuff, 0, c));
-            }
-        } catch (final Exception e) {
-            logger.error("Unexpected exception", e);
-        } finally {
-            sshClient.close();
-
-            synchronized (lock) {
-                if (disconnectPromise != null) {
-                    ctx.disconnect(disconnectPromise);
-                }
-            }
-        }
-    }
-
-    // TODO: needs rework to match netconf framer API.
-    public void write(final ByteBuf message) throws IOException {
-        synchronized (lock) {
-            if (stdIn == null) {
-                postponed.add(message);
-                return;
-            }
-            writeImpl(message);
-        }
-    }
-
-    private void writeImpl(final ByteBuf message) throws IOException {
-        message.getBytes(0, stdIn, message.readableBytes());
-        message.release();
-        stdIn.flush();
-    }
-
-    public void stop(final ChannelPromise promise) {
-        synchronized (lock) {
-            stopRequested.set(true);
-            disconnectPromise = promise;
-        }
-    }
-
-    public Thread start(final ChannelHandlerContext ctx, final ChannelFuture channelFuture) {
-        checkArgument(channelFuture.isSuccess());
-        checkNotNull(ctx.channel().remoteAddress());
-        synchronized (this) {
-            checkState(this.ctx == null);
-            this.ctx = ctx;
-        }
-        final String threadName = toString();
-        final Thread thread = new Thread(this, threadName);
-        thread.start();
-        return thread;
-    }
-
-    @Override
-    public String toString() {
-        return "SshClientAdapter{" +
-                "sshClient=" + sshClient +
-                '}';
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshHandler.java
deleted file mode 100644 (file)
index c710a01..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.channel.ChannelFuture;
-import io.netty.channel.ChannelFutureListener;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelOutboundHandlerAdapter;
-import io.netty.channel.ChannelPromise;
-import java.io.IOException;
-import java.net.SocketAddress;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.virtualsocket.VirtualSocket;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Netty SSH handler class. Acts as interface between Netty and SSH library. All standard Netty message handling
- * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshClientAdapter};
- */
-public class SshHandler extends ChannelOutboundHandlerAdapter {
-    private static final Logger logger = LoggerFactory.getLogger(SshHandler.class);
-    private static final String SOCKET = "socket";
-
-    private final VirtualSocket virtualSocket = new VirtualSocket();
-    private final SshClientAdapter sshClientAdapter;
-
-
-    public static SshHandler createForNetconfSubsystem(AuthenticationHandler authenticationHandler) throws IOException {
-        return new SshHandler(authenticationHandler, Invoker.netconfSubsystem());
-    }
-
-
-    public SshHandler(AuthenticationHandler authenticationHandler, Invoker invoker) throws IOException {
-        SshClient sshClient = new SshClient(virtualSocket, authenticationHandler);
-        this.sshClientAdapter = new SshClientAdapter(sshClient, invoker);
-    }
-
-    @Override
-    public void handlerAdded(ChannelHandlerContext ctx){
-        if (ctx.channel().pipeline().get(SOCKET) == null) {
-            ctx.channel().pipeline().addFirst(SOCKET, virtualSocket);
-        }
-    }
-
-    @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) {
-        if (ctx.channel().pipeline().get(SOCKET) != null) {
-            ctx.channel().pipeline().remove(SOCKET);
-        }
-    }
-
-    @Override
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws IOException {
-        this.sshClientAdapter.write((ByteBuf) msg);
-    }
-
-    @Override
-    public void connect(final ChannelHandlerContext ctx,
-                        SocketAddress remoteAddress,
-                        SocketAddress localAddress,
-                        ChannelPromise promise) {
-        ctx.connect(remoteAddress, localAddress, promise);
-
-        promise.addListener(new ChannelFutureListener() {
-            public void operationComplete(ChannelFuture channelFuture) {
-                if (channelFuture.isSuccess()) {
-                    sshClientAdapter.start(ctx, channelFuture);
-                } else {
-                    logger.debug("Failed to connect to remote host");
-                }
-            }}
-        );
-    }
-
-    @Override
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
-        sshClientAdapter.stop(promise);
-    }
-}
diff --git a/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java b/opendaylight/netconf/netconf-netty-util/src/main/java/org/opendaylight/controller/netconf/nettyutil/handler/ssh/client/SshSession.java
deleted file mode 100644 (file)
index 9cdc592..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.netconf.nettyutil.handler.ssh.client;
-
-import ch.ethz.ssh2.Session;
-import ch.ethz.ssh2.channel.Channel;
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-/**
- * Wrapper class for proprietary SSH sessions implementations
- */
-class SshSession implements Closeable {
-    private final Session session;
-
-    public SshSession(final Session session) {
-        this.session = session;
-    }
-
-    public void startSubSystem(final String name) throws IOException {
-        session.startSubSystem(name);
-    }
-
-    public InputStream getStdout() {
-        return session.getStdout();
-    }
-
-    // FIXME according to http://www.ganymed.ethz.ch/ssh2/FAQ.html#blocking you should read data from both stdout and stderr to prevent window filling up (since stdout and stderr share a window)
-    // FIXME stdErr is not used anywhere
-    public InputStream getStderr() {
-        return session.getStderr();
-    }
-
-    public OutputStream getStdin() {
-        return session.getStdin();
-    }
-
-    @Override
-    public void close() {
-        if (session.getState() == Channel.STATE_OPEN || session.getState() == Channel.STATE_OPENING) {
-            session.close();
-        }
-    }
-}
index 6129783..1b22011 100644 (file)
@@ -29,7 +29,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.netty.EchoClientHandler.State;
 import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
-import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.SshHandler;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.client.AsyncSshHandler;
 import org.opendaylight.controller.netconf.ssh.NetconfSSHServer;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
 import org.opendaylight.controller.netconf.ssh.authentication.AuthProviderImpl;
@@ -94,7 +94,7 @@ public class SSHTest {
         ChannelInitializer<NioSocketChannel> channelInitializer = new ChannelInitializer<NioSocketChannel>() {
             @Override
             public void initChannel(NioSocketChannel ch) throws Exception {
-                ch.pipeline().addFirst(SshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
+                ch.pipeline().addFirst(AsyncSshHandler.createForNetconfSubsystem(new LoginPassword("a", "a")));
                 ch.pipeline().addLast(echoClientHandler);
             }
         };

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.