blob: bcb76e852ccbd9aa5372f93462acf08dd10f9974 [file] [log] [blame]
koder aka kdanilov39e449e2016-12-17 15:15:26 +02001import logging
2from typing import Dict, List, NamedTuple, Union, cast
3
4from paramiko.ssh_exception import AuthenticationException
5
6from .fuel_rest_api import get_cluster_id, reflect_cluster, FuelInfo, KeystoneAuth
7from .node_interfaces import NodeInfo
8from .ssh_utils import ConnCreds, parse_ssh_uri
9from .utils import check_input_param, StopTestError, parse_creds
10from .stage import Stage, StepOrder
11from .test_run_class import TestRun
12from .node import connect, setup_rpc
13from .config import ConfigBlock
14from .openstack_api import OSCreds
15
16
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020017logger = logging.getLogger("wally")
koder aka kdanilov39e449e2016-12-17 15:15:26 +020018
19
20FuelNodeInfo = NamedTuple("FuelNodeInfo",
21 [("version", List[int]),
22 ("fuel_ext_iface", str),
23 ("openrc", Dict[str, Union[str, bool]])])
24
25
26
27class DiscoverFuelStage(Stage):
28 """"Fuel nodes discovery, also can get openstack openrc"""
29
30 priority = StepOrder.DISCOVER
31 config_block = 'fuel'
32
33 @classmethod
34 def validate(cls, cfg: ConfigBlock) -> None:
35 # msg = "openstack_env should be provided in fuel config"
36 # check_input_param('openstack_env' in fuel_data, msg)
37 # fuel.openstack_env
38 pass
39
40 def run(self, ctx: TestRun) -> None:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020041 discovery = ctx.config.get("discovery")
42 if discovery == 'disable':
43 logger.info("Skip FUEL discovery due to config setting")
44 return
45
46 if 'all_nodes' in ctx.storage:
47 logger.debug("Skip FUEL discovery, use previously discovered nodes")
48 ctx.fuel_openstack_creds = ctx.storage['fuel_os_creds'] # type: ignore
49 ctx.fuel_version = ctx.storage['fuel_version'] # type: ignore
50 return
51
52 fuel = ctx.config.fuel
53 fuel_node_info = ctx.merge_node(fuel.ssh_creds, {'fuel_master'})
54 creds = dict(zip(("user", "passwd", "tenant"), parse_creds(fuel.creds)))
55 fuel_conn = KeystoneAuth(fuel.url, creds)
56
57 # get cluster information from REST API
58 if "fuel_os_creds" in ctx.storage and 'fuel_version' in ctx.storage:
59 ctx.fuel_openstack_creds = ctx.storage['fuel_os_creds'] # type: ignore
60 ctx.fuel_version = ctx.storage['fuel_version'] # type: ignore
61 return
62
63 cluster_id = get_cluster_id(fuel_conn, fuel.openstack_env)
64 cluster = reflect_cluster(fuel_conn, cluster_id)
65 ctx.fuel_version = FuelInfo(fuel_conn).get_version()
66 ctx.storage["fuel_version"] = ctx.fuel_version
67
68 logger.info("Found FUEL {0}".format(".".join(map(str, ctx.fuel_version))))
69 openrc = cluster.get_openrc()
70
71 if openrc:
72 auth_url = cast(str, openrc['os_auth_url'])
73 if ctx.fuel_version >= [8, 0] and auth_url.startswith("https://"):
74 logger.warning("Fixing FUEL 8.0 AUTH url - replace https://->http://")
75 auth_url = auth_url.replace("https", "http", 1)
76
77 os_creds = OSCreds(name=cast(str, openrc['username']),
78 passwd=cast(str, openrc['password']),
79 tenant=cast(str, openrc['tenant_name']),
80 auth_url=cast(str, auth_url),
81 insecure=cast(bool, openrc['insecure']))
82
83 ctx.fuel_openstack_creds = os_creds
koder aka kdanilov39e449e2016-12-17 15:15:26 +020084 else:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020085 ctx.fuel_openstack_creds = None
86 ctx.storage["fuel_os_creds"] = ctx.fuel_openstack_creds
koder aka kdanilov39e449e2016-12-17 15:15:26 +020087
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020088 if discovery == 'metadata':
89 logger.debug("Skip FUEL nodes discovery due to discovery settings")
90 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +020091
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020092 try:
93 fuel_rpc = setup_rpc(connect(fuel_node_info),
94 ctx.rpc_code,
95 ctx.default_rpc_plugins,
96 log_level=ctx.config.rpc_log_level)
97 except AuthenticationException:
98 msg = "FUEL nodes discovery failed - wrong FUEL master SSH credentials"
99 if discovery != 'ignore_errors':
100 raise StopTestError(msg)
101 logger.warning(msg)
102 return
103 except Exception as exc:
104 if discovery != 'ignore_errors':
105 logger.exception("While connection to FUEL")
106 raise StopTestError("Failed to connect to FUEL")
107 logger.warning("Failed to connect to FUEL - %s", exc)
108 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200109
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200110 logger.debug("Downloading FUEL node ssh master key")
111 fuel_key = fuel_rpc.get_file_content('/root/.ssh/id_rsa')
112 network = 'fuelweb_admin' if ctx.fuel_version >= [6, 0] else 'admin'
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200113
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200114 count = 0
115 for count, fuel_node in enumerate(list(cluster.get_nodes())):
116 ip = str(fuel_node.get_ip(network))
117 ctx.merge_node(ConnCreds(ip, "root", key=fuel_key), set(fuel_node.get_roles()))
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200118
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200119 logger.debug("Found {} FUEL nodes for env {}".format(count, fuel.openstack_env))