]> git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/orchestrator.py
a01db2574e853e4fa4181441dea3a7c0e5e83a70
[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
70 class InventoryManager(ResourceManager):
71 @wait_api_result
72 def list(self, hosts=None, refresh=False):
73 host_filter = InventoryFilter(hosts=hosts) if hosts else None
74 return self.api.get_inventory(host_filter=host_filter, refresh=refresh)
75
76
77 class ServiceManager(ResourceManager):
78 @wait_api_result
79 def list(self, service_name: Optional[str] = None) -> List[ServiceDescription]:
80 return self.api.describe_service(None, service_name)
81
82 @wait_api_result
83 def get(self, service_name: str) -> ServiceDescription:
84 return self.api.describe_service(None, service_name)
85
86 @wait_api_result
87 def list_daemons(self,
88 service_name: Optional[str] = None,
89 hostname: Optional[str] = None) -> List[DaemonDescription]:
90 return self.api.list_daemons(service_name, host=hostname)
91
92 def reload(self, service_type, service_ids):
93 if not isinstance(service_ids, list):
94 service_ids = [service_ids]
95
96 completion_list = [
97 self.api.service_action('reload', service_type, service_name,
98 service_id)
99 for service_name, service_id in service_ids
100 ]
101 self.api.orchestrator_wait(completion_list)
102 for c in completion_list:
103 raise_if_exception(c)
104
105
106 class OsdManager(ResourceManager):
107 @wait_api_result
108 def create(self, drive_group_specs):
109 return self.api.apply_drivegroups(drive_group_specs)
110
111 @wait_api_result
112 def remove(self, osd_ids):
113 return self.api.remove_osds(osd_ids)
114
115 @wait_api_result
116 def removing_status(self):
117 return self.api.remove_osds_status()
118
119
120 class OrchClient(object):
121
122 _instance = None
123
124 @classmethod
125 def instance(cls):
126 if cls._instance is None:
127 cls._instance = cls()
128 return cls._instance
129
130 def __init__(self):
131 self.api = OrchestratorAPI()
132
133 self.hosts = HostManger(self.api)
134 self.inventory = InventoryManager(self.api)
135 self.services = ServiceManager(self.api)
136 self.osds = OsdManager(self.api)
137
138 def available(self):
139 return self.status()['available']
140
141 def status(self):
142 return self.api.status()
143
144 @wait_api_result
145 def blink_device_light(self, hostname, device, ident_fault, on):
146 # type: (str, str, str, bool) -> Completion
147 return self.api.blink_device_light(
148 ident_fault, on, [DeviceLightLoc(hostname, device, device)])