From c47bf9bc3835d4399185376ac07920ef903d79e8 Mon Sep 17 00:00:00 2001 From: Mehdi Abaakouk Date: Fri, 8 Mar 2013 13:01:57 +0100 Subject: [PATCH] Implement get_volume_stats in NFS driver Use the already existing code (ie: _get_available_capacity) to implement get_volume_stats in the nfs driver Change the netapp nfs driver to use this new implementation instead of the dumb one. Fixes bug #1152501 Change-Id: Ie16d9628ba4b096c60966b4aa6192fbdcb9a4f20 --- cinder/tests/test_nfs.py | 55 +++++++++++---- cinder/volume/drivers/netapp/nfs.py | 106 ++++++---------------------- cinder/volume/drivers/nfs.py | 49 ++++++++++--- 3 files changed, 102 insertions(+), 108 deletions(-) diff --git a/cinder/tests/test_nfs.py b/cinder/tests/test_nfs.py index 302cd05f4..ebeb0d1cd 100644 --- a/cinder/tests/test_nfs.py +++ b/cinder/tests/test_nfs.py @@ -20,6 +20,8 @@ import __builtin__ import errno import os +from oslo.config import cfg + import mox as mox_lib from mox import IgnoreArg from mox import IsA @@ -335,9 +337,11 @@ class NfsDriverTestCase(test.TestCase): mox = self._mox drv = self._driver + df_total_size = 2620544 df_avail = 1490560 df_head = 'Filesystem 1K-blocks Used Available Use% Mounted on\n' - df_data = 'nfs-host:/export 2620544 996864 %d 41%% /mnt' % df_avail + df_data = 'nfs-host:/export %d 996864 %d 41%% /mnt' % (df_total_size, + df_avail) df_output = df_head + df_data self.configuration.nfs_disk_util = 'df' @@ -352,7 +356,7 @@ class NfsDriverTestCase(test.TestCase): mox.ReplayAll() - self.assertEquals(df_avail, + self.assertEquals((df_avail, df_total_size), drv._get_available_capacity(self.TEST_NFS_EXPORT1)) mox.VerifyAll() @@ -390,7 +394,7 @@ class NfsDriverTestCase(test.TestCase): mox.ReplayAll() - self.assertEquals(df_total_size - du_used, + self.assertEquals((df_total_size - du_used, df_total_size), drv._get_available_capacity(self.TEST_NFS_EXPORT1)) mox.VerifyAll() @@ -474,7 +478,7 @@ class NfsDriverTestCase(test.TestCase): """do_setup should throw error if shares config is not configured.""" drv = self._driver - nfs.FLAGS.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE + cfg.CONF.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE self.assertRaises(exception.NfsException, drv.do_setup, IsA(context.RequestContext)) @@ -484,7 +488,7 @@ class NfsDriverTestCase(test.TestCase): mox = self._mox drv = self._driver self.configuration.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE - nfs.FLAGS.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE + cfg.CONF.nfs_shares_config = self.TEST_SHARES_CONFIG_FILE mox.StubOutWithMock(os.path, 'exists') os.path.exists(self.TEST_SHARES_CONFIG_FILE).AndReturn(True) @@ -517,9 +521,9 @@ class NfsDriverTestCase(test.TestCase): mox.StubOutWithMock(drv, '_get_available_capacity') drv._get_available_capacity(self.TEST_NFS_EXPORT1).\ - AndReturn(2 * self.ONE_GB_IN_BYTES) + AndReturn((2 * self.ONE_GB_IN_BYTES, 5 * self.ONE_GB_IN_BYTES)) drv._get_available_capacity(self.TEST_NFS_EXPORT2).\ - AndReturn(3 * self.ONE_GB_IN_BYTES) + AndReturn((3 * self.ONE_GB_IN_BYTES, 10 * self.ONE_GB_IN_BYTES)) mox.ReplayAll() @@ -537,9 +541,9 @@ class NfsDriverTestCase(test.TestCase): mox.StubOutWithMock(drv, '_get_available_capacity') drv._get_available_capacity(self.TEST_NFS_EXPORT1).\ - AndReturn(0) + AndReturn((0, 5 * self.ONE_GB_IN_BYTES)) drv._get_available_capacity(self.TEST_NFS_EXPORT2).\ - AndReturn(0) + AndReturn((0, 10 * self.ONE_GB_IN_BYTES)) mox.ReplayAll() @@ -561,7 +565,7 @@ class NfsDriverTestCase(test.TestCase): drv = self._driver volume = self._simple_volume() - setattr(nfs.FLAGS, 'nfs_sparsed_volumes', True) + setattr(cfg.CONF, 'nfs_sparsed_volumes', True) mox.StubOutWithMock(drv, '_create_sparsed_file') mox.StubOutWithMock(drv, '_set_rw_permissions_for_all') @@ -575,7 +579,7 @@ class NfsDriverTestCase(test.TestCase): mox.VerifyAll() - delattr(nfs.FLAGS, 'nfs_sparsed_volumes') + delattr(cfg.CONF, 'nfs_sparsed_volumes') def test_create_nonsparsed_volume(self): mox = self._mox @@ -583,7 +587,7 @@ class NfsDriverTestCase(test.TestCase): self.configuration.nfs_sparsed_volumes = False volume = self._simple_volume() - setattr(nfs.FLAGS, 'nfs_sparsed_volumes', False) + setattr(cfg.CONF, 'nfs_sparsed_volumes', False) mox.StubOutWithMock(drv, '_create_regular_file') mox.StubOutWithMock(drv, '_set_rw_permissions_for_all') @@ -597,7 +601,7 @@ class NfsDriverTestCase(test.TestCase): mox.VerifyAll() - delattr(nfs.FLAGS, 'nfs_sparsed_volumes') + delattr(cfg.CONF, 'nfs_sparsed_volumes') def test_create_volume_should_ensure_nfs_mounted(self): """create_volume ensures shares provided in config are mounted.""" @@ -729,3 +733,28 @@ class NfsDriverTestCase(test.TestCase): drv.delete_volume(volume) mox.VerifyAll() + + def test_get_volume_stats(self): + """get_volume_stats must fill the correct values""" + mox = self._mox + drv = self._driver + + drv._mounted_shares = [self.TEST_NFS_EXPORT1, self.TEST_NFS_EXPORT2] + + mox.StubOutWithMock(drv, '_ensure_shares_mounted') + mox.StubOutWithMock(drv, '_get_available_capacity') + + drv._ensure_shares_mounted() + + drv._get_available_capacity(self.TEST_NFS_EXPORT1).\ + AndReturn((2 * self.ONE_GB_IN_BYTES, 10 * self.ONE_GB_IN_BYTES)) + drv._get_available_capacity(self.TEST_NFS_EXPORT2).\ + AndReturn((3 * self.ONE_GB_IN_BYTES, 20 * self.ONE_GB_IN_BYTES)) + + mox.ReplayAll() + + drv.get_volume_stats() + self.assertEqual(drv._stats['total_capacity_gb'], 30.0) + self.assertEqual(drv._stats['free_capacity_gb'], 5.0) + + mox.VerifyAll() diff --git a/cinder/volume/drivers/netapp/nfs.py b/cinder/volume/drivers/netapp/nfs.py index 60a986222..1976beac0 100644 --- a/cinder/volume/drivers/netapp/nfs.py +++ b/cinder/volume/drivers/netapp/nfs.py @@ -280,31 +280,15 @@ class NetAppNFSDriver(nfs.NfsDriver): return {'provider_location': share} - def get_volume_stats(self, refresh=False): - """Get volume status. - - If 'refresh' is True, run update the stats first.""" - if refresh: - self._update_volume_status() - - return self._stats - def _update_volume_status(self): """Retrieve status info from volume group.""" + super(NetAppNFSDriver, self)._update_volume_status() - LOG.debug(_("Updating volume status")) - data = {} backend_name = self.configuration.safe_get('volume_backend_name') - data["volume_backend_name"] = backend_name or 'NetApp_NFS_7mode' - data["vendor_name"] = 'NetApp' - data["driver_version"] = '1.0' - data["storage_protocol"] = 'NFS' - - data['total_capacity_gb'] = 'infinite' - data['free_capacity_gb'] = 'infinite' - data['reserved_percentage'] = 100 - data['QoS_support'] = False - self._stats = data + self._stats["volume_backend_name"] = (backend_name or + 'NetApp_NFS_7mode') + self._stats["vendor_name"] = 'NetApp' + self._stats["driver_version"] = '1.0' class NetAppCmodeNfsDriver (NetAppNFSDriver): @@ -351,31 +335,15 @@ class NetAppCmodeNfsDriver (NetAppNFSDriver): password=self.configuration.netapp_password) return client - def get_volume_stats(self, refresh=False): - """Get volume status. - - If 'refresh' is True, run update the stats first.""" - if refresh: - self._update_volume_status() - - return self._stats - def _update_volume_status(self): """Retrieve status info from volume group.""" + super(NetAppCmodeNfsDriver, self)._update_volume_status() - LOG.debug(_("Updating volume status")) - data = {} backend_name = self.configuration.safe_get('volume_backend_name') - data["volume_backend_name"] = backend_name or 'NetApp_NFS_Cluster' - data["vendor_name"] = 'NetApp' - data["driver_version"] = '1.0' - data["storage_protocol"] = 'NFS' - - data['total_capacity_gb'] = 'infinite' - data['free_capacity_gb'] = 'infinite' - data['reserved_percentage'] = 100 - data['QoS_support'] = False - self._stats = data + self._stats["volume_backend_name"] = (backend_name or + 'NetApp_NFS_Cluster') + self._stats["vendor_name"] = 'NetApp' + self._stats["driver_version"] = '1.0' class NetAppDirectNfsDriver (NetAppNFSDriver): @@ -525,32 +493,15 @@ class NetAppDirectCmodeNfsDriver (NetAppDirectNfsDriver): 'destination-path': dest_path}) self._invoke_successfully(clone_create, vserver) - def get_volume_stats(self, refresh=False): - """Get volume status. - - If 'refresh' is True, run update the stats first.""" - if refresh: - self._update_volume_status() - - return self._stats - def _update_volume_status(self): """Retrieve status info from volume group.""" + super(NetAppDirectCmodeNfsDriver, self)._update_volume_status() - LOG.debug(_("Updating volume status")) - data = {} backend_name = self.configuration.safe_get('volume_backend_name') - data["volume_backend_name"] = (backend_name - or 'NetApp_NFS_cluster_direct') - data["vendor_name"] = 'NetApp' - data["driver_version"] = '1.0' - data["storage_protocol"] = 'NFS' - - data['total_capacity_gb'] = 'infinite' - data['free_capacity_gb'] = 'infinite' - data['reserved_percentage'] = 100 - data['QoS_support'] = False - self._stats = data + self._stats["volume_backend_name"] = (backend_name or + 'NetApp_NFS_cluster_direct') + self._stats["vendor_name"] = 'NetApp' + self._stats["driver_version"] = '1.0' class NetAppDirect7modeNfsDriver (NetAppDirectNfsDriver): @@ -655,29 +606,12 @@ class NetAppDirect7modeNfsDriver (NetAppDirectNfsDriver): time.sleep(5) retry = retry - 1 - def get_volume_stats(self, refresh=False): - """Get volume status. - - If 'refresh' is True, run update the stats first.""" - if refresh: - self._update_volume_status() - - return self._stats - def _update_volume_status(self): """Retrieve status info from volume group.""" + super(NetAppDirect7modeNfsDriver, self)._update_volume_status() - LOG.debug(_("Updating volume status")) - data = {} backend_name = self.configuration.safe_get('volume_backend_name') - data["volume_backend_name"] = (backend_name - or 'NetApp_NFS_7mode_direct') - data["vendor_name"] = 'NetApp' - data["driver_version"] = '1.0' - data["storage_protocol"] = 'NFS' - - data['total_capacity_gb'] = 'infinite' - data['free_capacity_gb'] = 'infinite' - data['reserved_percentage'] = 100 - data['QoS_support'] = False - self._stats = data + self._stats["volume_backend_name"] = (backend_name or + 'NetApp_NFS_7mode_direct') + self._stats["vendor_name"] = 'NetApp' + self._stats["driver_version"] = '1.0' diff --git a/cinder/volume/drivers/nfs.py b/cinder/volume/drivers/nfs.py index 0c1df91da..74b3aecd4 100755 --- a/cinder/volume/drivers/nfs.py +++ b/cinder/volume/drivers/nfs.py @@ -22,7 +22,6 @@ import os from oslo.config import cfg from cinder import exception -from cinder import flags from cinder.openstack.common import log as logging from cinder.volume import driver @@ -49,9 +48,6 @@ volume_opts = [ 'of the nfs man page for details'), ] -FLAGS = flags.FLAGS -FLAGS.register_opts(volume_opts) - class RemoteFsDriver(driver.VolumeDriver): """Common base for drivers that work like NFS.""" @@ -263,7 +259,7 @@ class NfsDriver(RemoteFsDriver): greatest_share = None for nfs_share in self._mounted_shares: - capacity = self._get_available_capacity(nfs_share) + capacity = self._get_available_capacity(nfs_share)[0] if capacity > greatest_size: greatest_share = nfs_share greatest_size = capacity @@ -292,17 +288,17 @@ class NfsDriver(RemoteFsDriver): available = 0 + size = int(out.split()[1]) if self.configuration.nfs_disk_util == 'df': available = int(out.split()[3]) else: - size = int(out.split()[1]) out, _ = self._execute('du', '-sb', '--apparent-size', '--exclude', '*snapshot*', mount_point, run_as_root=True) used = int(out.split()[0]) available = size - used - return available + return available, size def _mount_nfs(self, nfs_share, mount_path, ensure=False): """Mount NFS share to mount path""" @@ -311,8 +307,8 @@ class NfsDriver(RemoteFsDriver): # Construct the NFS mount command. nfs_cmd = ['mount', '-t', 'nfs'] - if FLAGS.nfs_mount_options is not None: - nfs_cmd.extend(['-o', FLAGS.nfs_mount_options]) + if cfg.CONF.nfs_mount_options is not None: + nfs_cmd.extend(['-o', cfg.CONF.nfs_mount_options]) nfs_cmd.extend([nfs_share, mount_path]) try: @@ -322,3 +318,38 @@ class NfsDriver(RemoteFsDriver): LOG.warn(_("%s is already mounted"), nfs_share) else: raise + + def get_volume_stats(self, refresh=False): + """Get volume status. + + If 'refresh' is True, run update the stats first.""" + if refresh or not self._stats: + self._update_volume_status() + + return self._stats + + def _update_volume_status(self): + """Retrieve status info from volume group.""" + + LOG.debug(_("Updating volume status")) + data = {} + backend_name = self.configuration.safe_get('volume_backend_name') + data["volume_backend_name"] = backend_name or 'Generic_NFS' + data["vendor_name"] = 'Open Source' + data["driver_version"] = '1.0' + data["storage_protocol"] = 'nfs' + + self._ensure_shares_mounted() + + global_capacity = 0 + global_free = 0 + for nfs_share in self._mounted_shares: + free, capacity = self._get_available_capacity(nfs_share) + global_capacity += capacity + global_free += free + + data['total_capacity_gb'] = global_capacity / 1024.0 ** 3 + data['free_capacity_gb'] = global_free / 1024.0 ** 3 + data['reserved_percentage'] = 0 + data['QoS_support'] = False + self._stats = data -- 2.45.2