]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/pybind/mgr/dashboard/controllers/orchestrator.py
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / pybind / mgr / dashboard / controllers / orchestrator.py
index a7fda9f85081c7706c2c77143f7320e11d6a30fc..085870a0f4aac7bbbda82e87dc3d71e6c530bf18 100644 (file)
 # -*- coding: utf-8 -*-
 from __future__ import absolute_import
-import os.path
 
-import time
+from functools import wraps
 
-from . import ApiController, Endpoint, ReadPermission, UpdatePermission
-from . import RESTController, Task
-from .. import mgr
 from ..exceptions import DashboardException
-from ..security import Scope
-from ..services.exception import handle_orchestrator_error
 from ..services.orchestrator import OrchClient
-from ..tools import TaskManager, wraps
-
-
-def get_device_osd_map():
-    """Get mappings from inventory devices to OSD IDs.
-
-    :return: Returns a dictionary containing mappings. Note one device might
-        shared between multiple OSDs.
-        e.g. {
-                 'node1': {
-                     'nvme0n1': [0, 1],
-                     'vdc': [0],
-                     'vdb': [1]
-                 },
-                 'node2': {
-                     'vdc': [2]
-                 }
-             }
-    :rtype: dict
-    """
-    result: dict = {}
-    for osd_id, osd_metadata in mgr.get('osd_metadata').items():
-        hostname = osd_metadata.get('hostname')
-        devices = osd_metadata.get('devices')
-        if not hostname or not devices:
-            continue
-        if hostname not in result:
-            result[hostname] = {}
-        # for OSD contains multiple devices, devices is in `sda,sdb`
-        for device in devices.split(','):
-            if device not in result[hostname]:
-                result[hostname][device] = [int(osd_id)]
-            else:
-                result[hostname][device].append(int(osd_id))
-    return result
-
-
-def orchestrator_task(name, metadata, wait_for=2.0):
-    return Task("orchestrator/{}".format(name), metadata, wait_for)
-
-
-def raise_if_no_orchestrator(method):
-    @wraps(method)
-    def inner(self, *args, **kwargs):
-        orch = OrchClient.instance()
-        if not orch.available():
-            raise DashboardException(code='orchestrator_status_unavailable',  # pragma: no cover
-                                     msg='Orchestrator is unavailable',
-                                     component='orchestrator',
-                                     http_status_code=503)
-        return method(self, *args, **kwargs)
+from . import ApiController, ControllerDoc, Endpoint, EndpointDoc, ReadPermission, RESTController
+
+STATUS_SCHEMA = {
+    "available": (bool, "Orchestrator status"),
+    "message": (str, "Error message")
+}
+
+
+def raise_if_no_orchestrator(features=None):
+    def inner(method):
+        @wraps(method)
+        def _inner(self, *args, **kwargs):
+            orch = OrchClient.instance()
+            if not orch.available():
+                raise DashboardException(code='orchestrator_status_unavailable',  # pragma: no cover
+                                         msg='Orchestrator is unavailable',
+                                         component='orchestrator',
+                                         http_status_code=503)
+            if features is not None:
+                missing = orch.get_missing_features(features)
+                if missing:
+                    msg = 'Orchestrator feature(s) are unavailable: {}'.format(', '.join(missing))
+                    raise DashboardException(code='orchestrator_features_unavailable',
+                                             msg=msg,
+                                             component='orchestrator',
+                                             http_status_code=503)
+            return method(self, *args, **kwargs)
+        return _inner
     return inner
 
 
 @ApiController('/orchestrator')
+@ControllerDoc("Orchestrator Management API", "Orchestrator")
 class Orchestrator(RESTController):
 
     @Endpoint()
     @ReadPermission
+    @EndpointDoc("Display Orchestrator Status",
+                 responses={200: STATUS_SCHEMA})
     def status(self):
         return OrchClient.instance().status()
-
-    @Endpoint(method='POST')
-    @UpdatePermission
-    @raise_if_no_orchestrator
-    @handle_orchestrator_error('osd')
-    @orchestrator_task('identify_device', ['{hostname}', '{device}'])
-    def identify_device(self, hostname, device, duration):  # pragma: no cover
-        # type: (str, str, int) -> None
-        """
-        Identify a device by switching on the device light for N seconds.
-        :param hostname: The hostname of the device to process.
-        :param device: The device identifier to process, e.g. ``/dev/dm-0`` or
-          ``ABC1234DEF567-1R1234_ABC8DE0Q``.
-        :param duration: The duration in seconds how long the LED should flash.
-        """
-        orch = OrchClient.instance()
-        TaskManager.current_task().set_progress(0)
-        orch.blink_device_light(hostname, device, 'ident', True)
-        for i in range(int(duration)):
-            percentage = int(round(i / float(duration) * 100))
-            TaskManager.current_task().set_progress(percentage)
-            time.sleep(1)
-        orch.blink_device_light(hostname, device, 'ident', False)
-        TaskManager.current_task().set_progress(100)
-
-
-@ApiController('/orchestrator/inventory', Scope.HOSTS)
-class OrchestratorInventory(RESTController):
-
-    @raise_if_no_orchestrator
-    def list(self, hostname=None):
-        orch = OrchClient.instance()
-        hosts = [hostname] if hostname else None
-        inventory_hosts = [host.to_json() for host in orch.inventory.list(hosts)]
-        device_osd_map = get_device_osd_map()
-        for inventory_host in inventory_hosts:
-            host_osds = device_osd_map.get(inventory_host['name'])
-            for device in inventory_host['devices']:
-                if host_osds:  # pragma: no cover
-                    dev_name = os.path.basename(device['path'])
-                    device['osd_ids'] = sorted(host_osds.get(dev_name, []))
-                else:
-                    device['osd_ids'] = []
-        return inventory_hosts