From e25c105740bb8a10ad05b188f8262af940539baa Mon Sep 17 00:00:00 2001 From: Lakhinder Walia Date: Thu, 11 Jul 2013 18:27:16 -0700 Subject: [PATCH] Minor reorg for (array resource usage and backend options naming) 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 --- cinder/tests/test_hds.py | 52 ++++++++++++++-------- cinder/volume/drivers/hds/hds.py | 55 ++++++++++++++++-------- cinder/volume/drivers/hds/hus_backend.py | 51 ++++++++++++---------- etc/cinder/rootwrap.d/volume.filters | 2 +- 4 files changed, 100 insertions(+), 60 deletions(-) diff --git a/cinder/tests/test_hds.py b/cinder/tests/test_hds.py index d9cea266252..20365eb8d1b 100644 --- a/cinder/tests/test_hds.py +++ b/cinder/tests/test_hds.py @@ -69,28 +69,32 @@ class SimulatedHusBackend: 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" % @@ -99,14 +103,14 @@ class SimulatedHusBackend: 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)) @@ -114,21 +118,31 @@ class SimulatedHusBackend: 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 @@ -234,9 +248,11 @@ class HUSiSCSIDriverTest(test.TestCase): 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): diff --git a/cinder/volume/drivers/hds/hds.py b/cinder/volume/drivers/hds/hds.py index b023a43a847..13efb0bb592 100644 --- a/cinder/volume/drivers/hds/hds.py +++ b/cinder/volume/drivers/hds/hds.py @@ -19,7 +19,6 @@ iSCSI Cinder Volume driver for Hitachi Unified Storage (HUS) platform. """ - from oslo.config import cfg from xml.etree import ElementTree as ETree @@ -30,6 +29,7 @@ from cinder import utils from cinder.volume import driver from cinder.volume.drivers.hds.hus_backend import HusBackend +HDS_VERSION = '1.0.1' LOG = logging.getLogger(__name__) @@ -43,7 +43,7 @@ CONF.register_opts(HUS_OPTS) 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'} @@ -135,6 +135,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -145,6 +146,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -187,6 +189,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -203,7 +206,7 @@ class HUSDriver(driver.ISCSIDriver): 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 @@ -212,6 +215,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -238,6 +242,12 @@ class HUSDriver(driver.ISCSIDriver): 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) @@ -291,6 +301,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -323,6 +334,7 @@ class HUSDriver(driver.ISCSIDriver): % {'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'], @@ -340,43 +352,45 @@ class HUSDriver(driver.ISCSIDriver): (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) @@ -387,6 +401,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -408,6 +423,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], @@ -438,6 +454,7 @@ class HUSDriver(driver.ISCSIDriver): 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'], diff --git a/cinder/volume/drivers/hds/hus_backend.py b/cinder/volume/drivers/hds/hus_backend.py index 52d6882b83d..860e908eefc 100644 --- a/cinder/volume/drivers/hds/hus_backend.py +++ b/cinder/volume/drivers/hds/hus_backend.py @@ -27,8 +27,9 @@ LOG = logging.getLogger("cinder.volume.driver") 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, @@ -39,8 +40,9 @@ class HusBackend: 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, @@ -50,8 +52,9 @@ class HusBackend: 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, @@ -61,14 +64,16 @@ class HusBackend: 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, @@ -77,28 +82,30 @@ class HusBackend: 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, @@ -108,35 +115,35 @@ class HusBackend: 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, diff --git a/etc/cinder/rootwrap.d/volume.filters b/etc/cinder/rootwrap.d/volume.filters index 29dacec3dca..ef1f9d0d3a0 100644 --- a/etc/cinder/rootwrap.d/volume.filters +++ b/etc/cinder/rootwrap.d/volume.filters @@ -55,7 +55,7 @@ rm: CommandFilter, rm, root 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