From 1ae7ebb98b223e560cdce8c9186237e4d6eb4874 Mon Sep 17 00:00:00 2001 From: Gorka Eguileor Date: Wed, 30 Jan 2019 13:20:36 +0100 Subject: [PATCH] Fix HPE3PAR not returning cached stats All Cinder drivers must honor this: stats = driver.get_volume_stats(refresh=True) cached_stats = driver.get_volume_stats(refresh=False) assert stats == cached_stats But HPE 3PAR drivers don't. If you try to get cached stats values you'll get an empty dictionary instead. This is caused by the get_volume_stats method calling the _login method which in turn calls _init_common, which returns a new HPE3PARCommon instance on each call, so it won't have any cached values. Closes-Bug: #1813930 Change-Id: I011e7142db5d54882fd2cd9c07276ac71a07b4b7 --- .../unit/volume/drivers/hpe/test_hpe3par.py | 26 +++++++++++++++++++ cinder/volume/drivers/hpe/hpe_3par_base.py | 8 ++++++ 2 files changed, 34 insertions(+) diff --git a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py index 19466394bc2..80f070503d1 100644 --- a/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py +++ b/cinder/tests/unit/volume/drivers/hpe/test_hpe3par.py @@ -7632,6 +7632,32 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver): expected + self.standard_logout) + def test_get_volume_stats5(self): + # Testing get_volume_stats(refresh=False) for cached values + config = self.setup_configuration() + self.setup_driver(config=config) + with mock.patch.object(self.driver, '_login') as login_mock, \ + mock.patch.object(self.driver, '_logout') as logout_mock: + stats_mock = login_mock.return_value.get_volume_stats + + stats = self.driver.get_volume_stats(True) + + self.assertEqual(stats_mock.return_value, stats) + login_mock.assert_called_once_with() + stats_mock.assert_called_once_with(True, FILTER_FUNCTION, + GOODNESS_FUNCTION) + logout_mock.assert_called_once_with(login_mock.return_value) + + login_mock.reset_mock() + stats_mock.reset_mock() + logout_mock.reset_mock() + + cached_stats = self.driver.get_volume_stats(False) + self.assertEqual(stats, cached_stats) + login_mock.assert_not_called() + stats_mock.assert_not_called() + logout_mock.assert_not_called() + def test_create_host_with_unmanage_fc_and_manage_iscsi_hosts(self): # setup_mock_client drive with default configuration # and return the mock HTTP 3PAR client diff --git a/cinder/volume/drivers/hpe/hpe_3par_base.py b/cinder/volume/drivers/hpe/hpe_3par_base.py index 97844b64425..37ca5a16a19 100644 --- a/cinder/volume/drivers/hpe/hpe_3par_base.py +++ b/cinder/volume/drivers/hpe/hpe_3par_base.py @@ -115,6 +115,14 @@ class HPE3PARDriverBase(driver.ManageableVD, @utils.trace def get_volume_stats(self, refresh=False): + # NOTE(geguileo): We don't need to login to the backed if we are not + # going to refresh the stats, furthermore if we login, then we'll + # return an empty dict, because the _login method calls calls + # _init_common which returns a new HPE3PARCommon instance each time, + # so it won't have any cached values. + if not refresh: + return self._stats + common = self._login() try: self._stats = common.get_volume_stats(