blob: 9319d2a8a1f0ede76e730edc67f950138c909ea5 [file] [log] [blame]
Sean Dague556add52013-07-19 14:28:44 -04001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
Attila Fazekasa23f5002012-10-23 19:32:45 +020013import re
Matthew Treinisha83a16e2012-12-07 13:44:02 -050014import time
15
David Kranz968f1b32015-06-18 16:58:18 -040016from oslo_log import log as logging
Matthew Treinish96e9e882014-06-09 18:37:19 -040017
Sean Dague86bd8422013-12-20 09:56:44 -050018from tempest import config
Ken'ichi Ohmichid25a1a32017-03-01 13:40:35 -080019from tempest.lib.common.utils.linux import remote_client
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050020import tempest.lib.exceptions
Daryl Walleck98e66dd2012-06-21 04:58:39 -050021
Sean Dague86bd8422013-12-20 09:56:44 -050022CONF = config.CONF
23
David Kranz968f1b32015-06-18 16:58:18 -040024LOG = logging.getLogger(__name__)
25
Daryl Walleck6b9b2882012-04-08 21:43:39 -050026
Ken'ichi Ohmichid25a1a32017-03-01 13:40:35 -080027class RemoteClient(remote_client.RemoteClient):
Andrea Frittoli (andreaf)5f5e4fc2016-04-29 16:00:17 -050028
Ken'ichi Ohmichid25a1a32017-03-01 13:40:35 -080029 # TODO(oomichi): Make this class deprecated after migrating
30 # necessary methods to tempest.lib and cleaning
31 # unnecessary methods up from this class.
Andrea Frittoli (andreaf)5f5e4fc2016-04-29 16:00:17 -050032 def __init__(self, ip_address, username, password=None, pkey=None,
33 server=None, servers_client=None):
34 """Executes commands in a VM over ssh
35
36 :param ip_address: IP address to ssh to
37 :param username: ssh username
38 :param password: ssh password (optional)
39 :param pkey: ssh public key (optional)
40 :param server: server dict, used for debugging purposes
41 :param servers_client: servers client, used for debugging purposes
42 """
Ken'ichi Ohmichid25a1a32017-03-01 13:40:35 -080043 super(RemoteClient, self).__init__(
44 ip_address, username, password=password, pkey=pkey,
45 server=server, servers_client=servers_client,
46 ssh_timeout=CONF.validation.ssh_timeout,
47 connect_timeout=CONF.validation.connect_timeout,
48 console_output_enabled=CONF.compute_feature_enabled.console_output,
49 ssh_shell_prologue=CONF.validation.ssh_shell_prologue,
50 ping_count=CONF.validation.ping_count,
51 ping_size=CONF.validation.ping_size)
Daryl Walleck6b9b2882012-04-08 21:43:39 -050052
Emily Hugenbruch877811f2017-03-24 14:32:03 -040053 # Note that this method will not work on SLES11 guests, as they do
54 # not support the TYPE column on lsblk
Evgeny Antyshev4894a912016-11-21 12:17:18 +000055 def get_disks(self):
56 # Select root disk devices as shown by lsblk
57 command = 'lsblk -lb --nodeps'
Elena Ezhova91db24e2014-02-28 20:47:10 +040058 output = self.exec_command(command)
Evgeny Antyshev4894a912016-11-21 12:17:18 +000059 selected = []
60 pos = None
61 for l in output.splitlines():
62 if pos is None and l.find("TYPE") > 0:
63 pos = l.find("TYPE")
64 # Show header line too
65 selected.append(l)
66 # lsblk lists disk type in a column right-aligned with TYPE
67 elif pos > 0 and l[pos:pos + 4] == "disk":
68 selected.append(l)
69
70 return "\n".join(selected)
Daryl Walleck98e66dd2012-06-21 04:58:39 -050071
72 def get_boot_time(self):
Vincent Untz3c0b5b92014-01-18 10:56:00 +010073 cmd = 'cut -f1 -d. /proc/uptime'
Elena Ezhova91db24e2014-02-28 20:47:10 +040074 boot_secs = self.exec_command(cmd)
Vincent Untz3c0b5b92014-01-18 10:56:00 +010075 boot_time = time.time() - int(boot_secs)
76 return time.localtime(boot_time)
Attila Fazekasa23f5002012-10-23 19:32:45 +020077
78 def write_to_console(self, message):
79 message = re.sub("([$\\`])", "\\\\\\\\\\1", message)
80 # usually to /dev/ttyS0
81 cmd = 'sudo sh -c "echo \\"%s\\" >/dev/console"' % message
Elena Ezhova91db24e2014-02-28 20:47:10 +040082 return self.exec_command(cmd)
Yair Fried5f670ab2013-12-09 09:26:51 +020083
Yair Friedbc46f592015-11-18 16:29:34 +020084 def get_mac_address(self, nic=""):
85 show_nic = "show {nic} ".format(nic=nic) if nic else ""
86 cmd = "ip addr %s| awk '/ether/ {print $2}'" % show_nic
87 return self.exec_command(cmd).strip().lower()
Yair Fried3097dc12014-01-26 08:46:43 +020088
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +000089 def get_nic_name_by_mac(self, address):
90 cmd = "ip -o link | awk '/%s/ {print $2}'" % address
91 nic = self.exec_command(cmd)
92 return nic.strip().strip(":").lower()
93
94 def get_nic_name_by_ip(self, address):
Evgeny Antyshevf58ab6d2015-04-15 08:23:05 +000095 cmd = "ip -o addr | awk '/%s/ {print $2}'" % address
Daniel Mellado9e3e1062015-08-06 18:07:05 +020096 nic = self.exec_command(cmd)
97 return nic.strip().strip(":").lower()
Yair Fried413bf2d2014-11-19 17:07:11 +020098
Yair Fried413bf2d2014-11-19 17:07:11 +020099 def get_dns_servers(self):
100 cmd = 'cat /etc/resolv.conf'
101 resolve_file = self.exec_command(cmd).strip().split('\n')
102 entries = (l.split() for l in resolve_file)
103 dns_servers = [l[1] for l in entries
104 if len(l) and l[0] == 'nameserver']
105 return dns_servers
106
Yair Fried413bf2d2014-11-19 17:07:11 +0200107 def _renew_lease_udhcpc(self, fixed_ip=None):
108 """Renews DHCP lease via udhcpc client. """
109 file_path = '/var/run/udhcpc.'
Evgeny Antyshev9b77ae52016-02-16 09:48:57 +0000110 nic_name = self.get_nic_name_by_ip(fixed_ip)
Yair Fried413bf2d2014-11-19 17:07:11 +0200111 pid = self.exec_command('cat {path}{nic}.pid'.
112 format(path=file_path, nic=nic_name))
113 pid = pid.strip()
Ken'ichi Ohmichi4e5a69e2017-03-01 18:15:29 -0800114 cmd = 'sudo /bin/kill -{sig} {pid}'.format(pid=pid, sig='USR1')
115 self.exec_command(cmd)
Yair Fried413bf2d2014-11-19 17:07:11 +0200116
117 def _renew_lease_dhclient(self, fixed_ip=None):
118 """Renews DHCP lease via dhclient client. """
Itzik Brownffb14022015-03-23 17:03:55 +0200119 cmd = "sudo /sbin/dhclient -r && sudo /sbin/dhclient"
Yair Fried413bf2d2014-11-19 17:07:11 +0200120 self.exec_command(cmd)
121
Ken'ichi Ohmichi4e337852017-03-01 12:04:23 -0800122 def renew_lease(self, fixed_ip=None, dhcp_client='udhcpc'):
Yair Fried413bf2d2014-11-19 17:07:11 +0200123 """Wrapper method for renewing DHCP lease via given client
124
125 Supporting:
126 * udhcpc
127 * dhclient
128 """
129 # TODO(yfried): add support for dhcpcd
Takashi NATSUME6d5a2b42015-09-08 11:27:49 +0900130 supported_clients = ['udhcpc', 'dhclient']
Takashi NATSUME6d5a2b42015-09-08 11:27:49 +0900131 if dhcp_client not in supported_clients:
Matthew Treinish4217a702016-10-07 17:27:11 -0400132 raise tempest.lib.exceptions.InvalidConfiguration(
133 '%s DHCP client unsupported' % dhcp_client)
Yair Fried413bf2d2014-11-19 17:07:11 +0200134 if dhcp_client == 'udhcpc' and not fixed_ip:
135 raise ValueError("need to set 'fixed_ip' for udhcpc client")
Joe Gordon28788b42015-02-25 12:42:37 -0800136 return getattr(self, '_renew_lease_' + dhcp_client)(fixed_ip=fixed_ip)
Alexander Gubanovabd154c2015-09-23 23:24:06 +0300137
138 def mount(self, dev_name, mount_path='/mnt'):
139 cmd_mount = 'sudo mount /dev/%s %s' % (dev_name, mount_path)
140 self.exec_command(cmd_mount)
141
142 def umount(self, mount_path='/mnt'):
143 self.exec_command('sudo umount %s' % mount_path)
144
145 def make_fs(self, dev_name, fs='ext4'):
146 cmd_mkfs = 'sudo /usr/sbin/mke2fs -t %s /dev/%s' % (fs, dev_name)
Sean Dague57c66552016-02-08 08:51:13 -0500147 try:
148 self.exec_command(cmd_mkfs)
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -0500149 except tempest.lib.exceptions.SSHExecCommandFailed:
Sean Dague57c66552016-02-08 08:51:13 -0500150 LOG.error("Couldn't mke2fs")
151 cmd_why = 'sudo ls -lR /dev'
Jordan Pittier525ec712016-12-07 17:51:26 +0100152 LOG.info("Contents of /dev: %s", self.exec_command(cmd_why))
Sean Dague57c66552016-02-08 08:51:13 -0500153 raise