From 19fcec84d8d7d21e796c7624e521b60d28ee21ed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:45:59 +0200 Subject: Adding upstream version 16.2.11+ds. Signed-off-by: Daniel Baumann --- .../mgr/dashboard/tests/test_rbd_mirroring.py | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py (limited to 'src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py') diff --git a/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py new file mode 100644 index 000000000..69e3f11e2 --- /dev/null +++ b/src/pybind/mgr/dashboard/tests/test_rbd_mirroring.py @@ -0,0 +1,195 @@ +from __future__ import absolute_import + +import json + +try: + import mock +except ImportError: + import unittest.mock as mock + +from .. import mgr +from ..controllers.orchestrator import Orchestrator +from ..controllers.rbd_mirroring import RbdMirroring, \ + RbdMirroringPoolBootstrap, RbdMirroringStatus, RbdMirroringSummary +from ..controllers.summary import Summary +from ..services import progress +from ..tests import ControllerTestCase + +mock_list_servers = [{ + 'hostname': 'ceph-host', + 'services': [{'id': 3, 'type': 'rbd-mirror'}] +}] + +mock_get_metadata = { + 'id': 1, + 'instance_id': 3, + 'ceph_version': 'ceph version 13.0.0-5719 mimic (dev)' +} + +_status = { + 1: { + 'callouts': {}, + 'image_local_count': 5, + 'image_remote_count': 6, + 'image_error_count': 7, + 'image_warning_count': 8, + 'name': 'pool_name' + } +} + +mock_get_daemon_status = { + 'json': json.dumps(_status) +} + +mock_osd_map = { + 'pools': [{ + 'pool_name': 'rbd', + 'application_metadata': {'rbd'} + }] +} + + +class RbdMirroringControllerTest(ControllerTestCase): + + @classmethod + def setup_server(cls): + cls.setup_controllers([RbdMirroring]) + + @mock.patch('dashboard.controllers.rbd_mirroring.rbd.RBD') + def test_site_name(self, mock_rbd): + result = {'site_name': 'fsid'} + mock_rbd_instance = mock_rbd.return_value + mock_rbd_instance.mirror_site_name_get.return_value = \ + result['site_name'] + + self._get('/api/block/mirroring/site_name') + self.assertStatus(200) + self.assertJsonBody(result) + + result['site_name'] = 'site-a' + mock_rbd_instance.mirror_site_name_get.return_value = \ + result['site_name'] + self._put('/api/block/mirroring/site_name', result) + self.assertStatus(200) + self.assertJsonBody(result) + mock_rbd_instance.mirror_site_name_set.assert_called_with( + mock.ANY, result['site_name']) + + +class RbdMirroringPoolBootstrapControllerTest(ControllerTestCase): + + @classmethod + def setup_server(cls): + 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 + def setup_server(cls): + mgr.list_servers.return_value = mock_list_servers + mgr.get_metadata = mock.Mock(return_value=mock_get_metadata) + mgr.get_daemon_status.return_value = mock_get_daemon_status + mgr.get.side_effect = lambda key: { + 'osd_map': mock_osd_map, + 'health': {'json': '{"status": 1}'}, + 'fs_map': {'filesystems': []}, + 'mgr_map': { + 'services': { + 'dashboard': 'https://ceph.dev:11000/' + }, + } + }[key] + mgr.url_prefix = '' + mgr.get_mgr_id.return_value = 0 + mgr.have_mon_connection.return_value = True + mgr.version = 'ceph version 13.1.0-534-g23d3751b89 ' \ + '(23d3751b897b31d2bda57aeaf01acb5ff3c4a9cd) ' \ + 'nautilus (dev)' + + progress.get_progress_tasks = mock.MagicMock() + progress.get_progress_tasks.return_value = ([], []) + + cls.setup_controllers([RbdMirroringSummary, Summary], '/test') + + @mock.patch('dashboard.controllers.rbd_mirroring.rbd.RBD') + def test_default(self, mock_rbd): + mock_rbd_instance = mock_rbd.return_value + mock_rbd_instance.mirror_site_name_get.return_value = 'site-a' + + self._get('/test/api/block/mirroring/summary') + result = self.json_body() + self.assertStatus(200) + self.assertEqual(result['site_name'], 'site-a') + self.assertEqual(result['status'], 0) + for k in ['daemons', 'pools', 'image_error', 'image_syncing', 'image_ready']: + self.assertIn(k, result['content_data']) + + @mock.patch('dashboard.controllers.BaseController._has_permissions') + @mock.patch('dashboard.controllers.rbd_mirroring.rbd.RBD') + def test_summary(self, mock_rbd, has_perms_mock): + """We're also testing `summary`, as it also uses code from `rbd_mirroring.py`""" + mock_rbd_instance = mock_rbd.return_value + mock_rbd_instance.mirror_site_name_get.return_value = 'site-a' + + has_perms_mock.return_value = True + self._get('/test/api/summary') + self.assertStatus(200) + + summary = self.json_body()['rbd_mirroring'] + self.assertEqual(summary, {'errors': 0, 'warnings': 1}) + + +class RbdMirroringStatusControllerTest(ControllerTestCase): + + @classmethod + def setup_server(cls): + cls.setup_controllers([RbdMirroringStatus, Orchestrator]) + + @mock.patch('dashboard.controllers.orchestrator.OrchClient.instance') + def test_status(self, instance): + status = {'available': False, 'description': ''} + fake_client = mock.Mock() + fake_client.status.return_value = status + instance.return_value = fake_client + + self._get('/ui-api/block/mirroring/status') + self.assertStatus(200) + self.assertJsonBody({'available': True, 'message': None}) + + def test_configure(self): + self._post('/ui-api/block/mirroring/configure') + self.assertStatus(200) -- cgit v1.2.3