From d6fa2e23015c405775c89c2f1bd55d10c0d8a710 Mon Sep 17 00:00:00 2001 From: Michael Fritch Date: Tue, 21 Jul 2020 15:06:19 -0600 Subject: [PATCH] mgr/cephadm: add `orch host ok-to-stop` command $ ceph orch host ok-to-stop host1 It is presumed safe to stop host host1 Signed-off-by: Michael Fritch --- src/pybind/mgr/cephadm/module.py | 23 +++++++++++++++++++++++ src/pybind/mgr/orchestrator/_interface.py | 8 ++++++++ src/pybind/mgr/orchestrator/module.py | 10 ++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/pybind/mgr/cephadm/module.py b/src/pybind/mgr/cephadm/module.py index e025a2091866a..d6ade94fac4cb 100644 --- a/src/pybind/mgr/cephadm/module.py +++ b/src/pybind/mgr/cephadm/module.py @@ -1143,6 +1143,29 @@ you may want to run: self.log.info('Removed label %s to host %s' % (label, host)) return 'Removed label %s from host %s' % (label, host) + @trivial_completion + def host_ok_to_stop(self, hostname: str): + if hostname not in self.cache.get_hosts(): + raise OrchestratorError(f'Cannot find host "{hostname}"') + + daemons = self.cache.get_daemons() + daemon_map = defaultdict(lambda: []) + for dd in daemons: + if dd.hostname == hostname: + daemon_map[dd.daemon_type].append(dd.daemon_id) + + for daemon_type,daemon_ids in daemon_map.items(): + r = self.cephadm_services[daemon_type].ok_to_stop(daemon_ids) + if r.retval: + self.log.error(f'It is NOT safe to stop host {hostname}') + raise orchestrator.OrchestratorError( + r.stderr, + errno=r.retval) + + msg = f'It is presumed safe to stop host {hostname}' + self.log.info(msg) + return msg + def update_osdspec_previews(self, search_host: str = ''): # Set global 'pending' flag for host self.cache.loading_osdspec_preview.add(search_host) diff --git a/src/pybind/mgr/orchestrator/_interface.py b/src/pybind/mgr/orchestrator/_interface.py index f40157c4acb14..2bbf89b02a09d 100644 --- a/src/pybind/mgr/orchestrator/_interface.py +++ b/src/pybind/mgr/orchestrator/_interface.py @@ -845,6 +845,14 @@ class Orchestrator(object): """ raise NotImplementedError() + def host_ok_to_stop(self, hostname:str) -> Completion: + """ + Check if the specified host can be safely stopped without reducing availability + + :param host: hostname + """ + raise NotImplementedError() + def get_inventory(self, host_filter=None, refresh=False): # type: (Optional[InventoryFilter], bool) -> Completion """ diff --git a/src/pybind/mgr/orchestrator/module.py b/src/pybind/mgr/orchestrator/module.py index d4abda8e5dd2f..aae20f7e8f39b 100644 --- a/src/pybind/mgr/orchestrator/module.py +++ b/src/pybind/mgr/orchestrator/module.py @@ -348,6 +348,16 @@ class OrchestratorCli(OrchestratorClientMixin, MgrModule, raise_if_exception(completion) return HandleCommandResult(stdout=completion.result_str()) + @_cli_write_command( + 'orch host ok-to-stop', + 'name=hostname,type=CephString', + desc='Check if the specified host can be safely stopped without reducing availability') + def _host_ok_to_stop(self, hostname: str): + completion = self.host_ok_to_stop(hostname) + self._orchestrator_wait([completion]) + raise_if_exception(completion) + return HandleCommandResult(stdout=completion.result_str()) + @_cli_read_command( 'orch device ls', "name=hostname,type=CephString,n=N,req=false " -- 2.39.5