Hitachi: Make the parameters name variable for supporting OEM storages

This patch makes the parameters name variable for supporting OEM
storages

Change-Id: Ib5a1f7cfa0f3480dc850bf37b9ce2c988ff0f5d6
This commit is contained in:
Atsushi Kawai 2022-01-17 06:09:28 +00:00
parent 2925aa974f
commit 4082ed3bea
11 changed files with 321 additions and 236 deletions

View File

@ -95,10 +95,10 @@ from cinder.volume.drivers.fusionstorage import dsware as \
cinder_volume_drivers_fusionstorage_dsware
from cinder.volume.drivers.hitachi import hbsd_common as \
cinder_volume_drivers_hitachi_hbsdcommon
from cinder.volume.drivers.hitachi import hbsd_fc as \
cinder_volume_drivers_hitachi_hbsdfc
from cinder.volume.drivers.hitachi import hbsd_rest as \
cinder_volume_drivers_hitachi_hbsdrest
from cinder.volume.drivers.hitachi import hbsd_rest_fc as \
cinder_volume_drivers_hitachi_hbsdrestfc
from cinder.volume.drivers.hpe import hpe_3par_common as \
cinder_volume_drivers_hpe_hpe3parcommon
from cinder.volume.drivers.huawei import common as \
@ -328,8 +328,8 @@ def list_opts():
cinder_volume_drivers_fujitsu_eternus_dx_eternusdxcommon.
FJ_ETERNUS_DX_OPT_opts,
cinder_volume_drivers_hitachi_hbsdcommon.COMMON_VOLUME_OPTS,
cinder_volume_drivers_hitachi_hbsdfc.FC_VOLUME_OPTS,
cinder_volume_drivers_hitachi_hbsdrest.REST_VOLUME_OPTS,
cinder_volume_drivers_hitachi_hbsdrestfc.FC_VOLUME_OPTS,
cinder_volume_drivers_hpe_hpe3parcommon.hpe3par_opts,
cinder_volume_drivers_huawei_common.huawei_opts,
cinder_volume_drivers_ibm_flashsystemcommon.flashsystem_opts,

View File

@ -23,6 +23,7 @@ from requests import models
from cinder import context as cinder_context
from cinder.db.sqlalchemy import api as sqlalchemy_api
from cinder import exception
from cinder.objects import group_snapshot as obj_group_snap
from cinder.objects import snapshot as obj_snap
from cinder.tests.unit import fake_group
@ -36,7 +37,6 @@ from cinder.volume.drivers.hitachi import hbsd_common
from cinder.volume.drivers.hitachi import hbsd_fc
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_rest_api
from cinder.volume.drivers.hitachi import hbsd_utils
from cinder.volume import volume_types
from cinder.volume import volume_utils
from cinder.zonemanager import utils as fczm_utils
@ -617,7 +617,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
request.return_value = FakeResponse(
500, ERROR_RESULT,
headers={'Content-Type': 'json'})
self.assertRaises(hbsd_utils.HBSDError,
self.assertRaises(exception.VolumeDriverException,
self.driver.create_volume,
fake_volume.fake_volume_obj(self.ctxt))
self.assertGreater(request.call_count, 1)
@ -651,7 +651,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
FakeResponse(200, GET_LDEV_RESULT_PAIR),
FakeResponse(200, GET_LDEV_RESULT_PAIR),
FakeResponse(200, GET_LDEV_RESULT_PAIR)]
self.assertRaises(hbsd_utils.HBSDError,
self.assertRaises(exception.VolumeDriverException,
self.driver.delete_volume,
TEST_VOLUME[0])
self.assertGreater(request.call_count, 2)
@ -741,7 +741,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(fczm_utils, "add_fc_zone")
@mock.patch.object(requests.Session, "request")
def test_initialize_connection(self, request, add_fc_zone):
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
@ -757,7 +757,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(requests.Session, "request")
def test_initialize_connection_already_mapped(self, request, add_fc_zone):
"""Normal case: ldev have already mapped."""
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [
FakeResponse(200, GET_HOST_WWNS_RESULT),
@ -776,7 +776,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(requests.Session, "request")
def test_initialize_connection_shared_target(self, request, add_fc_zone):
"""Normal case: A target shared with other systems."""
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, NOTFOUND_RESULT),
FakeResponse(200, NOTFOUND_RESULT),
@ -794,7 +794,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(fczm_utils, "remove_fc_zone")
@mock.patch.object(requests.Session, "request")
def test_terminate_connection(self, request, remove_fc_zone):
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
FakeResponse(200, GET_LDEV_RESULT_MAPPED),
@ -809,7 +809,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(requests.Session, "request")
def test_terminate_connection_not_connector(self, request, remove_fc_zone):
"""Normal case: Connector is None."""
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_LDEV_RESULT_MAPPED),
FakeResponse(200, GET_HOST_GROUP_RESULT),
@ -827,7 +827,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(requests.Session, "request")
def test_terminate_connection_not_lun(self, request, remove_fc_zone):
"""Normal case: Lun already not exist."""
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
FakeResponse(200, GET_LDEV_RESULT)]
@ -838,7 +838,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(fczm_utils, "add_fc_zone")
@mock.patch.object(requests.Session, "request")
def test_initialize_connection_snapshot(self, request, add_fc_zone):
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
FakeResponse(202, COMPLETED_SUCCEEDED_RESULT)]
@ -853,7 +853,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
@mock.patch.object(fczm_utils, "remove_fc_zone")
@mock.patch.object(requests.Session, "request")
def test_terminate_connection_snapshot(self, request, remove_fc_zone):
self.configuration.hitachi_zoning_request = True
self.driver.common.conf.hitachi_zoning_request = True
self.driver.common._lookup_service = FakeLookupService()
request.side_effect = [FakeResponse(200, GET_HOST_WWNS_RESULT),
FakeResponse(200, GET_LDEV_RESULT_MAPPED),
@ -1020,7 +1020,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
def test_create_group_from_src_volume_error(self):
self.assertRaises(
hbsd_utils.HBSDError, self.driver.create_group_from_src,
exception.VolumeDriverException, self.driver.create_group_from_src,
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[3]]
)
@ -1036,7 +1036,7 @@ class HBSDRESTFCDriverTest(test.TestCase):
def test_update_group_error(self, is_group_a_cg_snapshot_type):
is_group_a_cg_snapshot_type.return_value = True
self.assertRaises(
hbsd_utils.HBSDError, self.driver.update_group,
exception.VolumeDriverException, self.driver.update_group,
self.ctxt, TEST_GROUP[0], add_volumes=[TEST_VOLUME[3]],
remove_volumes=[TEST_VOLUME[0]]
)

View File

@ -21,6 +21,7 @@ import requests
from cinder import context as cinder_context
from cinder.db.sqlalchemy import api as sqlalchemy_api
from cinder import exception
from cinder.objects import group_snapshot as obj_group_snap
from cinder.objects import snapshot as obj_snap
from cinder.tests.unit import fake_group
@ -34,7 +35,6 @@ from cinder.volume.drivers.hitachi import hbsd_common
from cinder.volume.drivers.hitachi import hbsd_iscsi
from cinder.volume.drivers.hitachi import hbsd_rest
from cinder.volume.drivers.hitachi import hbsd_rest_api
from cinder.volume.drivers.hitachi import hbsd_utils
from cinder.volume import volume_types
from cinder.volume import volume_utils
@ -497,14 +497,14 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
@mock.patch.object(driver.ISCSIDriver, "get_goodness_function")
@mock.patch.object(driver.ISCSIDriver, "get_filter_function")
@mock.patch.object(requests.Session, "request")
def test_get_volume_stats(
def test__update_volume_stats(
self, request, get_filter_function, get_goodness_function):
request.return_value = FakeResponse(200, GET_POOL_RESULT)
get_filter_function.return_value = None
get_goodness_function.return_value = None
stats = self.driver.get_volume_stats(True)
self.assertEqual('Hitachi', stats['vendor_name'])
self.assertTrue(stats["pools"][0]['multiattach'])
self.driver._update_volume_stats()
self.assertEqual('Hitachi', self.driver._stats['vendor_name'])
self.assertTrue(self.driver._stats["pools"][0]['multiattach'])
self.assertEqual(1, request.call_count)
self.assertEqual(1, get_filter_function.call_count)
self.assertEqual(1, get_goodness_function.call_count)
@ -826,7 +826,7 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
def test_create_group_from_src_volume_error(self):
self.assertRaises(
hbsd_utils.HBSDError, self.driver.create_group_from_src,
exception.VolumeDriverException, self.driver.create_group_from_src,
self.ctxt, TEST_GROUP[1], [TEST_VOLUME[1]],
source_group=TEST_GROUP[0], source_vols=[TEST_VOLUME[3]]
)
@ -842,7 +842,7 @@ class HBSDRESTISCSIDriverTest(test.TestCase):
def test_update_group_error(self, is_group_a_cg_snapshot_type):
is_group_a_cg_snapshot_type.return_value = True
self.assertRaises(
hbsd_utils.HBSDError, self.driver.update_group,
exception.VolumeDriverException, self.driver.update_group,
self.ctxt, TEST_GROUP[0], add_volumes=[TEST_VOLUME[3]],
remove_volumes=[TEST_VOLUME[0]]
)

View File

@ -22,12 +22,11 @@ from oslo_utils import excutils
from cinder import coordination
from cinder import exception
from cinder.i18n import _
from cinder.volume import configuration
from cinder.volume.drivers.hitachi import hbsd_utils as utils
from cinder.volume import volume_utils
VERSION = '2.2.0'
_STR_VOLUME = 'volume'
_STR_SNAPSHOT = 'snapshot'
@ -106,11 +105,6 @@ COMMON_VOLUME_OPTS = [
'a copy pair deletion or data restoration.'),
]
_REQUIRED_COMMON_OPTS = [
'hitachi_storage_id',
'hitachi_pool',
]
CONF = cfg.CONF
CONF.register_opts(COMMON_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
@ -155,6 +149,10 @@ class HBSDCommon():
'wwns': {},
'portals': {},
}
self._required_common_opts = [
self.driver_info['param_prefix'] + '_storage_id',
self.driver_info['param_prefix'] + '_pool',
]
def create_ldev(self, size):
"""Create an LDEV and return its LDEV number."""
@ -189,7 +187,7 @@ class HBSDCommon():
ldev_info = self.get_ldev_info(['status', 'attributes'], pvol)
if ldev_info['status'] != 'NML':
msg = utils.output_log(MSG.INVALID_LDEV_STATUS_FOR_COPY, ldev=pvol)
raise utils.HBSDError(msg)
self.raise_error(msg)
svol = self.create_ldev(size)
try:
self.create_pair_on_storage(pvol, svol, is_snapshot)
@ -197,7 +195,7 @@ class HBSDCommon():
with excutils.save_and_reraise_exception():
try:
self.delete_ldev(svol)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.DELETE_LDEV_FAILED, ldev=svol)
return svol
@ -209,7 +207,7 @@ class HBSDCommon():
if ldev is None:
msg = utils.output_log(
MSG.INVALID_LDEV_FOR_VOLUME_COPY, type=src_type, id=src['id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
size = volume['size']
new_ldev = self._copy_on_storage(ldev, size)
@ -243,7 +241,7 @@ class HBSDCommon():
if pair_info['pvol'] == ldev:
utils.output_log(
MSG.UNABLE_TO_DELETE_PAIR, pvol=pair_info['pvol'])
raise utils.HBSDBusy()
self.raise_busy()
else:
self.delete_pair_based_on_svol(
pair_info['pvol'], pair_info['svol_info'][0])
@ -284,8 +282,11 @@ class HBSDCommon():
return
try:
self.delete_ldev(ldev)
except utils.HBSDBusy:
raise exception.VolumeIsBusy(volume_name=volume['name'])
except exception.VolumeDriverException as ex:
if ex.msg == utils.BUSY_MESSAGE:
raise exception.VolumeIsBusy(volume_name=volume['name'])
else:
raise ex
def create_snapshot(self, snapshot):
"""Create a snapshot from a volume and return its properties."""
@ -295,7 +296,7 @@ class HBSDCommon():
msg = utils.output_log(
MSG.INVALID_LDEV_FOR_VOLUME_COPY,
type='volume', id=src_vref['id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
size = snapshot['volume_size']
new_ldev = self._copy_on_storage(ldev, size, True)
return {
@ -312,8 +313,11 @@ class HBSDCommon():
return
try:
self.delete_ldev(ldev)
except utils.HBSDBusy:
raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
except exception.VolumeDriverException as ex:
if ex.msg == utils.BUSY_MESSAGE:
raise exception.SnapshotIsBusy(snapshot_name=snapshot['name'])
else:
raise ex
def get_pool_info(self):
"""Return the total and free capacity of the storage pool."""
@ -326,8 +330,8 @@ class HBSDCommon():
self.driver_info['volume_backend_name'])
data = {
'volume_backend_name': backend_name,
'vendor_name': 'Hitachi',
'driver_version': VERSION,
'vendor_name': self.driver_info['vendor_name'],
'driver_version': self.driver_info['version'],
'storage_protocol': self.storage_info['protocol'],
'pools': [],
}
@ -344,7 +348,7 @@ class HBSDCommon():
try:
(total_capacity, free_capacity,
provisioned_capacity) = self.get_pool_info()
except utils.HBSDError:
except exception.VolumeDriverException:
single_pool.update(dict(
provisioned_capacity_gb=0,
backend_state='down'))
@ -387,11 +391,11 @@ class HBSDCommon():
if ldev is None:
msg = utils.output_log(MSG.INVALID_LDEV_FOR_EXTENSION,
volume_id=volume['id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
if self.check_pair_svol(ldev):
msg = utils.output_log(MSG.INVALID_VOLUME_TYPE_FOR_EXTEND,
volume_id=volume['id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
self.delete_pair(ldev)
self.extend_ldev(ldev, volume['size'], new_size)
@ -448,8 +452,11 @@ class HBSDCommon():
raise exception.VolumeIsBusy(volume_name=volume['name'])
try:
self.delete_pair(ldev)
except utils.HBSDBusy:
raise exception.VolumeIsBusy(volume_name=volume['name'])
except exception.VolumeDriverException as ex:
if ex.msg == utils.BUSY_MESSAGE:
raise exception.VolumeIsBusy(volume_name=volume['name'])
else:
raise ex
def _range2list(self, param):
"""Analyze a 'xxx-xxx' string and return a list of two integers."""
@ -457,7 +464,7 @@ class HBSDCommon():
self.conf.safe_get(param).split('-')]
if len(values) != 2 or None in values or values[0] > values[1]:
msg = utils.output_log(MSG.INVALID_PARAMETER, param=param)
raise utils.HBSDError(msg)
self.raise_error(msg)
return values
def check_param_iscsi(self):
@ -466,38 +473,37 @@ class HBSDCommon():
if not self.conf.chap_username:
msg = utils.output_log(MSG.INVALID_PARAMETER,
param='chap_username')
raise utils.HBSDError(msg)
self.raise_error(msg)
if not self.conf.chap_password:
msg = utils.output_log(MSG.INVALID_PARAMETER,
param='chap_password')
raise utils.HBSDError(msg)
self.raise_error(msg)
def check_param(self):
"""Check parameter values and consistency among them."""
utils.check_opt_value(self.conf, _INHERITED_VOLUME_OPTS)
utils.check_opts(self.conf, COMMON_VOLUME_OPTS)
utils.check_opts(self.conf, self.driver_info['volume_opts'])
self.check_opts(self.conf, COMMON_VOLUME_OPTS)
if self.conf.hitachi_ldev_range:
self.storage_info['ldev_range'] = self._range2list(
'hitachi_ldev_range')
self.driver_info['param_prefix'] + '_ldev_range')
if (not self.conf.hitachi_target_ports and
not self.conf.hitachi_compute_target_ports):
msg = utils.output_log(
MSG.INVALID_PARAMETER,
param='hitachi_target_ports or '
'hitachi_compute_target_ports')
raise utils.HBSDError(msg)
self.raise_error(msg)
if (self.conf.hitachi_group_delete and
not self.conf.hitachi_group_create):
msg = utils.output_log(
MSG.INVALID_PARAMETER,
param='hitachi_group_delete or '
'hitachi_group_create')
raise utils.HBSDError(msg)
for opt in _REQUIRED_COMMON_OPTS:
self.raise_error(msg)
for opt in self._required_common_opts:
if not self.conf.safe_get(opt):
msg = utils.output_log(MSG.INVALID_PARAMETER, param=opt)
raise utils.HBSDError(msg)
self.raise_error(msg)
if self.storage_info['protocol'] == 'iSCSI':
self.check_param_iscsi()
@ -535,7 +541,7 @@ class HBSDCommon():
return connector[self.driver_info['hba_id']]
msg = utils.output_log(MSG.RESOURCE_NOT_FOUND,
resource=self.driver_info['hba_id_type'])
raise utils.HBSDError(msg)
self.raise_error(msg)
def create_target_to_storage(self, port, connector, hba_ids):
"""Create a host group or an iSCSI target on the specified port."""
@ -579,7 +585,7 @@ class HBSDCommon():
try:
self._create_target(targets, port, connector, hba_ids)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(
self.driver_info['msg_id']['target'], port=port)
@ -604,7 +610,7 @@ class HBSDCommon():
self.conf.hitachi_group_create):
self.create_mapping_targets(targets, connector)
utils.require_target_existed(targets)
self.require_target_existed(targets)
def do_setup(self, context):
"""Prepare for the startup of the driver."""
@ -627,12 +633,12 @@ class HBSDCommon():
not self.storage_info['controller_ports']):
msg = utils.output_log(MSG.RESOURCE_NOT_FOUND,
resource="Target ports")
raise utils.HBSDError(msg)
self.raise_error(msg)
if (self.conf.hitachi_compute_target_ports and
not self.storage_info['compute_ports']):
msg = utils.output_log(MSG.RESOURCE_NOT_FOUND,
resource="Compute target ports")
raise utils.HBSDError(msg)
self.raise_error(msg)
utils.output_log(MSG.SET_CONFIG_VALUE, object='target port list',
value=self.storage_info['controller_ports'])
utils.output_log(MSG.SET_CONFIG_VALUE,
@ -694,8 +700,9 @@ class HBSDCommon():
# A synchronization to prevent conflicts between host group creation
# and deletion.
@coordination.synchronized('hbsd-host-{self.conf.hitachi_storage_id}-'
'{connector[host]}')
@coordination.synchronized(
'{self.driver_info[driver_file_prefix]}-host-'
'{self.conf.hitachi_storage_id}-{connector[host]}')
def initialize_connection(self, volume, connector):
"""Initialize connection between the server and the volume."""
targets = {
@ -709,7 +716,7 @@ class HBSDCommon():
if ldev is None:
msg = utils.output_log(MSG.INVALID_LDEV_FOR_CONNECTION,
volume_id=volume['id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
target_lun = self.attach_ldev(volume, ldev, connector, targets)
@ -758,7 +765,8 @@ class HBSDCommon():
# A synchronization to prevent conflicts between host group creation
# and deletion.
@coordination.synchronized(
'hbsd-host-%(storage_id)s-%(host)s' % {
'%(prefix)s-host-%(storage_id)s-%(host)s' % {
'prefix': self.driver_info['driver_file_prefix'],
'storage_id': self.conf.hitachi_storage_id,
'host': connector.get('host'),
}
@ -819,3 +827,34 @@ class HBSDCommon():
def delete_group_snapshot(self, group_snapshot, snapshots):
raise NotImplementedError()
def check_opts(self, conf, opts):
"""Check if the specified configuration is valid."""
names = []
for opt in opts:
if opt.required and not conf.safe_get(opt.name):
msg = utils.output_log(MSG.INVALID_PARAMETER, param=opt.name)
self.raise_error(msg)
names.append(opt.name)
utils.check_opt_value(conf, names)
def require_target_existed(self, targets):
"""Check if the target list includes one or more members."""
if not targets['list']:
msg = utils.output_log(MSG.NO_CONNECTED_TARGET)
self.raise_error(msg)
def raise_error(self, msg):
"""Raise a VolumeDriverException by driver error message."""
message = _(
'%(prefix)s error occurred. %(msg)s' % {
'prefix': self.driver_info['driver_prefix'],
'msg': msg,
}
)
raise exception.VolumeDriverException(message)
def raise_busy(self):
"""Raise a VolumeDriverException by driver busy message."""
message = _(utils.BUSY_MESSAGE)
raise exception.VolumeDriverException(message)

View File

@ -14,28 +14,21 @@
#
"""Fibre channel module for Hitachi HBSD Driver."""
from oslo_config import cfg
import os
from oslo_utils import excutils
from cinder import interface
from cinder.volume import configuration
from cinder.volume import driver
from cinder.volume.drivers.hitachi import hbsd_common as common
from cinder.volume.drivers.hitachi import hbsd_rest_fc as rest_fc
from cinder.volume.drivers.hitachi import hbsd_utils as utils
from cinder.volume import volume_utils
FC_VOLUME_OPTS = [
cfg.BoolOpt(
'hitachi_zoning_request',
default=False,
help='If True, the driver will configure FC zoning between the server '
'and the storage system provided that FC zoning manager is '
'enabled.'),
]
MSG = utils.HBSDMsg
_DRIVER_INFO = {
'version': utils.VERSION,
'proto': 'FC',
'hba_id': 'wwpns',
'hba_id_type': 'World Wide Name',
@ -45,13 +38,19 @@ _DRIVER_INFO = {
'volume_backend_name': '%(prefix)sFC' % {
'prefix': utils.DRIVER_PREFIX,
},
'volume_opts': FC_VOLUME_OPTS,
'volume_type': 'fibre_channel',
'param_prefix': utils.PARAM_PREFIX,
'vendor_name': utils.VENDOR_NAME,
'driver_prefix': utils.DRIVER_PREFIX,
'driver_file_prefix': utils.DRIVER_FILE_PREFIX,
'target_prefix': utils.TARGET_PREFIX,
'hdp_vol_attr': utils.HDP_VOL_ATTR,
'hdt_vol_attr': utils.HDT_VOL_ATTR,
'nvol_ldev_type': utils.NVOL_LDEV_TYPE,
'target_iqn_suffix': utils.TARGET_IQN_SUFFIX,
'pair_attr': utils.PAIR_ATTR,
}
CONF = cfg.CONF
CONF.register_opts(FC_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
@interface.volumedriver
class HBSDFCDriver(driver.FibreChannelDriver):
@ -67,13 +66,14 @@ class HBSDFCDriver(driver.FibreChannelDriver):
API for communication with the storage backend.
2.1.0 - Add Cinder generic volume groups.
2.2.0 - Add maintenance parameters.
2.2.1 - Make the parameters name variable for supporting OEM storages.
"""
VERSION = common.VERSION
VERSION = utils.VERSION
# ThirdPartySystems wiki page
CI_WIKI_NAME = "Hitachi_VSP_CI"
CI_WIKI_NAME = utils.CI_WIKI_NAME
def __init__(self, *args, **kwargs):
"""Initialize instance variables."""
@ -83,9 +83,12 @@ class HBSDFCDriver(driver.FibreChannelDriver):
super(HBSDFCDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(common.COMMON_VOLUME_OPTS)
self.configuration.append_config_values(FC_VOLUME_OPTS)
self.common = utils.import_object(
self.configuration, _DRIVER_INFO, kwargs.get('db'))
self.configuration.append_config_values(rest_fc.FC_VOLUME_OPTS)
os.environ['LANG'] = 'C'
self.common = self._init_common(self.configuration, kwargs.get('db'))
def _init_common(self, conf, db):
return rest_fc.HBSDRESTFC(conf, _DRIVER_INFO, db)
def check_for_setup_error(self):
pass

View File

@ -14,17 +14,21 @@
#
"""iSCSI module for Hitachi HBSD Driver."""
import os
from oslo_utils import excutils
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.hitachi import hbsd_common as common
from cinder.volume.drivers.hitachi import hbsd_rest_iscsi as rest_iscsi
from cinder.volume.drivers.hitachi import hbsd_utils as utils
from cinder.volume import volume_utils
MSG = utils.HBSDMsg
_DRIVER_INFO = {
'version': utils.VERSION,
'proto': 'iSCSI',
'hba_id': 'initiator',
'hba_id_type': 'iSCSI initiator IQN',
@ -34,8 +38,17 @@ _DRIVER_INFO = {
'volume_backend_name': '%(prefix)siSCSI' % {
'prefix': utils.DRIVER_PREFIX,
},
'volume_opts': [],
'volume_type': 'iscsi',
'param_prefix': utils.PARAM_PREFIX,
'vendor_name': utils.VENDOR_NAME,
'driver_prefix': utils.DRIVER_PREFIX,
'driver_file_prefix': utils.DRIVER_FILE_PREFIX,
'target_prefix': utils.TARGET_PREFIX,
'hdp_vol_attr': utils.HDP_VOL_ATTR,
'hdt_vol_attr': utils.HDT_VOL_ATTR,
'nvol_ldev_type': utils.NVOL_LDEV_TYPE,
'target_iqn_suffix': utils.TARGET_IQN_SUFFIX,
'pair_attr': utils.PAIR_ATTR,
}
@ -53,13 +66,14 @@ class HBSDISCSIDriver(driver.ISCSIDriver):
API for communication with the storage backend.
2.1.0 - Add Cinder generic volume groups.
2.2.0 - Add maintenance parameters.
2.2.1 - Make the parameters name variable for supporting OEM storages.
"""
VERSION = common.VERSION
VERSION = utils.VERSION
# ThirdPartySystems wiki page
CI_WIKI_NAME = "Hitachi_VSP_CI"
CI_WIKI_NAME = utils.CI_WIKI_NAME
def __init__(self, *args, **kwargs):
"""Initialize instance variables."""
@ -69,8 +83,11 @@ class HBSDISCSIDriver(driver.ISCSIDriver):
super(HBSDISCSIDriver, self).__init__(*args, **kwargs)
self.configuration.append_config_values(common.COMMON_VOLUME_OPTS)
self.common = utils.import_object(
self.configuration, _DRIVER_INFO, kwargs.get('db'))
os.environ['LANG'] = 'C'
self.common = self._init_common(self.configuration, kwargs.get('db'))
def _init_common(self, conf, db):
return rest_iscsi.HBSDRESTISCSI(conf, _DRIVER_INFO, db)
def check_for_setup_error(self):
pass

View File

@ -38,12 +38,6 @@ _LUN_TIMEOUT = 50
_LUN_RETRY_INTERVAL = 1
_RESTORE_TIMEOUT = 24 * 60 * 60
_STATE_TRANSITION_TIMEOUT = 15 * 60
PAIR_ATTR = 'HTI'
_SNAP_MODE = 'A'
_CLONE_MODE = 'C'
_NORMAL_MODE = '-'
_PERMITTED_TYPES = set(['CVS', 'HDP', 'HDT'])
_CHECK_LDEV_MANAGEABILITY_KEYS = (
'emulationType', 'numOfPorts', 'attributes', 'status')
@ -75,9 +69,6 @@ _STATUS_TABLE = {
'SMPP': SMPP,
}
SNAP_NAME = 'HBSD-snap'
CLONE_NAME = 'HBSD-clone'
_SNAP_HASH_SIZE = 8
EX_ENOOBJ = 'EX_ENOOBJ'
@ -202,13 +193,13 @@ LOG = logging.getLogger(__name__)
MSG = utils.HBSDMsg
def _is_valid_target(target, target_name, target_ports):
def _is_valid_target(self, target, target_name, target_ports):
"""Check if the specified target is valid."""
return (target[:utils.PORT_ID_LENGTH] in target_ports and
target_name.startswith(utils.TARGET_PREFIX))
target_name.startswith(self.driver_info['target_prefix']))
def _check_ldev_manageability(ldev_info, ldev, existing_ref):
def _check_ldev_manageability(self, ldev_info, ldev, existing_ref):
"""Check if the LDEV meets the criteria for being managed."""
if ldev_info['status'] != NORMAL_STS:
msg = utils.output_log(MSG.INVALID_LDEV_FOR_MANAGE)
@ -216,9 +207,12 @@ def _check_ldev_manageability(ldev_info, ldev, existing_ref):
existing_ref=existing_ref, reason=msg)
attributes = set(ldev_info['attributes'])
if (not ldev_info['emulationType'].startswith('OPEN-V') or
len(attributes) < 2 or not attributes.issubset(_PERMITTED_TYPES)):
len(attributes) < 2 or
not attributes.issubset(
set(['CVS', self.driver_info['hdp_vol_attr'],
self.driver_info['hdt_vol_attr']]))):
msg = utils.output_log(MSG.INVALID_LDEV_ATTR_FOR_MANAGE, ldev=ldev,
ldevtype=utils.NVOL_LDEV_TYPE)
ldevtype=self.driver_info['nvol_ldev_type'])
raise exception.ManageExistingInvalidReference(
existing_ref=existing_ref, reason=msg)
if ldev_info['numOfPorts']:
@ -262,6 +256,7 @@ class HBSDREST(common.HBSDCommon):
self.conf.hitachi_storage_id,
self.conf.san_login,
self.conf.san_password,
self.driver_info['driver_prefix'],
tcp_keepalive=self.conf.hitachi_rest_tcp_keepalive,
verify=verify)
self.client.login()
@ -343,12 +338,12 @@ class HBSDREST(common.HBSDCommon):
if not loop.start(interval=interval).wait():
msg = utils.output_log(
MSG.PAIR_STATUS_WAIT_TIMEOUT, svol=ldev)
raise utils.HBSDError(msg)
self.raise_error(msg)
def _create_snap_pair(self, pvol, svol):
"""Create a snapshot copy pair on the storage."""
snapshot_name = '%(prefix)s%(svol)s' % {
'prefix': SNAP_NAME,
'prefix': self.driver_info['driver_prefix'] + '-snap',
'svol': svol % _SNAP_HASH_SIZE,
}
try:
@ -360,13 +355,14 @@ class HBSDREST(common.HBSDCommon):
"canCascade": True,
"isDataReductionForceCopy": True}
self.client.add_snapshot(body)
except utils.HBSDError as ex:
except exception.VolumeDriverException as ex:
if (utils.safe_get_err_code(ex.kwargs.get('errobj')) ==
rest_api.INVALID_SNAPSHOT_POOL and
not self.conf.hitachi_snap_pool):
msg = utils.output_log(
MSG.INVALID_PARAMETER, param='hitachi_snap_pool')
raise utils.HBSDError(msg)
MSG.INVALID_PARAMETER,
param=self.driver_info['param_prefix'] + '_snap_pool')
self.raise_error(msg)
else:
raise
try:
@ -375,14 +371,14 @@ class HBSDREST(common.HBSDCommon):
with excutils.save_and_reraise_exception():
try:
self._delete_pair_from_storage(pvol, svol)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(
MSG.DELETE_PAIR_FAILED, pvol=pvol, svol=svol)
def _create_clone_pair(self, pvol, svol):
"""Create a clone copy pair on the storage."""
snapshot_name = '%(prefix)s%(svol)s' % {
'prefix': CLONE_NAME,
'prefix': self.driver_info['driver_prefix'] + '-clone',
'svol': svol % _SNAP_HASH_SIZE,
}
try:
@ -401,13 +397,14 @@ class HBSDREST(common.HBSDCommon):
"copySpeed": pace,
"isDataReductionForceCopy": True}
self.client.add_snapshot(body)
except utils.HBSDError as ex:
except exception.VolumeDriverException as ex:
if (utils.safe_get_err_code(ex.kwargs.get('errobj')) ==
rest_api.INVALID_SNAPSHOT_POOL and
not self.conf.hitachi_snap_pool):
msg = utils.output_log(
MSG.INVALID_PARAMETER, param='hitachi_snap_pool')
raise utils.HBSDError(msg)
MSG.INVALID_PARAMETER,
param=self.driver_info['param_prefix'] + '_snap_pool')
self.raise_error(msg)
else:
raise
try:
@ -416,7 +413,7 @@ class HBSDREST(common.HBSDCommon):
with excutils.save_and_reraise_exception():
try:
self._delete_pair_from_storage(pvol, svol)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(
MSG.DELETE_PAIR_FAILED, pvol=pvol, svol=svol)
@ -444,7 +441,8 @@ class HBSDREST(common.HBSDCommon):
"""Raise True if the LDEV is no longer in a copy pair."""
ldev_info = self.get_ldev_info(['status', 'attributes'], ldev)
if (ldev_info['status'] != NORMAL_STS or
PAIR_ATTR not in ldev_info['attributes']):
self.driver_info['pair_attr'] not in
ldev_info['attributes']):
raise loopingcall.LoopingCallDone()
if utils.timed_out(
start_time, _STATE_TRANSITION_TIMEOUT):
@ -455,7 +453,7 @@ class HBSDREST(common.HBSDCommon):
if not loop.start(interval=interval).wait():
msg = utils.output_log(
MSG.PAIR_STATUS_WAIT_TIMEOUT, svol=ldev)
raise utils.HBSDError(msg)
self.raise_error(msg)
def _delete_pair_from_storage(self, pvol, svol):
"""Disconnect the volume pair that consists of the specified LDEVs."""
@ -479,23 +477,23 @@ class HBSDREST(common.HBSDCommon):
# If the pair status does not satisfy the execution condition,
if not (svol_info['is_psus'] or
_STATUS_TABLE.get(svol_info['status']) == SMPP):
msg = utils.output_log(
utils.output_log(
MSG.UNABLE_TO_DELETE_PAIR, pvol=pvol, svol=svol_info['ldev'])
raise utils.HBSDBusy(msg)
self.raise_busy()
self._delete_pair_from_storage(pvol, svol_info['ldev'])
def check_param(self):
"""Check parameter values and consistency among them."""
super(HBSDREST, self).check_param()
utils.check_opts(self.conf, REST_VOLUME_OPTS)
utils.check_opts(self.conf, san.san_opts)
self.check_opts(self.conf, REST_VOLUME_OPTS)
self.check_opts(self.conf, san.san_opts)
LOG.debug(
'Setting ldev_range: %s', self.storage_info['ldev_range'])
for opt in _REQUIRED_REST_OPTS:
if not self.conf.safe_get(opt):
msg = utils.output_log(MSG.INVALID_PARAMETER, param=opt)
raise utils.HBSDError(msg)
self.raise_error(msg)
if not self.conf.safe_get('san_api_port'):
self.conf.san_api_port = _REST_DEFAULT_PORT
@ -552,7 +550,7 @@ class HBSDREST(common.HBSDCommon):
lun2 = self._run_add_lun(ldev, port, gid, lun=lun)
if lun2 is not None:
targets['lun'][port] = True
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.MAP_LDEV_FAILED, ldev=ldev,
port=port, id=gid, lun=lun)
return lun
@ -565,7 +563,7 @@ class HBSDREST(common.HBSDCommon):
self.conf.hitachi_group_create):
self.create_mapping_targets(targets, connector)
utils.require_target_existed(targets)
self.require_target_existed(targets)
targets['list'].sort()
for port in target_ports:
@ -578,7 +576,7 @@ class HBSDREST(common.HBSDCommon):
if not ldev_info['ports']:
return
for port_info in ldev_info['ports']:
if _is_valid_target(port_info['portId'],
if _is_valid_target(self, port_info['portId'],
port_info['hostGroupName'],
target_ports):
targets['list'].append(port_info)
@ -631,7 +629,7 @@ class HBSDREST(common.HBSDCommon):
try:
self.client.delete_host_grp(port, gid)
result = 0
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.DELETE_TARGET_FAILED, port=port, id=gid)
else:
LOG.debug(
@ -701,7 +699,7 @@ class HBSDREST(common.HBSDCommon):
if 'errorSource' in result:
msg = utils.output_log(MSG.POOL_NOT_FOUND,
pool=self.storage_info['pool_id'])
raise utils.HBSDError(msg)
self.raise_error(msg)
tp_cap = result['totalPoolCapacity'] / units.Ki
ta_cap = result['availableVolumeCapacity'] / units.Ki
@ -715,7 +713,7 @@ class HBSDREST(common.HBSDCommon):
ldev = utils.get_ldev(volume)
try:
self.client.discard_zero_page(ldev)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.DISCARD_ZERO_PAGE_FAILED, ldev=ldev)
def _get_copy_pair_info(self, ldev):
@ -747,7 +745,7 @@ class HBSDREST(common.HBSDCommon):
pair_info = {}
ldev_info = self.get_ldev_info(['status', 'attributes'], ldev)
if (ldev_info['status'] != NORMAL_STS or
PAIR_ATTR not in ldev_info['attributes']):
self.driver_info['pair_attr'] not in ldev_info['attributes']):
return None
pvol, svol_info = self._get_copy_pair_info(ldev)
@ -791,7 +789,7 @@ class HBSDREST(common.HBSDCommon):
"""Check if the LDEV meets the criteria for being managed."""
ldev_info = self.get_ldev_info(
_CHECK_LDEV_MANAGEABILITY_KEYS, ldev)
_check_ldev_manageability(ldev_info, ldev, existing_ref)
_check_ldev_manageability(self, ldev_info, ldev, existing_ref)
def get_ldev_size_in_gigabyte(self, ldev, existing_ref):
"""Return the size[GB] of the specified LDEV."""
@ -819,7 +817,7 @@ class HBSDREST(common.HBSDCommon):
if self.storage_info['pool_id'] is None:
msg = utils.output_log(
MSG.POOL_NOT_FOUND, pool=self.conf.hitachi_pool)
raise utils.HBSDError(msg)
self.raise_error(msg)
snap_pool = self.conf.hitachi_snap_pool
if snap_pool is not None:
@ -831,7 +829,7 @@ class HBSDREST(common.HBSDCommon):
if self.storage_info['snap_pool_id'] is None:
msg = utils.output_log(MSG.POOL_NOT_FOUND,
pool=self.conf.hitachi_snap_pool)
raise utils.HBSDError(msg)
self.raise_error(msg)
else:
self.storage_info['snap_pool_id'] = self.storage_info['pool_id']
@ -883,7 +881,7 @@ class HBSDREST(common.HBSDCommon):
"""Check if the volume have the pair of the snapshot."""
ldev_info = self.get_ldev_info(['status', 'attributes'], svol)
if (ldev_info['status'] != NORMAL_STS or
PAIR_ATTR not in ldev_info['attributes']):
self.driver_info['pair_attr'] not in ldev_info['attributes']):
return False
params_s = {"svolLdevId": svol}
result = self.client.get_snapshots(params_s)
@ -908,7 +906,7 @@ class HBSDREST(common.HBSDCommon):
else:
self.delete_volume(obj)
obj_update['status'] = 'deleted'
except (utils.HBSDError, exception.VolumeIsBusy,
except (exception.VolumeDriverException, exception.VolumeIsBusy,
exception.SnapshotIsBusy) as exc:
obj_update['status'] = 'available' if isinstance(
exc, (exception.VolumeIsBusy,
@ -954,7 +952,7 @@ class HBSDREST(common.HBSDCommon):
MSG.INVALID_LDEV_FOR_VOLUME_COPY,
type='snapshot' if from_snapshot else 'volume',
id=src.id)
raise utils.HBSDError(msg)
self.raise_error(msg)
volume_model_update.update(
self.create_volume_from_snapshot(volume, src) if
from_snapshot else self.create_cloned_volume(volume,
@ -984,13 +982,13 @@ class HBSDREST(common.HBSDCommon):
if ldev is not None:
new_ldevs.append(ldev)
if not is_success:
raise utils.HBSDError(msg)
self.raise_error(msg)
except Exception:
with excutils.save_and_reraise_exception():
for new_ldev in new_ldevs:
try:
self.delete_ldev(new_ldev)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.DELETE_LDEV_FAILED, ldev=new_ldev)
return None, volumes_model_update
@ -1003,7 +1001,7 @@ class HBSDREST(common.HBSDCommon):
volume_id=volume.id,
group='consistency group',
group_id=group.id)
raise utils.HBSDError(msg)
self.raise_error(msg)
return None, None, None
def _create_non_cgsnapshot(self, group_snapshot, snapshots):
@ -1044,7 +1042,7 @@ class HBSDREST(common.HBSDCommon):
now = timeutils.utcnow()
strnow = now.strftime("%y%m%d%H%M%S%f")
ctg_name = '%(prefix)sC%(ldev)s%(time)s' % {
'prefix': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'ldev': "{0:06X}".format(ldev),
'time': strnow[:len(strnow) - 3],
}
@ -1054,7 +1052,7 @@ class HBSDREST(common.HBSDCommon):
for pair in pairs:
try:
self._delete_pair_from_storage(pair['pvol'], pair['svol'])
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.DELETE_PAIR_FAILED, pvol=pair['pvol'],
svol=pair['svol'])
@ -1073,19 +1071,21 @@ class HBSDREST(common.HBSDCommon):
"canCascade": True,
"isDataReductionForceCopy": True}
self.client.add_snapshot(body)
except utils.HBSDError as ex:
except exception.VolumeDriverException as ex:
if ((utils.safe_get_err_code(ex.kwargs.get('errobj')) ==
_MAX_CTG_COUNT_EXCEEDED_ADD_SNAPSHOT) or
(utils.safe_get_err_code(ex.kwargs.get('errobj')) ==
_MAX_PAIR_COUNT_IN_CTG_EXCEEDED_ADD_SNAPSHOT)):
msg = utils.output_log(MSG.FAILED_CREATE_CTG_SNAPSHOT)
raise utils.HBSDError(msg)
self.raise_error(msg)
elif (utils.safe_get_err_code(ex.kwargs.get('errobj')) ==
rest_api.INVALID_SNAPSHOT_POOL and
not self.conf.hitachi_snap_pool):
msg = utils.output_log(
MSG.INVALID_PARAMETER, param='hitachi_snap_pool')
raise utils.HBSDError(msg)
MSG.INVALID_PARAMETER,
param=self.driver_info['param_prefix'] +
'_snap_pool')
self.raise_error(msg)
raise
self._wait_copy_pair_status(pair['svol'], PAIR)
self.client.split_snapshotgroup(snapshotgroup_name)
@ -1108,7 +1108,7 @@ class HBSDREST(common.HBSDCommon):
msg = utils.output_log(
MSG.INVALID_LDEV_FOR_VOLUME_COPY,
type='volume', id=snapshot.volume_id)
raise utils.HBSDError(msg)
self.raise_error(msg)
size = snapshot.volume_size
pair['svol'] = self.create_ldev(size)
except Exception as exc:
@ -1122,7 +1122,7 @@ class HBSDREST(common.HBSDCommon):
msg = utils.output_log(
MSG.INVALID_LDEV_FOR_VOLUME_COPY, type='volume',
id=snapshot.volume_id)
raise utils.HBSDError(msg)
self.raise_error(msg)
for snapshot in snapshots:
loop = loopingcall.FixedIntervalLoopingCall(
_create_cgsnapshot_volume, snapshot)
@ -1136,14 +1136,14 @@ class HBSDREST(common.HBSDCommon):
msg = pair['msg']
pairs.append(pair)
if not is_success:
raise utils.HBSDError(msg)
self.raise_error(msg)
self._create_ctg_snap_pair(pairs)
except Exception:
for pair in pairs:
if 'svol' in pair and pair['svol'] is not None:
try:
self.delete_ldev(pair['svol'])
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(
MSG.DELETE_LDEV_FAILED, ldev=pair['svol'])
model_update = {'status': fields.GroupSnapshotStatus.ERROR}
@ -1169,26 +1169,41 @@ class HBSDREST(common.HBSDCommon):
def init_timer_values(self):
global _LUN_TIMEOUT, _LUN_RETRY_INTERVAL
global _RESTORE_TIMEOUT, _STATE_TRANSITION_TIMEOUT
_LUN_TIMEOUT = self.conf.hitachi_lun_timeout
_LUN_RETRY_INTERVAL = self.conf.hitachi_lun_retry_interval
_RESTORE_TIMEOUT = self.conf.hitachi_restore_timeout
_STATE_TRANSITION_TIMEOUT = self.conf.hitachi_state_transition_timeout
rest_api._LOCK_TIMEOUT = self.conf.hitachi_lock_timeout
rest_api._REST_TIMEOUT = self.conf.hitachi_rest_timeout
rest_api._EXTEND_TIMEOUT = self.conf.hitachi_extend_timeout
rest_api._EXEC_RETRY_INTERVAL = self.conf.hitachi_exec_retry_interval
rest_api._DEFAULT_CONNECT_TIMEOUT = (
self.conf.hitachi_rest_connect_timeout)
rest_api._JOB_API_RESPONSE_TIMEOUT = (
self.conf.hitachi_rest_job_api_response_timeout)
rest_api._GET_API_RESPONSE_TIMEOUT = (
self.conf.hitachi_rest_get_api_response_timeout)
rest_api._REST_SERVER_BUSY_TIMEOUT = (
self.conf.hitachi_rest_server_busy_timeout)
rest_api._KEEP_SESSION_LOOP_INTERVAL = (
self.conf.hitachi_rest_keep_session_loop_interval)
rest_api._ANOTHER_LDEV_MAPPED_RETRY_TIMEOUT = (
self.conf.hitachi_rest_another_ldev_mapped_retry_timeout)
rest_api._TCP_KEEPIDLE = self.conf.hitachi_rest_tcp_keepidle
rest_api._TCP_KEEPINTVL = self.conf.hitachi_rest_tcp_keepintvl
rest_api._TCP_KEEPCNT = self.conf.hitachi_rest_tcp_keepcnt
_LUN_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_lun_timeout')
_LUN_RETRY_INTERVAL = self.conf.safe_get(
self.driver_info['param_prefix'] + '_lun_retry_interval')
_RESTORE_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_restore_timeout')
_STATE_TRANSITION_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_state_transition_timeout')
rest_api._LOCK_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_lock_timeout')
rest_api._REST_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_timeout')
rest_api._EXTEND_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_extend_timeout')
rest_api._EXEC_RETRY_INTERVAL = self.conf.safe_get(
self.driver_info['param_prefix'] + '_exec_retry_interval')
rest_api._DEFAULT_CONNECT_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_connect_timeout')
rest_api._JOB_API_RESPONSE_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] +
'_rest_job_api_response_timeout')
rest_api._GET_API_RESPONSE_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] +
'_rest_get_api_response_timeout')
rest_api._REST_SERVER_BUSY_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_server_busy_timeout')
rest_api._KEEP_SESSION_LOOP_INTERVAL = self.conf.safe_get(
self.driver_info['param_prefix'] +
'_rest_keep_session_loop_interval')
rest_api._ANOTHER_LDEV_MAPPED_RETRY_TIMEOUT = self.conf.safe_get(
self.driver_info['param_prefix'] +
'_rest_another_ldev_mapped_retry_timeout')
rest_api._TCP_KEEPIDLE = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_tcp_keepidle')
rest_api._TCP_KEEPINTVL = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_tcp_keepintvl')
rest_api._TCP_KEEPCNT = self.conf.safe_get(
self.driver_info['param_prefix'] + '_rest_tcp_keepcnt')

View File

@ -29,6 +29,8 @@ from requests.adapters import HTTPAdapter
from requests.packages.urllib3.connection import HTTPConnection
from requests.packages.urllib3.poolmanager import PoolManager
from cinder import exception
from cinder.i18n import _
from cinder.volume.drivers.hitachi import hbsd_utils as utils
from cinder.volume import volume_utils
@ -217,7 +219,7 @@ class ResponseData(dict):
class RestApiClient():
def __init__(self, ip_addr, ip_port, storage_device_id,
user_id, user_pass, tcp_keepalive=False,
user_id, user_pass, driver_prefix, tcp_keepalive=False,
verify=False, connect_timeout=_DEFAULT_CONNECT_TIMEOUT):
"""Initialize instance variables."""
self.ip_addr = ip_addr
@ -244,6 +246,7 @@ class RestApiClient():
}
self.headers = {"content-type": "application/json",
"accept": "application/json"}
self.driver_prefix = driver_prefix
class Session(requests.auth.AuthBase):
@ -312,7 +315,13 @@ class RestApiClient():
MSG.REST_SERVER_CONNECT_FAILED,
exception=type(e), message=e,
method=method, url=url, params=params, body=body)
raise utils.HBSDError(msg)
message = _(
'%(prefix)s error occurred. %(msg)s' % {
'prefix': self.driver_prefix,
'msg': msg,
}
)
raise exception.VolumeDriverException(message)
response = ResponseData(rsp)
if (response['status_code'] == httpclient.INTERNAL_SERVER_ERROR and
@ -348,7 +357,14 @@ class RestApiClient():
params=params, body=body,
**response.get_errobj())
if kwargs['do_raise']:
raise utils.HBSDError(msg, errobj=errobj)
message = _(
'%(prefix)s error occurred. %(msg)s' % {
'prefix': self.driver_prefix,
'msg': msg,
}
)
raise exception.VolumeDriverException(
message, errobj=errobj)
return False, rsp_body, errobj
else:
LOG.debug("The resource group to which the operation object ",
@ -402,7 +418,14 @@ class RestApiClient():
method=method, url=url,
params=params, body=body)
if kwargs['do_raise']:
raise utils.HBSDError(msg, errobj=errobj)
message = _(
'%(prefix)s error occurred. %(msg)s' % {
'prefix': self.driver_prefix,
'msg': msg,
}
)
raise exception.VolumeDriverException(
message, errobj=errobj)
return False, rsp_body, errobj
if errobj:
@ -425,7 +448,14 @@ class RestApiClient():
method=method, url=url,
params=params, body=body)
if kwargs['do_raise']:
raise utils.HBSDError(msg, errobj=errobj)
message = _(
'%(prefix)s error occurred. %(msg)s' % {
'prefix': self.driver_prefix,
'msg': msg,
}
)
raise exception.VolumeDriverException(
message, errobj=errobj)
return retry, rsp_body, errobj
def set_my_session(self, session):
@ -469,7 +499,7 @@ class RestApiClient():
if session is not None:
self.get_session(session.id, no_retry=True, no_log=True)
has_session = True
except utils.HBSDError as ex:
except exception.VolumeDriverException as ex:
LOG.debug('Failed to get session info: %s', ex)
return has_session

View File

@ -14,17 +14,32 @@
#
"""REST interface fibre channel module for Hitachi HBSD Driver."""
from oslo_config import cfg
from oslo_log import log as logging
from cinder import exception
from cinder.volume import configuration
from cinder.volume.drivers.hitachi import hbsd_rest as rest
from cinder.volume.drivers.hitachi import hbsd_utils as utils
from cinder.zonemanager import utils as fczm_utils
FC_VOLUME_OPTS = [
cfg.BoolOpt(
'hitachi_zoning_request',
default=False,
help='If True, the driver will configure FC zoning between the server '
'and the storage system provided that FC zoning manager is '
'enabled.'),
]
_FC_HMO_DISABLE_IO = 91
LOG = logging.getLogger(__name__)
MSG = utils.HBSDMsg
CONF = cfg.CONF
CONF.register_opts(FC_VOLUME_OPTS, group=configuration.SHARED_CONF_GROUP)
class HBSDRESTFC(rest.HBSDREST):
"""REST interface fibre channel class for Hitachi HBSD Driver."""
@ -89,11 +104,16 @@ class HBSDRESTFC(rest.HBSDREST):
utils.output_log(MSG.SET_CONFIG_VALUE, object='port-wwn list',
value=self.storage_info['wwns'])
def check_param(self):
"""Check parameter values and consistency among them."""
super(HBSDRESTFC, self).check_param()
self.check_opts(self.conf, FC_VOLUME_OPTS)
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': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'wwpns': min(wwpns),
}
try:
@ -116,13 +136,13 @@ class HBSDRESTFC(rest.HBSDREST):
try:
self.client.add_hba_wwn(port, gid, wwn, no_log=True)
registered_wwns.append(wwn)
except utils.HBSDError:
except exception.VolumeDriverException:
utils.output_log(MSG.ADD_HBA_WWN_FAILED, port=port, gid=gid,
wwn=wwn)
if not registered_wwns:
msg = utils.output_log(MSG.NO_HBA_WWN_ADDED_TO_HOST_GRP, port=port,
gid=gid)
raise utils.HBSDError(msg)
self.raise_error(msg)
def set_target_mode(self, port, gid):
"""Configure the host group to meet the environment."""
@ -193,14 +213,14 @@ class HBSDRESTFC(rest.HBSDREST):
wwpns = self.get_hba_ids_from_connector(connector)
target_names = [
'%(prefix)s-%(wwpns)s' % {
'prefix': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'wwpns': min(wwpns),
}
]
if 'ip' in connector:
target_names.append(
'%(prefix)s-%(ip)s' % {
'prefix': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'ip': connector['ip'],
}
)

View File

@ -91,14 +91,14 @@ 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': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'ip': connector['ip'],
}
body = {'portId': port, 'hostGroupName': target_name}
if hba_ids:
body['iscsiName'] = '%(id)s%(suffix)s' % {
'id': hba_ids,
'suffix': utils.TARGET_IQN_SUFFIX,
'suffix': self.driver_info['target_iqn_suffix'],
}
try:
gid = self.client.add_host_grp(body, no_log=True)
@ -184,7 +184,7 @@ class HBSDRESTISCSI(rest.HBSDREST):
targets['info'][port] = False
if 'ip' in connector:
target_name = '%(prefix)s-%(ip)s' % {
'prefix': utils.DRIVER_PREFIX,
'prefix': self.driver_info['driver_prefix'],
'ip': connector['ip'],
}
if self._set_target_info_by_name(
@ -215,7 +215,7 @@ class HBSDRESTISCSI(rest.HBSDREST):
if not iqn:
msg = utils.output_log(MSG.RESOURCE_NOT_FOUND,
resource='Target IQN')
raise utils.HBSDError(msg)
self.raise_error(msg)
targets['iqns'][target] = iqn
LOG.debug(
'Found target iqn of host group. (port: %(port)s, '

View File

@ -16,34 +16,31 @@
import enum
import logging as base_logging
import os
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import importutils
from oslo_utils import timeutils
from oslo_utils import units
from cinder import exception
from cinder.i18n import _
_DRIVER_DIR = 'cinder.volume.drivers.hitachi'
_DRIVERS = {
'REST': {
'FC': 'hbsd_rest_fc.HBSDRESTFC',
'iSCSI': 'hbsd_rest_iscsi.HBSDRESTISCSI',
},
}
VERSION = '2.2.1'
CI_WIKI_NAME = 'Hitachi_VSP_CI'
PARAM_PREFIX = 'hitachi'
VENDOR_NAME = 'Hitachi'
DRIVER_PREFIX = 'HBSD'
DRIVER_FILE_PREFIX = 'hbsd'
TARGET_PREFIX = 'HBSD-'
HDP_VOL_ATTR = 'HDP'
HDT_VOL_ATTR = 'HDT'
NVOL_LDEV_TYPE = 'DP-VOL'
TARGET_IQN_SUFFIX = '.hbsd-target'
PAIR_ATTR = 'HTI'
GIGABYTE_PER_BLOCK_SIZE = units.Gi / 512
NORMAL_LDEV_TYPE = 'Normal'
NVOL_LDEV_TYPE = 'DP-VOL'
INFO_SUFFIX = 'I'
WARNING_SUFFIX = 'W'
@ -51,13 +48,7 @@ ERROR_SUFFIX = 'E'
PORT_ID_LENGTH = 5
class HBSDError(exception.VolumeDriverException):
message = _("HBSD error occurred. %(message)s")
class HBSDBusy(HBSDError):
message = _("Device or resource is busy.")
BUSY_MESSAGE = "Device or resource is busy."
@enum.unique
@ -464,18 +455,6 @@ def timed_out(start_time, timeout):
return timeutils.is_older_than(start_time, timeout)
def import_object(conf, driver_info, db):
"""Import a class and return an instance of it."""
os.environ['LANG'] = 'C'
cli = _DRIVERS.get('REST')
return importutils.import_object(
'%(dir)s.%(proto)s' % {
'dir': _DRIVER_DIR,
'proto': cli[driver_info['proto']],
},
conf, driver_info, db)
def check_opt_value(conf, names):
"""Check if the parameter names and values are valid."""
for name in names:
@ -486,24 +465,6 @@ def check_opt_value(conf, names):
output_log(MSG.INVALID_PARAMETER, param=name)
def check_opts(conf, opts):
"""Check if the specified configuration is valid."""
names = []
for opt in opts:
if opt.required and not conf.safe_get(opt.name):
msg = output_log(MSG.INVALID_PARAMETER, param=opt.name)
raise HBSDError(msg)
names.append(opt.name)
check_opt_value(conf, names)
def require_target_existed(targets):
"""Check if the target list includes one or more members."""
if not targets['list']:
msg = output_log(MSG.NO_CONNECTED_TARGET)
raise HBSDError(msg)
def build_initiator_target_map(connector, target_wwns, lookup_service):
"""Return a dictionary mapping server-wwns and lists of storage-wwns."""
init_targ_map = {}