Add manage/unmanage methods for Hitachi Block Storage Driver
This patch adds manage_existing, manage_existing_get_size, and unmanage methods for Hitachi Block Storage Driver. Implements: blueprint hitachi-driver-manage-api Change-Id: I8dc9086452f4db2e2635bf9c933e1fd9d4328367 Signed-off-by: Seiji Aguchi <seiji.aguchi.tr@hitachi.com>
This commit is contained in:
parent
56551e66d6
commit
83e15a1653
@ -903,6 +903,10 @@ class HBSDNotFound(NotFound):
|
||||
message = _("Storage resource could not be found.")
|
||||
|
||||
|
||||
class HBSDVolumeIsBusy(VolumeIsBusy):
|
||||
message = _("Volume %(volume_name)s is busy.")
|
||||
|
||||
|
||||
# Datera driver
|
||||
class DateraAPIException(VolumeBackendAPIException):
|
||||
message = _("Bad response from Datera API")
|
||||
|
@ -33,6 +33,38 @@ def _exec_raidcom(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_vals.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_no_stdout(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_no_stdout.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_no_nml(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_no_nml.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_no_open_v(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_no_open_v.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_no_hdp(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_no_hdp.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_pair(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_pair.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_permit(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_permit.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_invalid_size(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_invalid_size.get(args)
|
||||
|
||||
|
||||
def _exec_raidcom_get_ldev_num_port(*args, **kargs):
|
||||
return HBSDHORCMFCDriverTest.horcm_get_ldev_num_port.get(args)
|
||||
|
||||
|
||||
class HBSDHORCMFCDriverTest(test.TestCase):
|
||||
"""Test HBSDHORCMFCDriver."""
|
||||
|
||||
@ -52,7 +84,11 @@ VOL_TYPE : NOT DEFINED"
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS"
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : CVS : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
raidcom_get_result3 = "Serial# : 210944\n\
|
||||
LDEV : 0\n\
|
||||
@ -298,6 +334,108 @@ HBSD-127.0.0.1None1A30P HBSD-127.0.0.1None1A30S -mirror_id 0'):
|
||||
('raidcom', u'delete lun -port CL1-A-1 -ldev_id 1'):
|
||||
[1, "", ""]}
|
||||
|
||||
horcm_get_ldev_no_stdout = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "", ""]}
|
||||
|
||||
raidcom_get_ldev_no_nml = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : CVS : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS :"
|
||||
|
||||
horcm_get_ldev_no_nml = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_no_nml, ""]}
|
||||
|
||||
raidcom_get_ldev_no_open_v = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : CVS\n\
|
||||
VOL_ATTR : CVS : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_no_open_v = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_no_open_v, ""]}
|
||||
|
||||
raidcom_get_ldev_no_hdp = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : CVS :\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_no_hdp = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_no_hdp, ""]}
|
||||
|
||||
raidcom_get_ldev_pair = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : HORC : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_pair = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_pair, ""]}
|
||||
|
||||
raidcom_get_ldev_permit = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : XXX : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_permit = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_permit, ""]}
|
||||
|
||||
raidcom_get_ldev_invalid_size = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : CVS : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097151\n\
|
||||
NUM_PORT : 0\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_invalid_size = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_invalid_size, ""]}
|
||||
|
||||
raidcom_get_ldev_num_port = "DUMMY\n\
|
||||
LDEV : 1\n\
|
||||
DUMMY\n\
|
||||
DUMMY\n\
|
||||
VOL_TYPE : OPEN-V-CVS\n\
|
||||
VOL_ATTR : CVS : HDP\n\
|
||||
VOL_Capacity(BLK) : 2097152\n\
|
||||
NUM_PORT : 1\n\
|
||||
STS : NML"
|
||||
|
||||
horcm_get_ldev_num_port = {
|
||||
('raidcom', 'get ldev -ldev_id 1'):
|
||||
[0, "%s" % raidcom_get_ldev_num_port, ""]}
|
||||
|
||||
# The following information is passed on to tests, when creating a volume
|
||||
|
||||
_VOLUME = {'size': 128, 'volume_type': None, 'source_volid': '0',
|
||||
@ -347,6 +485,17 @@ HBSD-127.0.0.1None1A30P HBSD-127.0.0.1None1A30S -mirror_id 0'):
|
||||
'volume': _VOLUME,
|
||||
'provider_location': '1', 'status': 'available'}
|
||||
|
||||
SERIAL_NUM = '210944'
|
||||
test_existing_ref = {'ldev': '1', 'serial_number': SERIAL_NUM}
|
||||
test_existing_none_ldev_ref = {'ldev': None,
|
||||
'serial_number': SERIAL_NUM}
|
||||
test_existing_invalid_ldev_ref = {'ldev': 'AAA',
|
||||
'serial_number': SERIAL_NUM}
|
||||
test_existing_no_ldev_ref = {'serial_number': SERIAL_NUM}
|
||||
test_existing_none_serial_ref = {'ldev': '1', 'serial_number': None}
|
||||
test_existing_invalid_serial_ref = {'ldev': '1', 'serial_number': '999999'}
|
||||
test_existing_no_serial_ref = {'ldev': '1'}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HBSDHORCMFCDriverTest, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -364,6 +513,7 @@ HBSD-127.0.0.1None1A30P HBSD-127.0.0.1None1A30S -mirror_id 0'):
|
||||
self._setup_driver()
|
||||
self.driver.check_param()
|
||||
self.driver.common.pair_flock = hbsd_basiclib.NopLock()
|
||||
self.driver.common.command = hbsd_horcm.HBSDHORCM(self.configuration)
|
||||
self.driver.common.command.horcmgr_flock = hbsd_basiclib.NopLock()
|
||||
self.driver.common.create_lock_file()
|
||||
self.driver.common.command.connect_storage()
|
||||
@ -668,3 +818,184 @@ HBSD-127.0.0.1None1A30P HBSD-127.0.0.1None1A30S -mirror_id 0'):
|
||||
self.driver.terminate_connection,
|
||||
self._VOLUME, connector)
|
||||
return
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
def test_manage_existing(self, arg1, arg2):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
rc = self.driver.manage_existing(self._VOLUME, self.test_existing_ref)
|
||||
self.assertEqual(1, rc['provider_location'])
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
size = self.driver.manage_existing_get_size(self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
self.assertEqual(1, size)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_serial_ref(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_serial_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_serial_ref(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_serial_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_serial_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_serial_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'start_horcm',
|
||||
return_value=[0, "", ""])
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'check_horcm',
|
||||
return_value=[0, "", ""])
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
def test_unmanage(self, arg1, arg2, arg3, arg4):
|
||||
self.driver.unmanage(self._VOLUME)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom)
|
||||
def test_unmanage_busy(self, arg1, arg2):
|
||||
self.assertRaises(exception.HBSDVolumeIsBusy,
|
||||
self.driver.unmanage, self.test_volume_error3)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_no_stdout)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_no_stdout(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_no_nml)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_no_nml(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_no_open_v)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_no_open_v(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_no_hdp)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_no_hdp(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_pair)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_pair(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_permit)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_permit(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_invalid_size)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_invalid_size(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_horcm.HBSDHORCM, 'exec_raidcom',
|
||||
side_effect=_exec_raidcom_get_ldev_num_port)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_get_ldev_num_port(self, arg1, arg2,
|
||||
arg3):
|
||||
self.configuration.hitachi_serial_number = self.SERIAL_NUM
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
@ -32,6 +32,26 @@ def _exec_hsnm(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_vals.get(args)
|
||||
|
||||
|
||||
def _exec_hsnm_get_lu_ret_err(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_get_lu_ret_err.get(args)
|
||||
|
||||
|
||||
def _exec_hsnm_get_lu_vol_type_err(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_get_lu_vol_type_err.get(args)
|
||||
|
||||
|
||||
def _exec_hsnm_get_lu_dppool_err(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_get_lu_dppool_err.get(args)
|
||||
|
||||
|
||||
def _exec_hsnm_get_lu_size_err(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_get_lu_size_err.get(args)
|
||||
|
||||
|
||||
def _exec_hsnm_get_lu_num_port_err(*args, **kargs):
|
||||
return HBSDSNM2FCDriverTest.hsnm_get_lu_num_port_err.get(args)
|
||||
|
||||
|
||||
class HBSDSNM2FCDriverTest(test.TestCase):
|
||||
"""Test HBSDSNM2FCDriver."""
|
||||
|
||||
@ -63,7 +83,13 @@ LUN Status Copy Type Group \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 5( 3D+1P) SAS"
|
||||
0 2097152 blocks 256KB 0 0 Enable 0 Normal"
|
||||
|
||||
auluref_result1 = " Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 0 DUMMY"
|
||||
|
||||
auhgwwn_result = "Port 00 Host Group Security ON\n Detected WWN\n \
|
||||
Name Port Name Host Group\n\
|
||||
@ -103,11 +129,63 @@ Host Group\n abcdefg 10000000C97BCE7A \
|
||||
('auluadd', '-unit None -lu 1 -dppoolno 30 -size 128g'): [0, 0, ""],
|
||||
('auluadd', '-unit None -lu 1 -dppoolno 30 -size 256g'): [1, "", ""],
|
||||
('auluref', '-unit None'): [0, "%s" % auluref_result, ""],
|
||||
('auluref', '-unit None -lu 0'): [0, "%s" % auluref_result, ""],
|
||||
('auhgmap', '-unit None -add 0 0 1 1 1'): [0, 0, ""],
|
||||
('auhgwwn', '-unit None -refer'): [0, "%s" % auhgwwn_result, ""],
|
||||
('aufibre1', '-unit None -refer'): [0, "%s" % aufibre1_result, ""],
|
||||
('auhgmap', '-unit None -refer'): [0, "%s" % auhgmap_result, ""]}
|
||||
|
||||
auluref_ret_err = "Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 0 Normal"
|
||||
|
||||
hsnm_get_lu_ret_err = {
|
||||
('auluref', '-unit None -lu 0'): [1, "%s" % auluref_ret_err, ""],
|
||||
}
|
||||
|
||||
auluref_vol_type_err = "Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 0 DUMMY"
|
||||
|
||||
hsnm_get_lu_vol_type_err = {
|
||||
('auluref', '-unit None -lu 0'):
|
||||
[0, "%s" % auluref_vol_type_err, ""],
|
||||
}
|
||||
|
||||
auluref_dppool_err = "Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 N/A Enable 0 Normal"
|
||||
|
||||
hsnm_get_lu_dppool_err = {
|
||||
('auluref', '-unit None -lu 0'):
|
||||
[0, "%s" % auluref_dppool_err, ""],
|
||||
}
|
||||
|
||||
auluref_size_err = "Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097151 blocks 256KB N/A 0 Enable 0 Normal"
|
||||
hsnm_get_lu_size_err = {
|
||||
('auluref', '-unit None -lu 0'): [0, "%s" % auluref_size_err, ""],
|
||||
}
|
||||
|
||||
auluref_num_port_err = "Stripe RAID DP Tier \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 1 Normal"
|
||||
|
||||
hsnm_get_lu_num_port_err = {
|
||||
('auluref', '-unit None -lu 0'): [0, "%s" % auluref_num_port_err, ""],
|
||||
}
|
||||
|
||||
# The following information is passed on to tests, when creating a volume
|
||||
|
||||
_VOLUME = {'size': 128, 'volume_type': None, 'source_volid': '0',
|
||||
@ -151,6 +229,15 @@ Host Group\n abcdefg 10000000C97BCE7A \
|
||||
'volume': test_volume_error,
|
||||
'provider_location': None, 'status': 'available'}
|
||||
|
||||
UNIT_NAME = 'HUS110_91122819'
|
||||
test_existing_ref = {'ldev': '0', 'unit_name': UNIT_NAME}
|
||||
test_existing_none_ldev_ref = {'ldev': None, 'unit_name': UNIT_NAME}
|
||||
test_existing_invalid_ldev_ref = {'ldev': 'AAA', 'unit_name': UNIT_NAME}
|
||||
test_existing_no_ldev_ref = {'unit_name': UNIT_NAME}
|
||||
test_existing_none_unit_ref = {'ldev': '0', 'unit_name': None}
|
||||
test_existing_invalid_unit_ref = {'ldev': '0', 'unit_name': 'Dummy'}
|
||||
test_existing_no_unit_ref = {'ldev': '0'}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HBSDSNM2FCDriverTest, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -184,6 +271,8 @@ Host Group\n abcdefg 10000000C97BCE7A \
|
||||
self.driver.common.command = hbsd_snm2.HBSDSNM2(self.configuration)
|
||||
self.driver.common.pair_flock = \
|
||||
self.driver.common.command.set_pair_flock()
|
||||
self.driver.common.horcmgr_flock = \
|
||||
self.driver.common.command.set_horcmgr_flock()
|
||||
self.driver.do_setup_status.set()
|
||||
|
||||
# API test cases
|
||||
@ -377,3 +466,133 @@ Host Group\n abcdefg 10000000C97BCE7A \
|
||||
self.driver.terminate_connection,
|
||||
self._VOLUME, connector)
|
||||
return
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_manage_existing(self, arg1, arg2):
|
||||
rc = self.driver.manage_existing(self._VOLUME, self.test_existing_ref)
|
||||
self.assertEqual(0, rc['provider_location'])
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
size = self.driver.manage_existing_get_size(self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
self.assertEqual(1, size)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_ldev(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm',
|
||||
side_effect=_exec_hsnm_get_lu_ret_err)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_ret_err(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm',
|
||||
side_effect=_exec_hsnm_get_lu_vol_type_err)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_lu_vol_type_err(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm',
|
||||
side_effect=_exec_hsnm_get_lu_dppool_err)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_lu_dppool_err(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm',
|
||||
side_effect=_exec_hsnm_get_lu_size_err)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_lu_size_err(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm',
|
||||
side_effect=_exec_hsnm_get_lu_num_port_err)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_lu_num_port_err(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_unmanage(self, arg1, arg2):
|
||||
self.driver.unmanage(self._VOLUME)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_unmanage_busy(self, arg1, arg2):
|
||||
self.assertRaises(exception.HBSDVolumeIsBusy,
|
||||
self.driver.unmanage, self.test_volume_error3)
|
||||
|
@ -68,7 +68,7 @@ LUN Status Copy Type Group \
|
||||
RAID Rotational Number\n\
|
||||
LU Capacity Size Group Pool Mode Level Type\
|
||||
Speed of Paths Status\n\
|
||||
0 2097152 blocks 256KB 0 0 Enable 5( 3D+1P) SAS"
|
||||
0 2097152 blocks 256KB 0 0 Enable 0 Normal"
|
||||
|
||||
auhgwwn_result = "Port 00 Host Group Security ON\n Detected WWN\n \
|
||||
Name Port Name Host Group\n\
|
||||
@ -144,6 +144,7 @@ Authentication\n\
|
||||
('auluadd', '-unit None -lu 1 -dppoolno 30 -size 128g'): [0, "", ""],
|
||||
('auluadd', '-unit None -lu 1 -dppoolno 30 -size 256g'): [1, "", ""],
|
||||
('auluref', '-unit None'): [0, "%s" % auluref_result, ""],
|
||||
('auluref', '-unit None -lu 0'): [0, "%s" % auluref_result, ""],
|
||||
('autargetmap', '-unit None -add 0 0 1 1 1'): [0, "", ""],
|
||||
('autargetmap', '-unit None -add 0 0 0 0 1'): [0, "", ""],
|
||||
('autargetini', '-unit None -refer'):
|
||||
@ -244,6 +245,15 @@ Authentication\n\
|
||||
'volume': test_volume_error,
|
||||
'provider_location': None, 'status': 'available'}
|
||||
|
||||
UNIT_NAME = 'HUS110_91122819'
|
||||
test_existing_ref = {'ldev': '0', 'unit_name': UNIT_NAME}
|
||||
test_existing_none_ldev_ref = {'ldev': None, 'unit_name': UNIT_NAME}
|
||||
test_existing_invalid_ldev_ref = {'ldev': 'AAA', 'unit_name': UNIT_NAME}
|
||||
test_existing_no_ldev_ref = {'unit_name': UNIT_NAME}
|
||||
test_existing_none_unit_ref = {'ldev': '0', 'unit_name': None}
|
||||
test_existing_invalid_unit_ref = {'ldev': '0', 'unit_name': 'Dummy'}
|
||||
test_existing_no_unit_ref = {'ldev': '0'}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(HBSDSNM2ISCSIDriverTest, self).__init__(*args, **kwargs)
|
||||
|
||||
@ -296,6 +306,9 @@ Authentication\n\
|
||||
db = None
|
||||
self.driver.common = hbsd_common.HBSDCommon(
|
||||
self.configuration, self.driver, context, db)
|
||||
self.driver.common.command = hbsd_snm2.HBSDSNM2(self.configuration)
|
||||
self.driver.common.horcmgr_flock = \
|
||||
self.driver.common.command.set_horcmgr_flock()
|
||||
|
||||
# API test cases
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@ -492,3 +505,83 @@ Authentication\n\
|
||||
self.driver.terminate_connection,
|
||||
self._VOLUME, connector)
|
||||
return
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_manage_existing(self, arg1, arg2):
|
||||
rc = self.driver.manage_existing(self._VOLUME, self.test_existing_ref)
|
||||
self.assertEqual(0, rc['provider_location'])
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
size = self.driver.manage_existing_get_size(self._VOLUME,
|
||||
self.test_existing_ref)
|
||||
self.assertEqual(1, size)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_ldev(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_ldev_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_ldev_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_none_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_none_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_invalid_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_invalid_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
@mock.patch.object(hbsd_common.HBSDCommon, '_update_volume_metadata')
|
||||
def test_manage_existing_get_size_no_unit_ref(self, arg1, arg2, arg3):
|
||||
self.configuration.hitachi_unit_name = self.UNIT_NAME
|
||||
self.assertRaises(exception.ManageExistingInvalidReference,
|
||||
self.driver.manage_existing_get_size, self._VOLUME,
|
||||
self.test_existing_no_unit_ref)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_unmanage(self, arg1, arg2):
|
||||
self.driver.unmanage(self._VOLUME)
|
||||
|
||||
@mock.patch.object(hbsd_basiclib, 'get_process_lock')
|
||||
@mock.patch.object(hbsd_snm2.HBSDSNM2, 'exec_hsnm', side_effect=_exec_hsnm)
|
||||
def test_unmanage_busy(self, arg1, arg2):
|
||||
self.assertRaises(exception.HBSDVolumeIsBusy,
|
||||
self.driver.unmanage, self.test_volume_error3)
|
||||
|
@ -48,6 +48,8 @@ DEFAULT_GROUP_RANGE = [0, 65535]
|
||||
|
||||
NAME_PREFIX = 'HBSD-'
|
||||
|
||||
NORMAL_VOLUME_TYPE = 'Normal'
|
||||
|
||||
LOCK_DIR = '/var/lock/hbsd/'
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -56,6 +58,9 @@ HBSD_INFO_MSG = {
|
||||
1: _('The parameter of the storage backend. '
|
||||
'(config_group: %(config_group)s)'),
|
||||
3: _('The storage backend can be used. (config_group: %(config_group)s)'),
|
||||
4: _('The volume %(volume_id)s is managed successfully. (LDEV: %(ldev)s)'),
|
||||
5: _('The volume %(volume_id)s is unmanaged successfully. '
|
||||
'(LDEV: %(ldev)s)'),
|
||||
}
|
||||
|
||||
HBSD_WARN_MSG = {
|
||||
@ -131,6 +136,20 @@ HBSD_ERR_MSG = {
|
||||
655: _('A snapshot status is invalid. (status: %(status)s)'),
|
||||
659: _('A host group is invalid. (host group: %(gid)s)'),
|
||||
660: _('The specified %(desc)s is busy.'),
|
||||
700: _('There is no designation of the %(param)s. '
|
||||
'The specified storage is essential to manage the volume.'),
|
||||
701: _('There is no designation of the ldev. '
|
||||
'The specified ldev is essential to manage the volume.'),
|
||||
702: _('The specified ldev %(ldev)s could not be managed. '
|
||||
'The volume type must be DP-VOL.'),
|
||||
703: _('The specified ldev %(ldev)s could not be managed. '
|
||||
'The ldev size must be in multiples of gigabyte.'),
|
||||
704: _('The specified ldev %(ldev)s could not be managed. '
|
||||
'The ldev must not be mapping.'),
|
||||
705: _('The specified ldev %(ldev)s could not be managed. '
|
||||
'The ldev must not be paired.'),
|
||||
706: _('The volume %(volume_id)s could not be unmanaged. '
|
||||
'The volume type must be %(volume_type)s.'),
|
||||
}
|
||||
|
||||
|
||||
@ -249,6 +268,9 @@ class HBSDBasicLib(object):
|
||||
def set_pair_flock(self):
|
||||
return NopLock()
|
||||
|
||||
def set_horcmgr_flock(self):
|
||||
return NopLock()
|
||||
|
||||
def discard_zero_page(self, ldev):
|
||||
pass
|
||||
|
||||
|
@ -35,8 +35,12 @@ from cinder.volume.drivers.hitachi import hbsd_horcm as horcm
|
||||
from cinder.volume.drivers.hitachi import hbsd_snm2 as snm2
|
||||
from cinder.volume import utils as volume_utils
|
||||
|
||||
|
||||
VERSION = '1.0.0'
|
||||
"""
|
||||
Version history:
|
||||
1.0.0 - Initial driver
|
||||
1.1.0 - Add manage_existing/manage_existing_get_size/unmanage methods
|
||||
"""
|
||||
VERSION = '1.1.0'
|
||||
|
||||
PARAM_RANGE = {
|
||||
'hitachi_copy_check_interval': {'min': 1, 'max': 600},
|
||||
@ -152,6 +156,10 @@ class HBSDCommon(object):
|
||||
def get_snapshot_metadata(self, snapshot_id):
|
||||
return self.db.snapshot_metadata_get(self.context, snapshot_id)
|
||||
|
||||
def _update_volume_metadata(self, volume_id, volume_metadata):
|
||||
self.db.volume_metadata_update(self.context, volume_id,
|
||||
volume_metadata, False)
|
||||
|
||||
def get_ldev(self, obj):
|
||||
if not obj:
|
||||
return None
|
||||
@ -195,6 +203,21 @@ class HBSDCommon(object):
|
||||
method = self.configuration.hitachi_default_copy_method
|
||||
return method
|
||||
|
||||
def _string2int(self, num):
|
||||
if not num:
|
||||
return None
|
||||
if num.isdigit():
|
||||
return int(num, 10)
|
||||
if not re.match(r'\w\w:\w\w:\w\w', num):
|
||||
return None
|
||||
|
||||
try:
|
||||
num = int(num.replace(':', ''), 16)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
return num
|
||||
|
||||
def _range2list(self, conf, param):
|
||||
str = getattr(conf, param)
|
||||
lists = str.split('-')
|
||||
@ -305,6 +328,7 @@ class HBSDCommon(object):
|
||||
self.command = horcm.HBSDHORCM(conf)
|
||||
self.command.check_param()
|
||||
self.pair_flock = self.command.set_pair_flock()
|
||||
self.horcmgr_flock = self.command.set_horcmgr_flock()
|
||||
|
||||
def create_lock_file(self):
|
||||
basic_lib.create_empty_file(self.system_lock_file)
|
||||
@ -734,3 +758,85 @@ class HBSDCommon(object):
|
||||
|
||||
def init_volinfo(self, vol_info, ldev):
|
||||
vol_info[ldev] = {'in_use': TryLock(), 'lock': threading.Lock()}
|
||||
|
||||
def manage_existing(self, volume, existing_ref):
|
||||
"""Manage an existing Hitachi storage volume.
|
||||
|
||||
existing_ref is a dictionary of the form:
|
||||
|
||||
For HUS 100 Family,
|
||||
{'ldev': <logical device number on storage>,
|
||||
'unit_name': <storage device name>}
|
||||
|
||||
For VSP G1000/VSP/HUS VM,
|
||||
{'ldev': <logical device number on storage>,
|
||||
'serial_number': <product number of storage system>}
|
||||
"""
|
||||
|
||||
ldev = self._string2int(existing_ref.get('ldev'))
|
||||
|
||||
msg = basic_lib.set_msg(4, volume_id=volume['id'], ldev=ldev)
|
||||
LOG.info(msg)
|
||||
|
||||
return {'provider_location': ldev}
|
||||
|
||||
def _manage_existing_get_size(self, volume, existing_ref):
|
||||
"""Return size of volume for manage_existing."""
|
||||
|
||||
ldev = self._string2int(existing_ref.get('ldev'))
|
||||
if ldev is None:
|
||||
msg = basic_lib.output_err(701)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
size = self.command.get_ldev_size_in_gigabyte(ldev, existing_ref)
|
||||
|
||||
metadata = {'type': basic_lib.NORMAL_VOLUME_TYPE, 'ldev': ldev}
|
||||
self._update_volume_metadata(volume['id'], metadata)
|
||||
|
||||
return size
|
||||
|
||||
def manage_existing_get_size(self, volume, existing_ref):
|
||||
try:
|
||||
return self._manage_existing_get_size(volume, existing_ref)
|
||||
except exception.HBSDError as ex:
|
||||
raise exception.ManageExistingInvalidReference(
|
||||
existing_ref=existing_ref,
|
||||
reason=six.text_type(ex))
|
||||
|
||||
def _unmanage(self, volume, ldev):
|
||||
with self.horcmgr_flock:
|
||||
self.delete_pair(ldev)
|
||||
|
||||
with self.volinfo_lock:
|
||||
if ldev in self.volume_info:
|
||||
self.volume_info.pop(ldev)
|
||||
|
||||
def unmanage(self, volume):
|
||||
"""Remove the specified volume from Cinder management."""
|
||||
|
||||
ldev = self.get_ldev(volume)
|
||||
|
||||
if ldev is None:
|
||||
return
|
||||
|
||||
self.add_volinfo(ldev, volume['id'])
|
||||
if not self.volume_info[ldev]['in_use'].lock.acquire(False):
|
||||
desc = self.volume_info[ldev]['in_use'].desc
|
||||
basic_lib.output_err(660, desc=desc)
|
||||
raise exception.HBSDVolumeIsBusy(volume_name=volume['name'])
|
||||
|
||||
is_vvol = self.get_volume_is_vvol(volume)
|
||||
if is_vvol:
|
||||
basic_lib.output_err(706, volume_id=volume['id'],
|
||||
volume_type=basic_lib.NORMAL_VOLUME_TYPE)
|
||||
raise exception.HBSDVolumeIsBusy(volume_name=volume['name'])
|
||||
try:
|
||||
self._unmanage(volume, ldev)
|
||||
except exception.HBSDBusy:
|
||||
raise exception.HBSDVolumeIsBusy(volume_name=volume['name'])
|
||||
else:
|
||||
msg = basic_lib.set_msg(5, volume_id=volume['id'], ldev=ldev)
|
||||
LOG.info(msg)
|
||||
finally:
|
||||
if ldev in self.volume_info:
|
||||
self.volume_info[ldev]['in_use'].lock.release()
|
||||
|
@ -519,3 +519,14 @@ class HBSDFCDriver(cinder.volume.driver.FibreChannelDriver):
|
||||
super(HBSDFCDriver, self).restore_backup(context, backup,
|
||||
volume, backup_service)
|
||||
self.discard_zero_page(volume)
|
||||
|
||||
def manage_existing(self, volume, existing_ref):
|
||||
return self.common.manage_existing(volume, existing_ref)
|
||||
|
||||
def manage_existing_get_size(self, volume, existing_ref):
|
||||
self.do_setup_status.wait()
|
||||
return self.common.manage_existing_get_size(volume, existing_ref)
|
||||
|
||||
def unmanage(self, volume):
|
||||
self.do_setup_status.wait()
|
||||
self.common.unmanage(volume)
|
||||
|
@ -23,6 +23,7 @@ import time
|
||||
from oslo_concurrency import processutils as putils
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import units
|
||||
import six
|
||||
|
||||
from cinder import exception
|
||||
@ -46,6 +47,8 @@ LUN_DELETE_INTERVAL = 3
|
||||
EXEC_MAX_WAITTIME = 30
|
||||
EXEC_RETRY_INTERVAL = 5
|
||||
HORCM_WAITTIME = 1
|
||||
PAIR_TYPE = ('HORC', 'MRCF', 'QS')
|
||||
PERMITTED_TYPE = ('CVS', 'HDP', 'HDT')
|
||||
|
||||
RAIDCOM_LOCK_FILE = basic_lib.LOCK_DIR + 'raidcom_'
|
||||
HORCMGR_LOCK_FILE = basic_lib.LOCK_DIR + 'horcmgr_'
|
||||
@ -1507,3 +1510,78 @@ HORCM_CMD
|
||||
self.add_used_hlun(port, gid, list)
|
||||
|
||||
return list
|
||||
|
||||
def get_ldev_size_in_gigabyte(self, ldev, existing_ref):
|
||||
param = 'serial_number'
|
||||
|
||||
if param not in existing_ref:
|
||||
msg = basic_lib.output_err(700, param=param)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
storage = existing_ref.get(param)
|
||||
if storage != self.conf.hitachi_serial_number:
|
||||
msg = basic_lib.output_err(648, resource=param)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
stdout = self.comm_get_ldev(ldev)
|
||||
if not stdout:
|
||||
msg = basic_lib.output_err(648, resource='LDEV')
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
sts_line = vol_type = ""
|
||||
vol_attrs = []
|
||||
size = num_port = 1
|
||||
|
||||
lines = stdout.splitlines()
|
||||
for line in lines:
|
||||
if line.startswith("STS :"):
|
||||
sts_line = line
|
||||
|
||||
elif line.startswith("VOL_TYPE :"):
|
||||
vol_type = shlex.split(line)[2]
|
||||
|
||||
elif line.startswith("VOL_ATTR :"):
|
||||
vol_attrs = shlex.split(line)[2:]
|
||||
|
||||
elif line.startswith("VOL_Capacity(BLK) :"):
|
||||
size = int(shlex.split(line)[2])
|
||||
|
||||
elif line.startswith("NUM_PORT :"):
|
||||
num_port = int(shlex.split(line)[2])
|
||||
|
||||
if 'NML' not in sts_line:
|
||||
msg = basic_lib.output_err(648, resource='LDEV')
|
||||
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
if 'OPEN-V' not in vol_type:
|
||||
msg = basic_lib.output_err(702, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
if 'HDP' not in vol_attrs:
|
||||
msg = basic_lib.output_err(702, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
for vol_attr in vol_attrs:
|
||||
if vol_attr == ':':
|
||||
continue
|
||||
|
||||
if vol_attr in PAIR_TYPE:
|
||||
msg = basic_lib.output_err(705, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
if vol_attr not in PERMITTED_TYPE:
|
||||
msg = basic_lib.output_err(702, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
# Hitachi storage calculates volume sizes in a block unit, 512 bytes.
|
||||
# So, units.Gi is divided by 512.
|
||||
if size % (units.Gi / 512):
|
||||
msg = basic_lib.output_err(703, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
if num_port:
|
||||
msg = basic_lib.output_err(704, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
return size / (units.Gi / 512)
|
||||
|
@ -418,3 +418,14 @@ class HBSDISCSIDriver(cinder.volume.driver.ISCSIDriver):
|
||||
super(HBSDISCSIDriver, self).copy_volume_to_image(context, volume,
|
||||
image_service,
|
||||
image_meta)
|
||||
|
||||
def manage_existing(self, volume, existing_ref):
|
||||
return self.common.manage_existing(volume, existing_ref)
|
||||
|
||||
def manage_existing_get_size(self, volume, existing_ref):
|
||||
self.do_setup_status.wait()
|
||||
return self.common.manage_existing_get_size(volume, existing_ref)
|
||||
|
||||
def unmanage(self, volume):
|
||||
self.do_setup_status.wait()
|
||||
self.common.unmanage(volume)
|
||||
|
@ -18,6 +18,8 @@ import shlex
|
||||
import threading
|
||||
import time
|
||||
|
||||
from oslo_utils import excutils
|
||||
from oslo_utils import units
|
||||
import six
|
||||
|
||||
from cinder import exception
|
||||
@ -99,6 +101,21 @@ class HBSDSNM2(basic_lib.HBSDBasicLib):
|
||||
|
||||
return loop.start(interval=interval).wait()
|
||||
|
||||
def _execute_with_exception(self, cmd, args, **kwargs):
|
||||
ret, stdout, stderr = self.exec_hsnm(cmd, args, **kwargs)
|
||||
if ret:
|
||||
cmds = '%(cmd)s %(args)s' % {'cmd': cmd, 'args': args}
|
||||
msg = basic_lib.output_err(
|
||||
600, cmd=cmds, ret=ret, out=stdout, err=stderr)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
return ret, stdout, stderr
|
||||
|
||||
def _execute_and_return_stdout(self, cmd, args, **kwargs):
|
||||
result = self._execute_with_exception(cmd, args, **kwargs)
|
||||
|
||||
return result[1]
|
||||
|
||||
def get_comm_version(self):
|
||||
ret, stdout, stderr = self.exec_hsnm('auman', '-help')
|
||||
m = re.search('Version (\d+).(\d+)', stdout)
|
||||
@ -132,6 +149,15 @@ class HBSDSNM2(basic_lib.HBSDBasicLib):
|
||||
return hlu
|
||||
return None
|
||||
|
||||
def _get_lu(self, lu=None):
|
||||
# When 'lu' is 0, it should be true. So, it cannot remove 'is None'.
|
||||
if lu is None:
|
||||
args = '-unit %s' % self.unit_name
|
||||
else:
|
||||
args = '-unit %s -lu %s' % (self.unit_name, lu)
|
||||
|
||||
return self._execute_and_return_stdout('auluref', args)
|
||||
|
||||
def get_unused_ldev(self, ldev_range):
|
||||
start = ldev_range[0]
|
||||
end = ldev_range[1]
|
||||
@ -1084,3 +1110,48 @@ class HBSDSNM2(basic_lib.HBSDBasicLib):
|
||||
self.add_used_hlun('auhgmap', port, gid, list, DUMMY_LU)
|
||||
|
||||
return list
|
||||
|
||||
def get_ldev_size_in_gigabyte(self, ldev, existing_ref):
|
||||
param = 'unit_name'
|
||||
if param not in existing_ref:
|
||||
msg = basic_lib.output_err(700, param=param)
|
||||
raise exception.HBSDError(data=msg)
|
||||
storage = existing_ref.get(param)
|
||||
if storage != self.conf.hitachi_unit_name:
|
||||
msg = basic_lib.output_err(648, resource=param)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
try:
|
||||
stdout = self._get_lu(ldev)
|
||||
except exception.HBSDError:
|
||||
with excutils.save_and_reraise_exception():
|
||||
basic_lib.output_err(648, resource='LDEV')
|
||||
|
||||
lines = stdout.splitlines()
|
||||
line = lines[2]
|
||||
|
||||
splits = shlex.split(line)
|
||||
|
||||
vol_type = splits[len(splits) - 1]
|
||||
if basic_lib.NORMAL_VOLUME_TYPE != vol_type:
|
||||
msg = basic_lib.output_err(702, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
dppool = splits[5]
|
||||
if 'N/A' == dppool:
|
||||
msg = basic_lib.output_err(702, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
# Hitachi storage calculates volume sizes in a block unit, 512 bytes.
|
||||
# So, units.Gi is divided by 512.
|
||||
size = int(splits[1])
|
||||
if size % (units.Gi / 512):
|
||||
msg = basic_lib.output_err(703, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
num_port = int(splits[len(splits) - 2])
|
||||
if num_port:
|
||||
msg = basic_lib.output_err(704, ldev=ldev)
|
||||
raise exception.HBSDError(data=msg)
|
||||
|
||||
return size / (units.Gi / 512)
|
||||
|
Loading…
x
Reference in New Issue
Block a user