Merge "HPE 3PAR: Support duplicated FQDN in network" into stable/train
This commit is contained in:
commit
bce5c6946d
|
@ -295,6 +295,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_datera_dateraiscsi.d_opts,
|
||||
cinder_volume_drivers_dell_emc_powermax_common.powermax_opts,
|
||||
cinder_volume_drivers_dell_emc_ps.eqlx_opts,
|
||||
|
|
|
@ -19,6 +19,7 @@ import copy
|
|||
import mock
|
||||
|
||||
import ddt
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import units
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
|
@ -29,6 +30,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
|
||||
|
@ -39,6 +41,8 @@ from cinder.volume import volume_utils
|
|||
|
||||
hpeexceptions = hpe3parclient.hpeexceptions
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
HPE3PAR_CPG = 'OpenStackCPG'
|
||||
HPE3PAR_CPG2 = 'fakepool'
|
||||
|
@ -5167,9 +5171,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')
|
||||
|
|
|
@ -17,6 +17,7 @@ import re
|
|||
|
||||
import ddt
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import units
|
||||
import time
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -319,6 +319,16 @@ image_opts = [
|
|||
'image transfer will be aborted when multipathd is not '
|
||||
'running. Otherwise, it will fallback to single path.'),
|
||||
]
|
||||
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
|
||||
|
@ -333,6 +343,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')
|
||||
|
||||
|
||||
|
@ -394,6 +405,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
|
||||
|
|
|
@ -58,6 +58,7 @@ from cinder import objects
|
|||
from cinder.objects import fields
|
||||
from cinder import utils
|
||||
from cinder.volume import configuration
|
||||
from cinder.volume import driver
|
||||
from cinder.volume import qos_specs
|
||||
from cinder.volume import volume_types
|
||||
from cinder.volume import volume_utils
|
||||
|
@ -297,11 +298,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 = {}
|
||||
|
||||
|
@ -372,7 +374,7 @@ class HPE3PARCommon(object):
|
|||
|
||||
@staticmethod
|
||||
def get_driver_options():
|
||||
return hpe3par_opts
|
||||
return hpe3par_opts + driver.fqdn_opts
|
||||
|
||||
def check_flags(self, options, required_flags):
|
||||
for flag in required_flags:
|
||||
|
@ -1468,19 +1470,29 @@ 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
|
||||
LOG.debug("unique_fqdn_network: %(fqdn)s",
|
||||
{'fqdn': 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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -35,6 +35,7 @@ from cinder import objects
|
|||
from cinder.objects import fields
|
||||
from cinder import utils
|
||||
from cinder.volume import configuration
|
||||
from cinder.volume import driver
|
||||
from cinder.volume.drivers.san import san
|
||||
from cinder.volume import volume_utils
|
||||
|
||||
|
@ -51,14 +52,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 "
|
||||
|
@ -137,7 +130,7 @@ class KaminarioCinderDriver(cinder.volume.driver.ISCSIDriver):
|
|||
|
||||
@staticmethod
|
||||
def get_driver_options():
|
||||
return kaminario_opts
|
||||
return kaminario_opts + driver.fqdn_opts
|
||||
|
||||
@utils.trace
|
||||
def check_for_setup_error(self):
|
||||
|
@ -844,7 +837,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])
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
Loading…
Reference in New Issue