class IPV4FunctionalNoServerTestCase(TestCase):
    def setUp(self):
        self.hostname = "127.0.0.1"
        self.user = getpass.getuser()
        self.password = "******"
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            "hostname": self.hostname,
            "port": self.portnum + 1,
            "user": self.user,
            "password": self.password,
            "buffersize": 32768,
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        # Wait for the deferred that tell us we disconnected.
        return defer.gatherResults([d])

    def test_run_command_connect_failure(self):
        "test what happens if the server isnt running"
        d = self.client.run("echo hi")
        return self.assertFailure(d, ConnectError)

    def test_ls_connect_failure(self):
        "test what happens if the server isnt running"

        sandbox = tempfile.mkdtemp()
        d = self.client.ls(sandbox)

        def sandbox_cleanup(data):
            shutil.rmtree(sandbox)
            return data

        d.addBoth(sandbox_cleanup)
        return self.assertFailure(d, ConnectError)
Exemple #2
0
class IPV4FunctionalNoServerTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum + 1,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        # Wait for the deferred that tell us we disconnected.
        return defer.gatherResults([d])

    def test_run_command_connect_failure(self):
        'test what happens if the server isnt running'
        d = self.client.run('echo hi')
        return self.assertFailure(d, ConnectError)

    def test_ls_connect_failure(self):
        'test what happens if the server isnt running'

        sandbox = tempfile.mkdtemp()
        d = self.client.ls(sandbox)

        def sandbox_cleanup(data):
            shutil.rmtree(sandbox)
            return data

        d.addBoth(sandbox_cleanup)
        return self.assertFailure(d, ConnectError)
Exemple #3
0
class IPV6FunctionalBaseTestCase(TestCase):
    def setUp(self):
        self.hostname = '::1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults(
            [d, client.onConnectionLost, server.onConnectionLost])

    def test_run_command(self):

        d = self.client.run('echo hi')

        def got_hi(data):
            log.debug('Got Data %s' % (data, ))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, 'hi\n')
            return data

        d.addCallback(got_hi)
        #d = defer.Deferred()
        #d.callback('done')
        return d
class IPV6FunctionalBaseTestCase(TestCase):
    def setUp(self):
        self.hostname = '::1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.user,
                   'password': self.password,
                   'buffersize': 32768}

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults([d,
                                    client.onConnectionLost,
                                    server.onConnectionLost])

    def test_run_command(self):

        d = self.client.run('echo hi')

        def got_hi(data):
            log.debug('Got Data %s' % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output,  'hi\n')
            return data

        d.addCallback(got_hi)
        #d = defer.Deferred()
        #d.callback('done')
        return d
Exemple #5
0
class IPV4CommandTimeoutTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults(
            [d, client.onConnectionLost, server.onConnectionLost])

    def test_run_command_timeout_failed(self):
        d = self.client.run('sleep 2 && ls', timeout=1)
        return self.assertFailure(d, TimeoutError)
class IPV4CommandTimeoutTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.user,
                   'password': self.password,
                   'buffersize': 32768}

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults([d,
                                    client.onConnectionLost,
                                    server.onConnectionLost])

    def test_run_command_timeout_failed(self):
        d = self.client.run('sleep 2 && ls', timeout=1)
        return self.assertFailure(d, TimeoutError)
class IPV4FunctionalReconnectionTestCase(TestCase):
    def setUp(self):
        self.hostname = "127.0.0.1"
        self.user = getpass.getuser()
        self.password = "******"
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            "hostname": self.hostname,
            "port": self.portnum,
            "user": self.user,
            "password": self.password,
            "buffersize": 32768,
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug("tearing down")
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults([d, client.onConnectionLost, server.onConnectionLost])

    def test_run_command(self):
        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            return server.onConnectionLost

        def run_command(sld):
            results = self.client.run("echo hi")
            return results

        def test_failure(data):
            return self.assertFailure(data, ConnectionLost)

        def test_success(data):
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, "hi\n")
            return data

        def start_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum, self.server, interface=self.hostname)
            return self.port

        d = self.client.run("echo hi")
        d.addBoth(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(run_command)
        d.addBoth(test_failure)
        d.addBoth(start_server)
        d.addCallback(run_command)
        d.addBoth(test_success)
        return d
class IPV4FunctionalNoReconnectionTestCase(TestCase):
    def setUp(self):
        self.timeout = 10
        self.hostname = "127.0.0.1"
        self.user = getpass.getuser()
        self.password = "******"
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            "hostname": self.hostname,
            "port": self.portnum,
            "user": self.user,
            "password": self.password,
            "buffersize": 32768,
        }

        self.client = SSHClient(options)
        self.client.maxRetries = 0
        # self.client.maxDelay = 0
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug("tearing down")
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        # Wait for the server to stop.
        return defer.gatherResults([d])

    def test_run_command(self):
        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            log.debug("Dropping server connection")
            return self.client.onConnectionLost

        def run_command(data):

            log.debug("running command hi2")
            results = self.client.run("echo hi2")
            return results

        def test_failure_done(deferred):
            log.debug("Failure %s " % deferred)
            return self.assertEqual(deferred.type, ConnectionDone)

        def test_success(data):
            log.debug("Success %s" % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, "hi\n")

        def bring_up_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum, self.server, interface=self.hostname)
            log.debug("server started")
            return data.factory.dConnected

        d = self.client.run("echo hi")
        d.addBoth(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(bring_up_server)
        d.addCallback(run_command)
        d.addErrback(test_failure_done)

        return d

    def test_lsdir(self):
        test_file = "test_ls_dir"
        sandbox = tempfile.mkdtemp()
        testfile = "/".join([sandbox, test_file])
        touch(testfile)
        d = self.client.ls(sandbox)

        def cleanup_sandbox(data):
            log.debug("Cleaning up sandbox")
            shutil.rmtree(sandbox)

        def test_success(data):
            return self.assertEqual(data[0][0], test_file)

        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            log.debug("Dropping server connection")
            return self.client.onConnectionLost

        def bring_up_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum, self.server, interface=self.hostname)
            log.debug("server started")
            return data.factory.dConnected

        def run_lsdir(data):

            log.debug("running command ls again")
            results = self.client.ls(sandbox)
            return results

        def test_failure_done(deferred):
            log.debug("Failure %s " % deferred)
            return self.assertEqual(deferred.type, ConnectionDone)

        d.addCallback(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(bring_up_server)
        d.addCallback(run_lsdir)
        d.addErrback(test_failure_done)
        d.addBoth(cleanup_sandbox)

        return d
Exemple #9
0
class IPV4FunctionalBaseTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults(
            [d, client.onConnectionLost, server.onConnectionLost])

    def test_run_command(self):

        d = self.client.run('echo hi')

        def got_hi(data):
            log.debug('Got Data %s' % (data, ))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, 'hi\n')
            return data

        d.addCallback(got_hi)
        return d

    @defer.inlineCallbacks
    def test_lsdir(self):
        try:
            test_file = 'test_ls_dir'
            sandbox = tempfile.mkdtemp()
            testfile = '/'.join([sandbox, test_file])
            touch(testfile)
            d = yield self.client.ls(sandbox)

            self.assertEquals(d[0][0], test_file)
            defer.returnValue(d)
        finally:
            shutil.rmtree(sandbox)

    def test_lsdir_no_dir(self):
        d = self.client.ls('/_not_real')
        return self.assertFailure(d, SFTPError)

    @defer.inlineCallbacks
    def test_mkdir(self):
        try:
            sandbox = tempfile.mkdtemp()
            test_dir = 'tmpMkdir'
            directory = '/'.join([sandbox, test_dir])
            result = yield self.client.mkdir(directory)
            self.assertEquals(result[0], 'mkdir succeeded')
            self.assertTrue(os.path.isdir(directory))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rmdir(self):
        try:
            sandbox = tempfile.mkdtemp()
            test_dir = 'tmpRmdir'
            directory = '/'.join([sandbox, test_dir])
            os.mkdir(directory)
            result = yield self.client.rmdir(directory)
            self.assertEquals(result[0], 'rmdir succeeded')
            self.assertFalse(os.path.exists(directory))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rename(self):
        try:
            original_filename = 'test_rename'
            destination_filename = 'test_rename_changed'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            destination_path = '/'.join([sandbox, destination_filename])
            touch(original_path)

            result = yield self.client.rename(original_path, destination_path)
            self.assertEquals(result[0], 'rename succeeded')
            self.assertFalse(os.path.exists(original_path))
            self.assertTrue(os.path.exists(destination_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_ln(self):
        try:
            original_filename = 'test_ln'
            destination_filename = 'test_ln_destination'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            destination_path = '/'.join([sandbox, destination_filename])
            touch(original_path)
            result = yield self.client.ln(destination_path, original_path)

            self.assertEquals(result[0], 'symlink succeeded')
            self.assertTrue(os.path.isfile(original_path))
            self.assertTrue(os.path.islink(destination_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rm(self):
        try:
            original_filename = 'test_rm_file'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            touch(original_path)

            result = yield self.client.rm(original_path)

            self.assertEquals(result[0], 'remove succeeded')
            self.assertFalse(os.path.exists(original_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_put(self):
        try:
            source_data = 'This was my sourcefile...'
            source_filename = 'test_source_file'
            destination_filename = 'test_destination_file'

            source_sandbox = tempfile.mkdtemp()
            destination_sandbox = tempfile.mkdtemp()

            source_path = '/'.join([source_sandbox, source_filename])
            destination_path = '/'.join(
                [destination_sandbox, destination_filename])
            open(source_path, 'w').write(source_data)

            result = yield self.client.put(source_path, destination_path)
            self.assertTrue(os.path.isfile(source_path))
            self.assertTrue(os.path.isfile(destination_path))
            self.assertEqual(source_data, open(destination_path, 'r').read())
            defer.returnValue(result)
        finally:
            shutil.rmtree(source_sandbox)
            shutil.rmtree(destination_sandbox)

    @defer.inlineCallbacks
    def test_get(self):
        try:
            source_data = 'This was my sourcefile...'
            source_filename = 'test_source_file'
            destination_filename = 'test_destination_file'

            source_sandbox = tempfile.mkdtemp()
            destination_sandbox = tempfile.mkdtemp()

            source_path = '/'.join([source_sandbox, source_filename])
            destination_path = '/'.join(
                [destination_sandbox, destination_filename])
            open(source_path, 'w').write(source_data)

            result = yield self.client.get(source_path, destination_path)
            self.assertTrue(os.path.isfile(source_path))
            self.assertTrue(os.path.isfile(destination_path))
            self.assertEqual(source_data, open(destination_path, 'r').read())
            defer.returnValue(result)
        finally:
            shutil.rmtree(source_sandbox)
            shutil.rmtree(destination_sandbox)

    @defer.inlineCallbacks
    def test_chown(self):
        try:
            chown_filename = 'test_chown_file'
            sandbox = tempfile.mkdtemp()
            chown_path = '/'.join([sandbox, chown_filename])
            touch(chown_path)

            import os
            import pwd
            uid = pwd.getpwuid(os.getuid()).pw_uid
            result = yield self.client.chown(chown_path, uid)

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_chgrp(self):
        try:
            chgrp_filename = 'test_chgrp_file'
            sandbox = tempfile.mkdtemp()
            chgrp_path = '/'.join([sandbox, chgrp_filename])
            touch(chgrp_path)

            import os
            import pwd
            gid = pwd.getpwuid(os.getuid()).pw_gid
            result = yield self.client.chgrp(chgrp_path, gid)

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_chmod(self):
        try:
            chmod_filename = 'test_chmod_file'
            sandbox = tempfile.mkdtemp()
            chmod_path = '/'.join([sandbox, chmod_filename])
            touch(chmod_path)

            result = yield self.client.chmod(chmod_path, '1000')

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)
Exemple #10
0
class IPV4FunctionalReconnectionTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults(
            [d, client.onConnectionLost, server.onConnectionLost])

    def test_run_command(self):
        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            return server.onConnectionLost

        def run_command(sld):
            results = self.client.run('echo hi')
            return results

        def test_failure(data):
            return self.assertFailure(data, ConnectionLost)

        def test_success(data):
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, 'hi\n')
            return data

        def start_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum,
                                          self.server,
                                          interface=self.hostname)
            return self.port

        d = self.client.run('echo hi')
        d.addBoth(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(run_command)
        d.addBoth(test_failure)
        d.addBoth(start_server)
        d.addCallback(run_command)
        d.addBoth(test_success)
        return d
Exemple #11
0
class IPV4FunctionalNoReconnectionTestCase(TestCase):
    def setUp(self):
        self.timeout = 10
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {
            'hostname': self.hostname,
            'port': self.portnum,
            'user': self.user,
            'password': self.password,
            'buffersize': 32768
        }

        self.client = SSHClient(options)
        self.client.maxRetries = 0
        #self.client.maxDelay = 0
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        # Wait for the server to stop.
        return defer.gatherResults([d])

    def test_run_command(self):
        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            log.debug('Dropping server connection')
            return self.client.onConnectionLost

        def run_command(data):

            log.debug('running command hi2')
            results = self.client.run('echo hi2')
            return results

        def test_failure_done(deferred):
            log.debug('Failure %s ' % deferred)
            return self.assertEqual(deferred.type, ConnectionDone)

        def test_success(data):
            log.debug('Success %s' % (data, ))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output, 'hi\n')

        def bring_up_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum,
                                          self.server,
                                          interface=self.hostname)
            log.debug('server started')
            return data.factory.dConnected

        d = self.client.run('echo hi')
        d.addBoth(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(bring_up_server)
        d.addCallback(run_command)
        d.addErrback(test_failure_done)

        return d

    def test_lsdir(self):
        test_file = 'test_ls_dir'
        sandbox = tempfile.mkdtemp()
        testfile = '/'.join([sandbox, test_file])
        touch(testfile)
        d = self.client.ls(sandbox)

        def cleanup_sandbox(data):
            log.debug('Cleaning up sandbox')
            shutil.rmtree(sandbox)

        def test_success(data):
            return self.assertEqual(data[0][0], test_file)

        def server_stop_listening(data):
            sld = self.port.stopListening()
            return sld

        def server_drop_connections(data):
            port, self.port = self.port, None
            server, self.server = self.server, None
            server.protocol.transport.loseConnection()
            log.debug('Dropping server connection')
            return self.client.onConnectionLost

        def bring_up_server(data):
            self.server = SSHServer()
            self.server.protocol = ServerProtocol
            self.port = reactor.listenTCP(self.portnum,
                                          self.server,
                                          interface=self.hostname)
            log.debug('server started')
            return data.factory.dConnected

        def run_lsdir(data):

            log.debug('running command ls again')
            results = self.client.ls(sandbox)
            return results

        def test_failure_done(deferred):
            log.debug('Failure %s ' % deferred)
            return self.assertEqual(deferred.type, ConnectionDone)

        d.addCallback(test_success)
        d.addCallback(server_stop_listening)
        d.addCallback(server_drop_connections)
        d.addCallback(bring_up_server)
        d.addCallback(run_lsdir)
        d.addErrback(test_failure_done)
        d.addBoth(cleanup_sandbox)

        return d
    def collect(self, device, log):
        manageIp = str(device.manageIp)

        log.info('Connecting to ssh://%s@%s:%d' % (
            device.zCommandUsername,
            manageIp,
            device.zCommandPort
            ))

        client = SSHClient({
            'hostname': manageIp,
            'port': device.zCommandPort,
            'user': device.zCommandUsername,
            'password': device.zCommandPassword,
            'buffersize': 32768})
        client.connect()
        timeout = device.zCommandCommandTimeout
        data = {}

        try:
            for instanceId, instanceUUID in device.openstack_instanceList:
                cmd = "virsh --readonly -c 'qemu:///system' dumpxml '%s'" % instanceUUID
                log.info("Running %s" % cmd)
                d = yield client.run(cmd, timeout=timeout)

                if d.exitCode != 0 or d.stderr:
                    if 'Domain not found' in d.stderr:
                        log.debug("Domain not found while running virsh (rc=%s, stderr='%s')" % (d.exitCode, d.stderr))
                    else:
                        log.error("Error running virsh (rc=%s, stderr='%s')" % (d.exitCode, d.stderr))
                    continue

                try:
                    tree = etree.fromstring(d.output)

                    instanceName = str(tree.xpath("/domain/name/text()")[0])
                    zenossInstanceId = 'server-%s' % (instanceUUID)
                    data[instanceUUID] = {
                        'id': zenossInstanceId,
                        'serialNumber': str(tree.xpath("/domain/sysinfo/system/entry[@name='serial']/text()")[0]),
                        'biosUuid': str(tree.xpath("/domain/sysinfo/system/entry[@name='uuid']/text()")[0])
                    }

                except Exception:
                    log.error("Invalid XML Received from (%s):\n%s\n\n" % (cmd, d.output))
                    raise LibvirtXMLError('Incomplete or invalid XML returned from virsh command. Consult log for more details.')

                vnics = []
                for interface in tree.xpath("/domain/devices/interface"):
                    target = interface.find("target/[@dev]")
                    mac = interface.find("mac/[@address]")

                    if target is None or mac is None:
                        # unrecognized interface type
                        continue

                    # compute the resourceId in the same way that ceilometer's
                    # net pollster does.
                    vnicName = str(target.get('dev'))
                    zenossVnicId = 'vnic-%s-%s' % (instanceUUID, vnicName)
                    ceilometerResourceId = '%s-%s-%s' % (instanceName, instanceUUID, vnicName)

                    vnics.append({
                        'id': zenossVnicId,
                        'name': vnicName,
                        'macaddress': str(mac.get('address')),
                        'resourceId': ceilometerResourceId
                    })
                data[instanceUUID]['vnics'] = vnics

        finally:
            client.disconnect()

        returnValue(data)
class inifiles(PythonPlugin):

    _yaml_config = None
    _eventService = None

    deviceProperties = PythonPlugin.deviceProperties \
        + ('zCommandUsername', 'zCommandPassword',
           'zCommandPort', 'zCommandCommandTimeout',
           'zOpenStackNeutronConfigDir')

    def sendEvent(self, evt):
        if not self._eventService:
            self._eventService = zope.component.queryUtility(IEventService)
        self._eventService.sendEvent(evt)

    def sendFileClearEvent(self, device, filename):
        evt = dict(
            device=device.id,
            component='',
            summary="File %s was loaded successfully" % filename,
            severity=Event.Clear,
            eventClassKey='openStackIniFileAccess',
            eventKey=filename
        )
        self.sendEvent(evt)

    def sendFileErrorEvent(self, device, filename, errmsg):
        evt = dict(
            device=device.id,
            component='',
            summary="File %s could not be accessed: %s" % (filename, errmsg),
            severity=Event.Error,
            eventClassKey='openStackIniFileAccess',
            eventKey=filename
        )
        self.sendEvent(evt)

    def sendOptionClearEvent(self, device, filename, section, option):
        evt = dict(
            device=device.id,
            component='',
            summary="%s: Required option [%s] %s was loaded successfully" % (filename, section, option),
            severity=Event.Clear,
            eventClassKey='openStackIniFileOptionParsing',
            eventKey="%s/%s/%s" % (filename, section, option)
        )
        self.sendEvent(evt)

    def sendOptionErrorEvent(self, device, filename, section, option):
        evt = dict(
            device=device.id,
            component='',
            summary="%s: Required option [%s] %s was not found" % (filename, section, option),
            severity=Event.Error,
            eventClassKey='openStackIniFileOptionParsing',
            eventKey="%s/%s/%s" % (filename, section, option)
        )
        self.sendEvent(evt)

    def ini_get(self, device, filename, ini, section, option, required=False):
        try:
            return ini.get(section, option)
            if required:
                self.sendOptionClearEvent(device, filename, section, option)
        except ConfigParser.NoOptionError:
            if required:
                self.sendOptionErrorEvent(device, filename, section, option)
            return None

    @defer.inlineCallbacks
    def read_ini(self, device, filename, required=False):
        filepath = os.path.join(device.zOpenStackNeutronConfigDir, filename)
        log.info("Retrieving %s", filepath)

        cmd = "cat %s" % filepath
        d = yield self.client.run(cmd, timeout=self.timeout)

        if d.exitCode != 0 or d.stderr:
            if required:
                log.error("Unable to access required file %s (%s)" % (filepath, d.stderr.strip()))
                self.sendFileErrorEvent(device, filepath, d.stderr)
            else:
                log.info("Unable to access optional file %s (%s)" % (filepath, d.stderr.strip()))

            defer.returnValue(None)
            return

        self.sendFileClearEvent(device, filepath)

        ini = ConfigParser.RawConfigParser(allow_no_value=True)
        ini.readfp(io.BytesIO(d.output))
        defer.returnValue(ini)

        return

    @defer.inlineCallbacks
    def collect(self, device, log):
        manageIp = str(device.manageIp)

        log.info('Connecting to ssh://%s@%s:%d' % (
            device.zCommandUsername,
            manageIp,
            device.zCommandPort
            ))

        self.client = SSHClient({
            'hostname': manageIp,
            'port': device.zCommandPort,
            'user': device.zCommandUsername,
            'password': device.zCommandPassword,
            'buffersize': 32768})
        self.client.connect()
        self.timeout = device.zCommandCommandTimeout

        data = {}
        required_files = ['neutron.conf']
        optional_files = ['plugins/ml2/ml2_conf.ini']
        plugin_names = set()

        try:
            # Check if neutron-server runs on this machine
            d = yield self.client.run("pgrep neutron-server", timeout=self.timeout)
            if d.exitCode != 0:
                # neutron isn't running on this host, so its config
                # files are suspect, and should be ignored.
                log.info("neutron-server not running on host- not collecting ini files")
                defer.returnValue(data)
                return

            # Collect ini files
            for filename in required_files:
                if filename not in data:
                    data[filename] = yield self.read_ini(device, filename, required=True)
            for filename in optional_files:
                if filename not in data:
                    data[filename] = yield self.read_ini(device, filename)

            required_files = []
            optional_files = []

            if data['neutron.conf']:
                ini = data['neutron.conf']
                neutron_core_plugin = self.ini_get(device, filename, ini, 'DEFAULT', 'core_plugin', required=True)
                plugin_names.add(neutron_core_plugin)

            if 'plugins/ml2/ml2_conf.ini' in data:
                mechanism_drivers = split_list(self.ini_get(
                    device,
                    filename,
                    data['plugins/ml2/ml2_conf.ini'],
                    'ml2',
                    'mechanism_drivers',
                    required=True) or '')

                for mechanism_driver in mechanism_drivers:
                    plugin_names.add("ml2." + mechanism_driver)

            data['plugin_names'] = set()
            for plugin_name in plugin_names:
                plugin = zope.component.queryUtility(INeutronImplementationPlugin, plugin_name)
                if not plugin:
                    continue

                plugin_class = plugin.__class__.__name__
                log.info("Checking for additinal ini requirements in neutron implementation plugin '%s': %s" % (plugin_name, plugin_class))
                data['plugin_names'].add(plugin_name)

                for filename, section, option in plugin.ini_required():
                    required_files.append(filename)

                for filename, section, option in plugin.ini_optional():
                    optional_files.append(filename)

            for filename in required_files:
                if filename not in data:
                    data[filename] = yield self.read_ini(device, filename, required=True)
            for filename in optional_files:
                if filename not in data:
                    data[filename] = yield self.read_ini(device, filename)

        except Exception:
            raise
        finally:
            self.client.disconnect()

        defer.returnValue(data)

    def process(self, device, results, log):
        log.info("Modeler %s processing data for device %s",
                 self.name(), device.id)

        if 'neutron.conf' not in results:
            log.info("No neutron ini files to process.")
            return

        data = {
            'neutron_core_plugin': None,
            'neutron_mechanism_drivers': [],
            'neutron_type_drivers': [],
            'set_neutron_ini': {}
        }

        if 'plugin_names' not in results:
            log.error("No neutron implementation plugins were identified, unable to continue.")
            return

        if results['neutron.conf']:
            filename = 'neutron.conf'
            ini = results[filename]
            data['neutron_core_plugin'] = self.ini_get(device, filename, ini, 'DEFAULT', 'core_plugin', required=True)

        if data['neutron_core_plugin']:
            if data['neutron_core_plugin'] in ('neutron.plugins.ml2.plugin.Ml2Plugin', 'ml2'):
                filename = 'plugins/ml2/ml2_conf.ini'
                ini = results[filename]
                if ini:
                    data['neutron_type_drivers'] = split_list(self.ini_get(device, filename, ini, 'ml2', 'type_drivers', required=True))
                    data['neutron_mechanism_drivers'] = split_list(self.ini_get(device, filename, ini, 'ml2', 'mechanism_drivers', required=True))

        for plugin_name in results['plugin_names']:
            # See if we have any plugins registered for the core module
            # (if not ML2) or mechanism type (if ML2)
            plugin = zope.component.queryUtility(INeutronImplementationPlugin, plugin_name)
            if not plugin:
                continue

            log.debug("(Process) Using plugin '%s'" % plugin_name)
            for filename, section, option in plugin.ini_required():
                ini = results.get(filename, None)
                if ini:
                    data['set_neutron_ini'][(filename, section, option)] = self.ini_get(device, filename, ini, section, option, required=True)

            for filename, section, option in plugin.ini_optional():
                ini = results.get(filename, None)
                if ini:
                    data['set_neutron_ini'][(filename, section, option)] = self.ini_get(device, filename, ini, section, option)

            return ObjectMap({'setApplyDataMapToOpenStackInfrastructureEndpoint': ObjectMap(data)})
class IPV4FunctionalBaseTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.user = getpass.getuser()
        self.password = '******'
        self.server = SSHServer()
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.user,
                   'password': self.password,
                   'buffersize': 32768}

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

    def tearDown(self):
        # Shut down the server and client
        log.debug('tearing down')
        port, self.port = self.port, None
        client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Tell the client to disconnect and not retry.
        client.disconnect()

        return defer.gatherResults([d,
                                    client.onConnectionLost,
                                    server.onConnectionLost])

    def test_run_command(self):

        d = self.client.run('echo hi')

        def got_hi(data):
            log.debug('Got Data %s' % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output,  'hi\n')
            return data

        d.addCallback(got_hi)
        return d

    @defer.inlineCallbacks
    def test_lsdir(self):
        try:
            test_file = 'test_ls_dir'
            sandbox = tempfile.mkdtemp()
            testfile = '/'.join([sandbox, test_file])
            touch(testfile)
            d = yield self.client.ls(sandbox)

            self.assertEquals(d[0][0], test_file)
            defer.returnValue(d)
        finally:
            shutil.rmtree(sandbox)

    def test_lsdir_no_dir(self):
        d = self.client.ls('/_not_real')
        return self.assertFailure(d, SFTPError)

    @defer.inlineCallbacks
    def test_mkdir(self):
        try:
            sandbox = tempfile.mkdtemp()
            test_dir = 'tmpMkdir'
            directory = '/'.join([sandbox, test_dir])
            result = yield self.client.mkdir(directory)
            self.assertEquals(result[0], 'mkdir succeeded')
            self.assertTrue(os.path.isdir(directory))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rmdir(self):
        try:
            sandbox = tempfile.mkdtemp()
            test_dir = 'tmpRmdir'
            directory = '/'.join([sandbox, test_dir])
            os.mkdir(directory)
            result = yield self.client.rmdir(directory)
            self.assertEquals(result[0], 'rmdir succeeded')
            self.assertFalse(os.path.exists(directory))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rename(self):
        try:
            original_filename = 'test_rename'
            destination_filename = 'test_rename_changed'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            destination_path = '/'.join([sandbox, destination_filename])
            touch(original_path)

            result = yield self.client.rename(original_path,
                                              destination_path)
            self.assertEquals(result[0], 'rename succeeded')
            self.assertFalse(os.path.exists(original_path))
            self.assertTrue(os.path.exists(destination_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_ln(self):
        try:
            original_filename = 'test_ln'
            destination_filename = 'test_ln_destination'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            destination_path = '/'.join([sandbox, destination_filename])
            touch(original_path)
            result = yield self.client.ln(destination_path, original_path)

            self.assertEquals(result[0], 'symlink succeeded')
            self.assertTrue(os.path.isfile(original_path))
            self.assertTrue(os.path.islink(destination_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_rm(self):
        try:
            original_filename = 'test_rm_file'
            sandbox = tempfile.mkdtemp()
            original_path = '/'.join([sandbox, original_filename])
            touch(original_path)

            result = yield self.client.rm(original_path)

            self.assertEquals(result[0], 'remove succeeded')
            self.assertFalse(os.path.exists(original_path))
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_put(self):
        try:
            source_data = 'This was my sourcefile...'
            source_filename = 'test_source_file'
            destination_filename = 'test_destination_file'

            source_sandbox = tempfile.mkdtemp()
            destination_sandbox = tempfile.mkdtemp()

            source_path = '/'.join([source_sandbox, source_filename])
            destination_path = '/'.join([destination_sandbox,
                                         destination_filename])
            open(source_path, 'w').write(source_data)

            result = yield self.client.put(source_path, destination_path)
            self.assertTrue(os.path.isfile(source_path))
            self.assertTrue(os.path.isfile(destination_path))
            self.assertEqual(source_data,
                             open(destination_path, 'r').read())
            defer.returnValue(result)
        finally:
            shutil.rmtree(source_sandbox)
            shutil.rmtree(destination_sandbox)

    @defer.inlineCallbacks
    def test_get(self):
        try:
            source_data = 'This was my sourcefile...'
            source_filename = 'test_source_file'
            destination_filename = 'test_destination_file'

            source_sandbox = tempfile.mkdtemp()
            destination_sandbox = tempfile.mkdtemp()

            source_path = '/'.join([source_sandbox, source_filename])
            destination_path = '/'.join([destination_sandbox,
                                         destination_filename])
            open(source_path, 'w').write(source_data)

            result = yield self.client.get(source_path, destination_path)
            self.assertTrue(os.path.isfile(source_path))
            self.assertTrue(os.path.isfile(destination_path))
            self.assertEqual(source_data,
                             open(destination_path, 'r').read())
            defer.returnValue(result)
        finally:
            shutil.rmtree(source_sandbox)
            shutil.rmtree(destination_sandbox)

    @defer.inlineCallbacks
    def test_chown(self):
        try:
            chown_filename = 'test_chown_file'
            sandbox = tempfile.mkdtemp()
            chown_path = '/'.join([sandbox, chown_filename])
            touch(chown_path)

            import os
            import pwd
            uid = pwd.getpwuid(os.getuid()).pw_uid
            result = yield self.client.chown(chown_path, uid)

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_chgrp(self):
        try:
            chgrp_filename = 'test_chgrp_file'
            sandbox = tempfile.mkdtemp()
            chgrp_path = '/'.join([sandbox, chgrp_filename])
            touch(chgrp_path)

            import os
            import pwd
            gid = pwd.getpwuid(os.getuid()).pw_gid
            result = yield self.client.chgrp(chgrp_path, gid)

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)

    @defer.inlineCallbacks
    def test_chmod(self):
        try:
            chmod_filename = 'test_chmod_file'
            sandbox = tempfile.mkdtemp()
            chmod_path = '/'.join([sandbox, chmod_filename])
            touch(chmod_path)

            result = yield self.client.chmod(chmod_path, '1000')

            self.assertEquals(result[0], 'setstat succeeded')
            defer.returnValue(result)
        finally:
            shutil.rmtree(sandbox)
class IPV4FunctionalAuthTestCase(TestCase):
    def setUp(self):
        self.hostname = '127.0.0.1'
        self.sshServeruser = '******'
        self.sshServerPassword = '******'
        self.server = SSHServer(self.sshServeruser, self.sshServerPassword)
        self.server.protocol = ServerProtocol

        self.port = reactor.listenTCP(0, self.server, interface=self.hostname)
        self.portnum = self.port.getHost().port

        # create ssh auth sandbox for keys.
        self.sandbox = tempfile.mkdtemp()

    def tearDown(self):

        # Shut down the server and client
        port, self.port = self.port, None
        #client, self.client = self.client, None
        server, self.server = self.server, None

        # A Deferred for the server listening port
        d = port.stopListening()

        # Remove the sandbox
        shutil.rmtree(self.sandbox)

        # Wait for the deferred that tell us we disconnected.
        return defer.gatherResults([d])

    def test_password_auth_success(self):
        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.sshServeruser,
                   'password': self.sshServerPassword,
                   'buffersize': 32768}

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

        d = self.client.run('echo hi')

        def client_disconnect(data):
            log.debug('Disconnecting client')
            self.client.disconnect()
            return data

        def got_hi(data):
            log.debug('Got Data %s' % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output,  'hi\n')
            return data

        d.addBoth(client_disconnect)
        d.addCallback(got_hi)

        return d

    def test_password_auth_failure(self):
        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.sshServeruser,
                   'password': '******',
                   'buffersize': 32768}

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

        d = self.client.run('echo hi')

        def client_disconnect(data):
            log.debug('Disconnecting client')
            self.client.disconnect()
            return data

        d.addBoth(client_disconnect)

        return self.assertFailure(d, UnauthorizedLogin)

    def test_password_identity_success(self):
        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.sshServeruser,
                   'password': '******',  # sshkey phrase
                   'identities': [self.sandbox+'/id_rsa'],
                   'buffersize': 32768}

        id_rsa_pub = testUsers['testUser']['pub']
        id_rsa_priv = testUsers['testUser']['priv']

        open(self.sandbox+'/id_rsa.pub', 'w').write(id_rsa_pub)
        open(self.sandbox+'/id_rsa', 'w').write(id_rsa_priv)
        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

        d = self.client.run('echo hi')

        def client_disconnect(data):
            log.debug('Disconnecting client')
            self.client.disconnect()
            return data

        def got_hi(data):
            log.debug('Got Data %s' % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output,  'hi\n')
            return data

        d.addBoth(client_disconnect)
        d.addCallback(got_hi)

        return d

    def test_password_identity_failure(self):
        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': self.sshServeruser,
                   'password': '******',  # sshkey phrase
                   'identities': [self.sandbox + '/id_rsa'],
                   'buffersize': 32768}

        id_rsa_pub = testUsers['testUser']['pub']
        id_rsa_priv = testUsers['testUser']['priv']

        open(self.sandbox+'/id_rsa.pub', 'w').write(id_rsa_pub)
        open(self.sandbox+'/id_rsa', 'w').write(id_rsa_priv)

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

        d = self.client.run('echo hi')

        def client_disconnect(data):
            log.debug('Disconnecting client')
            self.client.disconnect()
            return data

        d.addBoth(client_disconnect)

        return self.assertFailure(d, UnauthorizedLogin)

    def test_password_identity_no_passphrase_success(self):
        options = {'hostname': self.hostname,
                   'port': self.portnum,
                   'user': '******',
                   'identities': [self.sandbox + '/id_rsa2'],
                   'buffersize': 32768}

        id_rsa_pub = testUsers['testUser2']['pub']
        id_rsa_priv = testUsers['testUser2']['priv']

        open(self.sandbox+'/id_rsa2.pub', 'w').write(id_rsa_pub)
        open(self.sandbox+'/id_rsa2', 'w').write(id_rsa_priv)

        self.client = SSHClient(options)
        self.client.protocol = ClientProtocol
        self.client.connect()

        d = self.client.run('echo hi')

        def client_disconnect(data):
            log.debug('Disconnecting client')
            self.client.disconnect()
            return data

        def got_hi(data):
            log.debug('Got Data %s' % (data,))
            self.assertEqual(data.exitCode, 0)
            self.assertEqual(data.output,  'hi\n')
            return data

        d.addBoth(client_disconnect)
        d.addCallback(got_hi)

        return d