Add tool to list cloud nodes processes

Change-Id: I6e482fc7d74f80d4045416e6730ef606f5ae1c1a
This commit is contained in:
Federico Ressi 2021-07-07 09:58:00 +02:00
parent d841aa112f
commit c16170f190
3 changed files with 81 additions and 1 deletions

View File

@ -17,6 +17,7 @@ from tobiko.openstack.topology import _assert
from tobiko.openstack.topology import _exception
from tobiko.openstack.topology import _neutron
from tobiko.openstack.topology import _topology
from tobiko.openstack.topology import _sh
assert_reachable_nodes = _assert.assert_reachable_nodes
assert_unreachable_nodes = _assert.assert_unreachable_nodes
@ -24,6 +25,8 @@ assert_unreachable_nodes = _assert.assert_unreachable_nodes
NoSuchOpenStackTopologyNodeGroup = _exception.NoSuchOpenStackTopologyNodeGroup
NoSuchOpenStackTopologyNode = _exception.NoSuchOpenStackTopologyNode
list_nodes_processes = _sh.list_nodes_processes
UnknowOpenStackContainerNameError = _topology.UnknowOpenStackContainerNameError
UnknowOpenStackServiceNameError = _topology.UnknowOpenStackServiceNameError
get_agent_service_name = _topology.get_agent_service_name

View File

@ -0,0 +1,37 @@
# Copyright 2021 Red Hat
#
# 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 __future__ import absolute_import
import typing
import tobiko
from tobiko.openstack.topology import _topology
from tobiko.shell import sh
def list_nodes_processes(command: str = None,
command_line: sh.ShellCommandType = None,
hostnames: typing.Iterable[str] = None,
topology: _topology.OpenStackTopology = None,
**list_processes_params) \
-> tobiko.Selection[sh.PsProcess]:
processes = tobiko.Selection[sh.PsProcess]()
nodes = _topology.list_openstack_nodes(topology=topology,
hostnames=hostnames)
for node in nodes:
processes += sh.list_processes(command=command,
command_line=command_line,
ssh_client=node.ssh_client,
**list_processes_params)
return processes

View File

@ -15,6 +15,8 @@
# under the License.
from __future__ import absolute_import
import random
import testtools
import tobiko
@ -43,7 +45,7 @@ class OpenStackTopologyTest(testtools.TestCase):
def test_ssh_client(self):
for node in self.topology.nodes:
self.assertIsNotNone(node.ssh_client)
hostname = sh.get_hostname(
hostname = sh.ssh_hostname(
ssh_client=node.ssh_client).split('.')[0]
self.assertEqual(node.name, hostname)
@ -88,6 +90,44 @@ class OpenStackTopologyTest(testtools.TestCase):
hostnames=[node.name for node in expected_nodes])
self.assertEqual(expected_nodes, actual_nodes)
def test_list_nodes_processes(self):
node = random.choice(topology.list_openstack_nodes())
filename = sh.execute(
'mktemp', ssh_client=node.ssh_client).stdout.strip()
self.addCleanup(sh.execute, f"rm -f '{filename}'",
ssh_client=node.ssh_client)
command_line = sh.shell_command(f"tail -F '{filename}'")
process = sh.process(command_line,
ssh_client=node.ssh_client)
# Process isn't listed before creation
processes = topology.list_nodes_processes(
command_line=command_line,
hostnames=[node.hostname])
self.assertEqual([], processes,
'Process listed before executing it')
# Process is listed after creation
process.execute()
self.addCleanup(process.kill)
processes = topology.list_nodes_processes(
command_line=command_line,
hostnames=[node.hostname])
self.assertEqual(command_line, processes.unique.command_line)
self.assertIs(node.ssh_client, processes.unique.ssh_client)
# Process isn't listed after kill
sh.execute(f"kill -9 {processes.unique.pid}",
ssh_client=node.ssh_client)
for attempt in tobiko.retry(timeout=30., interval=5.):
processes = topology.list_nodes_processes(
command_line=command_line,
hostnames=[node.hostname])
if not processes:
break
if attempt.is_last:
self.fail("Process listed after killing it")
def node_name_from_hostname(hostname):
return hostname.split('.', 1)[0].lower()