From 8c42011634afd9b40164f026828de07b32abf2d6 Mon Sep 17 00:00:00 2001 From: pinikomarov Date: Mon, 9 Mar 2020 14:33:07 +0200 Subject: [PATCH] add object container action support allows restart and all actions on containers Change-Id: I8cb5b8fea5d43916f422e35c0b73b311a26bcce9 --- tobiko/tripleo/containers.py | 77 +++++++++++++++++++++++++++++++++--- tobiko/tripleo/topology.py | 22 +++++++++++ 2 files changed, 93 insertions(+), 6 deletions(-) diff --git a/tobiko/tripleo/containers.py b/tobiko/tripleo/containers.py index cc6f153f7..2f5f7d9e4 100644 --- a/tobiko/tripleo/containers.py +++ b/tobiko/tripleo/containers.py @@ -5,11 +5,14 @@ import time from oslo_log import log import pandas +import podman as podmanlib +import docker as dockerlib import tobiko from tobiko import podman from tobiko import docker from tobiko.openstack import topology +from tobiko.tripleo import topology as tripleo_topology LOG = log.getLogger(__name__) @@ -220,23 +223,85 @@ def assert_ovn_containers_running(): LOG.info("Networking OVN not configured") -def comparable_container_keys(container): +def comparable_container_keys(container, include_container_objects=False): """returns the tuple : 'container_host','container_name', - 'container_state' + 'container_state, container object if specified' """ - if container_runtime_module == podman: - return (container._client._context.hostname, # pylint: disable=W0212 + if container_runtime_module == podman and include_container_objects: + return (tripleo_topology.ip_to_hostname( + container._client._context.hostname), # pylint: disable=W0212 + container.data['names'], container.data['status'], + container) + elif container_runtime_module == podman: + return (tripleo_topology.ip_to_hostname( + container._client._context.hostname), # pylint: disable=W0212 container.data['names'], container.data['status']) + elif container_runtime_module == docker and include_container_objects: + return (container.attrs['Config']['Hostname'], + container.attrs['Name'].strip('/'), + container.attrs['State']['Status'], + container) elif container_runtime_module == docker: return (container.attrs['Config']['Hostname'], container.attrs['Name'].strip('/'), container.attrs['State']['Status']) -def get_container_states_list(containers_list): +def list_containers_objects_df(): + containers_list = list_containers() + containers_objects_list_df = pandas.DataFrame( + get_container_states_list( + containers_list, include_container_objects=True), + columns=['container_host', 'container_name', + 'container_state', 'container_object']) + return containers_objects_list_df + + +def get_overcloud_container(container_name=None, container_host=None): + """gets an container object by name on specified host + container""" + con_obj_df = list_containers_objects_df() + if container_host: + contaniner_obj = con_obj_df.query( + 'container_name == "{container_name}"' + ' and container_host == "{container_host}"'. + format(container_host=container_host, + container_name=container_name))['container_object'] + else: + contaniner_obj = con_obj_df.query( + 'container_name == "{container_name}"'. + format(container_name=container_name))['container_object'] + if not contaniner_obj.empty: + return contaniner_obj.values[0] + else: + tobiko.fail('container {} not found!'.format(container_name)) + + +def action_on_container(action, + container_name=None, container_host=None): + """take a container snd preform an action on it + actions are as defined in : podman/libs/containers.py:14/164""" + container = get_overcloud_container( + container_name=container_name, + container_host=container_host) + # we get the specified action as function from podman lib + if container_runtime_module == podman: + container_function = getattr( + podmanlib.libs.containers.Container, '{}'.format(action)) + else: + container_function = getattr( + dockerlib.models.containers.Container, '{}'.format(action)) + LOG.info('action_on_container: executing : {} on {}'.format(action, + container)) + return container_function(container) + + +def get_container_states_list(containers_list, + include_container_objects=False): container_states_list = tobiko.Selection() - container_states_list.extend([comparable_container_keys(container) for + container_states_list.extend([comparable_container_keys( + container, include_container_objects=include_container_objects) for container in containers_list]) return container_states_list diff --git a/tobiko/tripleo/topology.py b/tobiko/tripleo/topology.py index 1c03a6cb5..8c42299f1 100644 --- a/tobiko/tripleo/topology.py +++ b/tobiko/tripleo/topology.py @@ -13,6 +13,8 @@ # under the License. from __future__ import absolute_import +import re + from oslo_log import log from tobiko.openstack import topology @@ -64,3 +66,23 @@ def setup_tripleo_topology(): if undercloud.has_undercloud() or overcloud.has_overcloud(): topology.set_default_openstack_topology_class( 'tobiko.tripleo.topology.TripleoTopology') + + +def get_ip_to_nodes_dict(openstack_nodes=None): + if not openstack_nodes: + openstack_controllers = topology.list_openstack_nodes( + group='controller') + openstack_computes = topology.list_openstack_nodes(group='compute') + openstack_nodes = openstack_controllers + openstack_computes + ip_to_nodes_dict = {str(node.public_ip): node.name for node in + openstack_nodes} + return ip_to_nodes_dict + + +def str_is_not_ip(check_str): + letters = re.compile('[A-Za-z]') + return bool(letters.match(check_str)) + + +def ip_to_hostname(oc_ip): + return get_ip_to_nodes_dict()[oc_ip]