From: Kiefer Chang Date: Wed, 18 Nov 2020 11:35:02 +0000 (+0800) Subject: mgr/dashboard: fix exception in get_smart_data_by_daemon X-Git-Tag: v15.2.13~13^2~26^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f13127daf8a0f2852f5b30435d7666ff1a210d9d;p=ceph.git mgr/dashboard: fix exception in get_smart_data_by_daemon - Fix string substitution exception. - Add more test coverage. Fixes: https://tracker.ceph.com/issues/48245 Signed-off-by: Kiefer Chang (cherry picked from commit d2ddea5a79a54086c4ee104aea4f59f10d174735) Conflicts: src/pybind/mgr/dashboard/requirements-lint.txt src/pybind/mgr/dashboard/tests/test_ceph_service.py - Added pytest; fixed and re-arranged imports; removed isort since it breaks make check in octopus --- diff --git a/src/pybind/mgr/dashboard/requirements-lint.txt b/src/pybind/mgr/dashboard/requirements-lint.txt index 8f68ad3856ec..54e187dd20cb 100644 --- a/src/pybind/mgr/dashboard/requirements-lint.txt +++ b/src/pybind/mgr/dashboard/requirements-lint.txt @@ -9,3 +9,4 @@ flake8-colors==0.1.6; python_version >= '3' rstcheck==3.3.1; python_version >= '3' autopep8; python_version >= '3' pyfakefs; python_version >= '3' +pytest<4 diff --git a/src/pybind/mgr/dashboard/services/ceph_service.py b/src/pybind/mgr/dashboard/services/ceph_service.py index ea918b6b3f95..ea794a4474ef 100644 --- a/src/pybind/mgr/dashboard/services/ceph_service.py +++ b/src/pybind/mgr/dashboard/services/ceph_service.py @@ -303,7 +303,7 @@ class CephService(object): CephService._get_smart_data_by_device(device)) else: msg = '[SMART] could not retrieve device list from daemon with type %s and ' +\ - 'with ID %d' + 'with ID %s' logger.debug(msg, daemon_type, daemon_id) return smart_data diff --git a/src/pybind/mgr/dashboard/tests/test_ceph_service.py b/src/pybind/mgr/dashboard/tests/test_ceph_service.py index 5111e68d492b..3b2aa8b13323 100644 --- a/src/pybind/mgr/dashboard/tests/test_ceph_service.py +++ b/src/pybind/mgr/dashboard/tests/test_ceph_service.py @@ -2,11 +2,12 @@ # pylint: disable=dangerous-default-value,too-many-public-methods from __future__ import absolute_import +import logging import unittest -try: - import mock -except ImportError: - import unittest.mock as mock +from unittest import mock +from contextlib import contextmanager + +import pytest from ..services.ceph_service import CephService @@ -65,3 +66,44 @@ class CephServiceTest(unittest.TestCase): def test_get_pg_status_without_match(self): self.assertEqual(self.service.get_pool_pg_status('no-pool'), {}) + + +@contextmanager +def mock_smart_data(data): + devices = [{'devid': devid} for devid in data] + + def _get_smart_data(d): + return {d['devid']: data[d['devid']]} + + with mock.patch.object(CephService, '_get_smart_data_by_device', side_effect=_get_smart_data), \ + mock.patch.object(CephService, 'get_devices_by_host', return_value=devices), \ + mock.patch.object(CephService, 'get_devices_by_daemon', return_value=devices): + yield + + +@pytest.mark.parametrize( + "by,args,log", + [ + ('host', ('osd0',), 'from host osd0'), + ('daemon', ('osd', '1'), 'with ID 1') + ] +) +def test_get_smart_data(caplog, by, args, log): + # pylint: disable=protected-access + expected_data = { + 'aaa': {'device': {'name': '/dev/sda'}}, + 'bbb': {'device': {'name': '/dev/sdb'}}, + } + with mock_smart_data(expected_data): + smart_data = getattr(CephService, 'get_smart_data_by_{}'.format(by))(*args) + getattr(CephService, 'get_devices_by_{}'.format(by)).assert_called_with(*args) + CephService._get_smart_data_by_device.assert_called() + assert smart_data == expected_data + + with caplog.at_level(logging.DEBUG): + with mock_smart_data([]): + smart_data = getattr(CephService, 'get_smart_data_by_{}'.format(by))(*args) + getattr(CephService, 'get_devices_by_{}'.format(by)).assert_called_with(*args) + CephService._get_smart_data_by_device.assert_not_called() + assert smart_data == {} + assert log in caplog.text