diff --git a/cinder/tests/unit/volume/drivers/test_kaminario.py b/cinder/tests/unit/volume/drivers/test_kaminario.py index 360f36048a1..cc591372ed4 100644 --- a/cinder/tests/unit/volume/drivers/test_kaminario.py +++ b/cinder/tests/unit/volume/drivers/test_kaminario.py @@ -13,6 +13,8 @@ # License for the specific language governing permissions and limitations # under the License. """Unit tests for kaminario driver.""" +import re + import mock from oslo_utils import units import time @@ -137,6 +139,7 @@ class TestKaminarioISCSI(test.TestCase): self.conf = mock.Mock(spec=configuration.Configuration) self.conf.kaminario_dedup_type_name = "dedup" self.conf.volume_dd_blocksize = 2 + self.conf.unique_fqdn_network = True def _setup_driver(self): self.driver = (kaminario_iscsi. @@ -527,6 +530,16 @@ class TestKaminarioISCSI(test.TestCase): 'test') self.assertIsNone(result) + def test_get_initiator_host_name(self): + result = self.driver.get_initiator_host_name(CONNECTOR) + self.assertEqual(CONNECTOR['host'], result) + + def test_get_initiator_host_name_unique(self): + self.driver.configuration.unique_fqdn_network = False + result = self.driver.get_initiator_host_name(CONNECTOR) + expected = re.sub('[:.]', '_', CONNECTOR['initiator'][::-1][:32]) + self.assertEqual(expected, result) + class TestKaminarioFC(TestKaminarioISCSI): @@ -553,3 +566,11 @@ class TestKaminarioFC(TestKaminarioISCSI): """Test terminate_connection.""" result = self.driver.terminate_connection(self.vol, CONNECTOR) self.assertIn('data', result) + + def test_get_initiator_host_name_unique(self): + connector = CONNECTOR.copy() + del connector['initiator'] + self.driver.configuration.unique_fqdn_network = False + result = self.driver.get_initiator_host_name(connector) + expected = re.sub('[:.]', '_', connector['wwnns'][0][::-1][:32]) + self.assertEqual(expected, result) diff --git a/cinder/volume/drivers/kaminario/kaminario_common.py b/cinder/volume/drivers/kaminario/kaminario_common.py index a77964cdbb6..db56a24b9c2 100644 --- a/cinder/volume/drivers/kaminario/kaminario_common.py +++ b/cinder/volume/drivers/kaminario/kaminario_common.py @@ -49,7 +49,16 @@ kaminario_opts = [ cfg.BoolOpt('auto_calc_max_oversubscription_ratio', default=False, help="K2 driver will calculate max_oversubscription_ratio " - "on setting this option as True.")] + "on setting this option as True."), + cfg.BoolOpt('unique_fqdn_network', + default=True, + help="Whether or not our private network has unique FQDN on " + "each initiator or not. For example networks with QA " + "systems usually have multiple servers/VMs with the same " + "FQDN. When true this will create host entries on K2 " + "using the FQDN, when false it will use the reversed " + "IQN/WWNN."), +] CONF = cfg.CONF CONF.register_opts(kaminario_opts) @@ -835,13 +844,20 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver): 'kaminario:replication': True} def get_initiator_host_name(self, connector): - """Return the initiator host name. + """Return the initiator host name or unique ID. + + Unique ID when configuration's unique_fqdn_network is false will be + the reversed IQN/WWPNS. Valid characters: 0-9, a-z, A-Z, '-', '_' All other characters are replaced with '_'. Total characters in initiator host name: 32 """ - return re.sub('[^0-9a-zA-Z-_]', '_', connector.get('host', ''))[:32] + name = connector.get('initiator', + connector.get('wwnns', [''])[0])[::-1] + if self.configuration.unique_fqdn_network: + name = connector.get('host', name) + return re.sub('[^0-9a-zA-Z-_]', '_', name[:32]) def get_volume_group_name(self, vid): """Return the volume group name.""" diff --git a/releasenotes/notes/k2-non-unique-fqdns-b62a269a26fd53d5.yaml b/releasenotes/notes/k2-non-unique-fqdns-b62a269a26fd53d5.yaml new file mode 100644 index 00000000000..76c3db28ba1 --- /dev/null +++ b/releasenotes/notes/k2-non-unique-fqdns-b62a269a26fd53d5.yaml @@ -0,0 +1,6 @@ +--- +issues: + - | + Kaminario K2 now supports networks with duplicated FQDNs via configuration + option `unique_fqdn_network` so attaching in these networks will work + (bug #1720147).