blob: 9734baaef7efa744c998a6929f8635416e671a4c [file] [log] [blame]
koder aka kdanilov39e449e2016-12-17 15:15:26 +02001""" Collect data about ceph nodes"""
2import json
3import logging
koder aka kdanilov962ee5f2016-12-19 02:40:08 +02004from typing import Dict, cast, List, Set, Optional
koder aka kdanilov39e449e2016-12-17 15:15:26 +02005
6
7from .node_interfaces import NodeInfo, IRPCNode
8from .ssh_utils import ConnCreds
9from .common_types import IP
10from .stage import Stage, StepOrder
11from .test_run_class import TestRun
12from .ssh_utils import parse_ssh_uri
13from .node import connect, setup_rpc
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +020014from .utils import StopTestError, to_ip
koder aka kdanilov39e449e2016-12-17 15:15:26 +020015
16
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030017from cephlib import discover
18from cephlib.discover import OSDInfo
19
20
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020021logger = logging.getLogger("wally")
koder aka kdanilov39e449e2016-12-17 15:15:26 +020022
23
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030024def get_osds_info(node: IRPCNode, ceph_extra_args: str = "") -> Dict[IP, List[OSDInfo]]:
koder aka kdanilov39e449e2016-12-17 15:15:26 +020025 """Get set of osd's ip"""
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030026 res = {} # type: Dict[IP, List[OSDInfo]]
27 return {IP(ip): osd_info_list
28 for ip, osd_info_list in discover.get_osds_nodes(node.run, ceph_extra_args)}
koder aka kdanilov39e449e2016-12-17 15:15:26 +020029
30
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030031def get_mons_ips(node: IRPCNode, ceph_extra_args: str = "") -> Set[IP]:
koder aka kdanilov39e449e2016-12-17 15:15:26 +020032 """Return mon ip set"""
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030033 return {IP(ip) for ip in discover.get_mons_nodes(node.run, ceph_extra_args).values()}
koder aka kdanilov39e449e2016-12-17 15:15:26 +020034
35
36class DiscoverCephStage(Stage):
37 config_block = 'ceph'
38 priority = StepOrder.DISCOVER
39
40 def run(self, ctx: TestRun) -> None:
41 """Return list of ceph's nodes NodeInfo"""
42
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020043 discovery = ctx.config.get("discovery")
44 if discovery == 'disable' or discovery == 'metadata':
45 logger.info("Skip ceph discovery due to config setting")
46 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +020047
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020048 if 'all_nodes' in ctx.storage:
49 logger.debug("Skip ceph discovery, use previously discovered nodes")
50 return
koder aka kdanilov39e449e2016-12-17 15:15:26 +020051
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020052 ceph = ctx.config.ceph
53 root_node_uri = cast(str, ceph.root_node)
54 cluster = ceph.get("cluster", "ceph")
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030055
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020056 conf = ceph.get("conf")
57 key = ceph.get("key")
koder aka kdanilov39e449e2016-12-17 15:15:26 +020058
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020059 if conf is None:
60 conf = "/etc/ceph/{}.conf".format(cluster)
koder aka kdanilov39e449e2016-12-17 15:15:26 +020061
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020062 if key is None:
63 key = "/etc/ceph/{}.client.admin.keyring".format(cluster)
koder aka kdanilov39e449e2016-12-17 15:15:26 +020064
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030065 ceph_extra_args = ""
66
67 if conf:
68 ceph_extra_args += " -c '{}'".format(conf)
69
70 if key:
71 ceph_extra_args += " -k '{}'".format(key)
72
73 logger.debug("Start discovering ceph nodes from root %s", root_node_uri)
74 logger.debug("cluster=%s key=%s conf=%s", cluster, conf, key)
75
76 info = NodeInfo(parse_ssh_uri(root_node_uri), set())
77
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020078 ceph_params = {"cluster": cluster, "conf": conf, "key": key}
79
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030080 with setup_rpc(connect(info), ctx.rpc_code, ctx.default_rpc_plugins,
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020081 log_level=ctx.config.rpc_log_level) as node:
82
83 ssh_key = node.get_file_content("~/.ssh/id_rsa")
84
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020085 try:
86 ips = set()
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +030087 for ip, osds_info in get_osds_info(node, ceph_extra_args).items():
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020088 ips.add(ip)
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +020089 creds = ConnCreds(to_ip(cast(str, ip)), user="root", key=ssh_key)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +020090 info = ctx.merge_node(creds, {'ceph-osd'})
91 info.params.setdefault('ceph-osds', []).extend(osds_info)
92 assert 'ceph' not in info.params or info.params['ceph'] == ceph_params
93 info.params['ceph'] = ceph_params
94
95 logger.debug("Found %s nodes with ceph-osd role", len(ips))
96 except Exception as exc:
97 if discovery != 'ignore_errors':
98 logger.exception("OSD discovery failed")
99 raise StopTestError()
100 else:
101 logger.warning("OSD discovery failed %s", exc)
102
103 try:
104 counter = 0
kdanylov aka koder0e0cfcb2017-03-27 22:19:09 +0300105 for counter, ip in enumerate(get_mons_ips(node, ceph_extra_args)):
koder aka kdanilovbbbe1dc2016-12-20 01:19:56 +0200106 creds = ConnCreds(to_ip(cast(str, ip)), user="root", key=ssh_key)
koder aka kdanilov962ee5f2016-12-19 02:40:08 +0200107 info = ctx.merge_node(creds, {'ceph-mon'})
108 assert 'ceph' not in info.params or info.params['ceph'] == ceph_params
109 info.params['ceph'] = ceph_params
110 logger.debug("Found %s nodes with ceph-mon role", counter + 1)
111 except Exception as exc:
112 if discovery != 'ignore_errors':
113 logger.exception("MON discovery failed")
114 raise StopTestError()
115 else:
116 logger.warning("MON discovery failed %s", exc)