diff --git a/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py b/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py index dc22da1ebc1..acced87f48b 100644 --- a/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py +++ b/cinder/tests/unit/volume/drivers/huawei/test_huawei_drivers.py @@ -23,6 +23,7 @@ import requests import tempfile import unittest from xml.dom import minidom +from xml.etree import ElementTree from cinder import context from cinder import exception @@ -5213,6 +5214,7 @@ class HuaweiFCDriverTestCase(HuaweiTestBase): self.assertTrue(ret) +@ddt.ddt class HuaweiConfTestCase(test.TestCase): def setUp(self): super(HuaweiConfTestCase, self).setUp() @@ -5224,7 +5226,7 @@ class HuaweiConfTestCase(test.TestCase): self.conf.cinder_huawei_conf_file = self.fake_xml_file self.huawei_conf = huawei_conf.HuaweiConf(self.conf) - def _create_fake_conf_file(self): + def _create_fake_conf_file(self, configs): """Create a fake Config file. Huawei storage customize a XML configuration file, the configuration @@ -5252,7 +5254,7 @@ class HuaweiConfTestCase(test.TestCase): password.appendChild(password_text) storage.appendChild(password) product = doc.createElement('Product') - product_text = doc.createTextNode('V3') + product_text = doc.createTextNode(configs.get('Product', 'V3')) product.appendChild(product_text) storage.appendChild(product) protocol = doc.createElement('Protocol') @@ -5262,10 +5264,13 @@ class HuaweiConfTestCase(test.TestCase): lun = doc.createElement('LUN') config.appendChild(lun) - luntype = doc.createElement('LUNType') - luntype_text = doc.createTextNode('Thick') - luntype.appendChild(luntype_text) - lun.appendChild(luntype) + + if 'LUNType' in configs: + luntype = doc.createElement('LUNType') + luntype_text = doc.createTextNode(configs['LUNType']) + luntype.appendChild(luntype_text) + lun.appendChild(luntype) + lun_ready_wait_interval = doc.createElement('LUNReadyWaitInterval') lun_ready_wait_interval_text = doc.createTextNode('2') lun_ready_wait_interval.appendChild(lun_ready_wait_interval_text) @@ -5313,6 +5318,56 @@ class HuaweiConfTestCase(test.TestCase): fakefile.write(doc.toprettyxml(indent='')) fakefile.close() + @ddt.data( + ( + { + 'Product': 'Dorado', + 'LUNType': 'Thin', + }, + 1, + ), + ( + { + 'Product': 'Dorado', + }, + 1, + ), + ( + { + 'Product': 'Dorado', + 'LUNType': 'Thick', + }, + exception.InvalidInput, + ), + ( + { + 'Product': 'V3', + 'LUNType': 'Thick', + }, + 0, + ), + ( + { + 'Product': 'V3', + 'LUNType': 'invalid', + }, + exception.InvalidInput, + ), + ) + @ddt.unpack + def test_luntype_config(self, custom_configs, expect_result): + self._create_fake_conf_file(custom_configs) + tree = ElementTree.parse(self.conf.cinder_huawei_conf_file) + xml_root = tree.getroot() + self.huawei_conf._san_product(xml_root) + + if isinstance(expect_result, int): + self.huawei_conf._lun_type(xml_root) + self.assertEqual(expect_result, self.conf.lun_type) + else: + self.assertRaises(expect_result, + self.huawei_conf._lun_type, xml_root) + @ddt.ddt class HuaweiRestClientTestCase(test.TestCase): diff --git a/cinder/volume/drivers/huawei/constants.py b/cinder/volume/drivers/huawei/constants.py index fdfc453390e..be37dc77caf 100644 --- a/cinder/volume/drivers/huawei/constants.py +++ b/cinder/volume/drivers/huawei/constants.py @@ -113,6 +113,13 @@ REPLICA_DATA_STATUS_SYNCED = '1' REPLICA_DATA_STATUS_COMPLETE = '2' REPLICA_DATA_STATUS_INCOMPLETE = '3' +LUN_TYPE_MAP = {'Thick': THICK_LUNTYPE, + 'Thin': THIN_LUNTYPE} + +PRODUCT_LUN_TYPE = { + 'Dorado': 'Thin', +} + VOLUME_NOT_EXISTS_WARN = 'warning' VOLUME_NOT_EXISTS_RAISE = 'raise' diff --git a/cinder/volume/drivers/huawei/huawei_conf.py b/cinder/volume/drivers/huawei/huawei_conf.py index c89a63f9420..4f8032af23c 100644 --- a/cinder/volume/drivers/huawei/huawei_conf.py +++ b/cinder/volume/drivers/huawei/huawei_conf.py @@ -138,20 +138,33 @@ class HuaweiConf(object): setattr(self.conf, 'san_protocol', protocol) def _lun_type(self, xml_root): - lun_type = constants.THICK_LUNTYPE + lun_type = constants.PRODUCT_LUN_TYPE.get(self.conf.san_product, + 'Thick') + + def _verify_conf_lun_type(lun_type): + if lun_type not in constants.LUN_TYPE_MAP: + msg = _("Invalid lun type %s is configured.") % lun_type + LOG.error(msg) + raise exception.InvalidInput(reason=msg) + + if self.conf.san_product in constants.PRODUCT_LUN_TYPE: + product_lun_type = constants.PRODUCT_LUN_TYPE[ + self.conf.san_product] + if lun_type != product_lun_type: + msg = _("%(array)s array requires %(valid)s lun type, " + "but %(conf)s is specified.") % { + 'array': self.conf.san_product, + 'valid': product_lun_type, + 'conf': lun_type} + LOG.error(msg) + raise exception.InvalidInput(reason=msg) text = xml_root.findtext('LUN/LUNType') if text: lun_type = text.strip() - if lun_type == 'Thick': - lun_type = constants.THICK_LUNTYPE - elif lun_type == 'Thin': - lun_type = constants.THIN_LUNTYPE - else: - msg = (_("Invalid lun type %s is configured.") % lun_type) - LOG.exception(msg) - raise exception.InvalidInput(reason=msg) + _verify_conf_lun_type(lun_type) + lun_type = constants.LUN_TYPE_MAP[lun_type] setattr(self.conf, 'lun_type', lun_type) def _lun_ready_wait_interval(self, xml_root): diff --git a/releasenotes/notes/verify-dorado-luntype-for-huawei-driver-4fc2f4cca3141bb3.yaml b/releasenotes/notes/verify-dorado-luntype-for-huawei-driver-4fc2f4cca3141bb3.yaml new file mode 100644 index 00000000000..0fa4e3d7604 --- /dev/null +++ b/releasenotes/notes/verify-dorado-luntype-for-huawei-driver-4fc2f4cca3141bb3.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Add 'LUNType' configuration verification for Huawei driver when + connecting to Dorado array. Because Dorado array only supports + 'Thin' lun type, so 'LUNType' only can be configured as 'Thin', + any other type is invalid and if 'LUNType' not explicitly configured, + by default use 'Thin' for Dorado array.