
Move project into a directory matching its name. Change-Id: I26934edd049909482ccc078d88b581fa369326b4 Signed-off-by: Stephen Finucane <sfinucan@redhat.com>
134 lines
4.4 KiB
Python
134 lines
4.4 KiB
Python
# Copyright 2016
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
from contextlib import contextmanager
|
|
try:
|
|
from shlex import quote
|
|
except ImportError:
|
|
from pipes import quote
|
|
import urlparse
|
|
|
|
from tempest import config
|
|
from tempest.lib.common import ssh
|
|
|
|
|
|
CONF = config.CONF
|
|
|
|
|
|
class SSHClient(object):
|
|
"""A client to execute remote commands, based on tempest.lib.common.ssh."""
|
|
_prefix_command = '/bin/bash -c'
|
|
|
|
def __init__(self):
|
|
self.ssh_key = CONF.compute_private_config.target_private_key_path
|
|
self.ssh_user = CONF.compute_private_config.target_ssh_user
|
|
|
|
def execute(self, hostname=None, cmd=None):
|
|
ssh_client = ssh.Client(hostname, self.ssh_user,
|
|
key_filename=self.ssh_key)
|
|
cmd = self._prefix_command + ' ' + quote(cmd)
|
|
return ssh_client.exec_command(cmd)
|
|
|
|
@contextmanager
|
|
def prefix_command(self, prefix_command=None):
|
|
saved_prefix = self._prefix_command
|
|
self._prefix_command = prefix_command
|
|
yield self
|
|
self._prefix_command = saved_prefix
|
|
|
|
@contextmanager
|
|
def sudo_command(self, user=None):
|
|
if user is not None:
|
|
user_arg = '-u {}'.format(user)
|
|
else:
|
|
user_arg = ''
|
|
cmd = 'sudo {} /bin/bash -c'.format(user_arg)
|
|
with self.prefix_command(cmd) as p:
|
|
yield p
|
|
|
|
@contextmanager
|
|
def container_command(self, container_name, user=None):
|
|
if user is not None:
|
|
user_arg = '-u {}'.format(user)
|
|
else:
|
|
user_arg = ''
|
|
cmd = 'sudo docker exec {} -i {} /bin/bash -c'.format(
|
|
user_arg, container_name)
|
|
with self.prefix_command(cmd) as p:
|
|
yield p
|
|
|
|
|
|
class VirshXMLClient(SSHClient):
|
|
def __init__(self, hostname=None):
|
|
super(VirshXMLClient, self).__init__()
|
|
self.host = hostname
|
|
|
|
def dumpxml(self, domain):
|
|
if CONF.compute_private_config.containers:
|
|
ctx = self.container_command('nova_compute', user='root')
|
|
else:
|
|
ctx = self.sudo_command()
|
|
with ctx:
|
|
command = "virsh dumpxml {}".format(domain)
|
|
return self.execute(self.host, command)
|
|
|
|
|
|
class MySQLClient(SSHClient):
|
|
def __init__(self):
|
|
super(MySQLClient, self).__init__()
|
|
# the nova conf file may contain a private IP.
|
|
# let's just assume the db is available on the same node.
|
|
self.host = CONF.compute_private_config.target_controller
|
|
|
|
# discover db connection params by accessing nova.conf remotely
|
|
ssh_client = SSHClient()
|
|
if CONF.compute_private_config.containers:
|
|
ctx = ssh_client.container_command('nova_api')
|
|
else:
|
|
ctx = ssh_client.sudo_command()
|
|
with ctx:
|
|
cmd = 'grep "connection=mysql+pymysql://nova:" /etc/nova/nova.conf'
|
|
connection = ssh_client.execute(self.host, cmd)
|
|
connection_url = "=".join(connection.split("=")[1:])
|
|
p = urlparse.urlparse(connection_url)
|
|
|
|
self.username = p.username
|
|
self.password = p.password
|
|
self.database = p.path[1:]
|
|
self.database_host = p.hostname
|
|
|
|
def execute_command(self, command):
|
|
sql_cmd = "mysql -u{} -p{} -h{} -e '{}' {}".format(
|
|
self.username,
|
|
self.password,
|
|
self.database_host,
|
|
command,
|
|
self.database)
|
|
return self.execute(self.host, sql_cmd)
|
|
|
|
|
|
class NovaManageClient(SSHClient):
|
|
def __init__(self):
|
|
super(NovaManageClient, self).__init__()
|
|
self.hostname = CONF.compute_private_config.target_controller
|
|
|
|
def execute_command(self, command):
|
|
if CONF.compute_private_config.containers:
|
|
ctx = self.container_command('nova_api')
|
|
else:
|
|
ctx = self.sudo_command()
|
|
with ctx:
|
|
nova_cmd = "nova-manage {}".format(command)
|
|
return self.execute(self.hostname, nova_cmd)
|