]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Add ErasureCodeProfile controller
authorSebastian Wagner <sebastian.wagner@suse.com>
Wed, 14 Mar 2018 14:51:10 +0000 (15:51 +0100)
committerSebastian Wagner <sebastian.wagner@suse.com>
Fri, 6 Apr 2018 15:40:03 +0000 (17:40 +0200)
Signed-off-by: Sebastian Wagner <sebastian.wagner@suse.com>
qa/tasks/mgr/dashboard/test_erasure_code_profile.py [new file with mode: 0644]
src/pybind/mgr/dashboard/controllers/erasure_code_profile.py [new file with mode: 0644]

diff --git a/qa/tasks/mgr/dashboard/test_erasure_code_profile.py b/qa/tasks/mgr/dashboard/test_erasure_code_profile.py
new file mode 100644 (file)
index 0000000..9cd0e78
--- /dev/null
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+
+from __future__ import absolute_import
+
+import unittest
+
+from .helper import DashboardTestCase, authenticate
+
+
+class ECPTest(DashboardTestCase):
+
+
+    @classmethod
+    def tearDownClass(cls):
+        super(ECPTest, cls).tearDownClass()
+        cls._ceph_cmd(['osd', 'erasure-code-profile', 'rm', 'ecp32'])
+        cls._ceph_cmd(['osd', 'erasure-code-profile', 'rm', 'lrc'])
+
+    @authenticate
+    def test_list(self):
+        data = self._get('/api/erasure_code_profile')
+        self.assertStatus(200)
+
+        default = [p for p in data if p['name'] == 'default']
+        if default:
+            default_ecp = {
+                'k': 2,
+                'technique': "reed_sol_van",
+                'm': 1,
+                'name': "default",
+                'plugin': "jerasure"
+            }
+            if 'crush-failure-domain' in default[0]:
+                default_ecp['crush-failure-domain'] = default[0]['crush-failure-domain']
+            self.assertEqual(default[0], default_ecp)
+            get_data = self._get('/api/erasure_code_profile/default')
+            self.assertEqual(get_data, default[0])
+
+
+    @authenticate
+    def test_create(self):
+        data = {'name': 'ecp32', 'k': 3, 'm': 2}
+        self._post('/api/erasure_code_profile', data)
+        self.assertStatus(201)
+
+        self._get('/api/erasure_code_profile/ecp32')
+        self.assertJsonBody({
+            "crush-device-class": "",
+            "crush-failure-domain": "osd",
+            "crush-root": "default",
+            "jerasure-per-chunk-alignment": "false",
+            "k": 3,
+            "m": 2,
+            "name": "ecp32",
+            "plugin": "jerasure",
+            "technique": "reed_sol_van",
+            "w": "8"
+        })
+
+        self.assertStatus(200)
+
+        self._delete('/api/erasure_code_profile/ecp32')
+        self.assertStatus(204)
+
+    @authenticate
+    def test_create_plugin(self):
+        data = {'name': 'lrc', 'k': '2', 'm': '2', 'l': '2', 'plugin': 'lrc'}
+        self._post('/api/erasure_code_profile', data)
+        self.assertJsonBody(None)
+        self.assertStatus(201)
+
+        self._get('/api/erasure_code_profile/lrc')
+        self.assertJsonBody({
+            "crush-device-class": "",
+            "crush-failure-domain": "host",
+            "crush-root": "default",
+            "k": 2,
+            "l": "2",
+            "m": 2,
+            "name": "lrc",
+            "plugin": "lrc"
+        })
+
+        self.assertStatus(200)
+
+        self._delete('/api/erasure_code_profile/lrc')
+        self.assertStatus(204)
+
diff --git a/src/pybind/mgr/dashboard/controllers/erasure_code_profile.py b/src/pybind/mgr/dashboard/controllers/erasure_code_profile.py
new file mode 100644 (file)
index 0000000..a6602eb
--- /dev/null
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
+from cherrypy import NotFound
+
+from . import ApiController, AuthRequired, RESTController
+from ..services.ceph_service import CephService
+from .. import mgr
+
+
+def _serialize_ecp(name, ecp):
+    ecp['name'] = name
+    ecp['k'] = int(ecp['k'])
+    ecp['m'] = int(ecp['m'])
+    return ecp
+
+
+@ApiController('erasure_code_profile')
+@AuthRequired()
+class ErasureCodeProfile(RESTController):
+    """
+    create() supports additional key-value arguments that are passed to the
+    ECP plugin.
+    """
+
+    def list(self):
+        ret = []
+        for name, ecp in mgr.get('osd_map').get('erasure_code_profiles', {}).items():
+            ret.append(_serialize_ecp(name, ecp))
+        return ret
+
+    def get(self, name):
+        try:
+            ecp = mgr.get('osd_map')['erasure_code_profiles'][name]
+            return _serialize_ecp(name, ecp)
+        except KeyError:
+            raise NotFound('No such erasure code profile')
+
+    # pylint: disable=too-many-arguments
+    @RESTController.args_from_json
+    def create(self, name, k, m, plugin=None, ruleset_failure_domain=None, **kwargs):
+        kwargs['k'] = k
+        kwargs['m'] = m
+        if plugin:
+            kwargs['plugin'] = plugin
+        if ruleset_failure_domain:
+            kwargs['ruleset_failure_domain'] = ruleset_failure_domain
+
+        profile = ['{}={}'.format(key, value) for key, value in kwargs.items()]
+        CephService.send_command('mon', 'osd erasure-code-profile set', name=name,
+                                 profile=profile)
+
+    def delete(self, name):
+        CephService.send_command('mon', 'osd erasure-code-profile rm', name=name)