blob: 99f731c22914f1e8faa9fce667da3d374b1e3906 [file] [log] [blame]
Jakub Libosvar7c58cb22017-05-03 09:00:14 +00001# All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
Federico Ressie9c89bf2018-04-19 13:02:33 +020015import os
16
17from oslo_log import log
Jakub Libosvar7c58cb22017-05-03 09:00:14 +000018from tempest.lib.common import ssh
19
Chandan Kumar667d3d32017-09-22 12:24:06 +053020from neutron_tempest_plugin import config
Jakub Libosvar7c58cb22017-05-03 09:00:14 +000021
22
Federico Ressie9c89bf2018-04-19 13:02:33 +020023CONF = config.CONF
24LOG = log.getLogger(__name__)
25
26
Jakub Libosvar7c58cb22017-05-03 09:00:14 +000027class Client(ssh.Client):
Federico Ressie9c89bf2018-04-19 13:02:33 +020028
29 timeout = CONF.validation.ssh_timeout
30
31 proxy_jump_host = CONF.neutron_plugin_options.ssh_proxy_jump_host
32 proxy_jump_username = CONF.neutron_plugin_options.ssh_proxy_jump_username
33 proxy_jump_password = CONF.neutron_plugin_options.ssh_proxy_jump_password
34 proxy_jump_keyfile = CONF.neutron_plugin_options.ssh_proxy_jump_keyfile
35 proxy_jump_port = CONF.neutron_plugin_options.ssh_proxy_jump_port
36
37 def __init__(self, host, username, password=None, timeout=None, pkey=None,
38 channel_timeout=10, look_for_keys=False, key_filename=None,
39 port=22, proxy_client=None):
40
41 timeout = timeout or self.timeout
42
43 if self.proxy_jump_host:
44 # Perform all SSH connections passing through configured SSH server
45 proxy_client = proxy_client or self.create_proxy_client(
46 timeout=timeout, channel_timeout=channel_timeout)
47
48 super(Client, self).__init__(
49 host=host, username=username, password=password, timeout=timeout,
50 pkey=pkey, channel_timeout=channel_timeout,
51 look_for_keys=look_for_keys, key_filename=key_filename, port=port,
52 proxy_client=proxy_client)
53
54 @classmethod
55 def create_proxy_client(cls, look_for_keys=True, **kwargs):
56 host = cls.proxy_jump_host
57 if not host:
58 # proxy_jump_host string cannot be empty or None
59 raise ValueError(
60 "'proxy_jump_host' configuration option is empty.")
61
62 # Let accept an empty string as a synonymous of default value on below
63 # options
64 password = cls.proxy_jump_password or None
65 key_file = cls.proxy_jump_keyfile or None
66 username = cls.proxy_jump_username
67
68 # Port must be a positive integer
69 port = cls.proxy_jump_port
70 if port <= 0 or port > 65535:
71 raise ValueError(
72 "Invalid value for 'proxy_jump_port' configuration option: "
73 "{!r}".format(port))
74
75 login = "{username}@{host}:{port}".format(username=username, host=host,
76 port=port)
77
78 if key_file:
79 # expand ~ character with user HOME directory
80 key_file = os.path.expanduser(key_file)
81 if os.path.isfile(key_file):
82 LOG.debug("Going to create SSH connection to %r using key "
83 "file: %s", login, key_file)
84
85 else:
86 # This message could help the user to identify a
87 # mis-configuration in tempest.conf
88 raise ValueError(
89 "Cannot find file specified as 'proxy_jump_keyfile' "
90 "option: {!r}".format(key_file))
91
92 elif password:
93 LOG.debug("Going to create SSH connection to %r using password.",
94 login)
95
96 elif look_for_keys:
97 # This message could help the user to identify a mis-configuration
98 # in tempest.conf
99 LOG.info("Both 'proxy_jump_password' and 'proxy_jump_keyfile' "
100 "options are empty. Going to create SSH connection to %r "
101 "looking for key file location into %r directory.",
102 login, os.path.expanduser('~/.ssh'))
103 else:
104 # An user that forces look_for_keys=False should really know what
105 # he really wants
106 LOG.warning("No authentication method provided to create an SSH "
107 "connection to %r. If it fails, then please "
108 "set 'proxy_jump_keyfile' to provide a valid SSH key "
109 "file.", login)
110
111 return ssh.Client(
112 host=host, username=username, password=password,
113 look_for_keys=look_for_keys, key_filename=key_file,
114 port=port, proxy_client=None, **kwargs)