Merge "HPE 3PAR: Support duplicated FQDN in network"

This commit is contained in:
Zuul 2020-04-22 11:33:13 +00:00 committed by Gerrit Code Review
commit 0dab916125
10 changed files with 143 additions and 32 deletions

View File

@ -288,6 +288,7 @@ def list_opts():
cinder_volume_driver.nvmet_opts,
cinder_volume_driver.scst_opts,
cinder_volume_driver.image_opts,
cinder_volume_driver.fqdn_opts,
cinder_volume_drivers_dell_emc_powermax_common.powermax_opts,
cinder_volume_drivers_dell_emc_sc_storagecentercommon.
common_opts,

View File

@ -18,6 +18,7 @@ import ast
import copy
from unittest import mock
from oslo_config import cfg
from oslo_utils import units
from oslo_utils import uuidutils
@ -28,6 +29,7 @@ from cinder import test
from cinder.tests.unit import fake_volume
from cinder.tests.unit.volume.drivers.hpe \
import fake_hpe_3par_client as hpe3parclient
from cinder.volume import configuration as cvol_cfg
from cinder.volume.drivers.hpe import hpe_3par_base as hpedriverbase
from cinder.volume.drivers.hpe import hpe_3par_common as hpecommon
from cinder.volume.drivers.hpe import hpe_3par_fc as hpefcdriver
@ -38,6 +40,8 @@ from cinder.volume import volume_utils
hpeexceptions = hpe3parclient.hpeexceptions
CONF = cfg.CONF
HPE3PAR_CPG = 'OpenStackCPG'
HPE3PAR_CPG2 = 'fakepool'
@ -4984,9 +4988,53 @@ class TestHPE3PARDriverBase(HPE3PARBaseDriver):
def test__safe_hostname(self):
long_hostname = "abc123abc123abc123abc123abc123abc123"
fixed_hostname = "abc123abc123abc123abc123abc123a"
common = hpecommon.HPE3PARCommon(None)
safe_host = common._safe_hostname(long_hostname)
self.assertEqual(fixed_hostname, safe_host)
mock_client = self.setup_driver()
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
mock_create_client.return_value = mock_client
common = self.driver._login()
safe_host = common._safe_hostname(long_hostname)
self.assertEqual(fixed_hostname, safe_host)
def test__safe_hostname_unique(self):
long_hostname = "abc123abc123abc123abc123abc123abc123"
mock_client = self.setup_driver()
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
mock_create_client.return_value = mock_client
common = self.driver._login()
self.addCleanup(CONF.clear_override,
'unique_fqdn_network',
group=cvol_cfg.SHARED_CONF_GROUP)
CONF.set_override('unique_fqdn_network',
False,
group=cvol_cfg.SHARED_CONF_GROUP)
my_connector = self.connector.copy()
my_connector['initiator'] = 'iqn.1993-08.org.debian:01:222:12345'
ret_name = '54321-222-10-naibed.gro.80-3991'
safe_host = common._safe_hostname(long_hostname, my_connector)
self.assertEqual(ret_name, safe_host)
def test__safe_hostname_unique_without_initiator(self):
long_hostname = "abc123abc123abc123abc123abc123abc123"
fixed_hostname = "abc123abc123abc123abc123abc123a"
mock_client = self.setup_driver()
with mock.patch.object(hpecommon.HPE3PARCommon,
'_create_client') as mock_create_client:
mock_create_client.return_value = mock_client
common = self.driver._login()
self.addCleanup(CONF.clear_override,
'unique_fqdn_network',
group=cvol_cfg.SHARED_CONF_GROUP)
CONF.set_override('unique_fqdn_network',
False,
group=cvol_cfg.SHARED_CONF_GROUP)
my_connector = self.connector.copy()
del(my_connector['initiator'])
safe_host = common._safe_hostname(long_hostname, my_connector)
self.assertEqual(fixed_hostname, safe_host)
@mock.patch('cinder.volume.drivers.hpe.hpe_3par_common.HPE3PARCommon.'
'is_volume_group_snap_type')

View File

@ -18,6 +18,7 @@ import time
from unittest import mock
import ddt
from oslo_config import cfg
from oslo_utils import units
from cinder import context
@ -34,6 +35,8 @@ from cinder.volume.drivers.kaminario import kaminario_fc
from cinder.volume.drivers.kaminario import kaminario_iscsi
from cinder.volume import volume_utils
CONF = cfg.CONF
CONNECTOR = {'initiator': 'iqn.1993-08.org.debian:01:12aa12aa12aa',
'ip': '192.168.2.5', 'platform': 'x86_64', 'host': 'test-k2',
'wwpns': ['12341a2a00001234', '12341a2a00001235'],
@ -141,7 +144,6 @@ class TestKaminarioCommon(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
self.conf.disable_discovery = False
def _setup_driver(self):
@ -524,7 +526,12 @@ class TestKaminarioCommon(test.TestCase):
self.assertEqual(CONNECTOR['host'], result)
def test_get_initiator_host_name_unique(self):
self.driver.configuration.unique_fqdn_network = False
self.addCleanup(CONF.clear_override,
'unique_fqdn_network',
group=configuration.SHARED_CONF_GROUP)
CONF.set_override('unique_fqdn_network',
False,
group=configuration.SHARED_CONF_GROUP)
result = self.driver.get_initiator_host_name(CONNECTOR)
expected = re.sub('[:.]', '_', CONNECTOR['initiator'][::-1][:32])
self.assertEqual(expected, result)
@ -627,7 +634,12 @@ class TestKaminarioFC(TestKaminarioCommon):
def test_get_initiator_host_name_unique(self):
connector = CONNECTOR.copy()
del connector['initiator']
self.driver.configuration.unique_fqdn_network = False
self.addCleanup(CONF.clear_override,
'unique_fqdn_network',
group=configuration.SHARED_CONF_GROUP)
CONF.set_override('unique_fqdn_network',
False,
group=configuration.SHARED_CONF_GROUP)
result = self.driver.get_initiator_host_name(connector)
expected = re.sub('[:.]', '_', connector['wwnns'][0][::-1][:32])
self.assertEqual(expected, result)

View File

@ -329,6 +329,16 @@ image_opts = [
'section or in [backend_defaults] section as a common '
'configuration for all backends.'),
]
fqdn_opts = [
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 3PAR "
"using the FQDN, when false it will use the reversed "
"IQN/WWNN."),
]
CONF = cfg.CONF
@ -343,6 +353,7 @@ CONF.register_opts(nvmet_opts)
CONF.register_opts(scst_opts)
CONF.register_opts(backup_opts)
CONF.register_opts(image_opts)
CONF.register_opts(fqdn_opts, group=configuration.SHARED_CONF_GROUP)
CONF.import_opt('backup_use_same_host', 'cinder.backup.api')
@ -404,6 +415,7 @@ class BaseVD(object):
self.configuration.append_config_values(scst_opts)
self.configuration.append_config_values(backup_opts)
self.configuration.append_config_values(image_opts)
self.configuration.append_config_values(fqdn_opts)
utils.setup_tracing(self.configuration.safe_get('trace_flags'))
# NOTE(geguileo): Don't allow to start if we are enabling

View File

@ -295,11 +295,12 @@ class HPE3PARCommon(object):
4.0.13 - Fixed detaching issue for volume with type multiattach
enabled. bug #1834660
4.0.14 - Added Peer Persistence feature
4.0.15 - Support duplicated FQDN in network. Bug #1834695
"""
VERSION = "4.0.14"
VERSION = "4.0.15"
stats = {}
@ -374,7 +375,7 @@ class HPE3PARCommon(object):
'san_ip', 'san_login', 'san_password', 'reserved_percentage',
'max_over_subscription_ratio', 'replication_device', 'target_port',
'san_ssh_port', 'ssh_conn_timeout', 'san_private_key',
'target_ip_address')
'target_ip_address', 'unique_fqdn_network')
return hpe3par_opts + additional_opts
def check_flags(self, options, required_flags):
@ -1451,19 +1452,27 @@ class HPE3PARCommon(object):
raise exception.VolumeBackendAPIException(
data=e.get_description())
def _safe_hostname(self, hostname):
def _safe_hostname(self, hostname, connector=None):
"""We have to use a safe hostname length for 3PAR host names."""
try:
index = hostname.index('.')
except ValueError:
# couldn't find it
index = len(hostname)
SHARED_CONF_GROUP = 'backend_defaults'
shared_backend_conf = CONF._get(SHARED_CONF_GROUP)
unique_fqdn_network = shared_backend_conf.unique_fqdn_network
if(not unique_fqdn_network and connector.get('initiator')):
iqn = connector.get('initiator')
iqn = iqn.replace(":", "-")
return iqn[::-1][:31]
else:
try:
index = hostname.index('.')
except ValueError:
# couldn't find it
index = len(hostname)
# we'll just chop this off for now.
if index > 31:
index = 31
# we'll just chop this off for now.
if index > 31:
index = 31
return hostname[:index]
return hostname[:index]
def _get_3par_host(self, hostname):
return self.client.getHost(hostname)

View File

@ -339,7 +339,7 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
# for now, do not remove zones
zone_remove = False
else:
hostname = common._safe_hostname(connector['host'])
hostname = common._safe_hostname(connector['host'], connector)
common.terminate_connection(volume, hostname,
wwn=connector['wwpns'],
remote_client=remote_client)
@ -528,7 +528,7 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase):
"""Creates or modifies existing 3PAR host."""
host = None
domain = None
hostname = common._safe_hostname(connector['host'])
hostname = common._safe_hostname(connector['host'], connector)
if remote_target:
cpg = common._get_cpg_from_cpg_map(
remote_target['cpg_map'], src_cpg)

View File

@ -495,7 +495,7 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
if is_force_detach:
common.terminate_connection(volume, None, None)
else:
hostname = common._safe_hostname(connector['host'])
hostname = common._safe_hostname(connector['host'], connector)
common.terminate_connection(
volume,
hostname,
@ -601,7 +601,7 @@ class HPE3PARISCSIDriver(hpebasedriver.HPE3PARDriverBase):
domain = None
username = None
password = None
hostname = common._safe_hostname(connector['host'])
hostname = common._safe_hostname(connector['host'], connector)
if remote_target:
cpg = common._get_cpg_from_cpg_map(

View File

@ -51,14 +51,6 @@ kaminario_opts = [
default=False,
help="K2 driver will calculate max_oversubscription_ratio "
"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."),
cfg.BoolOpt('disable_discovery',
default=False,
help="Disabling iSCSI discovery (sendtargets) for multipath "
@ -139,7 +131,7 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
def get_driver_options(cls):
additional_opts = cls._get_oslo_driver_opts(
'san_ip', 'san_login', 'san_password', 'replication_device',
'volume_dd_blocksize')
'volume_dd_blocksize', 'unique_fqdn_network')
return kaminario_opts + additional_opts
@utils.trace
@ -847,7 +839,10 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
"""
name = connector.get('initiator',
connector.get('wwnns', [''])[0])[::-1]
if self.configuration.unique_fqdn_network:
SHARED_CONF_GROUP = 'backend_defaults'
shared_backend_conf = CONF._get(SHARED_CONF_GROUP)
unique_fqdn_network = shared_backend_conf.unique_fqdn_network
if unique_fqdn_network:
name = connector.get('host', name)
return re.sub('[^0-9a-zA-Z-_]', '_', name[:32])

View File

@ -539,3 +539,30 @@ Specify ip address of quorum witness server in ``/etc/cinder/cinder.conf``
<other parameters>
...
Support duplicated FQDN in network
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The 3PAR driver uses the FQDN of the node that is doing the
attach as an unique identifier to map the volume.
The problem is that the FQDN is not always unique, there are
environments where the same FQDN can be found in different systems, and
in those cases if both try to attach volumes the second system will
fail.
One example of this happening would be on a QA environment where you are
creating VMs and they all have names like controller-0.localdomain and
compute-0.localdomain.
To support these kind of environments, the user can specify below flag
in backend_defaults section of cinder.conf as follows:
``unique_fqdn_network = False``
When this flag is used, then during attach volume to instance,
iscsi initiator name is used instead of FQDN.
If above mentioned flag is not specified in cinder.conf,
then its value is considered as True (by default) and
FQDN is used (existing behavior).

View File

@ -0,0 +1,7 @@
---
issues:
- |
HPE 3PAR driver now supports networks with duplicated FQDNs via configuration
option `unique_fqdn_network` so attaching in these networks will work
(bug #1834695).