From 29d2090aef7b31df23ca846d365c6d21957486ba Mon Sep 17 00:00:00 2001 From: Mohammed Naser Date: Thu, 15 Feb 2018 22:22:24 -0500 Subject: [PATCH] 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 _bytes_sec QoS value. Change-Id: Iafc22d37c4c50515d9f6cf1144ea25847c90f75d --- cinder/tests/unit/volume/test_connection.py | 10 ++++++-- cinder/volume/manager.py | 24 ++++++++----------- .../capacity-based-qos-9f5d174658a40bd5.yaml | 13 ++++++++++ 3 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 releasenotes/notes/capacity-based-qos-9f5d174658a40bd5.yaml diff --git a/cinder/tests/unit/volume/test_connection.py b/cinder/tests/unit/volume/test_connection.py index 25f6cb41f0d..9b75fea1d26 100644 --- a/cinder/tests/unit/volume/test_connection.py +++ b/cinder/tests/unit/volume/test_connection.py @@ -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( diff --git a/cinder/volume/manager.py b/cinder/volume/manager.py index 765e5f0d7b9..ecf590e96d4 100644 --- a/cinder/volume/manager.py +++ b/cinder/volume/manager.py @@ -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) diff --git a/releasenotes/notes/capacity-based-qos-9f5d174658a40bd5.yaml b/releasenotes/notes/capacity-based-qos-9f5d174658a40bd5.yaml new file mode 100644 index 00000000000..e85112ceefe --- /dev/null +++ b/releasenotes/notes/capacity-based-qos-9f5d174658a40bd5.yaml @@ -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.