| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 1 | import logging | 
|  | 2 | from typing import Dict, List, NamedTuple, Union, cast | 
|  | 3 |  | 
|  | 4 | from paramiko.ssh_exception import AuthenticationException | 
|  | 5 |  | 
|  | 6 | from .fuel_rest_api import get_cluster_id, reflect_cluster, FuelInfo, KeystoneAuth | 
| koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 7 | from .ssh_utils import ConnCreds | 
|  | 8 | from .utils import StopTestError, parse_creds, to_ip | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 9 | from .stage import Stage, StepOrder | 
|  | 10 | from .test_run_class import TestRun | 
|  | 11 | from .node import connect, setup_rpc | 
|  | 12 | from .config import ConfigBlock | 
|  | 13 | from .openstack_api import OSCreds | 
|  | 14 |  | 
|  | 15 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 16 | logger = logging.getLogger("wally") | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 17 |  | 
|  | 18 |  | 
|  | 19 | FuelNodeInfo = NamedTuple("FuelNodeInfo", | 
|  | 20 | [("version", List[int]), | 
|  | 21 | ("fuel_ext_iface", str), | 
|  | 22 | ("openrc", Dict[str, Union[str, bool]])]) | 
|  | 23 |  | 
|  | 24 |  | 
|  | 25 |  | 
|  | 26 | class DiscoverFuelStage(Stage): | 
|  | 27 | """"Fuel nodes discovery, also can get openstack openrc""" | 
|  | 28 |  | 
|  | 29 | priority = StepOrder.DISCOVER | 
|  | 30 | config_block = 'fuel' | 
|  | 31 |  | 
|  | 32 | @classmethod | 
|  | 33 | def validate(cls, cfg: ConfigBlock) -> None: | 
|  | 34 | # msg = "openstack_env should be provided in fuel config" | 
|  | 35 | # check_input_param('openstack_env' in fuel_data, msg) | 
|  | 36 | # fuel.openstack_env | 
|  | 37 | pass | 
|  | 38 |  | 
|  | 39 | def run(self, ctx: TestRun) -> None: | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 40 | discovery = ctx.config.get("discovery") | 
|  | 41 | if discovery == 'disable': | 
|  | 42 | logger.info("Skip FUEL discovery due to config setting") | 
|  | 43 | return | 
|  | 44 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame^] | 45 | if "fuel_os_creds" in ctx.storage and 'fuel_version' in ctx.storage: | 
|  | 46 | logger.debug("Skip FUEL credentials discovery, use previously discovered info") | 
|  | 47 | ctx.fuel_openstack_creds = OSCreds(*cast(List, ctx.storage.get('fuel_os_creds'))) | 
|  | 48 | ctx.fuel_version = ctx.storage.get('fuel_version') | 
|  | 49 | if 'all_nodes' in ctx.storage: | 
|  | 50 | logger.debug("Skip FUEL nodes discovery, use data from DB") | 
|  | 51 | return | 
|  | 52 | elif discovery == 'metadata': | 
|  | 53 | logger.debug("Skip FUEL nodes  discovery due to discovery settings") | 
|  | 54 | return | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 55 |  | 
|  | 56 | fuel = ctx.config.fuel | 
|  | 57 | fuel_node_info = ctx.merge_node(fuel.ssh_creds, {'fuel_master'}) | 
|  | 58 | creds = dict(zip(("user", "passwd", "tenant"), parse_creds(fuel.creds))) | 
|  | 59 | fuel_conn = KeystoneAuth(fuel.url, creds) | 
|  | 60 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 61 | cluster_id = get_cluster_id(fuel_conn, fuel.openstack_env) | 
|  | 62 | cluster = reflect_cluster(fuel_conn, cluster_id) | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 63 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame^] | 64 | if ctx.fuel_version is None: | 
|  | 65 | ctx.fuel_version = FuelInfo(fuel_conn).get_version() | 
|  | 66 | ctx.storage.put(ctx.fuel_version, "fuel_version") | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 67 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame^] | 68 | logger.info("Found FUEL {0}".format(".".join(map(str, ctx.fuel_version)))) | 
|  | 69 | openrc = cluster.get_openrc() | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 70 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame^] | 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) | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 76 |  | 
| koder aka kdanilov | 7f59d56 | 2016-12-26 01:34:23 +0200 | [diff] [blame^] | 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 | 
|  | 84 | else: | 
|  | 85 | ctx.fuel_openstack_creds = None | 
|  | 86 |  | 
|  | 87 | ctx.storage.put(list(ctx.fuel_openstack_creds), "fuel_os_creds") | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 88 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 89 | if discovery == 'metadata': | 
|  | 90 | logger.debug("Skip FUEL nodes  discovery due to discovery settings") | 
|  | 91 | return | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 92 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 93 | try: | 
|  | 94 | fuel_rpc = setup_rpc(connect(fuel_node_info), | 
|  | 95 | ctx.rpc_code, | 
|  | 96 | ctx.default_rpc_plugins, | 
|  | 97 | log_level=ctx.config.rpc_log_level) | 
|  | 98 | except AuthenticationException: | 
|  | 99 | msg = "FUEL nodes discovery failed - wrong FUEL master SSH credentials" | 
|  | 100 | if discovery != 'ignore_errors': | 
|  | 101 | raise StopTestError(msg) | 
|  | 102 | logger.warning(msg) | 
|  | 103 | return | 
|  | 104 | except Exception as exc: | 
|  | 105 | if discovery != 'ignore_errors': | 
|  | 106 | logger.exception("While connection to FUEL") | 
|  | 107 | raise StopTestError("Failed to connect to FUEL") | 
|  | 108 | logger.warning("Failed to connect to FUEL - %s", exc) | 
|  | 109 | return | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 110 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 111 | logger.debug("Downloading FUEL node ssh master key") | 
|  | 112 | fuel_key = fuel_rpc.get_file_content('/root/.ssh/id_rsa') | 
|  | 113 | network = 'fuelweb_admin' if ctx.fuel_version >= [6, 0] else 'admin' | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 114 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 115 | count = 0 | 
|  | 116 | for count, fuel_node in enumerate(list(cluster.get_nodes())): | 
|  | 117 | ip = str(fuel_node.get_ip(network)) | 
| koder aka kdanilov | bbbe1dc | 2016-12-20 01:19:56 +0200 | [diff] [blame] | 118 | ctx.merge_node(ConnCreds(to_ip(ip), "root", key=fuel_key), set(fuel_node.get_roles())) | 
| koder aka kdanilov | 39e449e | 2016-12-17 15:15:26 +0200 | [diff] [blame] | 119 |  | 
| koder aka kdanilov | 962ee5f | 2016-12-19 02:40:08 +0200 | [diff] [blame] | 120 | logger.debug("Found {} FUEL nodes for env {}".format(count, fuel.openstack_env)) |