]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/orchestrator.py
import 15.2.5
[ceph.git] / ceph / src / pybind / mgr / dashboard / services / orchestrator.py
1 # -*- coding: utf-8 -*-
2 from __future__ import absolute_import
3 import logging
4
5 from typing import List, Optional
6
7 from orchestrator import InventoryFilter, DeviceLightLoc, Completion
8 from orchestrator import ServiceDescription, DaemonDescription
9 from orchestrator import OrchestratorClientMixin, raise_if_exception, OrchestratorError
10 from orchestrator import HostSpec
11 from .. import mgr
12 from ..tools import wraps
13
14 logger = logging.getLogger('orchestrator')
15
16
17 # pylint: disable=abstract-method
18 class OrchestratorAPI(OrchestratorClientMixin):
19 def __init__(self):
20 super(OrchestratorAPI, self).__init__()
21 self.set_mgr(mgr) # type: ignore
22
23 def status(self):
24 try:
25 status, desc = super(OrchestratorAPI, self).available()
26 logger.info("is orchestrator available: %s, %s", status, desc)
27 return dict(available=status, description=desc)
28 except (RuntimeError, OrchestratorError, ImportError):
29 return dict(
30 available=False,
31 description='Orchestrator is unavailable for unknown reason')
32
33 def orchestrator_wait(self, completions):
34 return self._orchestrator_wait(completions)
35
36
37 def wait_api_result(method):
38 @wraps(method)
39 def inner(self, *args, **kwargs):
40 completion = method(self, *args, **kwargs)
41 self.api.orchestrator_wait([completion])
42 raise_if_exception(completion)
43 return completion.result
44 return inner
45
46
47 class ResourceManager(object):
48 def __init__(self, api):
49 self.api = api
50
51
52 class HostManger(ResourceManager):
53 @wait_api_result
54 def list(self) -> List[HostSpec]:
55 return self.api.get_hosts()
56
57 def get(self, hostname: str) -> Optional[HostSpec]:
58 hosts = [host for host in self.list() if host.hostname == hostname]
59 return hosts[0] if hosts else None
60
61 @wait_api_result
62 def add(self, hostname: str):
63 return self.api.add_host(HostSpec(hostname))
64
65 @wait_api_result
66 def remove(self, hostname: str):
67 return self.api.remove_host(hostname)
68
69 @wait_api_result
70 def add_label(self, host: str, label: str) -> Completion:
71 return self.api.add_host_label(host, label)
72
73 @wait_api_result
74 def remove_label(self, host: str, label: str) -> Completion:
75 return self.api.remove_host_label(host, label)
76
77
78 class InventoryManager(ResourceManager):
79 @wait_api_result
80 def list(self, hosts=None, refresh=False):
81 host_filter = InventoryFilter(hosts=hosts) if hosts else None
82 return self.api.get_inventory(host_filter=host_filter, refresh=refresh)
83
84
85 class ServiceManager(ResourceManager):
86 @wait_api_result
87 def list(self, service_name: Optional[str] = None) -> List[ServiceDescription]:
88 return self.api.describe_service(None, service_name)
89
90 @wait_api_result
91 def get(self, service_name: str) -> ServiceDescription:
92 return self.api.describe_service(None, service_name)
93
94 @wait_api_result
95 def list_daemons(self,
96 service_name: Optional[str] = None,
97 hostname: Optional[str] = None) -> List[DaemonDescription]:
98 return self.api.list_daemons(service_name, host=hostname)
99
100 def reload(self, service_type, service_ids):
101 if not isinstance(service_ids, list):
102 service_ids = [service_ids]
103
104 completion_list = [
105 self.api.service_action('reload', service_type, service_name,
106 service_id)
107 for service_name, service_id in service_ids
108 ]
109 self.api.orchestrator_wait(completion_list)
110 for c in completion_list:
111 raise_if_exception(c)
112
113
114 class OsdManager(ResourceManager):
115 @wait_api_result
116 def create(self, drive_group_specs):
117 return self.api.apply_drivegroups(drive_group_specs)
118
119 @wait_api_result
120 def remove(self, osd_ids, replace=False, force=False):
121 return self.api.remove_osds(osd_ids, replace, force)
122
123 @wait_api_result
124 def removing_status(self):
125 return self.api.remove_osds_status()
126
127
128 class OrchClient(object):
129
130 _instance = None
131
132 @classmethod
133 def instance(cls):
134 if cls._instance is None:
135 cls._instance = cls()
136 return cls._instance
137
138 def __init__(self):
139 self.api = OrchestratorAPI()
140
141 self.hosts = HostManger(self.api)
142 self.inventory = InventoryManager(self.api)
143 self.services = ServiceManager(self.api)
144 self.osds = OsdManager(self.api)
145
146 def available(self):
147 return self.status()['available']
148
149 def status(self):
150 return self.api.status()
151
152 @wait_api_result
153 def blink_device_light(self, hostname, device, ident_fault, on):
154 # type: (str, str, str, bool) -> Completion
155 return self.api.blink_device_light(
156 ident_fault, on, [DeviceLightLoc(hostname, device, device)])