diff --git a/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py b/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py index 18d40acdcf8..515672f8ba0 100644 --- a/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py +++ b/cinder/tests/unit/volume/drivers/ibm/test_xiv_proxy.py @@ -600,6 +600,67 @@ class XIVProxyTest(test.TestCase): perf_name = p._check_perf_class_on_backend({}) self.assertEqual('', perf_name) + def test_qos_class_name_contains_qos_type(self): + """Test backend naming + + Test if the naming convention is correct + when getting the right specs with qos type + """ + driver = mock.MagicMock() + driver.VERSION = "VERSION" + + p = self.proxy( + self.default_storage_info, + mock.MagicMock(), + test_mock.cinder.exception, + driver) + + p.ibm_storage_cli = mock.MagicMock() + p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = [] + perf_name = p._check_perf_class_on_backend({'bw': '100', + 'type': 'independent'}) + + self.assertEqual('cinder-qos_bw_100_type_independent', perf_name) + + def test_qos_called_with_type_parameter(self): + """Test xcli call for qos creation with type""" + driver = mock.MagicMock() + driver.VERSION = "VERSION" + + p = self.proxy( + self.default_storage_info, + mock.MagicMock(), + test_mock.cinder.exception, + driver) + + p.ibm_storage_cli = mock.MagicMock() + p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = [] + perf_name = p._check_perf_class_on_backend({'bw': '100', + 'type': 'independent'}) + p.ibm_storage_cli.cmd.perf_class_create.assert_called_once_with( + perf_class=perf_name, + type='independent') + + def test_qos_called_with_wrong_type_parameter(self): + """Test xcli call for qos creation with wrong type""" + driver = mock.MagicMock() + driver.VERSION = "VERSION" + + p = self.proxy( + self.default_storage_info, + mock.MagicMock(), + test_mock.cinder.exception, + driver) + + p.ibm_storage_cli = mock.MagicMock() + p.ibm_storage_cli.cmd.perf_class_list.return_value.as_list = [] + p.ibm_storage_cli.cmd.perf_class_create.side_effect = ( + errors.XCLIError('llegal value')) + + ex = getattr(p, "_get_exception")() + self.assertRaises(ex, p._check_perf_class_on_backend, + {'bw': '100', 'type': 'BAD'}) + def test_qos_class_on_backend_name_correct(self): """Test backend naming diff --git a/cinder/volume/drivers/ibm/ibm_storage/xiv_proxy.py b/cinder/volume/drivers/ibm/ibm_storage/xiv_proxy.py index 3e758a940c6..90f7f5cb413 100644 --- a/cinder/volume/drivers/ibm/ibm_storage/xiv_proxy.py +++ b/cinder/volume/drivers/ibm/ibm_storage/xiv_proxy.py @@ -111,6 +111,13 @@ class XIVProxy(proxy.IBMStorageProxy): """Proxy between the Cinder Volume and Spectrum Accelerate Storage. Supports IBM XIV, Spectrum Accelerate, A9000, A9000R + Version: 2.1.0 + Required pyxcli version: 1.1.2 + + 2.0 - First open source driver version + 2.1.0 - Support Consistency groups through Generic volume groups + - Support XIV\A9000 Volume independent QoS + """ async_rates = ( Rate(rpo=120, schedule='00:01:00'), @@ -172,6 +179,10 @@ class XIVProxy(proxy.IBMStorageProxy): self.ibm_storage_remote_cli = self._init_xcli(remote_id) self._event_service_start() self._update_stats() + LOG.info("IBM Storage %(common_ver)s " + "xiv_proxy %(proxy_ver)s. ", + {'common_ver': self.full_version, + 'proxy_ver': self.full_version}) self._update_system_id() if remote_id: self._update_active_schedule_objects() @@ -355,8 +366,10 @@ class XIVProxy(proxy.IBMStorageProxy): # list is not empty, check if class has the right values for perf_class in classes_list: - if (not perf_class.max_iops == specs.get('iops', '0') or - not perf_class.max_bw == specs.get('bw', '0')): + if (not perf_class.get('max_iops', + None) == specs.get('iops', '0') or + not perf_class.get('max_bw', + None) == specs.get('bw', '0')): raise self.meta['exception'].VolumeBackendAPIException( data=PERF_CLASS_VALUES_ERROR % {'details': perf_class_name}) @@ -374,8 +387,16 @@ class XIVProxy(proxy.IBMStorageProxy): def _create_qos_class(self, perf_class_name, specs): """Create the qos class on the backend.""" try: - self._call_xiv_xcli("perf_class_create", - perf_class=perf_class_name) + # check if we have a shared (default) perf class + # or an independent perf class + if 'type_' in perf_class_name: + _type = perf_class_name.split('type_')[1] + self._call_xiv_xcli("perf_class_create", + perf_class=perf_class_name, + type=_type) + else: + self._call_xiv_xcli("perf_class_create", + perf_class=perf_class_name) except errors.XCLIError as e: details = self._get_code_and_status_or_message(e) diff --git a/releasenotes/notes/xiv-new-qos-independent-type-58885c77efe24798.yaml b/releasenotes/notes/xiv-new-qos-independent-type-58885c77efe24798.yaml new file mode 100644 index 00000000000..31b84528045 --- /dev/null +++ b/releasenotes/notes/xiv-new-qos-independent-type-58885c77efe24798.yaml @@ -0,0 +1,7 @@ +--- +features: + - Added independent and shared types for qos classes in XIV & A9000. + Shared type enables to share bandwidth and IO rates between volumes + of the same class. Independent type gives each volume the same + bandwidth and IO rates without being affected by other volumes in + the same qos class.