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
This commit is contained in:
Mehdi Abaakouk 2013-03-08 13:01:57 +01:00
parent 2d84a97df2
commit c47bf9bc38
3 changed files with 102 additions and 108 deletions

View File

@ -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()

View File

@ -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'

View File

@ -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