blob: 668be2183e89a1086411683fde69d4faf5ddf315 [file] [log] [blame]
import logging
from typing import Dict, List, NamedTuple, Union, cast
from paramiko.ssh_exception import AuthenticationException
from cephlib.common import parse_creds, to_ip
from cephlib.ssh import ConnCreds
from cephlib.node_impl import connect, setup_rpc
from .fuel_rest_api import get_cluster_id, reflect_cluster, FuelInfo, KeystoneAuth
from .utils import StopTestError
from .stage import Stage, StepOrder
from .test_run_class import TestRun
from .config import ConfigBlock
from .openstack_api import OSCreds
logger = logging.getLogger("wally")
FuelNodeInfo = NamedTuple("FuelNodeInfo",
[("version", List[int]),
("fuel_ext_iface", str),
("openrc", Dict[str, Union[str, bool]])])
class DiscoverFuelStage(Stage):
""""Fuel nodes discovery, also can get openstack openrc"""
priority = StepOrder.DISCOVER
config_block = 'fuel'
@classmethod
def validate(cls, cfg: ConfigBlock) -> None:
# msg = "openstack_env should be provided in fuel config"
# check_input_param('openstack_env' in fuel_data, msg)
# fuel.openstack_env
pass
def run(self, ctx: TestRun) -> None:
full_discovery = 'fuel' in ctx.config.discover
metadata_only = (not full_discovery) and ('metadata' in ctx.config.discover)
ignore_errors = 'ignore_errors' in ctx.config.discover
if not (metadata_only or full_discovery):
logger.debug("Skip ceph discovery due to config setting")
return
if "fuel_os_creds" in ctx.storage and 'fuel_version' in ctx.storage:
logger.debug("Skip FUEL credentials discovery, use previously discovered info")
ctx.fuel_openstack_creds = OSCreds(*cast(List, ctx.storage.get('fuel_os_creds')))
ctx.fuel_version = ctx.storage.get('fuel_version')
if 'all_nodes' in ctx.storage:
logger.debug("Skip FUEL nodes discovery, use data from DB")
return
elif metadata_only:
logger.debug("Skip FUEL nodes discovery due to discovery settings")
return
fuel = ctx.config.fuel
fuel_node_info = ctx.merge_node(fuel.ssh_creds, {'fuel_master'})
creds = dict(zip(("user", "passwd", "tenant"), parse_creds(fuel.creds)))
fuel_conn = KeystoneAuth(fuel.url, creds)
cluster_id = get_cluster_id(fuel_conn, fuel.openstack_env)
cluster = reflect_cluster(fuel_conn, cluster_id)
if ctx.fuel_version is None:
ctx.fuel_version = FuelInfo(fuel_conn).get_version()
ctx.storage.put(ctx.fuel_version, "fuel_version")
logger.info("Found FUEL {0}".format(".".join(map(str, ctx.fuel_version))))
openrc = cluster.get_openrc()
if openrc:
auth_url = cast(str, openrc['os_auth_url'])
if ctx.fuel_version >= [8, 0] and auth_url.startswith("https://"):
logger.warning("Fixing FUEL 8.0 AUTH url - replace https://->http://")
auth_url = auth_url.replace("https", "http", 1)
os_creds = OSCreds(name=cast(str, openrc['username']),
passwd=cast(str, openrc['password']),
tenant=cast(str, openrc['tenant_name']),
auth_url=cast(str, auth_url),
insecure=cast(bool, openrc['insecure']))
ctx.fuel_openstack_creds = os_creds
else:
ctx.fuel_openstack_creds = None
ctx.storage.put(list(ctx.fuel_openstack_creds), "fuel_os_creds")
if metadata_only:
logger.debug("Skip FUEL nodes discovery due to discovery settings")
return
try:
fuel_rpc = setup_rpc(connect(fuel_node_info),
ctx.rpc_code,
ctx.default_rpc_plugins,
log_level=ctx.config.rpc_log_level)
except AuthenticationException:
msg = "FUEL nodes discovery failed - wrong FUEL master SSH credentials"
if ignore_errors:
raise StopTestError(msg)
logger.warning(msg)
return
except Exception as exc:
if ignore_errors:
logger.exception("While connection to FUEL")
raise StopTestError("Failed to connect to FUEL")
logger.warning("Failed to connect to FUEL - %s", exc)
return
logger.debug("Downloading FUEL node ssh master key")
fuel_key = fuel_rpc.get_file_content('/root/.ssh/id_rsa')
network = 'fuelweb_admin' if ctx.fuel_version >= [6, 0] else 'admin'
count = 0
for count, fuel_node in enumerate(list(cluster.get_nodes())):
ip = str(fuel_node.get_ip(network))
ctx.merge_node(ConnCreds(to_ip(ip), "root", key=fuel_key), set(fuel_node.get_roles()))
logger.debug("Found {} FUEL nodes for env {}".format(count, fuel.openstack_env))