2014-02-14 17:57:43 +00:00
|
|
|
"""
|
|
|
|
Connection utilities
|
|
|
|
"""
|
2011-07-15 19:08:59 +00:00
|
|
|
import base64
|
2011-05-18 21:46:49 +00:00
|
|
|
import paramiko
|
2013-12-11 21:08:51 +00:00
|
|
|
import os
|
2014-05-12 21:06:40 +00:00
|
|
|
import logging
|
|
|
|
|
2013-09-24 16:48:11 +00:00
|
|
|
from ..config import config
|
2014-05-12 21:06:40 +00:00
|
|
|
from ..contextutil import safe_while
|
|
|
|
|
|
|
|
log = logging.getLogger(__name__)
|
2011-05-18 21:46:49 +00:00
|
|
|
|
2013-09-25 13:25:35 +00:00
|
|
|
|
2011-05-18 21:46:49 +00:00
|
|
|
def split_user(user_at_host):
|
2014-02-14 17:57:43 +00:00
|
|
|
"""
|
|
|
|
break apart user@host fields into user and host.
|
|
|
|
"""
|
2011-05-18 21:46:49 +00:00
|
|
|
try:
|
|
|
|
user, host = user_at_host.rsplit('@', 1)
|
|
|
|
except ValueError:
|
|
|
|
user, host = None, user_at_host
|
|
|
|
assert user != '', \
|
|
|
|
"Bad input to split_user: {user_at_host!r}".format(user_at_host=user_at_host)
|
|
|
|
return user, host
|
|
|
|
|
2013-09-25 13:25:35 +00:00
|
|
|
|
2011-07-15 19:08:59 +00:00
|
|
|
def create_key(keytype, key):
|
2014-02-14 17:57:43 +00:00
|
|
|
"""
|
|
|
|
Create an ssh-rsa or ssh-dss key.
|
|
|
|
"""
|
2011-07-15 19:08:59 +00:00
|
|
|
if keytype == 'ssh-rsa':
|
|
|
|
return paramiko.rsakey.RSAKey(data=base64.decodestring(key))
|
|
|
|
elif keytype == 'ssh-dss':
|
|
|
|
return paramiko.dsskey.DSSKey(data=base64.decodestring(key))
|
|
|
|
else:
|
|
|
|
raise ValueError('keytype must be ssh-rsa or ssh-dsa')
|
2011-05-18 21:46:49 +00:00
|
|
|
|
2013-09-25 13:25:35 +00:00
|
|
|
|
2011-11-03 20:07:21 +00:00
|
|
|
def connect(user_at_host, host_key=None, keep_alive=False,
|
|
|
|
_SSHClient=None, _create_key=None):
|
2014-02-14 17:57:43 +00:00
|
|
|
"""
|
|
|
|
ssh connection routine.
|
|
|
|
|
|
|
|
:param user_at_host: user@host
|
|
|
|
:param host_key: ssh key
|
|
|
|
:param keep_alive: keep_alive indicator
|
|
|
|
:param _SSHClient: client, default is paramiko ssh client
|
|
|
|
:param _create_key: routine to create a key (defaults to local reate_key)
|
|
|
|
:return: ssh connection.
|
|
|
|
"""
|
2011-05-18 21:46:49 +00:00
|
|
|
user, host = split_user(user_at_host)
|
|
|
|
if _SSHClient is None:
|
|
|
|
_SSHClient = paramiko.SSHClient
|
|
|
|
ssh = _SSHClient()
|
2013-09-25 13:25:35 +00:00
|
|
|
|
2011-07-15 19:08:59 +00:00
|
|
|
if _create_key is None:
|
|
|
|
_create_key = create_key
|
|
|
|
|
2013-09-25 13:25:35 +00:00
|
|
|
if host_key is None:
|
|
|
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
|
|
if config.verify_host_keys is True:
|
|
|
|
ssh.load_system_host_keys()
|
|
|
|
|
2011-07-15 19:08:59 +00:00
|
|
|
else:
|
|
|
|
keytype, key = host_key.split(' ', 1)
|
|
|
|
ssh.get_host_keys().add(
|
|
|
|
hostname=host,
|
|
|
|
keytype=keytype,
|
|
|
|
key=_create_key(keytype, key)
|
|
|
|
)
|
2013-09-24 16:48:11 +00:00
|
|
|
|
2013-12-11 21:08:51 +00:00
|
|
|
connect_args = dict(
|
2012-06-06 01:41:45 +00:00
|
|
|
hostname=host,
|
|
|
|
username=user,
|
2013-12-11 21:08:51 +00:00
|
|
|
timeout=60
|
|
|
|
)
|
|
|
|
|
|
|
|
ssh_config_path = os.path.expanduser("~/.ssh/config")
|
|
|
|
if os.path.exists(ssh_config_path):
|
|
|
|
ssh_config = paramiko.SSHConfig()
|
|
|
|
ssh_config.parse(open(ssh_config_path))
|
|
|
|
opts = ssh_config.lookup(host)
|
|
|
|
opts_to_args = {
|
|
|
|
'identityfile': 'key_filename',
|
|
|
|
'host': 'hostname',
|
|
|
|
'user': 'username'
|
|
|
|
}
|
|
|
|
for opt_name, arg_name in opts_to_args.items():
|
|
|
|
if opt_name in opts:
|
|
|
|
connect_args[arg_name] = opts[opt_name]
|
|
|
|
|
2014-05-12 21:06:40 +00:00
|
|
|
log.info(connect_args)
|
|
|
|
|
2013-12-11 21:08:51 +00:00
|
|
|
# just let the exceptions bubble up to caller
|
2014-05-12 21:06:40 +00:00
|
|
|
with safe_while(sleep=1, action='connect to ' + host) as proceed:
|
|
|
|
while proceed():
|
|
|
|
try:
|
|
|
|
ssh.connect(**connect_args)
|
|
|
|
break
|
|
|
|
except paramiko.AuthenticationException:
|
|
|
|
log.exception("Error connecting to {host}".format(host=host))
|
2011-11-03 20:07:21 +00:00
|
|
|
ssh.get_transport().set_keepalive(keep_alive)
|
2011-05-18 21:46:49 +00:00
|
|
|
return ssh
|