diff --git a/cinder/tests/unit/volume/drivers/test_rbd.py b/cinder/tests/unit/volume/drivers/test_rbd.py index d0a182bea9c..a803f6635b2 100644 --- a/cinder/tests/unit/volume/drivers/test_rbd.py +++ b/cinder/tests/unit/volume/drivers/test_rbd.py @@ -79,12 +79,13 @@ def common_mocks(f): def _common_inner_inner1(inst, *args, **kwargs): @mock.patch('retrying.Retrying', _FakeRetrying) + @mock.patch.object(driver.RBDDriver, '_get_usage_info') @mock.patch('cinder.volume.drivers.rbd.RBDVolumeProxy') @mock.patch('cinder.volume.drivers.rbd.RADOSClient') @mock.patch('cinder.backup.drivers.ceph.rbd') @mock.patch('cinder.backup.drivers.ceph.rados') def _common_inner_inner2(mock_rados, mock_rbd, mock_client, - mock_proxy): + mock_proxy, mock_usage_info): inst.mock_rbd = mock_rbd inst.mock_rados = mock_rados inst.mock_client = mock_client @@ -821,7 +822,10 @@ class RBDTestCase(test.TestCase): storage_protocol='ceph', total_capacity_gb=28.44, free_capacity_gb=27.0, - reserved_percentage=0, + reserved_percentage='RBD', + thin_provisioning_support=True, + provisioned_capacity_gb=0.0, + max_over_subscription_ratio='RBD', multiattach=False) actual = self.driver.get_volume_stats(True) @@ -847,8 +851,11 @@ class RBDTestCase(test.TestCase): storage_protocol='ceph', total_capacity_gb='unknown', free_capacity_gb='unknown', - reserved_percentage=0, - multiattach=False) + reserved_percentage='RBD', + multiattach=False, + provisioned_capacity_gb=0.0, + max_over_subscription_ratio='RBD', + thin_provisioning_support=True) actual = self.driver.get_volume_stats(True) client.cluster.mon_command.assert_called_once_with( diff --git a/cinder/volume/drivers/rbd.py b/cinder/volume/drivers/rbd.py index 2c1e3ed709e..1269fa6d3b1 100644 --- a/cinder/volume/drivers/rbd.py +++ b/cinder/volume/drivers/rbd.py @@ -389,6 +389,20 @@ class RBDDriver(driver.TransferVD, driver.ExtendVD, ports.append(port) return hosts, ports + def _iterate_cb(self, offset, length, exists): + if exists: + self._total_usage += length + + def _get_usage_info(self): + with RADOSClient(self) as client: + for t in self.RBDProxy().list(client.ioctx): + if t.startswith('volume'): + # Only check for "volume" to allow some flexibility with + # non-default volume_name_template settings. Template + # must start with "volume". + with RBDVolumeProxy(self, t, read_only=True) as v: + v.diff_iterate(0, v.size(), None, self._iterate_cb) + def _update_volume_stats(self): stats = { 'vendor_name': 'Open Source', @@ -396,8 +410,14 @@ class RBDDriver(driver.TransferVD, driver.ExtendVD, 'storage_protocol': 'ceph', 'total_capacity_gb': 'unknown', 'free_capacity_gb': 'unknown', - 'reserved_percentage': 0, + 'provisioned_capacity_gb': 0, + 'reserved_percentage': ( + self.configuration.safe_get('reserved_percentage')), 'multiattach': False, + 'thin_provisioning_support': True, + 'max_over_subscription_ratio': ( + self.configuration.safe_get('max_over_subscription_ratio')) + } backend_name = self.configuration.safe_get('volume_backend_name') stats['volume_backend_name'] = backend_name or 'RBD' @@ -419,6 +439,11 @@ class RBDDriver(driver.TransferVD, driver.ExtendVD, pool_stats['bytes_used']) / units.Gi stats['total_capacity_gb'] = round( (stats['free_capacity_gb'] + used_capacity_gb), 2) + + self._total_usage = 0 + self._get_usage_info() + total_usage_gb = math.ceil(float(self._total_usage) / units.Gi) + stats['provisioned_capacity_gb'] = total_usage_gb except self.rados.Error: # just log and return unknown capacities LOG.exception(_LE('error refreshing volume stats')) diff --git a/releasenotes/notes/rbd-thin-provisioning-c98522d6fe7b71ff.yaml b/releasenotes/notes/rbd-thin-provisioning-c98522d6fe7b71ff.yaml new file mode 100644 index 00000000000..02667f9cd3b --- /dev/null +++ b/releasenotes/notes/rbd-thin-provisioning-c98522d6fe7b71ff.yaml @@ -0,0 +1,3 @@ +--- +features: + - Allow the RBD driver to work with max_over_subscription_ratio.