Merge "Minor reorg for (array resource usage and backend options naming)"

This commit is contained in:
Jenkins 2013-07-17 06:23:45 +00:00 committed by Gerrit Code Review
commit e9b5abbaf6
4 changed files with 100 additions and 60 deletions

View File

@ -69,28 +69,32 @@ class SimulatedHusBackend:
alloc_lun = [] # allocated LUs alloc_lun = [] # allocated LUs
connections = [] # iSCSI connections connections = [] # iSCSI connections
init_index = 0 # initiator index
target_index = 0 # target index
hlun = 0 # hlun index
def __init__(self): def __init__(self):
self.start_lun = 0 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" out = ("Array_ID: 92210013 (HUS130) version: 0920/B-S LU: 4096"
" RG: 75 RG_LU: 1024 Utility_version: 1.0.0") " RG: 75 RG_LU: 1024 Utility_version: 1.0.0")
return out 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 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: 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: 4 IP: 172.17.39.134 Port: 3260 Link: Up
CTL: 1 Port: 5 IP: 172.17.39.135 Port: 3260 Link: Up""" CTL: 1 Port: 5 IP: 172.17.39.135 Port: 3260 Link: Up"""
return out 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 out = """HDP: 2 272384 MB 33792 MB 12 % LUs: 70 Normal Normal
HDP: 9 546816 MB 73728 MB 13 % LUs: 194 Normal Normal""" HDP: 9 546816 MB 73728 MB 13 % LUs: 194 Normal Normal"""
return out 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 if self.start_lun < int(start): # initialize first time
self.start_lun = int(start) self.start_lun = int(start)
out = ("LUN: %d HDP: 9 size: %s MB, is successfully created" % out = ("LUN: %d HDP: 9 size: %s MB, is successfully created" %
@ -99,14 +103,14 @@ class SimulatedHusBackend:
self.start_lun += 1 self.start_lun += 1
return out 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 = "" out = ""
if lun in self.alloc_lun: if lun in self.alloc_lun:
out = "LUN: %s is successfully deleted" % (lun) out = "LUN: %s is successfully deleted" % (lun)
self.alloc_lun.remove(lun) self.alloc_lun.remove(lun)
return out 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): hdp, start, end, size):
out = ("LUN: %s HDP: 9 size: %s MB, is successfully created" % out = ("LUN: %s HDP: 9 size: %s MB, is successfully created" %
(self.start_lun, size)) (self.start_lun, size))
@ -114,21 +118,31 @@ class SimulatedHusBackend:
self.start_lun += 1 self.start_lun += 1
return out return out
def add_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn, def add_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
tgt_alias, initiator, init_alias): iqn, initiator):
conn = (initiator, iqn, ctl, port) conn = (self.hlun, lun, initiator, self.init_index, iqn,
out = ("iSCSI Initiator: %s, index: 26, and Target: %s, index 8 is \ self.target_index, ctl, port)
successfully paired @ CTL: %s, Port: %s" % conn) 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) SimulatedHusBackend.connections.append(conn)
return out return out
def del_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn, def del_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
initiator, force): iqn, initiator, force):
conn = (initiator, iqn, ctl, port) conn = ()
out = ("iSCSI Initiator: %s, index: 26, and Target: %s, index 8 is \ for connection in SimulatedHusBackend.connections:
successfully un-paired @ CTL: %s, Port: %s" % conn) if (connection[1] == lun):
if conn in SimulatedHusBackend.connections: conn = connection
SimulatedHusBackend.connections.remove(conn) 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 return out
@ -234,9 +248,11 @@ class HUSiSCSIDriverTest(test.TestCase):
connector['initiator'] = 'iqn.1993-08.org.debian:01:11f90746eb2' connector['initiator'] = 'iqn.1993-08.org.debian:01:11f90746eb2'
connector['host'] = 'dut_1.lab.hds.com' connector['host'] = 'dut_1.lab.hds.com'
vol = self.test_create_volume() vol = self.test_create_volume()
self.mox.StubOutWithMock(self.driver, '_update_vol_location')
conn = self.driver.initialize_connection(vol, connector) conn = self.driver.initialize_connection(vol, connector)
self.assertTrue('hitachi' in conn['data']['target_iqn']) self.assertTrue('hitachi' in conn['data']['target_iqn'])
self.assertTrue('3260' in conn['data']['target_portal']) self.assertTrue('3260' in conn['data']['target_portal'])
vol['provider_location'] = conn['data']['provider_location']
return (vol, connector) return (vol, connector)
def test_terminate_connection(self): def test_terminate_connection(self):

View File

@ -19,7 +19,6 @@
iSCSI Cinder Volume driver for Hitachi Unified Storage (HUS) platform. iSCSI Cinder Volume driver for Hitachi Unified Storage (HUS) platform.
""" """
from oslo.config import cfg from oslo.config import cfg
from xml.etree import ElementTree as ETree from xml.etree import ElementTree as ETree
@ -30,6 +29,7 @@ from cinder import utils
from cinder.volume import driver from cinder.volume import driver
from cinder.volume.drivers.hds.hus_backend import HusBackend from cinder.volume.drivers.hds.hus_backend import HusBackend
HDS_VERSION = '1.0.1'
LOG = logging.getLogger(__name__) 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. 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_start': '0',
'lun_end': '8192'} 'lun_end': '8192'}
@ -135,6 +135,7 @@ class HUSDriver(driver.ISCSIDriver):
def _array_info_get(self): def _array_info_get(self):
"""Get array parameters.""" """Get array parameters."""
out = self.bend.get_version(self.config['hus_cmd'], out = self.bend.get_version(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -145,6 +146,7 @@ class HUSDriver(driver.ISCSIDriver):
def _get_iscsi_info(self): def _get_iscsi_info(self):
"""Validate array iscsi parameters.""" """Validate array iscsi parameters."""
out = self.bend.get_iscsi_info(self.config['hus_cmd'], out = self.bend.get_iscsi_info(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -187,6 +189,7 @@ class HUSDriver(driver.ISCSIDriver):
total_cap = 0 total_cap = 0
total_used = 0 total_used = 0
out = self.bend.get_hdp_info(self.config['hus_cmd'], out = self.bend.get_hdp_info(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -203,7 +206,7 @@ class HUSDriver(driver.ISCSIDriver):
be_name = self.configuration.safe_get('volume_backend_name') be_name = self.configuration.safe_get('volume_backend_name')
hus_stat["volume_backend_name"] = be_name or 'HUSDriver' hus_stat["volume_backend_name"] = be_name or 'HUSDriver'
hus_stat["vendor_name"] = 'HDS' hus_stat["vendor_name"] = 'HDS'
hus_stat["driver_version"] = '1.0' hus_stat["driver_version"] = HDS_VERSION
hus_stat["storage_protocol"] = 'iSCSI' hus_stat["storage_protocol"] = 'iSCSI'
hus_stat['QoS_support'] = False hus_stat['QoS_support'] = False
hus_stat['reserved_percentage'] = 0 hus_stat['reserved_percentage'] = 0
@ -212,6 +215,7 @@ class HUSDriver(driver.ISCSIDriver):
def _get_hdp_list(self): def _get_hdp_list(self):
"""Get HDPs from HUS.""" """Get HDPs from HUS."""
out = self.bend.get_hdp_info(self.config['hus_cmd'], out = self.bend.get_hdp_info(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -238,6 +242,12 @@ class HUSDriver(driver.ISCSIDriver):
vol = self.db.volume_get(self.context, idd) vol = self.db.volume_get(self.context, idd)
return vol 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): def __init__(self, *args, **kwargs):
"""Initialize, read different config parameters.""" """Initialize, read different config parameters."""
super(HUSDriver, self).__init__(*args, **kwargs) super(HUSDriver, self).__init__(*args, **kwargs)
@ -291,6 +301,7 @@ class HUSDriver(driver.ISCSIDriver):
service = self._get_service(volume) service = self._get_service(volume)
(_ip, _ipp, _ctl, _port, hdp) = service (_ip, _ipp, _ctl, _port, hdp) = service
out = self.bend.create_lu(self.config['hus_cmd'], out = self.bend.create_lu(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -323,6 +334,7 @@ class HUSDriver(driver.ISCSIDriver):
% {'lun': lun, % {'lun': lun,
'name': name}) 'name': name})
_out = self.bend.delete_lu(self.config['hus_cmd'], _out = self.bend.delete_lu(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -340,43 +352,45 @@ class HUSDriver(driver.ISCSIDriver):
(ip, ipp, ctl, port, _hdp) = service (ip, ipp, ctl, port, _hdp) = service
loc = volume['provider_location'] loc = volume['provider_location']
(_array_id, lun) = loc.split('.') (_array_id, lun) = loc.split('.')
iqn = HI_IQN + loc iqn = HI_IQN + connector['host']
tgt_alias = 'cinder.' + loc out = self.bend.add_iscsi_conn(self.config['hus_cmd'],
init_alias = connector['host'][:(31 - len(loc))] + '.' + loc HDS_VERSION,
_out = self.bend.add_iscsi_conn(self.config['hus_cmd'], self.config['mgmt_ip0'],
self.config['mgmt_ip0'], self.config['mgmt_ip1'],
self.config['mgmt_ip1'], self.config['username'],
self.config['username'], self.config['password'],
self.config['password'], self.arid, lun, ctl, port, iqn,
self.arid, lun, ctl, port, iqn, connector['initiator'])
tgt_alias, connector['initiator'],
init_alias)
hus_portal = ip + ':' + ipp hus_portal = ip + ':' + ipp
tgt = hus_portal + ',' + iqn + ',' + loc + ',' + ctl + ',' + port tgt = hus_portal + ',' + iqn + ',' + loc + ',' + ctl + ',' + port
properties = {} properties = {}
hlun = out.split()[1]
properties['provider_location'] = tgt properties['provider_location'] = tgt
self._update_vol_location(volume['id'], tgt)
properties['target_discovered'] = False properties['target_discovered'] = False
properties['target_portal'] = hus_portal properties['target_portal'] = hus_portal
properties['target_iqn'] = iqn properties['target_iqn'] = iqn
properties['target_lun'] = 0 # for now ! properties['target_lun'] = hlun
properties['volume_id'] = volume['id'] properties['volume_id'] = volume['id']
return {'driver_volume_type': 'iscsi', 'data': properties} return {'driver_volume_type': 'iscsi', 'data': properties}
@utils.synchronized('hds_hus', external=True) @utils.synchronized('hds_hus', external=True)
def terminate_connection(self, volume, connector, **kwargs): def terminate_connection(self, volume, connector, **kwargs):
"""Terminate a connection to a volume.""" """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('.') (_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'], _out = self.bend.del_iscsi_conn(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
self.config['password'], self.config['password'],
self.arid, lun, ctl, port, iqn, self.arid, lun, ctl, port, iqn,
connector['initiator'], 1) connector['initiator'], 1)
self._update_vol_location(volume['id'], loc)
return {'provider_location': loc} return {'provider_location': loc}
@utils.synchronized('hds_hus', external=True) @utils.synchronized('hds_hus', external=True)
@ -387,6 +401,7 @@ class HUSDriver(driver.ISCSIDriver):
service = self._get_service(volume) service = self._get_service(volume)
(_ip, _ipp, _ctl, _port, hdp) = service (_ip, _ipp, _ctl, _port, hdp) = service
out = self.bend.create_dup(self.config['hus_cmd'], out = self.bend.create_dup(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -408,6 +423,7 @@ class HUSDriver(driver.ISCSIDriver):
size = int(snapshot['volume_size']) * 1024 size = int(snapshot['volume_size']) * 1024
(_arid, slun) = source_vol['provider_location'].split('.') (_arid, slun) = source_vol['provider_location'].split('.')
out = self.bend.create_dup(self.config['hus_cmd'], out = self.bend.create_dup(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],
@ -438,6 +454,7 @@ class HUSDriver(driver.ISCSIDriver):
msg = 'Array id mismatch in delete snapshot' msg = 'Array id mismatch in delete snapshot'
raise exception.VolumeBackendAPIException(data=msg) raise exception.VolumeBackendAPIException(data=msg)
_out = self.bend.delete_lu(self.config['hus_cmd'], _out = self.bend.delete_lu(self.config['hus_cmd'],
HDS_VERSION,
self.config['mgmt_ip0'], self.config['mgmt_ip0'],
self.config['mgmt_ip1'], self.config['mgmt_ip1'],
self.config['username'], self.config['username'],

View File

@ -27,8 +27,9 @@ LOG = logging.getLogger("cinder.volume.driver")
class HusBackend: class HusBackend:
"""Back end. Talks to HUS.""" """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, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
@ -39,8 +40,9 @@ class HusBackend:
LOG.debug('get_version: ' + out + ' -- ' + err) LOG.debug('get_version: ' + out + ' -- ' + err)
return out 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, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
@ -50,8 +52,9 @@ class HusBackend:
LOG.debug('get_iscsi_info: ' + out + ' -- ' + err) LOG.debug('get_iscsi_info: ' + out + ' -- ' + err)
return out 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, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
@ -61,14 +64,16 @@ class HusBackend:
LOG.debug('get_hdp_info: ' + out + ' -- ' + err) LOG.debug('get_hdp_info: ' + out + ' -- ' + err)
return out 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, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
'--password', pw, '--password', pw,
'--create_lun', '1', '--create-lun', '1',
'--array_id', id, '--array-id', id,
'--hdp', hdp, '--hdp', hdp,
'--start', start, '--start', start,
'--end', end, '--end', end,
@ -77,28 +82,30 @@ class HusBackend:
LOG.debug('create_lu: ' + out + ' -- ' + err) LOG.debug('create_lu: ' + out + ' -- ' + err)
return out 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, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
'--password', pw, '--password', pw,
'--delete_lun', '1', '--delete-lun', '1',
'--array_id', id, '--array-id', id,
'--lun', lun, '--lun', lun,
check_exit_code=True) check_exit_code=True)
LOG.debug('delete_lu: ' + out + ' -- ' + err) LOG.debug('delete_lu: ' + out + ' -- ' + err)
return out 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): hdp, start, end, size):
out, err = utils.execute(cmd, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
'--password', pw, '--password', pw,
'--create_dup', '1', '--create-dup', '1',
'--array_id', id, '--array-id', id,
'--pvol', src_lun, '--pvol', src_lun,
'--hdp', hdp, '--hdp', hdp,
'--start', start, '--start', start,
@ -108,35 +115,35 @@ class HusBackend:
LOG.debug('create_dup: ' + out + ' -- ' + err) LOG.debug('create_dup: ' + out + ' -- ' + err)
return out return out
def add_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn, def add_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
tgt_alias, initiator, init_alias): iqn, initiator):
out, err = utils.execute(cmd, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
'--password', pw, '--password', pw,
'--add_iscsi_connection', '1', '--add-iscsi-connection', '1',
'--array_id', id, '--array-id', id,
'--lun', lun, '--lun', lun,
'--ctl', ctl, '--ctl', ctl,
'--port', port, '--port', port,
'--target', iqn, '--target', iqn,
'--target_alias', tgt_alias,
'--initiator', initiator, '--initiator', initiator,
'--initiator_alias', init_alias,
check_exit_code=True) check_exit_code=True)
LOG.debug('add_iscsi_conn: ' + out + ' -- ' + err) LOG.debug('add_iscsi_conn: ' + out + ' -- ' + err)
return out return out
def del_iscsi_conn(self, cmd, ip0, ip1, user, pw, id, lun, ctl, port, iqn, def del_iscsi_conn(self, cmd, ver, ip0, ip1, user, pw, id, lun, ctl, port,
initiator, force): iqn, initiator, force):
out, err = utils.execute(cmd, out, err = utils.execute(cmd,
'--driver-version', ver,
'--ip0', ip0, '--ip0', ip0,
'--ip1', ip1, '--ip1', ip1,
'--user', user, '--user', user,
'--password', pw, '--password', pw,
'--delete_iscsi_connection', '1', '--delete-iscsi-connection', '1',
'--array_id', id, '--array-id', id,
'--lun', lun, '--lun', lun,
'--ctl', ctl, '--ctl', ctl,
'--port', port, '--port', port,

View File

@ -55,7 +55,7 @@ rm: CommandFilter, rm, root
lvs: CommandFilter, lvs, root lvs: CommandFilter, lvs, root
# cinder/volumes/drivers/hds/hds.py: # cinder/volumes/drivers/hds/hds.py:
hus_cmd: CommandFilter, hus_cmd, root hus-cmd: CommandFilter, hus-cmd, root
# cinder/brick/initiator/connector.py: # cinder/brick/initiator/connector.py:
ls: CommandFilter, ls, root ls: CommandFilter, ls, root