Add timeout in releng.ssh_utils
[releng.git] / modules / opnfv / utils / ssh_utils.py
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 ##############################################################################
10
11
12 import os
13 import paramiko
14
15 from opnfv.utils import opnfv_logger as logger
16
17 logger = logger.Logger("SSH utils").getLogger()
18 SSH_TIMEOUT = 60
19
20
21 def get_ssh_client(hostname,
22                    username,
23                    password=None,
24                    proxy=None,
25                    pkey_file=None):
26     client = None
27     try:
28         if proxy is None:
29             client = paramiko.SSHClient()
30         else:
31             client = ProxyHopClient()
32             client.configure_jump_host(proxy['ip'],
33                                        proxy['username'],
34                                        proxy['password'])
35         if client is None:
36             raise Exception('Could not connect to client')
37
38         client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
39         if pkey_file is not None:
40             key = paramiko.RSAKey.from_private_key_file(pkey_file)
41             client.load_system_host_keys()
42             client.connect(hostname,
43                            username=username,
44                            pkey=key,
45                            timeout=SSH_TIMEOUT)
46         else:
47             client.connect(hostname,
48                            username=username,
49                            password=password,
50                            timeout=SSH_TIMEOUT)
51
52         return client
53     except Exception as e:
54         logger.error(e)
55         return None
56
57
58 def get_file(ssh_conn, src, dest):
59     try:
60         sftp = ssh_conn.open_sftp()
61         sftp.get(src, dest)
62         return True
63     except Exception as e:
64         logger.error("Error [get_file(ssh_conn, '%s', '%s']: %s" %
65                      (src, dest, e))
66         return None
67
68
69 def put_file(ssh_conn, src, dest):
70     try:
71         sftp = ssh_conn.open_sftp()
72         sftp.put(src, dest)
73         return True
74     except Exception as e:
75         logger.error("Error [put_file(ssh_conn, '%s', '%s']: %s" %
76                      (src, dest, e))
77         return None
78
79
80 class ProxyHopClient(paramiko.SSHClient):
81     '''
82     Connect to a remote server using a proxy hop
83     '''
84
85     def __init__(self, *args, **kwargs):
86         self.proxy_ssh = None
87         self.proxy_transport = None
88         self.proxy_channel = None
89         self.proxy_ip = None
90         self.proxy_ssh_key = None
91         self.local_ssh_key = os.path.join(os.getcwd(), 'id_rsa')
92         super(ProxyHopClient, self).__init__(*args, **kwargs)
93
94     def configure_jump_host(self, jh_ip, jh_user, jh_pass,
95                             jh_ssh_key='/root/.ssh/id_rsa'):
96         self.proxy_ip = jh_ip
97         self.proxy_ssh_key = jh_ssh_key
98         self.proxy_ssh = paramiko.SSHClient()
99         self.proxy_ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
100         self.proxy_ssh.connect(jh_ip,
101                                username=jh_user,
102                                password=jh_pass,
103                                timeout=SSH_TIMEOUT)
104         self.proxy_transport = self.proxy_ssh.get_transport()
105
106     def connect(self, hostname, port=22, username='root', password=None,
107                 pkey=None, key_filename=None, timeout=None, allow_agent=True,
108                 look_for_keys=True, compress=False, sock=None, gss_auth=False,
109                 gss_kex=False, gss_deleg_creds=True, gss_host=None,
110                 banner_timeout=None):
111         try:
112             if self.proxy_ssh is None:
113                 raise Exception('You must configure the jump '
114                                 'host before calling connect')
115
116             get_file_res = get_file(self.proxy_ssh,
117                                     self.proxy_ssh_key,
118                                     self.local_ssh_key)
119             if get_file_res is None:
120                 raise Exception('Could\'t fetch SSH key from jump host')
121             proxy_key = (paramiko.RSAKey
122                          .from_private_key_file(self.local_ssh_key))
123
124             self.proxy_channel = self.proxy_transport.open_channel(
125                 "direct-tcpip",
126                 (hostname, 22),
127                 (self.proxy_ip, 22))
128
129             self.set_missing_host_key_policy(paramiko.AutoAddPolicy())
130             super(ProxyHopClient, self).connect(hostname,
131                                                 username=username,
132                                                 pkey=proxy_key,
133                                                 sock=self.proxy_channel,
134                                                 timeout=timeout)
135             os.remove(self.local_ssh_key)
136         except Exception as e:
137             logger.error(e)