示例#1
0
    def _internal_connect(self, server, timeout, share=False):
        """Connect to the remote host provided via an ssh port forward.

        An SSH process is fired with port forwarding established on localhost
        22181, which the zookeeper client connects to.

        :param server: Remote host to connect to, specified as hostname:port
        :type string

        :param timeout: An timeout interval in seconds.
        :type float

        Returns a connected client or error.
        """
        hostname, port = self._parse_servers(server or self._servers)
        start_time = time.time()

        # Determine which port we'll be using.
        local_port = get_open_port()
        port_watcher = PortWatcher("localhost", local_port, timeout)

        tunnel_error = Deferred()
        # On a tunnel error, stop the port watch early and bail with error.
        tunnel_error.addErrback(port_watcher.stop)
        # If a tunnel error happens now or later, close the connection.
        tunnel_error.addErrback(lambda x: self.close())

        # Setup tunnel via an ssh process for port forwarding.
        protocol = ClientTunnelProtocol(self, tunnel_error)
        self._process = forward_port(
            self.remote_user, local_port, hostname, int(port),
            process_protocol=protocol, share=share)

        # Wait for the tunneled port to open.
        try:
            yield port_watcher.async_wait()
        except socket.error:
            self.close()  # Stop the tunnel process.
            raise ConnectionTimeoutException("could not connect")
        else:
            # If we stopped because of a tunnel error, raise it.
            if protocol.error:
                yield tunnel_error

        # Check timeout
        new_timeout = timeout - (time.time() - start_time)
        if new_timeout <= 0:
            self.close()
            raise ConnectionTimeoutException(
                "could not connect before timeout")

        # Connect the client
        try:
            yield super(SSHClient, self).connect(
                "localhost:%d" % local_port, new_timeout)
        except:
            self.close()  # Stop the tunnel
            raise

        returnValue(self)
示例#2
0
 def test_connect_with_key(self):
     """
     A private key path can optionally be specified as an argument
     to connect in which case its passed to the ssh command line.
     """
     from twisted.internet import reactor
     file_path = self.makeFile("content")
     mock_reactor = self.mocker.patch(reactor)
     mock_reactor.spawnProcess(ARGS, KWARGS)
     saved = []
     self.mocker.call(lambda *args, **kwargs: saved.append((args, kwargs)))
     self.mocker.result("the-process")
     self.mocker.replay()
     result = forward_port("ubuntu", 22181, "remote_host", 2181,
                           private_key_path=file_path)
     self.assertEquals(result, "the-process")
     args, kwargs = saved[0]
     self.assertIsInstance(args[0], TunnelProtocol)
     self.assertEquals(args[1], "/usr/bin/ssh")
     self.assertEquals(args[2], [
         "ssh", "-T",
         "-i", file_path,
         "-o",
         "ControlPath " + self.home + "/.juju/ssh/master-%r@%h:%p",
         "-o", "ControlMaster no",
         "-o", "PasswordAuthentication no",
         "-Llocalhost:22181:localhost:2181", "ubuntu@remote_host"])
     self.assertEquals(kwargs, {"env": os.environ})
示例#3
0
 def test_ssh_spawn(self):
     """
     Forwarding a port spawns an ssh process with port forwarding arguments.
     """
     from twisted.internet import reactor
     mock_reactor = self.mocker.patch(reactor)
     mock_reactor.spawnProcess(ARGS, KWARGS)
     saved = []
     self.mocker.call(lambda *args, **kwargs: saved.append((args, kwargs)))
     self.mocker.result(None)
     self.mocker.replay()
     result = forward_port("ubuntu", 8888, "remote_host", 9999)
     self.assertEquals(result, None)
     self.assertTrue(saved)
     args, kwargs = saved[0]
     self.assertIsInstance(args[0], TunnelProtocol)
     self.assertEquals(args[1], "/usr/bin/ssh")
     self.assertEquals(args[2], [
         "ssh", "-T",
         "-o",
         "ControlPath " + self.home + "/.juju/ssh/master-%r@%h:%p",
         "-o", "ControlMaster no",
         "-o", "PasswordAuthentication no",
         "-Llocalhost:8888:localhost:9999", "ubuntu@remote_host"])
     self.assertEquals(kwargs, {"env": os.environ})
示例#4
0
 def test_ssh_spawn_sharing(self):
     """
     When sharing is enabled, ssh will be set up so that it becomes the
     master if there's no other master alive yet.
     """
     from twisted.internet import reactor
     mock_reactor = self.mocker.patch(reactor)
     mock_reactor.spawnProcess(ARGS, KWARGS)
     saved = []
     self.mocker.call(lambda *args, **kwargs: saved.append((args, kwargs)))
     self.mocker.result(None)
     self.mocker.replay()
     result = forward_port("ubuntu", 8888, "remote_host", 9999, share=True)
     self.assertEquals(result, None)
     self.assertTrue(saved)
     args, kwargs = saved[0]
     self.assertIsInstance(args[0], TunnelProtocol)
     self.assertEquals(args[1], "/usr/bin/ssh")
     self.assertEquals(args[2], [
         "ssh", "-T",
         "-o",
         "ControlPath " + self.home + "/.juju/ssh/master-%r@%h:%p",
         "-o", "ControlMaster auto",
         "-o", "PasswordAuthentication no",
         "-Llocalhost:8888:localhost:9999", "ubuntu@remote_host"])
     self.assertEquals(kwargs, {"env": os.environ})
示例#5
0
    def _internal_connect(self, server, timeout, share=False):
        """Connect to the remote host provided via an ssh port forward.

        An SSH process is fired with port forwarding established on localhost
        22181, which the zookeeper client connects to.

        :param server: Remote host to connect to, specified as hostname:port
        :type string

        :param timeout: An timeout interval in seconds.
        :type float

        Returns a connected client or error.
        """
        hostname, port = self._parse_servers(server or self._servers)
        start_time = time.time()

        # Determine which port we'll be using.
        local_port = get_open_port()
        port_watcher = PortWatcher("localhost", local_port, timeout)

        tunnel_error = Deferred()
        # On a tunnel error, stop the port watch early and bail with error.
        tunnel_error.addErrback(port_watcher.stop)
        # If a tunnel error happens now or later, close the connection.
        tunnel_error.addErrback(lambda x: self.close())

        # Setup tunnel via an ssh process for port forwarding.
        protocol = ClientTunnelProtocol(self, tunnel_error)
        self._process = forward_port(self.remote_user,
                                     local_port,
                                     hostname,
                                     int(port),
                                     process_protocol=protocol,
                                     share=share)

        # Wait for the tunneled port to open.
        try:
            yield port_watcher.async_wait()
        except socket.error:
            self.close()  # Stop the tunnel process.
            raise ConnectionTimeoutException("could not connect")
        else:
            # If we stopped because of a tunnel error, raise it.
            if protocol.error:
                yield tunnel_error

        # Check timeout
        new_timeout = timeout - (time.time() - start_time)
        if new_timeout <= 0:
            self.close()
            raise ConnectionTimeoutException(
                "could not connect before timeout")

        # Connect the client
        try:
            yield super(SSHClient, self).connect("localhost:%d" % local_port,
                                                 new_timeout)
        except:
            self.close()  # Stop the tunnel
            raise

        returnValue(self)