blob: 668be2183e89a1086411683fde69d4faf5ddf315 [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
kdanylov aka koder026e5f22017-05-15 01:04:39 +03006from cephlib.common import parse_creds, to_ip
7from cephlib.ssh import ConnCreds
8from cephlib.node_impl import connect, setup_rpc
9
koder aka kdanilov39e449e2016-12-17 15:15:26 +020010from .fuel_rest_api import get_cluster_id, reflect_cluster, FuelInfo, KeystoneAuth
kdanylov aka koder026e5f22017-05-15 01:04:39 +030011from .utils import StopTestError
koder aka kdanilov39e449e2016-12-17 15:15:26 +020012from .stage import Stage, StepOrder
13from .test_run_class import TestRun
koder aka kdanilov39e449e2016-12-17 15:15:26 +020014from .config import ConfigBlock
15from .openstack_api import OSCreds
16
17
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020018logger = logging.getLogger("wally")
koder aka kdanilov39e449e2016-12-17 15:15:26 +020019
20
21FuelNodeInfo = NamedTuple("FuelNodeInfo",
22 [("version", List[int]),
23 ("fuel_ext_iface", str),
24 ("openrc", Dict[str, Union[str, bool]])])
25
26
27
28class DiscoverFuelStage(Stage):
29 """"Fuel nodes discovery, also can get openstack openrc"""
30
31 priority = StepOrder.DISCOVER
32 config_block = 'fuel'
33
34 @classmethod
35 def validate(cls, cfg: ConfigBlock) -> None:
36 # msg = "openstack_env should be provided in fuel config"
37 # check_input_param('openstack_env' in fuel_data, msg)
38 # fuel.openstack_env
39 pass
40
41 def run(self, ctx: TestRun) -> None:
kdanylov aka kodercdfcdaf2017-04-29 10:03:39 +030042 full_discovery = 'fuel' in ctx.config.discover
43 metadata_only = (not full_discovery) and ('metadata' in ctx.config.discover)
44 ignore_errors = 'ignore_errors' in ctx.config.discover
kdanylov aka koder150b2192017-04-01 16:53:01 +030045
46 if not (metadata_only or full_discovery):
47 logger.debug("Skip ceph discovery due to config setting")
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020048 return
49
koder aka kdanilov7f59d562016-12-26 01:34:23 +020050 if "fuel_os_creds" in ctx.storage and 'fuel_version' in ctx.storage:
51 logger.debug("Skip FUEL credentials discovery, use previously discovered info")
52 ctx.fuel_openstack_creds = OSCreds(*cast(List, ctx.storage.get('fuel_os_creds')))
53 ctx.fuel_version = ctx.storage.get('fuel_version')
54 if 'all_nodes' in ctx.storage:
55 logger.debug("Skip FUEL nodes discovery, use data from DB")
56 return
kdanylov aka koder150b2192017-04-01 16:53:01 +030057 elif metadata_only:
koder aka kdanilov7f59d562016-12-26 01:34:23 +020058 logger.debug("Skip FUEL nodes discovery due to discovery settings")
59 return
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020060
61 fuel = ctx.config.fuel
62 fuel_node_info = ctx.merge_node(fuel.ssh_creds, {'fuel_master'})
63 creds = dict(zip(("user", "passwd", "tenant"), parse_creds(fuel.creds)))
64 fuel_conn = KeystoneAuth(fuel.url, creds)
65
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020066 cluster_id = get_cluster_id(fuel_conn, fuel.openstack_env)
67 cluster = reflect_cluster(fuel_conn, cluster_id)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020068
koder aka kdanilov7f59d562016-12-26 01:34:23 +020069 if ctx.fuel_version is None:
70 ctx.fuel_version = FuelInfo(fuel_conn).get_version()
71 ctx.storage.put(ctx.fuel_version, "fuel_version")
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020072
koder aka kdanilov7f59d562016-12-26 01:34:23 +020073 logger.info("Found FUEL {0}".format(".".join(map(str, ctx.fuel_version))))
74 openrc = cluster.get_openrc()
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020075
koder aka kdanilov7f59d562016-12-26 01:34:23 +020076 if openrc:
77 auth_url = cast(str, openrc['os_auth_url'])
78 if ctx.fuel_version >= [8, 0] and auth_url.startswith("https://"):
79 logger.warning("Fixing FUEL 8.0 AUTH url - replace https://->http://")
80 auth_url = auth_url.replace("https", "http", 1)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020081
koder aka kdanilov7f59d562016-12-26 01:34:23 +020082 os_creds = OSCreds(name=cast(str, openrc['username']),
83 passwd=cast(str, openrc['password']),
84 tenant=cast(str, openrc['tenant_name']),
85 auth_url=cast(str, auth_url),
86 insecure=cast(bool, openrc['insecure']))
87
88 ctx.fuel_openstack_creds = os_creds
89 else:
90 ctx.fuel_openstack_creds = None
91
92 ctx.storage.put(list(ctx.fuel_openstack_creds), "fuel_os_creds")
koder aka kdanilov39e449e2016-12-17 15:15:26 +020093
kdanylov aka koder150b2192017-04-01 16:53:01 +030094 if metadata_only:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020095 logger.debug("Skip FUEL nodes discovery due to discovery settings")
96 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +020097
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020098 try:
99 fuel_rpc = setup_rpc(connect(fuel_node_info),
100 ctx.rpc_code,
101 ctx.default_rpc_plugins,
102 log_level=ctx.config.rpc_log_level)
103 except AuthenticationException:
104 msg = "FUEL nodes discovery failed - wrong FUEL master SSH credentials"
kdanylov aka koder150b2192017-04-01 16:53:01 +0300105 if ignore_errors:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200106 raise StopTestError(msg)
107 logger.warning(msg)
108 return
109 except Exception as exc:
kdanylov aka koder150b2192017-04-01 16:53:01 +0300110 if ignore_errors:
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200111 logger.exception("While connection to FUEL")
112 raise StopTestError("Failed to connect to FUEL")
113 logger.warning("Failed to connect to FUEL - %s", exc)
114 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200115
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200116 logger.debug("Downloading FUEL node ssh master key")
117 fuel_key = fuel_rpc.get_file_content('/root/.ssh/id_rsa')
118 network = 'fuelweb_admin' if ctx.fuel_version >= [6, 0] else 'admin'
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200119
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200120 count = 0
121 for count, fuel_node in enumerate(list(cluster.get_nodes())):
122 ip = str(fuel_node.get_ip(network))
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +0200123 ctx.merge_node(ConnCreds(to_ip(ip), "root", key=fuel_key), set(fuel_node.get_roles()))
koder aka kdanilov39e449e2016-12-17 15:15:26 +0200124
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200125 logger.debug("Found {} FUEL nodes for env {}".format(count, fuel.openstack_env))