1. Use HUS target/initiator resources efficiently.
2. Command options aligned with openStack scheme of using dashes.
3. Self tests modified to accomodate #1 and #2.
Change-Id: I7d23a980f237c973538ca08215f77a1f69cc2517
Fixes: bug 1200441
alloc_lun = [] # allocated LUs
connections = [] # iSCSI connections
+ init_index = 0 # initiator index
+ target_index = 0 # target index
+ hlun = 0 # hlun index
def __init__(self):
self.start_lun = 0
- def get_version(self, cmd, ip0, ip1, user, pw):
+ def get_version(self, cmd, ver, ip0, ip1, user, pw):
out = ("Array_ID: 92210013 (HUS130) version: 0920/B-S LU: 4096"
" RG: 75 RG_LU: 1024 Utility_version: 1.0.0")
return out
- def get_iscsi_info(self, cmd, ip0, ip1, user, pw):
+ def get_iscsi_info(self, cmd, ver, ip0, ip1, user, pw):
out = """CTL: 0 Port: 4 IP: 172.17.39.132 Port: 3260 Link: Up
CTL: 0 Port: 5 IP: 172.17.39.133 Port: 3260 Link: Up
CTL: 1 Port: 4 IP: 172.17.39.134 Port: 3260 Link: Up
CTL: 1 Port: 5 IP: 172.17.39.135 Port: 3260 Link: Up"""
return out
- def get_hdp_info(self, cmd, ip0, ip1, user, pw):
+ def get_hdp_info(self, cmd, ver, ip0, ip1, user, pw):
out = """HDP: 2 272384 MB 33792 MB 12 % LUs: 70 Normal Normal
HDP: 9 546816 MB 73728 MB 13 % LUs: 194 Normal Normal"""
return out
- def create_lu(self, cmd, ip0, ip1, user, pw, id, hdp, start, end, size):
+ def create_lu(self, cmd, ver, ip0, ip1, user, pw, id, hdp, start,
+ end, size):
if self.start_lun < int(start): # initialize first time
self.start_lun = int(start)
out = ("LUN: %d HDP: 9 size: %s MB, is successfully created" %
self.start_lun += 1
return out
- def delete_lu(self, cmd, ip0, ip1, user, pw, id, lun):
+ def delete_lu(self, cmd, ver, ip0, ip1, user, pw, id, lun):
out = ""
if lun in self.alloc_lun:
out = "LUN: %s is successfully deleted" % (lun)
self.alloc_lun.remove(lun)
return out
- def create_dup(self, cmd, ip0, ip1, user, pw, id, src_lun,
+ def create_dup(self, cmd, ver, ip0, ip1, user, pw, id, src_lun,
hdp, start, end, size):
out = ("LUN: %s HDP: 9 size: %s MB, is successfully created" %
(self.start_lun, size))
self.start_lun += 1
return out
- def add_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn,
- tgt_alias, initiator, init_alias):
- conn = (initiator, iqn, ctl, port)
- out = ("iSCSI Initiator: %s, index: 26, and Target: %s, index 8 is \
- successfully paired @ CTL: %s, Port: %s" % conn)
+ def add_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
+ iqn, initiator):
+ conn = (self.hlun, lun, initiator, self.init_index, iqn,
+ self.target_index, ctl, port)
+ out = ("H-LUN: %d mapped. LUN: %s, iSCSI Initiator: %s @ index: %d, \
+ and Target: %s @ index %d is successfully paired @ CTL: %s, \
+ Port: %s" % conn)
+ self.init_index += 1
+ self.target_index += 1
+ self.hlun += 1
SimulatedHusBackend.connections.append(conn)
return out
- def del_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn,
- initiator, force):
- conn = (initiator, iqn, ctl, port)
- out = ("iSCSI Initiator: %s, index: 26, and Target: %s, index 8 is \
- successfully un-paired @ CTL: %s, Port: %s" % conn)
- if conn in SimulatedHusBackend.connections:
- SimulatedHusBackend.connections.remove(conn)
+ def del_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
+ iqn, initiator, force):
+ conn = ()
+ for connection in SimulatedHusBackend.connections:
+ if (connection[1] == lun):
+ conn = connection
+ SimulatedHusBackend.connections.remove(connection)
+ if conn is None:
+ return
+ (hlun, lun, initiator, init_index, iqn, target_index, ctl, port) = conn
+ detail = (hlun, iqn)
+ out = ("H-LUN: %d successfully deleted from target %s" % detail)
return out
connector['initiator'] = 'iqn.1993-08.org.debian:01:11f90746eb2'
connector['host'] = 'dut_1.lab.hds.com'
vol = self.test_create_volume()
+ self.mox.StubOutWithMock(self.driver, '_update_vol_location')
conn = self.driver.initialize_connection(vol, connector)
self.assertTrue('hitachi' in conn['data']['target_iqn'])
self.assertTrue('3260' in conn['data']['target_portal'])
+ vol['provider_location'] = conn['data']['provider_location']
return (vol, connector)
def test_terminate_connection(self):
iSCSI Cinder Volume driver for Hitachi Unified Storage (HUS) platform.
"""
-
from oslo.config import cfg
from xml.etree import ElementTree as ETree
from cinder.volume import driver
from cinder.volume.drivers.hds.hus_backend import HusBackend
+HDS_VERSION = '1.0.1'
LOG = logging.getLogger(__name__)
HI_IQN = 'iqn.1994-04.jp.co.hitachi:' # fixed string, for now.
-HUS_DEFAULT_CONFIG = {'hus_cmd': 'hus_cmd',
+HUS_DEFAULT_CONFIG = {'hus_cmd': 'hus-cmd',
'lun_start': '0',
'lun_end': '8192'}
def _array_info_get(self):
"""Get array parameters."""
out = self.bend.get_version(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
def _get_iscsi_info(self):
"""Validate array iscsi parameters."""
out = self.bend.get_iscsi_info(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
total_cap = 0
total_used = 0
out = self.bend.get_hdp_info(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
be_name = self.configuration.safe_get('volume_backend_name')
hus_stat["volume_backend_name"] = be_name or 'HUSDriver'
hus_stat["vendor_name"] = 'HDS'
- hus_stat["driver_version"] = '1.0'
+ hus_stat["driver_version"] = HDS_VERSION
hus_stat["storage_protocol"] = 'iSCSI'
hus_stat['QoS_support'] = False
hus_stat['reserved_percentage'] = 0
def _get_hdp_list(self):
"""Get HDPs from HUS."""
out = self.bend.get_hdp_info(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
vol = self.db.volume_get(self.context, idd)
return vol
+ def _update_vol_location(self, id, loc):
+ """Update the provider location."""
+ update = {}
+ update['provider_location'] = loc
+ self.db.volume_update(self.context, id, update)
+
def __init__(self, *args, **kwargs):
"""Initialize, read different config parameters."""
super(HUSDriver, self).__init__(*args, **kwargs)
service = self._get_service(volume)
(_ip, _ipp, _ctl, _port, hdp) = service
out = self.bend.create_lu(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
% {'lun': lun,
'name': name})
_out = self.bend.delete_lu(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
(ip, ipp, ctl, port, _hdp) = service
loc = volume['provider_location']
(_array_id, lun) = loc.split('.')
- iqn = HI_IQN + loc
- tgt_alias = 'cinder.' + loc
- init_alias = connector['host'][:(31 - len(loc))] + '.' + loc
- _out = self.bend.add_iscsi_conn(self.config['hus_cmd'],
- self.config['mgmt_ip0'],
- self.config['mgmt_ip1'],
- self.config['username'],
- self.config['password'],
- self.arid, lun, ctl, port, iqn,
- tgt_alias, connector['initiator'],
- init_alias)
+ iqn = HI_IQN + connector['host']
+ out = self.bend.add_iscsi_conn(self.config['hus_cmd'],
+ HDS_VERSION,
+ self.config['mgmt_ip0'],
+ self.config['mgmt_ip1'],
+ self.config['username'],
+ self.config['password'],
+ self.arid, lun, ctl, port, iqn,
+ connector['initiator'])
hus_portal = ip + ':' + ipp
tgt = hus_portal + ',' + iqn + ',' + loc + ',' + ctl + ',' + port
properties = {}
+ hlun = out.split()[1]
properties['provider_location'] = tgt
+ self._update_vol_location(volume['id'], tgt)
properties['target_discovered'] = False
properties['target_portal'] = hus_portal
properties['target_iqn'] = iqn
- properties['target_lun'] = 0 # for now !
+ properties['target_lun'] = hlun
properties['volume_id'] = volume['id']
return {'driver_volume_type': 'iscsi', 'data': properties}
@utils.synchronized('hds_hus', external=True)
def terminate_connection(self, volume, connector, **kwargs):
"""Terminate a connection to a volume."""
- loc = volume['provider_location']
+ info = volume['provider_location'].split(',')
+ if len(info) < 5: # connection not setup properly. bail out
+ return
+ (_portal, iqn, loc, ctl, port) = info
(_array_id, lun) = loc.split('.')
- iqn = HI_IQN + loc
- service = self._get_service(volume)
- (_ip, _ipp, ctl, port, _hdp) = service
_out = self.bend.del_iscsi_conn(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
self.config['password'],
self.arid, lun, ctl, port, iqn,
connector['initiator'], 1)
+ self._update_vol_location(volume['id'], loc)
return {'provider_location': loc}
@utils.synchronized('hds_hus', external=True)
service = self._get_service(volume)
(_ip, _ipp, _ctl, _port, hdp) = service
out = self.bend.create_dup(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
size = int(snapshot['volume_size']) * 1024
(_arid, slun) = source_vol['provider_location'].split('.')
out = self.bend.create_dup(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
msg = 'Array id mismatch in delete snapshot'
raise exception.VolumeBackendAPIException(data=msg)
_out = self.bend.delete_lu(self.config['hus_cmd'],
+ HDS_VERSION,
self.config['mgmt_ip0'],
self.config['mgmt_ip1'],
self.config['username'],
class HusBackend:
"""Back end. Talks to HUS."""
- def get_version(self, cmd, ip0, ip1, user, pw):
+ def get_version(self, cmd, ver, ip0, ip1, user, pw):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
LOG.debug('get_version: ' + out + ' -- ' + err)
return out
- def get_iscsi_info(self, cmd, ip0, ip1, user, pw):
+ def get_iscsi_info(self, cmd, ver, ip0, ip1, user, pw):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
LOG.debug('get_iscsi_info: ' + out + ' -- ' + err)
return out
- def get_hdp_info(self, cmd, ip0, ip1, user, pw):
+ def get_hdp_info(self, cmd, ver, ip0, ip1, user, pw):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
LOG.debug('get_hdp_info: ' + out + ' -- ' + err)
return out
- def create_lu(self, cmd, ip0, ip1, user, pw, id, hdp, start, end, size):
+ def create_lu(self, cmd, ver, ip0, ip1, user, pw, id, hdp, start,
+ end, size):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
'--password', pw,
- '--create_lun', '1',
- '--array_id', id,
+ '--create-lun', '1',
+ '--array-id', id,
'--hdp', hdp,
'--start', start,
'--end', end,
LOG.debug('create_lu: ' + out + ' -- ' + err)
return out
- def delete_lu(self, cmd, ip0, ip1, user, pw, id, lun):
+ def delete_lu(self, cmd, ver, ip0, ip1, user, pw, id, lun):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
'--password', pw,
- '--delete_lun', '1',
- '--array_id', id,
+ '--delete-lun', '1',
+ '--array-id', id,
'--lun', lun,
check_exit_code=True)
LOG.debug('delete_lu: ' + out + ' -- ' + err)
return out
- def create_dup(self, cmd, ip0, ip1, user, pw, id, src_lun,
+ def create_dup(self, cmd, ver, ip0, ip1, user, pw, id, src_lun,
hdp, start, end, size):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
'--password', pw,
- '--create_dup', '1',
- '--array_id', id,
+ '--create-dup', '1',
+ '--array-id', id,
'--pvol', src_lun,
'--hdp', hdp,
'--start', start,
LOG.debug('create_dup: ' + out + ' -- ' + err)
return out
- def add_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn,
- tgt_alias, initiator, init_alias):
+ def add_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
+ iqn, initiator):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
'--password', pw,
- '--add_iscsi_connection', '1',
- '--array_id', id,
+ '--add-iscsi-connection', '1',
+ '--array-id', id,
'--lun', lun,
'--ctl', ctl,
'--port', port,
'--target', iqn,
- '--target_alias', tgt_alias,
'--initiator', initiator,
- '--initiator_alias', init_alias,
check_exit_code=True)
LOG.debug('add_iscsi_conn: ' + out + ' -- ' + err)
return out
- def del_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn,
- initiator, force):
+ def del_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
+ iqn, initiator, force):
out, err = utils.execute(cmd,
+ '--driver-version', ver,
'--ip0', ip0,
'--ip1', ip1,
'--user', user,
'--password', pw,
- '--delete_iscsi_connection', '1',
- '--array_id', id,
+ '--delete-iscsi-connection', '1',
+ '--array-id', id,
'--lun', lun,
'--ctl', ctl,
'--port', port,
lvs: CommandFilter, lvs, root
# cinder/volumes/drivers/hds/hds.py:
-hus_cmd: CommandFilter, hus_cmd, root
+hus-cmd: CommandFilter, hus-cmd, root
# cinder/brick/initiator/connector.py:
ls: CommandFilter, ls, root