From: Jason Dillaman Date: Thu, 17 Oct 2019 19:10:21 +0000 (-0400) Subject: mgr/dashboard: new controller for RBD mirroring peer bootstrapping X-Git-Tag: v15.1.0~633^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=10e9132bf878d05b0b8cfe36436ade543c1f5835;p=ceph.git mgr/dashboard: new controller for RBD mirroring peer bootstrapping Signed-off-by: Jason Dillaman --- diff --git a/qa/tasks/mgr/dashboard/test_rbd_mirroring.py b/qa/tasks/mgr/dashboard/test_rbd_mirroring.py index bb6e3d0be807..598648f6a76f 100644 --- a/qa/tasks/mgr/dashboard/test_rbd_mirroring.py +++ b/qa/tasks/mgr/dashboard/test_rbd_mirroring.py @@ -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) diff --git a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py index 8d94b7090958..3cd9bb298b0f 100644 --- a/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py +++ b/src/pybind/mgr/dashboard/controllers/rbd_mirroring.py @@ -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): diff --git a/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py index 39f70594308b..9a0142b4b2c3 100644 --- a/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py +++ b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py @@ -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