Merge "Add topology which represents Podified RHOSP deployment"
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
ansi2html # LGPLv3+
|
ansi2html # LGPLv3+
|
||||||
dpkt # BSD
|
dpkt # BSD
|
||||||
|
openshift-client # Apache-2.0
|
||||||
pandas # BSD
|
pandas # BSD
|
||||||
podman==4.7.0 # Apache-2.0
|
podman==4.7.0 # Apache-2.0
|
||||||
pytest-cov # MIT
|
pytest-cov # MIT
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ CONFIG_MODULES = ['tobiko.common._case',
|
|||||||
'tobiko.shell.iperf3.config',
|
'tobiko.shell.iperf3.config',
|
||||||
'tobiko.shell.sh.config',
|
'tobiko.shell.sh.config',
|
||||||
'tobiko.shiftstack.config',
|
'tobiko.shiftstack.config',
|
||||||
|
'tobiko.rhosp.config',
|
||||||
|
'tobiko.podified.config',
|
||||||
'tobiko.tripleo.config']
|
'tobiko.tripleo.config']
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
24
tobiko/podified/__init__.py
Normal file
24
tobiko/podified/__init__.py
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Copyright 2023 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
|
||||||
|
|
||||||
|
from tobiko.podified import _topology
|
||||||
|
from tobiko.podified import _openshift
|
||||||
|
|
||||||
|
|
||||||
|
PodifiedTopology = _topology.PodifiedTopology
|
||||||
|
|
||||||
|
skip_if_not_podified = _topology.skip_if_not_podified
|
||||||
|
|
||||||
|
get_dataplane_ssh_keypair = _openshift.get_dataplane_ssh_keypair
|
||||||
126
tobiko/podified/_edpm.py
Normal file
126
tobiko/podified/_edpm.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
# Copyright 2023 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 base64
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import socket
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko import config
|
||||||
|
from tobiko.podified import _openshift
|
||||||
|
from tobiko.shell import ssh
|
||||||
|
|
||||||
|
CONF = config.CONF
|
||||||
|
|
||||||
|
|
||||||
|
def edpm_host_config(node=None,
|
||||||
|
ip_version: int = None,
|
||||||
|
key_filename: str = None):
|
||||||
|
node = node or {}
|
||||||
|
host_config = EdpmHostConfig(
|
||||||
|
host=node.get('host'),
|
||||||
|
hostname=node.get('hostname'),
|
||||||
|
ip_version=ip_version,
|
||||||
|
key_filename=key_filename,
|
||||||
|
port=node.get('port'),
|
||||||
|
username=node.get('username'))
|
||||||
|
return tobiko.setup_fixture(host_config)
|
||||||
|
|
||||||
|
|
||||||
|
def edpm_ssh_client(ip_version: int = None,
|
||||||
|
host_config=None,
|
||||||
|
node=None):
|
||||||
|
if host_config is None:
|
||||||
|
host_config = edpm_host_config(node=node,
|
||||||
|
ip_version=ip_version)
|
||||||
|
tobiko.check_valid_type(host_config.host, str)
|
||||||
|
return ssh.ssh_client(host=host_config.host,
|
||||||
|
**host_config.connect_parameters)
|
||||||
|
|
||||||
|
|
||||||
|
class EdpmSshKeyFileFixture(tobiko.SharedFixture):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def key_filename(self):
|
||||||
|
return tobiko.tobiko_config_path(
|
||||||
|
CONF.tobiko.podified.edpm_ssh_key_filename)
|
||||||
|
|
||||||
|
def setup_fixture(self):
|
||||||
|
self.setup_key_file()
|
||||||
|
|
||||||
|
def setup_key_file(self):
|
||||||
|
priv_key_filename = self.key_filename
|
||||||
|
pub_key_filename = priv_key_filename + ".pub"
|
||||||
|
key_dirname = os.path.dirname(priv_key_filename)
|
||||||
|
tobiko.makedirs(key_dirname, mode=0o700)
|
||||||
|
|
||||||
|
private_key, public_key = _openshift.get_dataplane_ssh_keypair()
|
||||||
|
if private_key:
|
||||||
|
with io.open(priv_key_filename, 'wb') as fd:
|
||||||
|
fd.write(base64.b64decode(private_key))
|
||||||
|
os.chmod(priv_key_filename, 0o600)
|
||||||
|
if public_key:
|
||||||
|
with io.open(pub_key_filename, 'wb') as fd:
|
||||||
|
fd.write(base64.b64decode(public_key))
|
||||||
|
os.chmod(pub_key_filename, 0o600)
|
||||||
|
|
||||||
|
|
||||||
|
class EdpmHostConfig(tobiko.SharedFixture):
|
||||||
|
|
||||||
|
key_file = tobiko.required_fixture(EdpmSshKeyFileFixture)
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
host: str,
|
||||||
|
hostname: str = None,
|
||||||
|
ip_version: int = None,
|
||||||
|
key_filename: str = None,
|
||||||
|
port: int = None,
|
||||||
|
username: str = None,
|
||||||
|
**kwargs):
|
||||||
|
super(EdpmHostConfig, self).__init__()
|
||||||
|
self.host = host
|
||||||
|
self.hostname = self._get_hostname(hostname)
|
||||||
|
self.ip_version = ip_version
|
||||||
|
self.key_filename = key_filename
|
||||||
|
self.port = port
|
||||||
|
self.username = username
|
||||||
|
self._connect_parameters = ssh.gather_ssh_connect_parameters(**kwargs)
|
||||||
|
|
||||||
|
def setup_fixture(self):
|
||||||
|
if self.port is None:
|
||||||
|
# TODO(slaweq): add config option
|
||||||
|
self.port = 22
|
||||||
|
if self.username is None:
|
||||||
|
# TODO(slaweq): add config option
|
||||||
|
self.username = 'cloud-admin'
|
||||||
|
if self.key_filename is None:
|
||||||
|
self.key_filename = self.key_file.key_filename
|
||||||
|
|
||||||
|
def _get_hostname(self, hostname):
|
||||||
|
try:
|
||||||
|
socket.gethostbyname(hostname)
|
||||||
|
return hostname
|
||||||
|
except socket.gaierror:
|
||||||
|
return self.host
|
||||||
|
|
||||||
|
@property
|
||||||
|
def connect_parameters(self):
|
||||||
|
parameters = ssh.ssh_host_config(
|
||||||
|
host=str(self.hostname)).connect_parameters
|
||||||
|
parameters.update(ssh.gather_ssh_connect_parameters(self))
|
||||||
|
parameters.update(self._connect_parameters)
|
||||||
|
return parameters
|
||||||
82
tobiko/podified/_openshift.py
Normal file
82
tobiko/podified/_openshift.py
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
# Copyright 2023 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 openshift as oc
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
from tobiko.shell import sh
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
OSP_CONTROLPLANE = 'openstackcontrolplane'
|
||||||
|
OSP_DP_NODESET = 'openstackdataplanenodeset'
|
||||||
|
DP_SSH_SECRET_NAME = 'secret/dataplane-ansible-ssh-private-key-secret'
|
||||||
|
|
||||||
|
|
||||||
|
def _is_oc_client_available() -> bool:
|
||||||
|
try:
|
||||||
|
if sh.execute('which oc').exit_status == 0:
|
||||||
|
return True
|
||||||
|
except sh.ShellCommandFailed:
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def has_podified_cp() -> bool:
|
||||||
|
if not _is_oc_client_available():
|
||||||
|
LOG.debug("Openshift CLI client isn't installed.")
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
return bool(oc.selector(OSP_CONTROLPLANE).objects())
|
||||||
|
except oc.OpenShiftPythonException:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_dataplane_ssh_keypair():
|
||||||
|
private_key = ""
|
||||||
|
public_key = ""
|
||||||
|
try:
|
||||||
|
secret_object = oc.selector(DP_SSH_SECRET_NAME).object()
|
||||||
|
private_key = secret_object.as_dict()['data']['ssh-privatekey']
|
||||||
|
public_key = secret_object.as_dict()['data']['ssh-publickey']
|
||||||
|
except oc.OpenShiftPythonException as err:
|
||||||
|
LOG.error("Error while trying to get Dataplane secret SSH Key: %s",
|
||||||
|
err)
|
||||||
|
return private_key, public_key
|
||||||
|
|
||||||
|
|
||||||
|
def list_edpm_nodes():
|
||||||
|
nodes = []
|
||||||
|
nodeset_sel = oc.selector(OSP_DP_NODESET)
|
||||||
|
for nodeset in nodeset_sel.objects():
|
||||||
|
node_template = nodeset.as_dict()['spec']['nodeTemplate']
|
||||||
|
nodeset_nodes = nodeset.as_dict()['spec']['nodes']
|
||||||
|
for node in nodeset_nodes.values():
|
||||||
|
node_dict = {
|
||||||
|
'hostname': node.get('hostName'),
|
||||||
|
'host': node['ansible']['ansibleHost'],
|
||||||
|
'port': (
|
||||||
|
node.get('ansible', {}).get('ansiblePort') or
|
||||||
|
node_template.get('ansible', {}).get('ansiblePort')),
|
||||||
|
'username': (
|
||||||
|
node.get('ansible', {}).get('ansibleUser') or
|
||||||
|
node_template.get('ansible', {}).get('ansibleUser')),
|
||||||
|
}
|
||||||
|
nodes.append(node_dict)
|
||||||
|
return nodes
|
||||||
|
|
||||||
|
|
||||||
|
def list_ocp_workers():
|
||||||
|
pass
|
||||||
95
tobiko/podified/_topology.py
Normal file
95
tobiko/podified/_topology.py
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
# Copyright 2023 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
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko.openstack import neutron
|
||||||
|
from tobiko.openstack import topology
|
||||||
|
from tobiko import rhosp
|
||||||
|
from tobiko.podified import _edpm
|
||||||
|
from tobiko.podified import _openshift
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
skip_if_not_podified = tobiko.skip_unless(
|
||||||
|
"Podified deployment not configured", _openshift.has_podified_cp
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PodifiedTopology(rhosp.RhospTopology):
|
||||||
|
|
||||||
|
# NOTE(slaweq): those service names are only valid for the EDPM nodes
|
||||||
|
agent_to_service_name_mappings = {
|
||||||
|
neutron.DHCP_AGENT: 'tripleo_neutron_dhcp',
|
||||||
|
neutron.OVN_METADATA_AGENT: 'tripleo_ovn_metadata_agent',
|
||||||
|
neutron.NEUTRON_OVN_METADATA_AGENT: 'tripleo_ovn_metadata_agent',
|
||||||
|
neutron.OVN_CONTROLLER: 'tripleo_ovn_controller',
|
||||||
|
neutron.OVN_BGP_AGENT: 'tripleo_ovn_bgp_agent',
|
||||||
|
neutron.FRR: 'tripleo_frr'
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE(slaweq): those container names are only valid for the EDPM nodes
|
||||||
|
agent_to_container_name_mappings = {
|
||||||
|
neutron.DHCP_AGENT: 'neutron_dhcp',
|
||||||
|
neutron.OVN_METADATA_AGENT: 'ovn_metadata_agent',
|
||||||
|
neutron.NEUTRON_OVN_METADATA_AGENT: 'ovn_metadata_agent',
|
||||||
|
neutron.OVN_CONTROLLER: 'ovn_controller',
|
||||||
|
neutron.OVN_BGP_AGENT: 'ovn_bgp_agent',
|
||||||
|
neutron.FRR: 'frr'
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_node(self, name, ssh_client, **kwargs):
|
||||||
|
return EdpmNode(topology=self,
|
||||||
|
name=name,
|
||||||
|
ssh_client=ssh_client,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
def discover_nodes(self):
|
||||||
|
self.discover_ssh_proxy_jump_node()
|
||||||
|
self.discover_ocp_worker_nodes()
|
||||||
|
self.discover_edpm_nodes()
|
||||||
|
|
||||||
|
def discover_ssh_proxy_jump_node(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def discover_ocp_worker_nodes(self):
|
||||||
|
# TODO(slaweq): discover OCP nodes where OpenStack CP is running
|
||||||
|
pass
|
||||||
|
|
||||||
|
def discover_edpm_nodes(self):
|
||||||
|
for node in _openshift.list_edpm_nodes():
|
||||||
|
LOG.debug(f"Found EDPM node {node['hostname']} "
|
||||||
|
f"(IP: {node['host']})")
|
||||||
|
host_config = _edpm.edpm_host_config(node)
|
||||||
|
ssh_client = _edpm.edpm_ssh_client(host_config=host_config)
|
||||||
|
node = self.add_node(address=host_config.host,
|
||||||
|
group='compute',
|
||||||
|
ssh_client=ssh_client)
|
||||||
|
assert isinstance(node, EdpmNode)
|
||||||
|
|
||||||
|
|
||||||
|
class EdpmNode(rhosp.RhospNode):
|
||||||
|
|
||||||
|
def power_on_node(self):
|
||||||
|
LOG.debug(f"Ensuring EDPM node {self.name} power is on...")
|
||||||
|
|
||||||
|
def power_off_node(self):
|
||||||
|
LOG.debug(f"Ensuring EDPM node {self.name} power is off...")
|
||||||
|
|
||||||
|
|
||||||
|
def setup_podified_topology():
|
||||||
|
topology.set_default_openstack_topology_class(PodifiedTopology)
|
||||||
23
tobiko/podified/config.py
Normal file
23
tobiko/podified/config.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Copyright 2023 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
|
||||||
|
|
||||||
|
|
||||||
|
def setup_tobiko_config(conf):
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
from tobiko.podified import _openshift
|
||||||
|
from tobiko.podified import _topology
|
||||||
|
|
||||||
|
if _openshift.has_podified_cp():
|
||||||
|
_topology.setup_podified_topology()
|
||||||
23
tobiko/rhosp/__init__.py
Normal file
23
tobiko/rhosp/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Copyright 2023 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
|
||||||
|
|
||||||
|
from tobiko.rhosp import _version_utils
|
||||||
|
from tobiko.rhosp import _topology
|
||||||
|
|
||||||
|
RhospTopology = _topology.RhospTopology
|
||||||
|
RhospNode = _topology.RhospNode
|
||||||
|
|
||||||
|
get_rhosp_release = _version_utils.get_rhosp_release
|
||||||
|
get_rhosp_version = _version_utils.get_rhosp_version
|
||||||
117
tobiko/rhosp/_topology.py
Normal file
117
tobiko/rhosp/_topology.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# Copyright 2023 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 netaddr
|
||||||
|
from oslo_log import log
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko.openstack import nova
|
||||||
|
from tobiko.openstack import topology
|
||||||
|
from tobiko.rhosp import _version_utils
|
||||||
|
from tobiko.shell import ssh
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RhospTopology(topology.OpenStackTopology):
|
||||||
|
|
||||||
|
"""Base topology for Red Hat OpenStack deployments.
|
||||||
|
|
||||||
|
This is base topology which represents common parts between Tripleo and
|
||||||
|
Podified deployments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
has_containers = True
|
||||||
|
|
||||||
|
|
||||||
|
class RhospNode(topology.OpenStackTopologyNode):
|
||||||
|
|
||||||
|
"""Base RHOSP Node
|
||||||
|
|
||||||
|
This class represents common parts between Overcloud nodes and EDPM nodes
|
||||||
|
in Red Hat OpenStack deployments.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
topology: topology.OpenStackTopology,
|
||||||
|
name: str,
|
||||||
|
ssh_client: ssh.SSHClientFixture,
|
||||||
|
addresses: typing.Iterable[netaddr.IPAddress],
|
||||||
|
hostname: str,
|
||||||
|
rhosp_version: tobiko.Version = None):
|
||||||
|
# pylint: disable=redefined-outer-name
|
||||||
|
super().__init__(topology=topology,
|
||||||
|
name=name,
|
||||||
|
ssh_client=ssh_client,
|
||||||
|
addresses=addresses,
|
||||||
|
hostname=hostname)
|
||||||
|
self._rhosp_version = rhosp_version
|
||||||
|
|
||||||
|
@property
|
||||||
|
def rhosp_version(self) -> tobiko.Version:
|
||||||
|
if self._rhosp_version is None:
|
||||||
|
self._rhosp_version = self._get_rhosp_version()
|
||||||
|
return self._rhosp_version
|
||||||
|
|
||||||
|
def _get_rhosp_version(self) -> tobiko.Version:
|
||||||
|
return _version_utils.get_rhosp_version(connection=self.connection)
|
||||||
|
|
||||||
|
def power_on_node(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def power_off_node(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reboot_node(self, reactivate_servers=True):
|
||||||
|
"""Reboot node
|
||||||
|
|
||||||
|
This method reboots a node and may start every Nova
|
||||||
|
server which is not in SHUTOFF status before restarting.
|
||||||
|
|
||||||
|
:param reactivate_servers: whether or not to re-start the servers which
|
||||||
|
are hosted on the compute node after the reboot
|
||||||
|
"""
|
||||||
|
|
||||||
|
running_servers: typing.List[nova.NovaServer] = []
|
||||||
|
if reactivate_servers:
|
||||||
|
running_servers = self.list_running_servers()
|
||||||
|
LOG.debug(f'Servers to restart after reboot: {running_servers}')
|
||||||
|
|
||||||
|
self.power_off_node()
|
||||||
|
self.power_on_node()
|
||||||
|
|
||||||
|
if running_servers:
|
||||||
|
LOG.info(f'Restart servers after rebooting compute node '
|
||||||
|
f'{self.name}...')
|
||||||
|
for server in running_servers:
|
||||||
|
nova.wait_for_server_status(server=server.id,
|
||||||
|
status='SHUTOFF')
|
||||||
|
LOG.debug(f'Re-activate server {server.name} with ID '
|
||||||
|
f'{server.id}')
|
||||||
|
nova.activate_server(server=server)
|
||||||
|
LOG.debug(f'Server {server.name} with ID {server.id} has '
|
||||||
|
f'been reactivated')
|
||||||
|
|
||||||
|
def list_running_servers(self) -> typing.List[nova.NovaServer]:
|
||||||
|
running_servers = list()
|
||||||
|
for server in nova.list_servers():
|
||||||
|
if server.status != 'SHUTOFF':
|
||||||
|
hypervisor_name = nova.get_server_hypervisor(server,
|
||||||
|
short=True)
|
||||||
|
if self.name == hypervisor_name:
|
||||||
|
running_servers.append(server)
|
||||||
|
return running_servers
|
||||||
0
tobiko/rhosp/_utils.py
Normal file
0
tobiko/rhosp/_utils.py
Normal file
110
tobiko/rhosp/config.py
Normal file
110
tobiko/rhosp/config.py
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
# Copyright 2019 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 itertools
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
TRIPLEO_GROUP_NAME = 'tripleo'
|
||||||
|
TRIPLEO_OPTIONS = [
|
||||||
|
# Undercloud options
|
||||||
|
cfg.StrOpt('undercloud_ssh_hostname',
|
||||||
|
default='undercloud-0',
|
||||||
|
help="hostname or IP address to be used to connect to "
|
||||||
|
"undercloud host"),
|
||||||
|
cfg.IntOpt('undercloud_ssh_port',
|
||||||
|
default=None,
|
||||||
|
help="TCP port of SSH server on undercloud host"),
|
||||||
|
cfg.StrOpt('undercloud_ssh_username',
|
||||||
|
default='stack',
|
||||||
|
help="Username with access to stackrc and overcloudrc files"),
|
||||||
|
cfg.StrOpt('undercloud_ssh_key_filename',
|
||||||
|
default=None,
|
||||||
|
help="SSH key filename used to login to Undercloud node"),
|
||||||
|
cfg.ListOpt('undercloud_rcfile',
|
||||||
|
default=['~/stackrc'],
|
||||||
|
help="Undercloud RC filename"),
|
||||||
|
cfg.StrOpt('undercloud_cloud_name',
|
||||||
|
default='undercloud',
|
||||||
|
help='undercloud cloud name to be used for loading credentials '
|
||||||
|
'from the undercloud clouds files'),
|
||||||
|
cfg.StrOpt('undercloud_cacert_file',
|
||||||
|
default='/etc/pki/tls/certs/ca-bundle.trust.crt',
|
||||||
|
help='Path to cacert file that can be used to send https '
|
||||||
|
'request from the undercloud'),
|
||||||
|
|
||||||
|
# TODO(slaweq): those options may be also applicable for edpm nodes so
|
||||||
|
# maybe we will need to rename them to use in both topologies
|
||||||
|
# Overcloud options
|
||||||
|
cfg.IntOpt('overcloud_ssh_port',
|
||||||
|
default=None,
|
||||||
|
help="TCP port of SSH server on overcloud hosts"),
|
||||||
|
cfg.StrOpt('overcloud_ssh_username',
|
||||||
|
default=None,
|
||||||
|
help="Default username used to connect to overcloud nodes"),
|
||||||
|
cfg.StrOpt('overcloud_ssh_key_filename',
|
||||||
|
default='~/.ssh/id_overcloud',
|
||||||
|
help="SSH key filename used to login to Overcloud nodes"),
|
||||||
|
cfg.ListOpt('overcloud_rcfile',
|
||||||
|
default=['~/overcloudrc', '~/qe-Cloud-0rc'],
|
||||||
|
help="Overcloud RC filenames"),
|
||||||
|
cfg.StrOpt('overcloud_cloud_name',
|
||||||
|
default='overcloud',
|
||||||
|
help='overcloud cloud name to be used for loading credentials '
|
||||||
|
'from the overcloud clouds files'),
|
||||||
|
cfg.IntOpt('overcloud_ip_version',
|
||||||
|
help=("Default IP address version to be used to connect to "
|
||||||
|
"overcloud nodes ")),
|
||||||
|
cfg.StrOpt('overcloud_network_name',
|
||||||
|
help="Name of network used to connect to overcloud nodes"),
|
||||||
|
cfg.DictOpt('overcloud_groups_dict',
|
||||||
|
help='Dictionary with the node groups corresponding to '
|
||||||
|
'different hostname prefixes',
|
||||||
|
default={'ctrl': 'controller', 'cmp': 'compute'}),
|
||||||
|
|
||||||
|
# NOTE(slaweq): same here
|
||||||
|
# Other options
|
||||||
|
cfg.StrOpt('inventory_file',
|
||||||
|
default='.ansible/inventory/tripleo.yaml',
|
||||||
|
help="path to where to export tripleo inventory file"),
|
||||||
|
|
||||||
|
cfg.BoolOpt('has_external_load_balancer',
|
||||||
|
default=False,
|
||||||
|
help="OSP env was done with an external load balancer"),
|
||||||
|
|
||||||
|
cfg.BoolOpt('ceph_rgw',
|
||||||
|
default=False,
|
||||||
|
help="whether Ceph RGW is deployed"),
|
||||||
|
]
|
||||||
|
|
||||||
|
PODIFIED_GROUP_NAME = "podified"
|
||||||
|
PODIFIED_OPTIONS = [
|
||||||
|
cfg.StrOpt('edpm_ssh_key_filename',
|
||||||
|
default='~/.ssh/id_podified_edpm',
|
||||||
|
help="SSH key filename used to login to EDPM nodes"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def register_tobiko_options(conf):
|
||||||
|
conf.register_opts(group=cfg.OptGroup(TRIPLEO_GROUP_NAME),
|
||||||
|
opts=TRIPLEO_OPTIONS)
|
||||||
|
conf.register_opts(group=cfg.OptGroup(PODIFIED_GROUP_NAME),
|
||||||
|
opts=PODIFIED_OPTIONS)
|
||||||
|
|
||||||
|
|
||||||
|
def list_options():
|
||||||
|
return [(TRIPLEO_GROUP_NAME, itertools.chain(TRIPLEO_OPTIONS)),
|
||||||
|
(PODIFIED_GROUP_NAME, itertools.chain(PODIFIED_OPTIONS))]
|
||||||
@@ -825,7 +825,7 @@ def test_controllers_shutdown():
|
|||||||
LOG.info("Ensure all controller nodes are running: "
|
LOG.info("Ensure all controller nodes are running: "
|
||||||
f"{all_node_names}")
|
f"{all_node_names}")
|
||||||
for node in all_nodes:
|
for node in all_nodes:
|
||||||
node.power_on_overcloud_node()
|
node.power_on_node()
|
||||||
topology.assert_reachable_nodes(all_nodes)
|
topology.assert_reachable_nodes(all_nodes)
|
||||||
|
|
||||||
LOG.debug('Check VM is running while all controllers nodes are on')
|
LOG.debug('Check VM is running while all controllers nodes are on')
|
||||||
@@ -840,8 +840,8 @@ def test_controllers_shutdown():
|
|||||||
LOG.info(f"Power off {quorum_level} random controller nodes: "
|
LOG.info(f"Power off {quorum_level} random controller nodes: "
|
||||||
f"{node_names}")
|
f"{node_names}")
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node.power_off_overcloud_node()
|
node.power_off_node()
|
||||||
test_case.addCleanup(node.power_on_overcloud_node)
|
test_case.addCleanup(node.power_on_node)
|
||||||
topology.assert_unreachable_nodes(nodes, retry_count=1)
|
topology.assert_unreachable_nodes(nodes, retry_count=1)
|
||||||
topology.assert_reachable_nodes(node
|
topology.assert_reachable_nodes(node
|
||||||
for node in all_nodes
|
for node in all_nodes
|
||||||
@@ -860,7 +860,7 @@ def test_controllers_shutdown():
|
|||||||
random.shuffle(nodes)
|
random.shuffle(nodes)
|
||||||
LOG.info(f"Power on controller nodes: {node_names}")
|
LOG.info(f"Power on controller nodes: {node_names}")
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
node.power_on_overcloud_node()
|
node.power_on_node()
|
||||||
|
|
||||||
LOG.debug("Check all controller nodes are running again: "
|
LOG.debug("Check all controller nodes are running again: "
|
||||||
f"{all_node_names}")
|
f"{all_node_names}")
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ class OctaviaBasicFaultTest(testtools.TestCase):
|
|||||||
LOG.debug('Rebooting compute node...')
|
LOG.debug('Rebooting compute node...')
|
||||||
|
|
||||||
# Reboot Amphora's compute node will initiate a failover
|
# Reboot Amphora's compute node will initiate a failover
|
||||||
amphora_compute_host.reboot_overcloud_node()
|
amphora_compute_host.reboot_node()
|
||||||
|
|
||||||
LOG.debug('Compute node has been rebooted')
|
LOG.debug('Compute node has been rebooted')
|
||||||
|
|
||||||
|
|||||||
0
tobiko/tests/functional/podified/__init__.py
Normal file
0
tobiko/tests/functional/podified/__init__.py
Normal file
32
tobiko/tests/functional/podified/test_topology.py
Normal file
32
tobiko/tests/functional/podified/test_topology.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Copyright (c) 2023 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# 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 __future__ import absolute_import
|
||||||
|
|
||||||
|
import tobiko
|
||||||
|
from tobiko.tests.functional.openstack import test_topology
|
||||||
|
from tobiko import podified
|
||||||
|
|
||||||
|
|
||||||
|
@podified.skip_if_not_podified
|
||||||
|
class PodifiedTopologyTest(test_topology.OpenStackTopologyTest):
|
||||||
|
|
||||||
|
@property
|
||||||
|
def topology(self) -> podified.PodifiedTopology:
|
||||||
|
return tobiko.setup_fixture(podified.PodifiedTopology)
|
||||||
|
|
||||||
|
def test_controller_group(self):
|
||||||
|
self.skipTest("Discovery of the OCP workers is "
|
||||||
|
"not implemented yet.")
|
||||||
@@ -15,7 +15,6 @@ from __future__ import absolute_import
|
|||||||
|
|
||||||
from tobiko.tripleo import _ansible
|
from tobiko.tripleo import _ansible
|
||||||
from tobiko.tripleo import _overcloud as overcloud
|
from tobiko.tripleo import _overcloud as overcloud
|
||||||
from tobiko.tripleo import _rhosp
|
|
||||||
from tobiko.tripleo import _topology as topology
|
from tobiko.tripleo import _topology as topology
|
||||||
from tobiko.tripleo import _undercloud as undercloud
|
from tobiko.tripleo import _undercloud as undercloud
|
||||||
from tobiko.tripleo import containers
|
from tobiko.tripleo import containers
|
||||||
@@ -56,9 +55,6 @@ get_overcloud_ssh_username = overcloud.get_overcloud_ssh_username
|
|||||||
skip_if_ceph_rgw = containers.skip_if_ceph_rgw
|
skip_if_ceph_rgw = containers.skip_if_ceph_rgw
|
||||||
get_container_runtime_name = containers.get_container_runtime_name
|
get_container_runtime_name = containers.get_container_runtime_name
|
||||||
|
|
||||||
get_rhosp_release = _rhosp.get_rhosp_release
|
|
||||||
get_rhosp_version = _rhosp.get_rhosp_version
|
|
||||||
|
|
||||||
TripleoTopology = topology.TripleoTopology
|
TripleoTopology = topology.TripleoTopology
|
||||||
|
|
||||||
UndercloudKeystoneCredentialsFixture = \
|
UndercloudKeystoneCredentialsFixture = \
|
||||||
|
|||||||
@@ -25,18 +25,18 @@ from tobiko import config
|
|||||||
from tobiko.openstack import neutron
|
from tobiko.openstack import neutron
|
||||||
from tobiko.openstack import nova
|
from tobiko.openstack import nova
|
||||||
from tobiko.openstack import topology
|
from tobiko.openstack import topology
|
||||||
|
from tobiko import rhosp
|
||||||
from tobiko.shell import files
|
from tobiko.shell import files
|
||||||
from tobiko.shell import sh
|
from tobiko.shell import sh
|
||||||
from tobiko.shell import ssh
|
from tobiko.shell import ssh
|
||||||
from tobiko.tripleo import _overcloud
|
from tobiko.tripleo import _overcloud
|
||||||
from tobiko.tripleo import _rhosp
|
|
||||||
from tobiko.tripleo import _undercloud
|
from tobiko.tripleo import _undercloud
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TripleoTopology(topology.OpenStackTopology):
|
class TripleoTopology(rhosp.RhospTopology):
|
||||||
|
|
||||||
agent_to_service_name_mappings = {
|
agent_to_service_name_mappings = {
|
||||||
neutron.DHCP_AGENT: 'tripleo_neutron_dhcp',
|
neutron.DHCP_AGENT: 'tripleo_neutron_dhcp',
|
||||||
@@ -63,8 +63,6 @@ class TripleoTopology(topology.OpenStackTopology):
|
|||||||
neutron.FRR: 'frr'
|
neutron.FRR: 'frr'
|
||||||
}
|
}
|
||||||
|
|
||||||
has_containers = True
|
|
||||||
|
|
||||||
config_file_mappings = {
|
config_file_mappings = {
|
||||||
'ml2_conf.ini': '/var/lib/config-data/puppet-generated/neutron'
|
'ml2_conf.ini': '/var/lib/config-data/puppet-generated/neutron'
|
||||||
'/etc/neutron/plugins/ml2/ml2_conf.ini',
|
'/etc/neutron/plugins/ml2/ml2_conf.ini',
|
||||||
@@ -154,7 +152,7 @@ class TripleoTopology(topology.OpenStackTopology):
|
|||||||
return subgroups
|
return subgroups
|
||||||
|
|
||||||
|
|
||||||
class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
class TripleoTopologyNode(rhosp.RhospNode):
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
topology: topology.OpenStackTopology,
|
topology: topology.OpenStackTopology,
|
||||||
@@ -186,37 +184,6 @@ class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
|||||||
l3_agent_conf_path = (
|
l3_agent_conf_path = (
|
||||||
'/var/lib/config-data/neutron/etc/neutron/l3_agent.ini')
|
'/var/lib/config-data/neutron/etc/neutron/l3_agent.ini')
|
||||||
|
|
||||||
def reboot_overcloud_node(self,
|
|
||||||
reactivate_servers=True):
|
|
||||||
"""Reboot overcloud node
|
|
||||||
|
|
||||||
This method reboots an overcloud node and may start every Nova
|
|
||||||
server which is not in SHUTOFF status before restarting.
|
|
||||||
|
|
||||||
:param reactivate_servers: whether or not to re-start the servers which
|
|
||||||
are hosted on the compute node after the reboot
|
|
||||||
"""
|
|
||||||
|
|
||||||
running_servers: typing.List[nova.NovaServer] = []
|
|
||||||
if reactivate_servers:
|
|
||||||
running_servers = self.list_running_servers()
|
|
||||||
LOG.debug(f'Servers to restart after reboot: {running_servers}')
|
|
||||||
|
|
||||||
self.power_off_overcloud_node()
|
|
||||||
self.power_on_overcloud_node()
|
|
||||||
|
|
||||||
if running_servers:
|
|
||||||
LOG.info(f'Restart servers after rebooting overcloud compute node '
|
|
||||||
f'{self.name}...')
|
|
||||||
for server in running_servers:
|
|
||||||
nova.wait_for_server_status(server=server.id,
|
|
||||||
status='SHUTOFF')
|
|
||||||
LOG.debug(f'Re-activate server {server.name} with ID '
|
|
||||||
f'{server.id}')
|
|
||||||
nova.activate_server(server=server)
|
|
||||||
LOG.debug(f'Server {server.name} with ID {server.id} has '
|
|
||||||
f'been reactivated')
|
|
||||||
|
|
||||||
def list_running_servers(self) -> typing.List[nova.NovaServer]:
|
def list_running_servers(self) -> typing.List[nova.NovaServer]:
|
||||||
running_servers = list()
|
running_servers = list()
|
||||||
for server in nova.list_servers():
|
for server in nova.list_servers():
|
||||||
@@ -227,7 +194,7 @@ class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
|||||||
running_servers.append(server)
|
running_servers.append(server)
|
||||||
return running_servers
|
return running_servers
|
||||||
|
|
||||||
def power_on_overcloud_node(self):
|
def power_on_node(self):
|
||||||
if self.overcloud_instance is None:
|
if self.overcloud_instance is None:
|
||||||
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
||||||
self.ssh_client.close()
|
self.ssh_client.close()
|
||||||
@@ -237,7 +204,7 @@ class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
|||||||
LOG.debug(f"Overcloud node {self.name} power is on ("
|
LOG.debug(f"Overcloud node {self.name} power is on ("
|
||||||
f"hostname={hostname})")
|
f"hostname={hostname})")
|
||||||
|
|
||||||
def power_off_overcloud_node(self):
|
def power_off_node(self):
|
||||||
if self.overcloud_instance is None:
|
if self.overcloud_instance is None:
|
||||||
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
raise TypeError(f"Node {self.name} is not and Overcloud server")
|
||||||
self.ssh_client.close()
|
self.ssh_client.close()
|
||||||
@@ -245,9 +212,6 @@ class TripleoTopologyNode(topology.OpenStackTopologyNode):
|
|||||||
_overcloud.power_off_overcloud_node(instance=self.overcloud_instance)
|
_overcloud.power_off_overcloud_node(instance=self.overcloud_instance)
|
||||||
LOG.debug(f"Overcloud server node {self.name} power is off.")
|
LOG.debug(f"Overcloud server node {self.name} power is off.")
|
||||||
|
|
||||||
def _get_rhosp_version(self) -> tobiko.Version:
|
|
||||||
return _rhosp.get_rhosp_version(connection=self.connection)
|
|
||||||
|
|
||||||
|
|
||||||
def is_valid_overcloud_group_name(group_name: str, node_name: str = None):
|
def is_valid_overcloud_group_name(group_name: str, node_name: str = None):
|
||||||
if not group_name:
|
if not group_name:
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ from oslo_log import log
|
|||||||
import tobiko
|
import tobiko
|
||||||
from tobiko import config
|
from tobiko import config
|
||||||
from tobiko.openstack import keystone
|
from tobiko.openstack import keystone
|
||||||
|
from tobiko import rhosp
|
||||||
from tobiko.shell import ssh
|
from tobiko.shell import ssh
|
||||||
from tobiko.shell import sh
|
from tobiko.shell import sh
|
||||||
from tobiko.tripleo import _rhosp
|
|
||||||
|
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
@@ -218,7 +218,7 @@ def undercloud_keystone_credentials() -> keystone.KeystoneCredentialsFixture:
|
|||||||
@functools.lru_cache()
|
@functools.lru_cache()
|
||||||
def undercloud_version() -> tobiko.Version:
|
def undercloud_version() -> tobiko.Version:
|
||||||
ssh_client = undercloud_ssh_client()
|
ssh_client = undercloud_ssh_client()
|
||||||
return _rhosp.get_rhosp_version(connection=ssh_client)
|
return rhosp.get_rhosp_version(connection=ssh_client)
|
||||||
|
|
||||||
|
|
||||||
def check_undercloud(min_version: tobiko.Version = None,
|
def check_undercloud(min_version: tobiko.Version = None,
|
||||||
|
|||||||
@@ -13,89 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
import itertools
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
|
||||||
|
|
||||||
|
|
||||||
GROUP_NAME = 'tripleo'
|
|
||||||
OPTIONS = [
|
|
||||||
# Undercloud options
|
|
||||||
cfg.StrOpt('undercloud_ssh_hostname',
|
|
||||||
default='undercloud-0',
|
|
||||||
help="hostname or IP address to be used to connect to "
|
|
||||||
"undercloud host"),
|
|
||||||
cfg.IntOpt('undercloud_ssh_port',
|
|
||||||
default=None,
|
|
||||||
help="TCP port of SSH server on undercloud host"),
|
|
||||||
cfg.StrOpt('undercloud_ssh_username',
|
|
||||||
default='stack',
|
|
||||||
help="Username with access to stackrc and overcloudrc files"),
|
|
||||||
cfg.StrOpt('undercloud_ssh_key_filename',
|
|
||||||
default=None,
|
|
||||||
help="SSH key filename used to login to Undercloud node"),
|
|
||||||
cfg.ListOpt('undercloud_rcfile',
|
|
||||||
default=['~/stackrc'],
|
|
||||||
help="Undercloud RC filename"),
|
|
||||||
cfg.StrOpt('undercloud_cloud_name',
|
|
||||||
default='undercloud',
|
|
||||||
help='undercloud cloud name to be used for loading credentials '
|
|
||||||
'from the undercloud clouds files'),
|
|
||||||
cfg.StrOpt('undercloud_cacert_file',
|
|
||||||
default='/etc/pki/tls/certs/ca-bundle.trust.crt',
|
|
||||||
help='Path to cacert file that can be used to send https '
|
|
||||||
'request from the undercloud'),
|
|
||||||
|
|
||||||
|
|
||||||
# Overcloud options
|
|
||||||
cfg.IntOpt('overcloud_ssh_port',
|
|
||||||
default=None,
|
|
||||||
help="TCP port of SSH server on overcloud hosts"),
|
|
||||||
cfg.StrOpt('overcloud_ssh_username',
|
|
||||||
default=None,
|
|
||||||
help="Default username used to connect to overcloud nodes"),
|
|
||||||
cfg.StrOpt('overcloud_ssh_key_filename',
|
|
||||||
default='~/.ssh/id_overcloud',
|
|
||||||
help="SSH key filename used to login to Overcloud nodes"),
|
|
||||||
cfg.ListOpt('overcloud_rcfile',
|
|
||||||
default=['~/overcloudrc', '~/qe-Cloud-0rc'],
|
|
||||||
help="Overcloud RC filenames"),
|
|
||||||
cfg.StrOpt('overcloud_cloud_name',
|
|
||||||
default='overcloud',
|
|
||||||
help='overcloud cloud name to be used for loading credentials '
|
|
||||||
'from the overcloud clouds files'),
|
|
||||||
cfg.IntOpt('overcloud_ip_version',
|
|
||||||
help=("Default IP address version to be used to connect to "
|
|
||||||
"overcloud nodes ")),
|
|
||||||
cfg.StrOpt('overcloud_network_name',
|
|
||||||
help="Name of network used to connect to overcloud nodes"),
|
|
||||||
cfg.DictOpt('overcloud_groups_dict',
|
|
||||||
help='Dictionary with the node groups corresponding to '
|
|
||||||
'different hostname prefixes',
|
|
||||||
default={'ctrl': 'controller', 'cmp': 'compute'}),
|
|
||||||
|
|
||||||
# Other options
|
|
||||||
cfg.StrOpt('inventory_file',
|
|
||||||
default='.ansible/inventory/tripleo.yaml',
|
|
||||||
help="path to where to export tripleo inventory file"),
|
|
||||||
|
|
||||||
cfg.BoolOpt('has_external_load_balancer',
|
|
||||||
default=False,
|
|
||||||
help="OSP env was done with an external load balancer"),
|
|
||||||
|
|
||||||
cfg.BoolOpt('ceph_rgw',
|
|
||||||
default=False,
|
|
||||||
help="whether Ceph RGW is deployed"),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_tobiko_options(conf):
|
|
||||||
conf.register_opts(group=cfg.OptGroup(GROUP_NAME), opts=OPTIONS)
|
|
||||||
|
|
||||||
|
|
||||||
def list_options():
|
|
||||||
return [(GROUP_NAME, itertools.chain(OPTIONS))]
|
|
||||||
|
|
||||||
|
|
||||||
def setup_tobiko_config(conf):
|
def setup_tobiko_config(conf):
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
|
|||||||
Reference in New Issue
Block a user