]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/dashboard/services/orchestrator.py
6829108e098d54315d9ba39eba891a6fcf12337c
1 # -*- coding: utf-8 -*-
4 from functools
import wraps
5 from typing
import Any
, Dict
, List
, Optional
7 from ceph
.deployment
.service_spec
import ServiceSpec
8 from orchestrator
import DaemonDescription
, DeviceLightLoc
, HostSpec
, \
9 InventoryFilter
, OrchestratorClientMixin
, OrchestratorError
, OrchResult
, \
10 ServiceDescription
, raise_if_exception
14 logger
= logging
.getLogger('orchestrator')
17 # pylint: disable=abstract-method
18 class OrchestratorAPI(OrchestratorClientMixin
):
20 super(OrchestratorAPI
, self
).__init
__()
21 self
.set_mgr(mgr
) # type: ignore
25 status
, message
, _module_details
= super().available()
26 logger
.info("is orchestrator available: %s, %s", status
, message
)
27 return dict(available
=status
, message
=message
)
28 except (RuntimeError, OrchestratorError
, ImportError) as e
:
31 message
='Orchestrator is unavailable: {}'.format(str(e
)))
34 def wait_api_result(method
):
36 def inner(self
, *args
, **kwargs
):
37 completion
= method(self
, *args
, **kwargs
)
38 raise_if_exception(completion
)
39 return completion
.result
43 class ResourceManager(object):
44 def __init__(self
, api
):
48 class HostManger(ResourceManager
):
50 def list(self
) -> List
[HostSpec
]:
51 return self
.api
.get_hosts()
54 def enter_maintenance(self
, hostname
: str, force
: bool = False):
55 return self
.api
.enter_host_maintenance(hostname
, force
)
58 def exit_maintenance(self
, hostname
: str):
59 return self
.api
.exit_host_maintenance(hostname
)
61 def get(self
, hostname
: str) -> Optional
[HostSpec
]:
62 hosts
= [host
for host
in self
.list() if host
.hostname
== hostname
]
63 return hosts
[0] if hosts
else None
66 def add(self
, hostname
: str, addr
: str, labels
: List
[str]):
67 return self
.api
.add_host(HostSpec(hostname
, addr
=addr
, labels
=labels
))
70 def get_facts(self
, hostname
: Optional
[str] = None) -> List
[Dict
[str, Any
]]:
71 return self
.api
.get_facts(hostname
)
74 def remove(self
, hostname
: str):
75 return self
.api
.remove_host(hostname
)
78 def add_label(self
, host
: str, label
: str) -> OrchResult
[str]:
79 return self
.api
.add_host_label(host
, label
)
82 def remove_label(self
, host
: str, label
: str) -> OrchResult
[str]:
83 return self
.api
.remove_host_label(host
, label
)
86 def drain(self
, hostname
: str):
87 return self
.api
.drain_host(hostname
)
90 class InventoryManager(ResourceManager
):
92 def list(self
, hosts
=None, refresh
=False):
93 host_filter
= InventoryFilter(hosts
=hosts
) if hosts
else None
94 return self
.api
.get_inventory(host_filter
=host_filter
, refresh
=refresh
)
97 class ServiceManager(ResourceManager
):
100 service_type
: Optional
[str] = None,
101 service_name
: Optional
[str] = None) -> List
[ServiceDescription
]:
102 return self
.api
.describe_service(service_type
, service_name
)
105 def get(self
, service_name
: str) -> ServiceDescription
:
106 return self
.api
.describe_service(None, service_name
)
109 def list_daemons(self
,
110 service_name
: Optional
[str] = None,
111 daemon_type
: Optional
[str] = None,
112 hostname
: Optional
[str] = None) -> List
[DaemonDescription
]:
113 return self
.api
.list_daemons(service_name
=service_name
,
114 daemon_type
=daemon_type
,
117 def reload(self
, service_type
, service_ids
):
118 if not isinstance(service_ids
, list):
119 service_ids
= [service_ids
]
122 self
.api
.service_action('reload', service_type
, service_name
,
124 for service_name
, service_id
in service_ids
126 self
.api
.orchestrator_wait(completion_list
)
127 for c
in completion_list
:
128 raise_if_exception(c
)
133 no_overwrite
: Optional
[bool] = False) -> OrchResult
[List
[str]]:
134 spec
= ServiceSpec
.from_json(service_spec
)
135 return self
.api
.apply([spec
], no_overwrite
)
138 def remove(self
, service_name
: str) -> List
[str]:
139 return self
.api
.remove_service(service_name
)
142 class OsdManager(ResourceManager
):
144 def create(self
, drive_group_specs
):
145 return self
.api
.apply_drivegroups(drive_group_specs
)
148 def remove(self
, osd_ids
, replace
=False, force
=False):
149 return self
.api
.remove_osds(osd_ids
, replace
, force
)
152 def removing_status(self
):
153 return self
.api
.remove_osds_status()
156 class DaemonManager(ResourceManager
):
158 def action(self
, daemon_name
='', action
='', image
=None):
159 return self
.api
.daemon_action(daemon_name
=daemon_name
, action
=action
, image
=image
)
162 class OrchClient(object):
168 # type: () -> OrchClient
169 if cls
._instance
is None:
170 cls
._instance
= cls()
174 self
.api
= OrchestratorAPI()
176 self
.hosts
= HostManger(self
.api
)
177 self
.inventory
= InventoryManager(self
.api
)
178 self
.services
= ServiceManager(self
.api
)
179 self
.osds
= OsdManager(self
.api
)
180 self
.daemons
= DaemonManager(self
.api
)
182 def available(self
, features
: Optional
[List
[str]] = None) -> bool:
183 available
= self
.status()['available']
184 if available
and features
is not None:
185 return not self
.get_missing_features(features
)
188 def status(self
) -> Dict
[str, Any
]:
189 status
= self
.api
.status()
190 status
['features'] = {}
191 if status
['available']:
192 status
['features'] = self
.api
.get_feature_set()
195 def get_missing_features(self
, features
: List
[str]) -> List
[str]:
196 supported_features
= {k
for k
, v
in self
.api
.get_feature_set().items() if v
['available']}
197 return list(set(features
) - supported_features
)
200 def blink_device_light(self
, hostname
, device
, ident_fault
, on
):
201 # type: (str, str, str, bool) -> OrchResult[List[str]]
202 return self
.api
.blink_device_light(
203 ident_fault
, on
, [DeviceLightLoc(hostname
, device
, device
)])
206 class OrchFeature(object):
207 HOST_LIST
= 'get_hosts'
208 HOST_ADD
= 'add_host'
209 HOST_REMOVE
= 'remove_host'
210 HOST_LABEL_ADD
= 'add_host_label'
211 HOST_LABEL_REMOVE
= 'remove_host_label'
212 HOST_MAINTENANCE_ENTER
= 'enter_host_maintenance'
213 HOST_MAINTENANCE_EXIT
= 'exit_host_maintenance'
214 HOST_DRAIN
= 'drain_host'
216 SERVICE_LIST
= 'describe_service'
217 SERVICE_CREATE
= 'apply'
218 SERVICE_EDIT
= 'apply'
219 SERVICE_DELETE
= 'remove_service'
220 SERVICE_RELOAD
= 'service_action'
221 DAEMON_LIST
= 'list_daemons'
223 OSD_GET_REMOVE_STATUS
= 'remove_osds_status'
225 OSD_CREATE
= 'apply_drivegroups'
226 OSD_DELETE
= 'remove_osds'
228 DEVICE_LIST
= 'get_inventory'
229 DEVICE_BLINK_LIGHT
= 'blink_device_light'
231 DAEMON_ACTION
= 'daemon_action'