self.configuration.nas_ip = None
self.configuration.nas_share_path = None
self.configuration.nas_mount_options = None
- self.configuration.nfs_used_ratio = .95
- self.configuration.nfs_oversub_ratio = 1.0
def test_setup_failure_when_rpc_port_unconfigured(self):
self.configuration.coho_rpc_port = None
self.configuration.nas_ip = None
self.configuration.nas_share_path = None
self.configuration.nas_mount_options = None
- self.configuration.nfs_used_ratio = .95
- self.configuration.nfs_oversub_ratio = 1.0
self.driver = nfs.HDSNFSDriver(configuration=self.configuration)
self.driver.do_setup("")
configuration.nfs_mount_point_base = '/mnt/test'
configuration.nfs_mount_options = None
configuration.nas_mount_options = None
- configuration.nfs_used_ratio = .95
- configuration.nfs_oversub_ratio = 1.0
configuration.netapp_server_hostname = CONNECTION_INFO['hostname']
configuration.netapp_transport_type = CONNECTION_INFO['transport_type']
configuration.netapp_server_port = CONNECTION_INFO['port']
self.cfg.nexenta_nms_cache_volroot = False
self.cfg.nfs_mount_attempts = 3
self.cfg.reserved_percentage = 20
- self.cfg.nfs_used_ratio = .95
- self.cfg.nfs_oversub_ratio = 1.0
self.cfg.max_over_subscription_ratio = 20.0
self.nms_mock = mock.Mock()
for mod in ('appliance', 'folder', 'server', 'volume', 'netstorsvc',
self.configuration.reserved_percentage = 5
self.configuration.nfs_shares_config = None
self.configuration.nfs_sparsed_volumes = True
- self.configuration.nfs_used_ratio = 0.95
- self.configuration.nfs_oversub_ratio = 1.0
self.configuration.nfs_reserved_percentage = 5.0
self.configuration.nfs_mount_point_base = self.TEST_MNT_POINT_BASE
self.configuration.nfs_mount_options = None
@ddt.data(True, False)
def test_update_volume_stats(self, thin):
- self._driver.over_subscription_ratio = 20.0
- self._driver.reserved_percentage = 5.0
+ self._driver.configuration.max_over_subscription_ratio = 20.0
+ self._driver.configuration.reserved_percentage = 5.0
self._driver.configuration.nfs_sparsed_volumes = thin
remotefs_volume_stats = {
self.assertEqual(expected, self._driver._stats)
self.assertEqual(thin, mock_get_provisioned_capacity.called)
- @ddt.data({'nfs_oversub_ratio': 1.0},
- {'nfs_oversub_ratio': 1.5})
- @ddt.unpack
- def test_get_over_subscription_ratio(self, nfs_oversub_ratio):
- self.configuration.nfs_oversub_ratio = nfs_oversub_ratio
- self._driver.configuration = self.configuration
- self.mock_object(nfs, 'LOG')
-
- oversub_ratio = self._driver._get_over_subscription_ratio()
-
- if nfs_oversub_ratio == 1.0:
- self.assertEqual(1.0, oversub_ratio)
- self.assertFalse(nfs.LOG.warn.called)
- else:
- self.assertEqual(nfs_oversub_ratio, oversub_ratio)
- self.assertTrue(nfs.LOG.warn.called)
-
- @ddt.data({'nfs_used_ratio': 0.95, 'nfs_reserved_percentage': 0.05},
- {'nfs_used_ratio': 0.80, 'nfs_reserved_percentage': 0.20})
- @ddt.unpack
- def test_get_reserved_percentage(self, nfs_used_ratio,
- nfs_reserved_percentage):
- self.configuration.nfs_used_ratio = nfs_used_ratio
- self.configuration.nfs_reserved_percentage = nfs_reserved_percentage
- self._driver.configuration = self.configuration
- self.mock_object(nfs, 'LOG')
-
- reserved_percentage = self._driver._get_reserved_percentage()
-
- if nfs_used_ratio == 0.95:
- self.assertEqual(self._driver.configuration.reserved_percentage,
- reserved_percentage)
- self.assertFalse(nfs.LOG.warn.called)
- else:
- expected = (1 - self._driver.configuration.nfs_used_ratio) * 100
- self.assertEqual(expected, reserved_percentage)
- self.assertTrue(nfs.LOG.warn.called)
-
def _check_is_share_eligible(self, total_size, total_available,
total_allocated, requested_volume_size):
with mock.patch.object(self._driver, '_get_capacity_info')\
total_allocated,
requested_volume_size))
- def test_is_share_eligible_above_used_ratio(self):
+ def test_share_eligibility_with_reserved_percentage(self):
total_size = 100.0 * units.Gi
total_available = 4.0 * units.Gi
total_allocated = 96.0 * units.Gi
config.append_config_values(nfs.nfs_opts)
self.configuration = config
- def test_init_should_throw_error_if_oversub_ratio_less_than_zero(self):
- """__init__ should throw error if nfs_oversub_ratio is less than 0."""
-
- self.override_config('nfs_oversub_ratio', -1)
-
- with self.assertRaisesRegex(exception.InvalidConfigurationValue,
- ".*'nfs_oversub_ratio' invalid.*"):
- nfs.NfsDriver(configuration=self.configuration)
-
- def test_init_should_throw_error_if_used_ratio_less_than_zero(self):
- """__init__ should throw error if nfs_used_ratio is less than 0."""
-
- self.override_config('nfs_used_ratio', -1)
-
- with self.assertRaisesRegex(exception.InvalidConfigurationValue,
- ".*'nfs_used_ratio' invalid.*"):
- nfs.NfsDriver(configuration=self.configuration)
-
- def test_init_should_throw_error_if_used_ratio_greater_than_one(self):
- """__init__ should throw error if nfs_used_ratio is greater than 1."""
-
- self.override_config('nfs_used_ratio', 2)
-
- with self.assertRaisesRegex(exception.InvalidConfigurationValue,
- ".*'nfs_used_ratio' invalid.*"):
- nfs.NfsDriver(configuration=self.configuration)
-
def test_setup_should_throw_error_if_shares_config_not_configured(self):
"""do_setup should throw error if shares config is not configured."""
configuration.nfs_mount_point_base = '/mnt/test'
configuration.nfs_mount_options = None
configuration.nas_mount_options = None
- configuration.nfs_used_ratio = 0.95
- configuration.nfs_oversub_ratio = 1.0
return configuration
def fake_stubs(self):
self.configuration.zfssa_nfs_share_compression = nfs_compression
self.configuration.zfssa_nfs_mount_options = ''
self.configuration.zfssa_rest_timeout = '30'
- self.configuration.nfs_oversub_ratio = 1
- self.configuration.nfs_used_ratio = 1
self.configuration.zfssa_enable_local_cache = True
self.configuration.zfssa_cache_directory = zfssa_cache_dir
configuration = mock.Mock()
configuration.reserved_percentage = 0
configuration.nfs_mount_point_base = '/mnt/test'
- configuration.nfs_used_ratio = 1.0
- configuration.nfs_oversub_ratio = 1.1
+ configuration.reserved_percentage = 0
+ configuration.max_over_subscription_ratio = 1.1
kwargs = {'configuration': configuration}
expected_free_capacity_gb = (na_utils.round_down(
fake.AVAILABLE_BYTES / units.Gi, '0.01'))
expected_reserved_percentage = round(
- 100 * (1 - self.driver.configuration.nfs_used_ratio))
+ self.driver.configuration.reserved_percentage)
result = self.driver._get_share_capacity_info(fake.NFS_SHARE)
return_value=(
total_bytes, available_bytes)):
with mock.patch.object(self.driver,
- 'over_subscription_ratio',
+ 'max_over_subscription_ratio',
over):
with mock.patch.object(self.driver,
'reserved_percentage',
mock_get_capacity.return_value = (total_bytes, available_bytes)
with mock.patch.object(self.driver,
- 'over_subscription_ratio',
+ 'max_over_subscription_ratio',
over):
with mock.patch.object(self.driver,
'reserved_percentage',
reserved = int(round(total_size * reserved_ratio))
available = max(0, total_available - reserved)
if thin:
- available = available * self.over_subscription_ratio
+ available = available * self.max_over_subscription_ratio
return available >= requested_size
capacity = dict()
capacity['reserved_percentage'] = self.reserved_percentage
- capacity['max_over_subscription_ratio'] = self.over_subscription_ratio
+ capacity['max_over_subscription_ratio'] = (
+ self.max_over_subscription_ratio)
total_size, total_available = self._get_capacity_info(nfs_share)
capacity['total_capacity_gb'] = na_utils.round_down(
total_size / units.Gi, '0.01')
from oslo_concurrency import processutils as putils
from oslo_config import cfg
from oslo_log import log as logging
-from oslo_log import versionutils
from oslo_utils import units
import six
from cinder.volume import driver
from cinder.volume.drivers import remotefs
-VERSION = '1.3.0'
+VERSION = '1.3.1'
LOG = logging.getLogger(__name__)
-NFS_USED_RATIO_DEFAULT = 0.95
-NFS_OVERSUB_RATIO_DEFAULT = 1.0
nfs_opts = [
cfg.StrOpt('nfs_shares_config',
help=('Create volumes as sparsed files which take no space.'
'If set to False volume is created as regular file.'
'In such case volume creation takes a lot of time.')),
- # TODO(tbarron): remove nfs_used_ratio in the Mitaka release.
- cfg.FloatOpt('nfs_used_ratio',
- default=NFS_USED_RATIO_DEFAULT,
- help=('Percent of ACTUAL usage of the underlying volume '
- 'before no new volumes can be allocated to the volume '
- 'destination. Note that this option is deprecated '
- 'in favor of "reserved_percentage" and will be removed '
- 'in the Mitaka release.')),
- # TODO(tbarron): remove nfs_oversub_ratio in the Mitaka release.
- cfg.FloatOpt('nfs_oversub_ratio',
- default=NFS_OVERSUB_RATIO_DEFAULT,
- help=('This will compare the allocated to available space on '
- 'the volume destination. If the ratio exceeds this '
- 'number, the destination will no longer be valid. '
- 'Note that this option is deprecated in favor of '
- '"max_over_subscription_ratio" and will be removed '
- 'in the Mitaka release.')),
cfg.StrOpt('nfs_mount_point_base',
default='$state_path/mnt',
help=('Base dir containing mount points for NFS shares.')),
nfs_mount_options=opts)
self._sparse_copy_volume_data = True
- self.reserved_percentage = self._get_reserved_percentage()
- self.over_subscription_ratio = self._get_over_subscription_ratio()
+ self.reserved_percentage = self.configuration.reserved_percentage
+ self.max_over_subscription_ratio = (
+ self.configuration.max_over_subscription_ratio)
def do_setup(self, context):
"""Any initialization the volume driver does while starting."""
"""Verifies NFS share is eligible to host volume with given size.
First validation step: ratio of actual space (used_space / total_space)
- is less than 'nfs_used_ratio'. Second validation step: apparent space
+ is less than used_ratio. Second validation step: apparent space
allocated (differs from actual space used when using sparse files)
and compares the apparent available
- space (total_available * nfs_oversub_ratio) to ensure enough space is
+ space (total_available * oversub_ratio) to ensure enough space is
available for the new volume.
:param nfs_share: NFS share
# this requires either pool support for the generic NFS
# driver or limiting each NFS backend driver to a single share.
- # 'nfs_used_ratio' is deprecated, so derive used_ratio from
- # reserved_percentage.
+ # derive used_ratio from reserved percentage
if share_info is None:
total_size, total_available, total_allocated = (
self._get_capacity_info(nfs_share))
used_percentage = 100 - self.reserved_percentage
used_ratio = used_percentage / 100.0
- oversub_ratio = self.over_subscription_ratio
requested_volume_size = volume_size_in_gib * units.Gi
- apparent_size = max(0, share_info['total_size'] * oversub_ratio)
+ apparent_size = max(0, share_info['total_size'] *
+ self.max_over_subscription_ratio)
+
apparent_available = max(0, apparent_size -
share_info['total_allocated'])
# available space but be within our oversubscription limit
# therefore allowing this share to still be selected as a valid
# target.
- LOG.debug('%s is above nfs_used_ratio', nfs_share)
+ LOG.debug('%s is not eligible - used ratio exceeded.',
+ nfs_share)
return False
if apparent_available <= requested_volume_size:
- LOG.debug('%s is above nfs_oversub_ratio', nfs_share)
+ LOG.debug('%s is not eligible - insufficient (apparent) available '
+ 'space.',
+ nfs_share)
return False
if share_info['total_allocated'] / share_info['total_size'] >= (
- oversub_ratio):
- LOG.debug('%s reserved space is above nfs_oversub_ratio',
+ self.max_over_subscription_ratio):
+ LOG.debug('%s is not eligible - utilization exceeds max '
+ 'over subscription ratio.',
nfs_share)
return False
return True
provisioned_capacity = round(global_capacity - global_free, 2)
data['provisioned_capacity_gb'] = provisioned_capacity
- data['max_over_subscription_ratio'] = self.over_subscription_ratio
+ data['max_over_subscription_ratio'] = self.max_over_subscription_ratio
data['reserved_percentage'] = self.reserved_percentage
data['thin_provisioning_support'] = thin_enabled
data['thick_provisioning_support'] = not thin_enabled
self._stats = data
-
- def _get_over_subscription_ratio(self):
- legacy_oversub_ratio = self.configuration.nfs_oversub_ratio
- if legacy_oversub_ratio == NFS_OVERSUB_RATIO_DEFAULT:
- return self.configuration.max_over_subscription_ratio
-
- # Honor legacy option if its value is not the default.
- msg = _LW("The option 'nfs_oversub_ratio' is deprecated and will "
- "be removed in the Mitaka release. Please set "
- "'max_over_subscription_ratio = %s' instead.") % (
- self.configuration.nfs_oversub_ratio)
- versionutils.report_deprecated_feature(LOG, msg)
-
- if not self.configuration.nfs_oversub_ratio > 0:
- msg = _("NFS config 'nfs_oversub_ratio' invalid. Must be > 0: "
- "%s.") % self.configuration.nfs_oversub_ratio
- LOG.error(msg)
- raise exception.InvalidConfigurationValue(msg)
-
- return legacy_oversub_ratio
-
- def _get_reserved_percentage(self):
- legacy_used_ratio = self.configuration.nfs_used_ratio
- legacy_reserved_ratio = 1 - legacy_used_ratio
- legacy_percentage = legacy_reserved_ratio * 100
- if legacy_used_ratio == NFS_USED_RATIO_DEFAULT:
- return self.configuration.reserved_percentage
-
- # Honor legacy option if its value is not the default.
- msg = _LW("The option 'nfs_used_ratio' is deprecated and will "
- "be removed in the Mitaka release. Please set "
- "'reserved_percentage = %d' instead.") % (
- legacy_percentage)
- versionutils.report_deprecated_feature(LOG, msg)
-
- if not ((self.configuration.nfs_used_ratio > 0) and
- (self.configuration.nfs_used_ratio <= 1)):
- msg = _("NFS config 'nfs_used_ratio' invalid. Must be > 0 "
- "and <= 1.0: %s.") % self.configuration.nfs_used_ratio
- LOG.error(msg)
- raise exception.InvalidConfigurationValue(msg)
-
- return legacy_percentage
self._stats = None
def do_setup(self, context):
- if not self.configuration.nfs_oversub_ratio > 0:
- msg = _("NFS config 'nfs_oversub_ratio' invalid. Must be > 0: "
- "%s") % self.configuration.nfs_oversub_ratio
- LOG.error(msg)
- raise exception.NfsException(msg)
-
- if ((not self.configuration.nfs_used_ratio > 0) and
- (self.configuration.nfs_used_ratio <= 1)):
- msg = _("NFS config 'nfs_used_ratio' invalid. Must be > 0 "
- "and <= 1.0: %s") % self.configuration.nfs_used_ratio
+ if not self.configuration.max_over_subscription_ratio > 0:
+ msg = _("Config 'max_over_subscription_ratio' invalid. Must be > "
+ "0: %s") % self.configuration.max_over_subscription_ratio
LOG.error(msg)
raise exception.NfsException(msg)
data['QoS_support'] = False
data['reserved_percentage'] = 0
- if ratio_used > self.configuration.nfs_used_ratio or \
- ratio_used >= self.configuration.nfs_oversub_ratio:
+ used_percentage_limit = 100 - self.configuration.reserved_percentage
+ used_ratio_limit = used_percentage_limit / 100.0
+ if (ratio_used > used_ratio_limit or
+ ratio_used >= self.configuration.max_over_subscription_ratio):
data['reserved_percentage'] = 100
data['total_capacity_gb'] = float(capacity) / units.Gi