]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: new controller for RBD mirroring peer bootstrapping
authorJason Dillaman <dillaman@redhat.com>
Thu, 17 Oct 2019 19:10:21 +0000 (15:10 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 5 Dec 2019 14:32:42 +0000 (09:32 -0500)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
qa/tasks/mgr/dashboard/test_rbd_mirroring.py
src/pybind/mgr/dashboard/controllers/rbd_mirroring.py
src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py

index bb6e3d0be807411124c4cf6a6e0430e26c6eb3d3..598648f6a76f308ec95baad1cf7cd3d12a4341e8 100644 (file)
@@ -187,3 +187,19 @@ class RbdMirroringTest(DashboardTestCase):
         site_name = self._get('/api/block/mirroring/site_name')
         self.assertStatus(200)
         self.assertEqual(expected_site_name, site_name)
+
+    def test_bootstrap(self):
+        self.update_pool('rbd', 'image')
+        token_data = self._task_post('/api/block/mirroring/pool/rbd/bootstrap/token', {})
+        self.assertStatus(200)
+
+        import_data = {
+            'token': token_data['token'],
+            'direction': 'invalid'}
+        self._task_post('/api/block/mirroring/pool/rbd/bootstrap/peer', import_data)
+        self.assertStatus(400)
+
+        # cannot import "youself" as peer
+        import_data['direction'] = 'rx'
+        self._task_post('/api/block/mirroring/pool/rbd/bootstrap/peer', import_data)
+        self.assertStatus(400)
index 8d94b7090958af86848369b976b73209d9f97910..3cd9bb298b0ffde30e0e605d1f94d73f5087fff6 100644 (file)
@@ -396,6 +396,37 @@ class RbdMirroringPoolMode(RESTController):
         return _rbd_call(pool_name, None, _edit, mirror_mode)
 
 
+@ApiController('/block/mirroring/pool/{pool_name}/bootstrap',
+               Scope.RBD_MIRRORING)
+class RbdMirroringPoolBootstrap(BaseController):
+
+    @Endpoint(method='POST', path='token')
+    @handle_rbd_mirror_error()
+    @UpdatePermission
+    def create_token(self, pool_name):
+        ioctx = mgr.rados.open_ioctx(pool_name)
+        token = rbd.RBD().mirror_peer_bootstrap_create(ioctx)
+        return {'token': token}
+
+    @Endpoint(method='POST', path='peer')
+    @handle_rbd_mirror_error()
+    @UpdatePermission
+    def import_token(self, pool_name, direction, token):
+        ioctx = mgr.rados.open_ioctx(pool_name)
+
+        directions = {
+            'rx': rbd.RBD_MIRROR_PEER_DIRECTION_RX,
+            'rx-tx': rbd.RBD_MIRROR_PEER_DIRECTION_RX_TX
+        }
+
+        direction_enum = directions.get(direction)
+        if direction_enum is None:
+            raise rbd.Error('invalid direction "{}"'.format(direction))
+
+        rbd.RBD().mirror_peer_bootstrap_import(ioctx, direction_enum, token)
+        return {}
+
+
 @ApiController('/block/mirroring/pool/{pool_name}/peer', Scope.RBD_MIRRORING)
 class RbdMirroringPoolPeer(RESTController):
 
index 39f70594308b1510f66a32b5c1241ac94dd77c95..9a0142b4b2c38274d361a7e47a58bc230054fc8b 100644 (file)
@@ -9,7 +9,8 @@ except ImportError:
 from . import ControllerTestCase
 from .. import mgr
 from ..controllers.summary import Summary
-from ..controllers.rbd_mirroring import RbdMirroring, RbdMirroringSummary
+from ..controllers.rbd_mirroring import RbdMirroring, RbdMirroringSummary, \
+    RbdMirroringPoolBootstrap
 from ..services import progress
 
 
@@ -78,6 +79,50 @@ class RbdMirroringControllerTest(ControllerTestCase):
             mock.ANY, result['site_name'])
 
 
+class RbdMirroringPoolBootstrapControllerTest(ControllerTestCase):
+
+    @classmethod
+    def setup_server(cls):
+        # pylint: disable=protected-access
+        RbdMirroringPoolBootstrap._cp_config['tools.authenticate.on'] = False
+        # pylint: enable=protected-access
+
+        cls.setup_controllers([RbdMirroringPoolBootstrap])
+
+    @mock.patch('dashboard.controllers.rbd_mirroring.rbd.RBD')
+    def test_token(self, mock_rbd):
+        mock_rbd_instance = mock_rbd.return_value
+        mock_rbd_instance.mirror_peer_bootstrap_create.return_value = "1234"
+
+        self._post('/api/block/mirroring/pool/abc/bootstrap/token')
+        self.assertStatus(200)
+        self.assertJsonBody({"token": "1234"})
+        mgr.rados.open_ioctx.assert_called_with("abc")
+
+        mock_rbd_instance.mirror_peer_bootstrap_create.assert_called()
+
+    @mock.patch('dashboard.controllers.rbd_mirroring.rbd')
+    def test_peer(self, mock_rbd_module):
+        mock_rbd_instance = mock_rbd_module.RBD.return_value
+
+        values = {
+            "direction": "invalid",
+            "token": "1234"
+        }
+        self._post('/api/block/mirroring/pool/abc/bootstrap/peer', values)
+        self.assertStatus(500)
+        mgr.rados.open_ioctx.assert_called_with("abc")
+
+        values["direction"] = "rx"
+        self._post('/api/block/mirroring/pool/abc/bootstrap/peer', values)
+        self.assertStatus(200)
+        self.assertJsonBody({})
+        mgr.rados.open_ioctx.assert_called_with("abc")
+
+        mock_rbd_instance.mirror_peer_bootstrap_import.assert_called_with(
+            mock.ANY, mock_rbd_module.RBD_MIRROR_PEER_DIRECTION_RX, '1234')
+
+
 class RbdMirroringSummaryControllerTest(ControllerTestCase):
 
     @classmethod