Use Ironic undercloud APIs to power on/off Overcloud nodes
Fixes topology node discovery to avoid repeating listing undercloud servers and to ensuring overcloud nodes are power on when they are being discovered. Change-Id: Ia834aa4282b604fca502948710e6b10676764c81
This commit is contained in:
parent
9e63f9d1c7
commit
bd7533cda0
@ -21,11 +21,11 @@ from tobiko import tripleo
|
||||
from tobiko.tests.functional.openstack import test_topology
|
||||
|
||||
|
||||
@tripleo.skip_if_missing_undercloud
|
||||
class TripleoTopologyTest(test_topology.OpenStackTopologyTest):
|
||||
|
||||
topology = tobiko.required_setup_fixture(tripleo.TripleoTopology)
|
||||
|
||||
@tripleo.skip_if_missing_undercloud
|
||||
def test_undercloud_group(self):
|
||||
ssh_client = tripleo.undercloud_ssh_client()
|
||||
name = sh.get_hostname(ssh_client=ssh_client).split('.')[0]
|
||||
|
@ -15,6 +15,7 @@ from __future__ import absolute_import
|
||||
|
||||
import io
|
||||
import os
|
||||
import typing
|
||||
|
||||
from oslo_log import log
|
||||
import six
|
||||
@ -22,6 +23,7 @@ import six
|
||||
import tobiko
|
||||
from tobiko import config
|
||||
from tobiko.openstack import keystone
|
||||
from tobiko.openstack import ironic
|
||||
from tobiko.openstack import nova
|
||||
from tobiko.shell import sh
|
||||
from tobiko.shell import ssh
|
||||
@ -67,17 +69,47 @@ def find_overcloud_node(**params):
|
||||
return nova.find_server(client=client, **params)
|
||||
|
||||
|
||||
def overcloud_ssh_client(hostname, ip_version=None, network_name=None):
|
||||
host_config = overcloud_host_config(hostname=hostname,
|
||||
ip_version=ip_version,
|
||||
network_name=network_name)
|
||||
def power_on_overcloud_node(server: typing.Union[nova.ServerType]):
|
||||
session = _undercloud.undercloud_keystone_session()
|
||||
node_id = getattr(server, 'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
None)
|
||||
if node_id is None:
|
||||
client = nova.get_nova_client(session=session)
|
||||
nova.activate_server(client=client, server=server)
|
||||
else:
|
||||
client = ironic.get_ironic_client(session=session)
|
||||
ironic.power_on_node(client=client, node=node_id)
|
||||
|
||||
|
||||
def power_off_overcloud_node(server: typing.Union[nova.ServerType]) \
|
||||
-> nova.NovaServer:
|
||||
session = _undercloud.undercloud_keystone_session()
|
||||
node_id = getattr(server, 'OS-EXT-SRV-ATTR:hypervisor_hostname',
|
||||
None)
|
||||
if node_id is None:
|
||||
client = nova.get_nova_client(session=session)
|
||||
nova.shutoff_server(client=client, server=server)
|
||||
else:
|
||||
client = ironic.get_ironic_client(session=session)
|
||||
ironic.power_off_node(client=client, node=node_id)
|
||||
|
||||
|
||||
def overcloud_ssh_client(hostname=None, ip_version=None, network_name=None,
|
||||
server=None, host_config=None):
|
||||
if host_config is None:
|
||||
host_config = overcloud_host_config(hostname=hostname,
|
||||
ip_version=ip_version,
|
||||
network_name=network_name,
|
||||
server=server)
|
||||
return ssh.ssh_client(host=hostname, host_config=host_config)
|
||||
|
||||
|
||||
def overcloud_host_config(hostname, ip_version=None, network_name=None):
|
||||
def overcloud_host_config(hostname=None, ip_version=None, network_name=None,
|
||||
server=None):
|
||||
host_config = OvercloudHostConfig(host=hostname,
|
||||
ip_version=ip_version,
|
||||
network_name=network_name)
|
||||
network_name=network_name,
|
||||
server=server)
|
||||
return tobiko.setup_fixture(host_config)
|
||||
|
||||
|
||||
@ -130,6 +162,7 @@ def _get_undercloud_file(ssh_client, source, destination, mode):
|
||||
|
||||
|
||||
class OvercloudHostConfig(tobiko.SharedFixture):
|
||||
host = None
|
||||
hostname = None
|
||||
port = None
|
||||
username = None
|
||||
@ -137,22 +170,29 @@ class OvercloudHostConfig(tobiko.SharedFixture):
|
||||
ip_version = None
|
||||
network_name = None
|
||||
key_filename = None
|
||||
server = None
|
||||
|
||||
def __init__(self, host, ip_version=None, network_name=None,
|
||||
**kwargs):
|
||||
def __init__(self, host=None, ip_version=None, network_name=None,
|
||||
server=None, **kwargs):
|
||||
super(OvercloudHostConfig, self).__init__()
|
||||
tobiko.check_valid_type(host, six.string_types)
|
||||
self.host = host
|
||||
if host:
|
||||
self.host = host
|
||||
if ip_version:
|
||||
self.ip_version = ip_version
|
||||
if network_name:
|
||||
self.network_name = network_name
|
||||
if server:
|
||||
self.server = server
|
||||
if self.host is None:
|
||||
self.host = server.name
|
||||
tobiko.check_valid_type(self.host, six.string_types)
|
||||
self._connect_parameters = ssh.gather_ssh_connect_parameters(**kwargs)
|
||||
|
||||
def setup_fixture(self):
|
||||
self.hostname = str(overcloud_node_ip_address(
|
||||
name=self.host, ip_version=self.ip_version,
|
||||
network_name=self.network_name))
|
||||
network_name=self.network_name,
|
||||
server=self.server))
|
||||
self.port = self.port or CONF.tobiko.tripleo.overcloud_ssh_port
|
||||
self.username = (self.username or
|
||||
CONF.tobiko.tripleo.overcloud_ssh_username)
|
||||
|
@ -19,8 +19,10 @@ import typing # noqa
|
||||
from oslo_log import log
|
||||
|
||||
from tobiko.openstack import neutron
|
||||
from tobiko.openstack import nova
|
||||
from tobiko.openstack import topology
|
||||
from tobiko.shell import files
|
||||
from tobiko.shell import sh
|
||||
from tobiko.tripleo import _overcloud
|
||||
from tobiko.tripleo import _undercloud
|
||||
|
||||
@ -66,6 +68,12 @@ class TripleoTopology(topology.OpenStackTopology):
|
||||
neutron.SERVER: '/var/log/containers/neutron/server.log*',
|
||||
}
|
||||
|
||||
def create_node(self, name, ssh_client, **kwargs):
|
||||
return TripleoTopologyNode(topology=self,
|
||||
name=name,
|
||||
ssh_client=ssh_client,
|
||||
**kwargs)
|
||||
|
||||
def discover_nodes(self):
|
||||
self.discover_ssh_proxy_jump_node()
|
||||
self.discover_undercloud_nodes()
|
||||
@ -82,15 +90,18 @@ class TripleoTopology(topology.OpenStackTopology):
|
||||
def discover_overcloud_nodes(self):
|
||||
if _overcloud.has_overcloud():
|
||||
for server in _overcloud.list_overcloud_nodes():
|
||||
config = _overcloud.overcloud_host_config(server.name)
|
||||
ssh_client = _overcloud.overcloud_ssh_client(server.name)
|
||||
node = self.add_node(address=config.hostname,
|
||||
_overcloud.power_on_overcloud_node(server)
|
||||
host_config = _overcloud.overcloud_host_config(server=server)
|
||||
ssh_client = _overcloud.overcloud_ssh_client(
|
||||
hostname=server.name,
|
||||
host_config=host_config)
|
||||
node = self.add_node(address=host_config.hostname,
|
||||
hostname=server.name,
|
||||
group='overcloud',
|
||||
ssh_client=ssh_client)
|
||||
assert isinstance(node, TripleoTopologyNode)
|
||||
node.overcloud_server = server
|
||||
self.discover_overcloud_node_subgroups(node)
|
||||
else:
|
||||
super(TripleoTopology, self).discover_nodes()
|
||||
|
||||
def discover_overcloud_node_subgroups(self, node):
|
||||
# set of subgroups extracted from node name
|
||||
@ -120,6 +131,31 @@ class TripleoTopology(topology.OpenStackTopology):
|
||||
return subgroups
|
||||
|
||||
|
||||
class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
||||
|
||||
overcloud_server: typing.Optional[nova.NovaServer] = None
|
||||
|
||||
def power_on_overcloud_node(self):
|
||||
server = self.overcloud_server
|
||||
if server is None:
|
||||
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
||||
self.ssh_client.close()
|
||||
LOG.debug(f"Ensuring overcloud node {self.name} power is on...")
|
||||
_overcloud.power_on_overcloud_node(server)
|
||||
hostname = sh.get_hostname(ssh_client=self.ssh_client)
|
||||
LOG.debug(f"Overcloud node {self.name} power is on ("
|
||||
f"hostname={hostname})")
|
||||
|
||||
def power_off_overcloud_node(self):
|
||||
server = self.overcloud_server
|
||||
if server is None:
|
||||
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
||||
self.ssh_client.close()
|
||||
LOG.debug(f"Ensuring overcloud node {self.name} power is off...")
|
||||
_overcloud.power_off_overcloud_node(server)
|
||||
LOG.debug(f"Overcloud server node {self.name} power is off.")
|
||||
|
||||
|
||||
def is_valid_overcloud_group_name(group_name: str, node_name: str = None):
|
||||
if not group_name:
|
||||
return False
|
||||
|
Loading…
x
Reference in New Issue
Block a user