From 5363d21d5799d410fedc28d7d598d7cb5d9565e2 Mon Sep 17 00:00:00 2001 From: Atsushi Kawai Date: Fri, 17 Feb 2023 18:19:20 +0000 Subject: [PATCH] Hitachi: add an option for host group name format This patch is to add an configuration option which specifies hostgroup(or iSCSI target) name format. Implements: blueprint hitachi-vsp-add-hostgroup-name-format-option Change-Id: Icf3c8dc4ba2fd96cda01d778e3a49406fec3b9db --- cinder/opts.py | 1 + .../hitachi/test_hitachi_hbsd_rest_fc.py | 50 ++++++++ .../hitachi/test_hitachi_hbsd_rest_iscsi.py | 52 ++++++++ cinder/volume/drivers/hitachi/hbsd_common.py | 113 ++++++++++++++++++ cinder/volume/drivers/hitachi/hbsd_fc.py | 3 + cinder/volume/drivers/hitachi/hbsd_iscsi.py | 3 + cinder/volume/drivers/hitachi/hbsd_rest.py | 22 ++++ cinder/volume/drivers/hitachi/hbsd_rest_fc.py | 15 +-- .../volume/drivers/hitachi/hbsd_rest_iscsi.py | 12 +- cinder/volume/drivers/hitachi/hbsd_utils.py | 2 +- ...p-name-format-option-4c8e4a5ddd69b9bd.yaml | 53 ++++++++ 11 files changed, 304 insertions(+), 22 deletions(-) create mode 100644 releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml diff --git a/cinder/opts.py b/cinder/opts.py index 9ef804512fe..ffdc4cf8947 100644 --- a/cinder/opts.py +++ b/cinder/opts.py @@ -354,6 +354,7 @@ def list_opts(): FJ_ETERNUS_DX_OPT_opts, cinder_volume_drivers_hitachi_hbsdcommon.COMMON_VOLUME_OPTS, cinder_volume_drivers_hitachi_hbsdcommon.COMMON_PORT_OPTS, + cinder_volume_drivers_hitachi_hbsdcommon.COMMON_NAME_OPTS, cinder_volume_drivers_hitachi_hbsdrest.REST_VOLUME_OPTS, cinder_volume_drivers_hitachi_hbsdrestfc.FC_VOLUME_OPTS, cinder_volume_drivers_hpe_hpe3parcommon.hpe3par_opts, diff --git a/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_fc.py b/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_fc.py index 733eb876186..6f236a055b1 100644 --- a/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_fc.py +++ b/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_fc.py @@ -470,6 +470,7 @@ class HBSDRESTFCDriverTest(test.TestCase): self.configuration.hitachi_copy_check_interval = 3 self.configuration.hitachi_async_copy_check_interval = 10 self.configuration.hitachi_port_scheduler = False + self.configuration.hitachi_group_name_format = None self.configuration.san_login = CONFIG_MAP['user_id'] self.configuration.san_password = CONFIG_MAP['user_pass'] @@ -617,6 +618,54 @@ class HBSDRESTFCDriverTest(test.TestCase): self.driver.common.client.keep_session_loop.stop() self.driver.common.client.keep_session_loop.wait() + @mock.patch.object(requests.Session, "request") + @mock.patch.object( + volume_utils, 'brick_get_connector_properties', + side_effect=_brick_get_connector_properties) + def test_do_setup_create_hg_format( + self, brick_get_connector_properties, request): + drv = hbsd_fc.HBSDFCDriver(configuration=self.configuration) + self._setup_config() + self.configuration.hitachi_group_name_format = ( + 'HBSD-{wwn}-{host}-_:.@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@') + request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT), + FakeResponse(200, GET_PORTS_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)] + drv.do_setup(None) + self.assertEqual( + {CONFIG_MAP['port_id']: CONFIG_MAP['target_wwn']}, + drv.common.storage_info['wwns']) + self.assertEqual(1, brick_get_connector_properties.call_count) + self.assertEqual(8, request.call_count) + # stop the Loopingcall within the do_setup treatment + self.driver.common.client.keep_session_loop.stop() + self.driver.common.client.keep_session_loop.wait() + + @mock.patch.object(requests.Session, "request") + @mock.patch.object( + volume_utils, 'brick_get_connector_properties', + side_effect=_brick_get_connector_properties) + def test_do_setup_create_hg_format_error( + self, brick_get_connector_properties, request): + drv = hbsd_fc.HBSDFCDriver(configuration=self.configuration) + self._setup_config() + self.configuration.hitachi_group_name_format = '{host}-{wwn}' + request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT), + FakeResponse(200, GET_PORTS_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)] + + self.assertRaises(exception.VolumeDriverException, drv.do_setup, None) + @mock.patch.object(requests.Session, "request") @mock.patch.object( volume_utils, 'brick_get_connector_properties', @@ -1286,6 +1335,7 @@ class HBSDRESTFCDriverTest(test.TestCase): ret = self.driver.get_driver_options() actual = (hbsd_common.COMMON_VOLUME_OPTS + hbsd_common.COMMON_PORT_OPTS + + hbsd_common.COMMON_NAME_OPTS + hbsd_rest.REST_VOLUME_OPTS + hbsd_rest_fc.FC_VOLUME_OPTS) self.assertEqual(actual, ret) diff --git a/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_iscsi.py b/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_iscsi.py index 65c6b1650e6..08b2f3e1403 100644 --- a/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_iscsi.py +++ b/cinder/tests/unit/volume/drivers/hitachi/test_hitachi_hbsd_rest_iscsi.py @@ -343,6 +343,7 @@ class HBSDRESTISCSIDriverTest(test.TestCase): self.configuration.hitachi_copy_check_interval = 3 self.configuration.hitachi_async_copy_check_interval = 10 self.configuration.hitachi_port_scheduler = False + self.configuration.hitachi_group_name_format = None self.configuration.san_login = CONFIG_MAP['user_id'] self.configuration.san_password = CONFIG_MAP['user_pass'] @@ -498,6 +499,56 @@ class HBSDRESTISCSIDriverTest(test.TestCase): self.driver.common.client.keep_session_loop.stop() self.driver.common.client.keep_session_loop.wait() + @mock.patch.object(requests.Session, "request") + @mock.patch.object( + volume_utils, 'brick_get_connector_properties', + side_effect=_brick_get_connector_properties) + def test_do_setup_create_hg_format( + self, brick_get_connector_properties, request): + drv = hbsd_iscsi.HBSDISCSIDriver(configuration=self.configuration) + self._setup_config() + self.configuration.hitachi_group_name_format = 'HBSD-{ip}@{host}-_:.' + request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT), + FakeResponse(200, GET_PORTS_RESULT), + FakeResponse(200, GET_PORT_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)] + drv.do_setup(None) + self.assertEqual( + {CONFIG_MAP['port_id']: + '%(ip)s:%(port)s' % { + 'ip': CONFIG_MAP['ipv4Address'], + 'port': CONFIG_MAP['tcpPort']}}, + drv.common.storage_info['portals']) + self.assertEqual(1, brick_get_connector_properties.call_count) + self.assertEqual(8, request.call_count) + # stop the Loopingcall within the do_setup treatment + self.driver.common.client.keep_session_loop.stop() + self.driver.common.client.keep_session_loop.wait() + + @mock.patch.object(requests.Session, "request") + @mock.patch.object( + volume_utils, 'brick_get_connector_properties', + side_effect=_brick_get_connector_properties) + def test_do_setup_create_hg_format_error( + self, brick_get_connector_properties, request): + drv = hbsd_iscsi.HBSDISCSIDriver(configuration=self.configuration) + self._setup_config() + self.configuration.hitachi_group_name_format = ( + 'HBSD-{ip}@{host}ZZZZZZZZZZZ') + request.side_effect = [FakeResponse(200, POST_SESSIONS_RESULT), + FakeResponse(200, GET_PORTS_RESULT), + FakeResponse(200, GET_PORT_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(200, NOTFOUND_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT), + FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)] + self.assertRaises(exception.VolumeDriverException, drv.do_setup, None) + @mock.patch.object(requests.Session, "request") def test_extend_volume(self, request): request.side_effect = [FakeResponse(200, GET_LDEV_RESULT), @@ -989,5 +1040,6 @@ class HBSDRESTISCSIDriverTest(test.TestCase): _get_oslo_driver_opts.return_value = [] ret = self.driver.get_driver_options() actual = (hbsd_common.COMMON_VOLUME_OPTS + + hbsd_common.COMMON_NAME_OPTS + hbsd_rest.REST_VOLUME_OPTS) self.assertEqual(actual, ret) diff --git a/cinder/volume/drivers/hitachi/hbsd_common.py b/cinder/volume/drivers/hitachi/hbsd_common.py index 5a49228eb5f..d6f437da8fa 100644 --- a/cinder/volume/drivers/hitachi/hbsd_common.py +++ b/cinder/volume/drivers/hitachi/hbsd_common.py @@ -28,6 +28,23 @@ from cinder.volume.drivers.hitachi import hbsd_utils as utils from cinder.volume import volume_types from cinder.volume import volume_utils +_GROUP_NAME_FORMAT_DEFAULT_FC = utils.TARGET_PREFIX + '{wwn}' +_GROUP_NAME_FORMAT_DEFAULT_ISCSI = utils.TARGET_PREFIX + '{ip}' +_GROUP_NAME_MAX_LEN_FC = 64 +_GROUP_NAME_MAX_LEN_ISCSI = 32 + +GROUP_NAME_ALLOWED_CHARS = 'a-zA-Z0-9.@_:-' +GROUP_NAME_VAR_WWN = '{wwn}' +GROUP_NAME_VAR_IP = '{ip}' +GROUP_NAME_VAR_HOST = '{host}' + +_GROUP_NAME_VAR_WWN_LEN = 16 +_GROUP_NAME_VAR_IP_LEN = 15 +_GROUP_NAME_VAR_HOST_LEN = 1 +_GROUP_NAME_VAR_LEN = {GROUP_NAME_VAR_WWN: _GROUP_NAME_VAR_WWN_LEN, + GROUP_NAME_VAR_IP: _GROUP_NAME_VAR_IP_LEN, + GROUP_NAME_VAR_HOST: _GROUP_NAME_VAR_HOST_LEN} + _STR_VOLUME = 'volume' _STR_SNAPSHOT = 'snapshot' @@ -114,9 +131,38 @@ COMMON_PORT_OPTS = [ 'WWNs are registered to ports in a round-robin fashion.'), ] +COMMON_NAME_OPTS = [ + cfg.StrOpt( + 'hitachi_group_name_format', + default=None, + help='Format of host groups, iSCSI targets, and server objects.'), +] + +_GROUP_NAME_FORMAT = { + 'FC': { + 'group_name_max_len': _GROUP_NAME_MAX_LEN_FC, + 'group_name_var_cnt': { + GROUP_NAME_VAR_WWN: [1], + GROUP_NAME_VAR_IP: [0], + GROUP_NAME_VAR_HOST: [0, 1], + }, + 'group_name_format_default': _GROUP_NAME_FORMAT_DEFAULT_FC, + }, + 'iSCSI': { + 'group_name_max_len': _GROUP_NAME_MAX_LEN_ISCSI, + 'group_name_var_cnt': { + GROUP_NAME_VAR_WWN: [0], + GROUP_NAME_VAR_IP: [1], + GROUP_NAME_VAR_HOST: [0, 1], + }, + 'group_name_format_default': _GROUP_NAME_FORMAT_DEFAULT_ISCSI, + } +} + CONF = cfg.CONF CONF.register_opts(COMMON_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP) CONF.register_opts(COMMON_PORT_OPTS, group=configuration.SHARED_CONF_GROUP) +CONF.register_opts(COMMON_NAME_OPTS, group=configuration.SHARED_CONF_GROUP) LOG = logging.getLogger(__name__) MSG = utils.HBSDMsg @@ -159,6 +205,24 @@ class HBSDCommon(): 'wwns': {}, 'portals': {}, } + self.group_name_format = _GROUP_NAME_FORMAT[driverinfo['proto']] + self.format_info = { + 'group_name_format': self.group_name_format[ + 'group_name_format_default'], + 'group_name_format_without_var_len': ( + len(re.sub('|'.join([GROUP_NAME_VAR_WWN, + GROUP_NAME_VAR_IP, GROUP_NAME_VAR_HOST]), '', + self.group_name_format['group_name_format_default']))), + 'group_name_var_cnt': { + GROUP_NAME_VAR_WWN: self.group_name_format[ + 'group_name_format_default'].count(GROUP_NAME_VAR_WWN), + GROUP_NAME_VAR_IP: self.group_name_format[ + 'group_name_format_default'].count(GROUP_NAME_VAR_IP), + GROUP_NAME_VAR_HOST: self.group_name_format[ + 'group_name_format_default'].count(GROUP_NAME_VAR_HOST), + } + } + self._required_common_opts = [ self.driver_info['param_prefix'] + '_storage_id', self.driver_info['param_prefix'] + '_pool', @@ -555,6 +619,10 @@ class HBSDCommon(): """Check parameter values and consistency among them.""" utils.check_opt_value(self.conf, _INHERITED_VOLUME_OPTS) self.check_opts(self.conf, COMMON_VOLUME_OPTS) + if hasattr( + self.conf, + self.driver_info['param_prefix'] + '_group_name_format'): + self.check_opts(self.conf, COMMON_NAME_OPTS) if self.conf.hitachi_ldev_range: self.storage_info['ldev_range'] = self._range2list( self.driver_info['param_prefix'] + '_ldev_range') @@ -565,6 +633,7 @@ class HBSDCommon(): param=self.driver_info['param_prefix'] + '_target_ports or ' + self.driver_info['param_prefix'] + '_compute_target_ports') self.raise_error(msg) + self._check_param_group_name_format() if (self.conf.hitachi_group_delete and not self.conf.hitachi_group_create): msg = utils.output_log( @@ -587,6 +656,50 @@ class HBSDCommon(): if self.storage_info['protocol'] == 'iSCSI': self.check_param_iscsi() + def _check_param_group_name_format(self): + if not hasattr( + self.conf, + self.driver_info['param_prefix'] + '_group_name_format'): + return + if self.conf.hitachi_group_name_format is not None: + error_flag = False + if re.match( + utils.TARGET_PREFIX + '(' + GROUP_NAME_VAR_WWN + '|' + + GROUP_NAME_VAR_IP + '|' + GROUP_NAME_VAR_HOST + '|' + '[' + + GROUP_NAME_ALLOWED_CHARS + '])+$', + self.conf.hitachi_group_name_format) is None: + error_flag = True + if not error_flag: + for var in _GROUP_NAME_VAR_LEN: + self.format_info['group_name_var_cnt'][var] = ( + self.conf.hitachi_group_name_format.count(var)) + if (self.format_info[ + 'group_name_var_cnt'][var] not in + self.group_name_format['group_name_var_cnt'][var]): + error_flag = True + break + if not error_flag: + group_name_var_replaced = self.conf.hitachi_group_name_format + for var, length in _GROUP_NAME_VAR_LEN.items(): + group_name_var_replaced = ( + group_name_var_replaced.replace(var, '_' * length)) + if len(group_name_var_replaced) > self.group_name_format[ + 'group_name_max_len']: + error_flag = True + if error_flag: + msg = utils.output_log( + MSG.INVALID_PARAMETER, + param=self.driver_info['param_prefix'] + + '_group_name_format') + raise self.raise_error(msg) + self.format_info['group_name_format'] = ( + self.conf.hitachi_group_name_format) + self.format_info['group_name_format_without_var_len'] = ( + len(re.sub('|'.join( + [GROUP_NAME_VAR_WWN, GROUP_NAME_VAR_IP, + GROUP_NAME_VAR_HOST]), '', + self.format_info['group_name_format']))) + def need_client_setup(self): """Check if the making of the communication client is necessary.""" raise NotImplementedError() diff --git a/cinder/volume/drivers/hitachi/hbsd_fc.py b/cinder/volume/drivers/hitachi/hbsd_fc.py index 658f982e579..63e79a60891 100644 --- a/cinder/volume/drivers/hitachi/hbsd_fc.py +++ b/cinder/volume/drivers/hitachi/hbsd_fc.py @@ -73,6 +73,7 @@ class HBSDFCDriver(driver.FibreChannelDriver): 2.2.3 - Add port scheduler. 2.3.0 - Support multi pool. 2.3.1 - Update retype and support storage assisted migration. + 2.3.2 - Add specifies format of the names HostGroups/iSCSI Targets. """ @@ -90,6 +91,7 @@ class HBSDFCDriver(driver.FibreChannelDriver): self.configuration.append_config_values(common.COMMON_VOLUME_OPTS) self.configuration.append_config_values(common.COMMON_PORT_OPTS) + self.configuration.append_config_values(common.COMMON_NAME_OPTS) self.configuration.append_config_values(rest_fc.FC_VOLUME_OPTS) os.environ['LANG'] = 'C' self.common = self._init_common(self.configuration, kwargs.get('db')) @@ -106,6 +108,7 @@ class HBSDFCDriver(driver.FibreChannelDriver): 'san_api_port', ])) return (common.COMMON_VOLUME_OPTS + common.COMMON_PORT_OPTS + + common.COMMON_NAME_OPTS + rest.REST_VOLUME_OPTS + rest_fc.FC_VOLUME_OPTS + additional_opts) diff --git a/cinder/volume/drivers/hitachi/hbsd_iscsi.py b/cinder/volume/drivers/hitachi/hbsd_iscsi.py index d29d01ec540..d2975025f02 100644 --- a/cinder/volume/drivers/hitachi/hbsd_iscsi.py +++ b/cinder/volume/drivers/hitachi/hbsd_iscsi.py @@ -73,6 +73,7 @@ class HBSDISCSIDriver(driver.ISCSIDriver): 2.2.3 - Add port scheduler. 2.3.0 - Support multi pool. 2.3.1 - Update retype and support storage assisted migration. + 2.3.2 - Add specifies format of the names HostGroups/iSCSI Targets. """ @@ -89,6 +90,7 @@ class HBSDISCSIDriver(driver.ISCSIDriver): super(HBSDISCSIDriver, self).__init__(*args, **kwargs) self.configuration.append_config_values(common.COMMON_VOLUME_OPTS) + self.configuration.append_config_values(common.COMMON_NAME_OPTS) os.environ['LANG'] = 'C' self.common = self._init_common(self.configuration, kwargs.get('db')) @@ -103,6 +105,7 @@ class HBSDISCSIDriver(driver.ISCSIDriver): ['driver_ssl_cert_verify', 'driver_ssl_cert_path', 'san_api_port', ])) return (common.COMMON_VOLUME_OPTS + + common.COMMON_NAME_OPTS + rest.REST_VOLUME_OPTS + additional_opts) diff --git a/cinder/volume/drivers/hitachi/hbsd_rest.py b/cinder/volume/drivers/hitachi/hbsd_rest.py index 6b31bc7fed9..35954053960 100644 --- a/cinder/volume/drivers/hitachi/hbsd_rest.py +++ b/cinder/volume/drivers/hitachi/hbsd_rest.py @@ -15,6 +15,7 @@ """REST interface module for Hitachi HBSD Driver.""" from collections import defaultdict +import re from oslo_config import cfg from oslo_config import types @@ -34,6 +35,9 @@ from cinder.volume.drivers.hitachi import hbsd_utils as utils from cinder.volume.drivers.san import san from cinder.volume import volume_utils +_GROUP_NAME_PROHIBITED_CHAR_PATTERN = re.compile( + '[^' + common.GROUP_NAME_ALLOWED_CHARS + ']') + _LU_PATH_DEFINED = ('B958', '015A') NORMAL_STS = 'NML' _LUN_TIMEOUT = 50 @@ -1312,3 +1316,21 @@ class HBSDREST(common.HBSDCommon): msg = utils.output_log( MSG.VOLUME_COPY_FAILED, pvol=pvol, svol=svol) self.raise_error(msg) + + def create_target_name(self, connector): + wwn = (min(self.get_hba_ids_from_connector(connector)) if + self.format_info['group_name_var_cnt'][ + common.GROUP_NAME_VAR_WWN] else '') + ip = (connector['ip'] if self.format_info[ + 'group_name_var_cnt'][common.GROUP_NAME_VAR_IP] else '') + if not self.format_info['group_name_var_cnt'][ + common.GROUP_NAME_VAR_HOST]: + return self.format_info['group_name_format'].format(wwn=wwn, ip=ip) + host = connector['host'] if 'host' in connector else '' + max_host_len = (self.group_name_format['group_name_max_len'] - + self.format_info['group_name_format_without_var_len'] - + len(wwn) - len(ip)) + host = _GROUP_NAME_PROHIBITED_CHAR_PATTERN.sub( + '_', host[:max_host_len]) + return self.format_info['group_name_format'].format( + host=host, wwn=wwn, ip=ip) diff --git a/cinder/volume/drivers/hitachi/hbsd_rest_fc.py b/cinder/volume/drivers/hitachi/hbsd_rest_fc.py index 6006afa029d..b05f98421b0 100644 --- a/cinder/volume/drivers/hitachi/hbsd_rest_fc.py +++ b/cinder/volume/drivers/hitachi/hbsd_rest_fc.py @@ -1,4 +1,4 @@ -# Copyright (C) 2020, 2021, Hitachi, Ltd. +# Copyright (C) 2020, 2023, Hitachi, Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -128,11 +128,7 @@ class HBSDRESTFC(rest.HBSDREST): def create_target_to_storage(self, port, connector, hba_ids): """Create a host group on the specified port.""" - wwpns = self.get_hba_ids_from_connector(connector) - target_name = '%(prefix)s-%(wwpns)s' % { - 'prefix': self.driver_info['driver_prefix'], - 'wwpns': min(wwpns), - } + target_name = self.create_target_name(connector) try: body = {'portId': port, 'hostGroupName': target_name} @@ -232,12 +228,7 @@ class HBSDRESTFC(rest.HBSDREST): self, targets, connector, target_ports): """Find mapped ports, memorize them and return unmapped port count.""" wwpns = self.get_hba_ids_from_connector(connector) - target_names = [ - '%(prefix)s-%(wwpns)s' % { - 'prefix': self.driver_info['driver_prefix'], - 'wwpns': min(wwpns), - } - ] + target_names = [self.create_target_name(connector)] if 'ip' in connector: target_names.append( '%(prefix)s-%(ip)s' % { diff --git a/cinder/volume/drivers/hitachi/hbsd_rest_iscsi.py b/cinder/volume/drivers/hitachi/hbsd_rest_iscsi.py index 2b3224fdf69..2be13e72722 100644 --- a/cinder/volume/drivers/hitachi/hbsd_rest_iscsi.py +++ b/cinder/volume/drivers/hitachi/hbsd_rest_iscsi.py @@ -1,4 +1,4 @@ -# Copyright (C) 2020, 2021, Hitachi, Ltd. +# Copyright (C) 2020, 2023, Hitachi, Ltd. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -90,10 +90,7 @@ class HBSDRESTISCSI(rest.HBSDREST): def create_target_to_storage(self, port, connector, hba_ids): """Create an iSCSI target on the specified port.""" - target_name = '%(prefix)s-%(ip)s' % { - 'prefix': self.driver_info['driver_prefix'], - 'ip': connector['ip'], - } + target_name = self.create_target_name(connector) body = {'portId': port, 'hostGroupName': target_name} if hba_ids: body['iscsiName'] = '%(id)s%(suffix)s' % { @@ -183,10 +180,7 @@ class HBSDRESTISCSI(rest.HBSDREST): for port in target_ports: targets['info'][port] = False if 'ip' in connector: - target_name = '%(prefix)s-%(ip)s' % { - 'prefix': self.driver_info['driver_prefix'], - 'ip': connector['ip'], - } + target_name = self.create_target_name(connector) if self._set_target_info_by_name( targets, port, target_name, iqn): continue diff --git a/cinder/volume/drivers/hitachi/hbsd_utils.py b/cinder/volume/drivers/hitachi/hbsd_utils.py index 1868ee1208b..c41e058b7ae 100644 --- a/cinder/volume/drivers/hitachi/hbsd_utils.py +++ b/cinder/volume/drivers/hitachi/hbsd_utils.py @@ -25,7 +25,7 @@ from oslo_utils import units from cinder import exception -VERSION = '2.3.1' +VERSION = '2.3.2' CI_WIKI_NAME = 'Hitachi_VSP_CI' PARAM_PREFIX = 'hitachi' VENDOR_NAME = 'Hitachi' diff --git a/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml b/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml new file mode 100644 index 00000000000..20ed2cb80fe --- /dev/null +++ b/releasenotes/notes/hitachi-vsp-add-hostgroup-name-format-option-4c8e4a5ddd69b9bd.yaml @@ -0,0 +1,53 @@ +--- +features: + - | + Hitachi driver: Add a config option ``hitachi_group_name_format`` for + hostgroup name format. + When using this option, users can specify the name format of + host groups or iSCSI targets. + Rules of the format: + + * Usable characters are alphanumerics, ".", "@", "_", ":", "-", + "{" and "}". "{" and "}" can be used only in variables. + * The specified value must start with ``HBSD-``. + * You can use the following variables: + + * ``{wwn}``: FC driver only. This is replaced with the smallest + WWPN of the WWPNs of the connecting node. + * ``{ip}``: iSCSI driver only. This is replaced with the IP address of + the connecting node. + * ``{host}``: This is replaced with the host name of the connecting node. + + * You can use each variable in the specified value no more than once. + * The specified value must include the following variables: + + * FC driver: ``{wwn}`` + * iSCSI driver: ``{ip}`` + + * The maximum length of a specified value is as follows: + + * FC driver: 64 + * iSCSI driver: 32 + + * In the length calculation, use the following values as the length of + each variable: + + * ``{wwn}``: 16 + * ``{ip}``: 15 + * ``{host}``: 1 + + * If the specified value includes ``{host}``, the following rules apply: + + * characters that are not permitted for this parameter, they are + replaced with ``_``. + * If the length of the name after variable replacement exceeds + the maximum length of host group (iSCSI target) names, the + host name is truncated so that the length of the host groups or + iSCSI targets do not exceed the maximum length. + + If you specify this parameter, it is recommended that you specify ``True`` + for the hitachi_group_create parameter to collect necessary + information automatically. + Examples: + * FC driver: ``HBSD-{host}-{wwn}`` + * iSCSI driver: ``HBSD-{host}-{ip}``