1 ##############################################################################
2 # Copyright (c) 2015 Ericsson AB and others.
3 # Authors: George Paraskevopoulos (geopar@intracom-telecom.com)
4 # Jose Lausuch (jose.lausuch@ericsson.com)
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ##############################################################################
15 from opnfv.utils import opnfv_logger as logger
17 logger = logger.Logger("SSH utils").getLogger()
20 ''' Monkey Patch paramiko _custom_start_client '''
21 # We are using paramiko 2.1.1 and in the CI in the SFC
22 # test we are facing this issue:
23 # https://github.com/robotframework/SSHLibrary/issues/158
24 # The fix was merged in paramiko 2.1.3 in this PR:
25 # https://github.com/robotframework/SSHLibrary/pull/159/files
26 # Until we upgrade we can use this monkey patch to work
30 def _custom_start_client(self, *args, **kwargs):
31 self.banner_timeout = 45
32 self._orig_start_client(*args, **kwargs)
35 paramiko.transport.Transport._orig_start_client = \
36 paramiko.transport.Transport.start_client
37 paramiko.transport.Transport.start_client = _custom_start_client
38 ''' Monkey Patch paramiko _custom_start_client '''
41 def get_ssh_client(hostname,
49 client = paramiko.SSHClient()
51 client = ProxyHopClient()
52 proxy_pkey_file = proxy.get('pkey_file', '/root/.ssh/id_rsa')
53 client.configure_jump_host(proxy['ip'],
58 raise Exception('Could not connect to client')
60 client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
61 if pkey_file is not None:
62 key = paramiko.RSAKey.from_private_key_file(pkey_file)
63 client.load_system_host_keys()
64 client.connect(hostname,
69 client.connect(hostname,
75 except Exception as e:
80 def get_file(ssh_conn, src, dest):
82 sftp = ssh_conn.open_sftp()
85 except Exception as e:
86 logger.error("Error [get_file(ssh_conn, '%s', '%s']: %s" %
91 def put_file(ssh_conn, src, dest):
93 sftp = ssh_conn.open_sftp()
96 except Exception as e:
97 logger.error("Error [put_file(ssh_conn, '%s', '%s']: %s" %
102 class ProxyHopClient(paramiko.SSHClient):
104 Connect to a remote server using a proxy hop
107 def __init__(self, *args, **kwargs):
108 self.proxy_ssh = None
109 self.proxy_transport = None
110 self.proxy_channel = None
112 self.proxy_ssh_key = None
113 self.local_ssh_key = os.path.join(os.getcwd(), 'id_rsa')
114 super(ProxyHopClient, self).__init__(*args, **kwargs)
116 def configure_jump_host(self, jh_ip, jh_user, jh_pass,
117 jh_ssh_key='/root/.ssh/id_rsa'):
118 self.proxy_ip = jh_ip
119 self.proxy_ssh_key = jh_ssh_key
120 self.local_ssh_key = os.path.join(os.getcwd(),
121 jh_ssh_key.split('/')[-1])
122 self.proxy_ssh = paramiko.SSHClient()
123 self.proxy_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
124 self.proxy_ssh.connect(jh_ip,
128 self.proxy_transport = self.proxy_ssh.get_transport()
130 def connect(self, hostname, port=22, username='root', password=None,
131 pkey=None, key_filename=None, timeout=None, allow_agent=True,
132 look_for_keys=True, compress=False, sock=None, gss_auth=False,
133 gss_kex=False, gss_deleg_creds=True, gss_host=None,
134 banner_timeout=None):
136 if self.proxy_ssh is None:
137 raise Exception('You must configure the jump '
138 'host before calling connect')
140 get_file_res = get_file(self.proxy_ssh,
143 if get_file_res is None:
144 raise Exception('Could\'t fetch SSH key from jump host')
145 if self.proxy_ssh_key.split('/')[-1] == 'id_dsa':
146 proxy_key = (paramiko.DSSKey
147 .from_private_key_file(self.local_ssh_key))
149 proxy_key = (paramiko.RSAKey
150 .from_private_key_file(self.local_ssh_key))
152 self.proxy_channel = self.proxy_transport.open_channel(
157 self.set_missing_host_key_policy(paramiko.AutoAddPolicy())
158 super(ProxyHopClient, self).connect(hostname,
161 sock=self.proxy_channel,
163 os.remove(self.local_ssh_key)
164 except Exception as e: