Add throughput limits that scale per-GB

This allows new values in QoS specs:
 - read_bytes_sec_per_gb
 - write_bytes_sec_per_gb
 - total_bytes_sec_per_gb

The bytes value specifed in the QoS spec is multiplied
by the size of the volume in initialize_connection,
and the result is passed along like a standard <x>_bytes_sec
QoS value.

Change-Id: Iafc22d37c4c50515d9f6cf1144ea25847c90f75d
This commit is contained in:
Mohammed Naser 2018-02-15 22:22:24 -05:00
parent 0841b40789
commit 29d2090aef
3 changed files with 31 additions and 16 deletions

View File

@ -194,7 +194,10 @@ class VolumeConnectionTestCase(base.BaseVolumeTestCase):
'specs': {
'write_iops_sec_per_gb': 5,
'read_iops_sec_per_gb': 7700,
'total_iops_sec_per_gb': 300000}
'total_iops_sec_per_gb': 300000,
'read_bytes_sec_per_gb': 10,
'write_bytes_sec_per_gb': 40,
'total_bytes_sec_per_gb': 1048576}
}
with mock.patch.object(cinder.volume.volume_types,
@ -206,7 +209,10 @@ class VolumeConnectionTestCase(base.BaseVolumeTestCase):
mock_get_target.return_value = None
qos_specs_expected = {'write_iops_sec': 15,
'read_iops_sec': 23100,
'total_iops_sec': 900000}
'total_iops_sec': 900000,
'read_bytes_sec': 30,
'write_bytes_sec': 120,
'total_bytes_sec': 3145728}
# initialize_connection() passes qos_specs that is designated to
# be consumed by front-end or both front-end and back-end
conn_info = self.volume.initialize_connection(

View File

@ -1602,22 +1602,18 @@ class VolumeManager(manager.CleanableManager,
if qos and qos.get('consumer') in ['front-end', 'both']:
specs = qos.get('specs')
# NOTE(mnaser): The following configures for per-GB QoS
if specs is not None:
# Compute fixed IOPS values for per-GB keys
if 'write_iops_sec_per_gb' in specs:
specs['write_iops_sec'] = (
int(specs['write_iops_sec_per_gb']) * int(volume.size))
specs.pop('write_iops_sec_per_gb')
volume_size = int(volume.size)
tune_opts = ('read_iops_sec', 'read_bytes_sec',
'write_iops_sec', 'write_bytes_sec',
'total_iops_sec', 'total_bytes_sec')
if 'read_iops_sec_per_gb' in specs:
specs['read_iops_sec'] = (
int(specs['read_iops_sec_per_gb']) * int(volume.size))
specs.pop('read_iops_sec_per_gb')
if 'total_iops_sec_per_gb' in specs:
specs['total_iops_sec'] = (
int(specs['total_iops_sec_per_gb']) * int(volume.size))
specs.pop('total_iops_sec_per_gb')
for option in tune_opts:
option_per_gb = '%s_per_gb' % option
if option_per_gb in specs:
specs[option] = int(specs[option_per_gb]) * volume_size
specs.pop(option_per_gb)
qos_spec = dict(qos_specs=specs)
conn_info['data'].update(qos_spec)

View File

@ -0,0 +1,13 @@
---
features:
- Cinder now allows for capacity based QoS which can be useful in
environments where storage performance scales with consumption (such as
RBD backed storage). The newly added QoS specs are `read_iops_sec_per_gb`,
`write_iops_sec_per_gb`, `total_iops_sec_per_gb`, `read_bytes_sec_per_gb`,
`write_bytes_sec_per_gb` and `total_bytes_sec_per_gb`. These values will
be multiplied by the size of the volume and passed to the consumer.
For example, setting `total_iops_sec_per_gb` to 30 and setting
`total_bytes_sec_per_gb` to `1048576` (1MB) then creating a 100 GB volume
with that QoS will result in a volume with 3,000 total IOPs and 100MB/s
throughput limit.