def connect(self, username, key=None, password=None, port=22): """Initialize an SSH connection. Tries to connect and configure self. If only password is provided, it will be used for authentication. If key is provided, it is treated as and OpenSSH private RSA key and used for authentication. If both key and password are provided, password is used as a passphrase to unlock the private key. Raises MachineUnauthorizedError if it fails to connect. """ if not key and not password: raise RequiredParameterMissingError("neither key nor password " "provided.") if key: rsa_key = paramiko.RSAKey.from_private_key(StringIO(key)) else: rsa_key = None attempts = 3 while attempts: attempts -= 1 try: self.ssh.connect( self.host, port=port, username=username, password=password, pkey=rsa_key, allow_agent=False, look_for_keys=False, timeout=10 ) break except paramiko.AuthenticationException as exc: log.error("ssh exception %r", exc) raise MachineUnauthorizedError("Couldn't connect to %s@%s:%s. %s" % (username, self.host, port, exc)) except socket.error as exc: log.error("Got ssh error: %r", exc) if not attempts: raise ServiceUnavailableError("SSH timed-out repeatedly.") except Exception as exc: log.error("ssh exception %r", exc) # don't fail if SSHException or other paramiko exception, # eg related to network, but keep until all attempts are made if not attempts: raise ServiceUnavailableError(repr(exc))
def __init__(self, host, username=None, key=None, password=None, port=22): """Initialize a Shell instance Initializes a Shell instance for host. If username is provided, then it tries to actually initiate the connection, by calling connect(). Check out the docstring of connect(). """ if not host: raise RequiredParameterMissingError('host not given') self.host = host self.sudo = False self.ssh = paramiko.SSHClient() self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # if username provided, try to connect if username: self.connect(username, key, password, port)