From: wuyuting Date: Fri, 20 Mar 2015 10:41:11 +0000 (+0800) Subject: Rbd update volume stats in wrong way X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=ac219d5dd93c5c637336a9c79389fc260af65d36;p=openstack-build%2Fcinder-build.git Rbd update volume stats in wrong way Cinder volume uses a RADOS pool to store volumes and update storage stats periodically. However, rbd driver reports the whole cluster stats but not the pool's. This is wrong. The right way is to report the pool stats but not the whole cluster. Change-Id: Ie18324ebd8b85f7b63dc034ba20857ae9e470804 Closes-Bug: #1434441 --- diff --git a/cinder/tests/test_rbd.py b/cinder/tests/test_rbd.py index b30735293..fcd3bcc63 100644 --- a/cinder/tests/test_rbd.py +++ b/cinder/tests/test_rbd.py @@ -662,10 +662,14 @@ class RBDTestCase(test.TestCase): client.__enter__.return_value = client client.cluster = mock.Mock() - client.cluster.get_cluster_stats = mock.Mock() - client.cluster.get_cluster_stats.return_value = {'kb': 1024 ** 3, - 'kb_avail': 1024 ** 2} - + client.cluster.mon_command = mock.Mock() + client.cluster.mon_command.return_value = ( + 0, '{"stats":{"total_bytes":64385286144,' + '"total_used_bytes":3289628672,"total_avail_bytes":61095657472},' + '"pools":[{"name":"rbd","id":2,"stats":{"kb_used":1510197,' + '"bytes_used":1546440971,"max_avail":28987613184,"objects":412}},' + '{"name":"volumes","id":3,"stats":{"kb_used":0,"bytes_used":0,' + '"max_avail":28987613184,"objects":0}}]}\n', '') self.driver.configuration.safe_get = mock.Mock() self.driver.configuration.safe_get.return_value = 'RBD' @@ -674,12 +678,13 @@ class RBDTestCase(test.TestCase): vendor_name='Open Source', driver_version=self.driver.VERSION, storage_protocol='ceph', - total_capacity_gb=1024, - free_capacity_gb=1, + total_capacity_gb=27, + free_capacity_gb=26, reserved_percentage=0) actual = self.driver.get_volume_stats(True) - client.cluster.get_cluster_stats.assert_called_once_with() + client.cluster.mon_command.assert_called_once_with( + '{"prefix":"df", "format":"json"}', '') self.assertDictMatch(expected, actual) @common_mocks @@ -688,8 +693,8 @@ class RBDTestCase(test.TestCase): client.__enter__.return_value = client client.cluster = mock.Mock() - client.cluster.get_cluster_stats = mock.Mock() - client.cluster.get_cluster_stats.side_effect = Exception + client.cluster.mon_command = mock.Mock() + client.cluster.mon_command.return_value = (22, '', '') self.driver.configuration.safe_get = mock.Mock() self.driver.configuration.safe_get.return_value = 'RBD' @@ -703,7 +708,8 @@ class RBDTestCase(test.TestCase): reserved_percentage=0) actual = self.driver.get_volume_stats(True) - client.cluster.get_cluster_stats.assert_called_once_with() + client.cluster.mon_command.assert_called_once_with( + '{"prefix":"df", "format":"json"}', '') self.assertDictMatch(expected, actual) @common_mocks diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index d9e939b5e..7dae2ec20 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -371,9 +371,20 @@ class RBDDriver(driver.VolumeDriver): try: with RADOSClient(self) as client: - new_stats = client.cluster.get_cluster_stats() - stats['total_capacity_gb'] = new_stats['kb'] / units.Mi - stats['free_capacity_gb'] = new_stats['kb_avail'] / units.Mi + ret, outbuf, _outs = client.cluster.mon_command( + '{"prefix":"df", "format":"json"}', '') + if ret != 0: + LOG.warning(_LW('Unable to get rados pool stats.')) + else: + outbuf = json.loads(outbuf) + pool_stats = [pool for pool in outbuf['pools'] if + pool['name'] == + self.configuration.rbd_pool][0]['stats'] + stats['free_capacity_gb'] = ( + pool_stats['max_avail'] / units.Gi) + used_capacity_gb = pool_stats['bytes_used'] / units.Gi + stats['total_capacity_gb'] = (stats['free_capacity_gb'] + + used_capacity_gb) except self.rados.Error: # just log and return unknown capacities LOG.exception(_LE('error refreshing volume stats'))