Merge "Implement get_volume_stats in NFS driver" into milestone-proposed
This commit is contained in:
commit
098daffa2e
@ -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()
|
||||
|
@ -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'
|
||||
|
@ -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."""
|
||||
@ -268,7 +264,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
|
||||
@ -297,17 +293,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"""
|
||||
@ -316,8 +312,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:
|
||||
@ -327,3 +323,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
|
||||
|
Loading…
Reference in New Issue
Block a user