670 lines
26 KiB
Python
670 lines
26 KiB
Python
# Copyright (c) 2014 Hitachi Data Systems, Inc.
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
#
|
|
|
|
"""
|
|
Hitachi Unified Storage (HUS-HNAS) platform. Backend operations.
|
|
"""
|
|
|
|
import re
|
|
|
|
from oslo_concurrency import processutils
|
|
from oslo_log import log as logging
|
|
from oslo_utils import units
|
|
import six
|
|
|
|
from cinder.i18n import _LE, _LW, _LI
|
|
from cinder import ssh_utils
|
|
from cinder import utils
|
|
|
|
LOG = logging.getLogger("cinder.volume.driver")
|
|
|
|
|
|
class HnasBackend(object):
|
|
"""Back end. Talks to HUS-HNAS."""
|
|
def __init__(self, drv_configs):
|
|
self.drv_configs = drv_configs
|
|
self.sshpool = None
|
|
|
|
def run_cmd(self, cmd, ip0, user, pw, *args, **kwargs):
|
|
"""Run a command on SMU or using SSH
|
|
|
|
:param cmd: the command that will be run on SMU
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:returns: formated string with version information
|
|
"""
|
|
LOG.debug('Enable ssh: %s',
|
|
six.text_type(self.drv_configs['ssh_enabled']))
|
|
|
|
if self.drv_configs['ssh_enabled'] != 'True':
|
|
# Direct connection via ssc
|
|
args = (cmd, '-u', user, '-p', pw, ip0) + args
|
|
out, err = utils.execute(*args, **kwargs)
|
|
LOG.debug("command %(cmd)s result: out = %(out)s - err = "
|
|
"%(err)s", {'cmd': cmd, 'out': out, 'err': err})
|
|
return out, err
|
|
else:
|
|
if self.drv_configs['cluster_admin_ip0'] is None:
|
|
# Connect to SMU through SSH and run ssc locally
|
|
args = (cmd, 'localhost') + args
|
|
else:
|
|
args = (cmd, '--smuauth',
|
|
self.drv_configs['cluster_admin_ip0']) + args
|
|
|
|
utils.check_ssh_injection(args)
|
|
command = ' '.join(args)
|
|
command = command.replace('"', '\\"')
|
|
|
|
if not self.sshpool:
|
|
server = self.drv_configs['mgmt_ip0']
|
|
port = int(self.drv_configs['ssh_port'])
|
|
username = self.drv_configs['username']
|
|
# We only accept private/public key auth
|
|
password = ""
|
|
privatekey = self.drv_configs['ssh_private_key']
|
|
self.sshpool = ssh_utils.SSHPool(server,
|
|
port,
|
|
None,
|
|
username,
|
|
password=password,
|
|
privatekey=privatekey)
|
|
|
|
with self.sshpool.item() as ssh:
|
|
try:
|
|
out, err = processutils.ssh_execute(ssh, command,
|
|
check_exit_code=True)
|
|
LOG.debug("command %(cmd)s result: out = %(out)s - err = "
|
|
"%(err)s", {'cmd': cmd, 'out': out, 'err': err})
|
|
return out, err
|
|
except processutils.ProcessExecutionError:
|
|
LOG.error(_LE("Error running SSH command."))
|
|
raise
|
|
|
|
def get_version(self, cmd, ver, ip0, user, pw):
|
|
"""Gets version information from the storage unit
|
|
|
|
:param ver: string driver version
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:returns: formated string with version information
|
|
"""
|
|
if (self.drv_configs['ssh_enabled'] == 'True' and
|
|
self.drv_configs['cluster_admin_ip0'] is not None):
|
|
util = 'SMU ' + cmd
|
|
else:
|
|
out, err = utils.execute(cmd,
|
|
"-version",
|
|
check_exit_code=True)
|
|
util = out.split()[1]
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "cluster-getmac",
|
|
check_exit_code=True)
|
|
hardware = out.split()[2]
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "ver",
|
|
check_exit_code=True)
|
|
lines = out.split('\n')
|
|
|
|
model = ""
|
|
for line in lines:
|
|
if 'Model:' in line:
|
|
model = line.split()[1]
|
|
if 'Software:' in line:
|
|
ver = line.split()[1]
|
|
|
|
out = "Array_ID: %s (%s) version: %s LU: 256 RG: 0 RG_LU: 0 \
|
|
Utility_version: %s" % (hardware, model, ver, util)
|
|
|
|
LOG.debug('get_version: %(out)s -- %(err)s', {'out': out, 'err': err})
|
|
return out
|
|
|
|
def get_iscsi_info(self, cmd, ip0, user, pw):
|
|
"""Gets IP addresses for EVSs, use EVSID as controller.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:returns: formated string with iSCSI information
|
|
"""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw,
|
|
'evsipaddr', '-l',
|
|
check_exit_code=True)
|
|
lines = out.split('\n')
|
|
|
|
newout = ""
|
|
for line in lines:
|
|
if 'evs' in line and 'admin' not in line:
|
|
inf = line.split()
|
|
(evsnum, ip) = (inf[1], inf[3])
|
|
newout += "CTL: %s Port: 0 IP: %s Port: 3260 Link: Up\n" \
|
|
% (evsnum, ip)
|
|
|
|
LOG.debug('get_iscsi_info: %(out)s -- %(err)s',
|
|
{'out': out, 'err': err})
|
|
return newout
|
|
|
|
def get_hdp_info(self, cmd, ip0, user, pw, fslabel=None):
|
|
"""Gets the list of filesystems and fsids.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param fslabel: filesystem label we want to get info
|
|
:returns: formated string with filesystems and fsids
|
|
"""
|
|
|
|
if fslabel is None:
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, 'df', '-a',
|
|
check_exit_code=True)
|
|
else:
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, 'df', '-f', fslabel,
|
|
check_exit_code=True)
|
|
|
|
lines = out.split('\n')
|
|
single_evs = True
|
|
|
|
LOG.debug("Parsing output: %s", lines)
|
|
|
|
newout = ""
|
|
for line in lines:
|
|
if 'Not mounted' in line or 'Not determined' in line:
|
|
continue
|
|
if 'not' not in line and 'EVS' in line:
|
|
single_evs = False
|
|
if 'GB' in line or 'TB' in line:
|
|
LOG.debug("Parsing output: %s", line)
|
|
inf = line.split()
|
|
|
|
if not single_evs:
|
|
(fsid, fslabel, capacity) = (inf[0], inf[1], inf[3])
|
|
(used, perstr) = (inf[5], inf[7])
|
|
(availunit, usedunit) = (inf[4], inf[6])
|
|
else:
|
|
(fsid, fslabel, capacity) = (inf[0], inf[1], inf[2])
|
|
(used, perstr) = (inf[4], inf[6])
|
|
(availunit, usedunit) = (inf[3], inf[5])
|
|
|
|
if usedunit == 'GB':
|
|
usedmultiplier = units.Ki
|
|
else:
|
|
usedmultiplier = units.Mi
|
|
if availunit == 'GB':
|
|
availmultiplier = units.Ki
|
|
else:
|
|
availmultiplier = units.Mi
|
|
m = re.match("\((\d+)\%\)", perstr)
|
|
if m:
|
|
percent = m.group(1)
|
|
else:
|
|
percent = 0
|
|
newout += "HDP: %s %d MB %d MB %d %% LUs: 256 Normal %s\n" \
|
|
% (fsid, int(float(capacity) * availmultiplier),
|
|
int(float(used) * usedmultiplier),
|
|
int(percent), fslabel)
|
|
|
|
LOG.debug('get_hdp_info: %(out)s -- %(err)s',
|
|
{'out': newout, 'err': err})
|
|
return newout
|
|
|
|
def _get_evs(self, cmd, ip0, user, pw, fsid):
|
|
"""Gets the EVSID for the named filesystem."""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "evsfs", "list",
|
|
check_exit_code=True)
|
|
LOG.debug('get_evs: out %s', out)
|
|
|
|
lines = out.split('\n')
|
|
for line in lines:
|
|
inf = line.split()
|
|
if fsid in line and (fsid == inf[0] or fsid == inf[1]):
|
|
return inf[3]
|
|
|
|
LOG.warning(_LW('get_evs: %(out)s -- No find for %(fsid)s'),
|
|
{'out': out, 'fsid': fsid})
|
|
return 0
|
|
|
|
def _get_evsips(self, cmd, ip0, user, pw, evsid):
|
|
"""Gets the EVS IPs for the named filesystem."""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw,
|
|
'evsipaddr', '-e', evsid,
|
|
check_exit_code=True)
|
|
|
|
iplist = ""
|
|
lines = out.split('\n')
|
|
for line in lines:
|
|
inf = line.split()
|
|
if 'evs' in line:
|
|
iplist += inf[3] + ' '
|
|
|
|
LOG.debug('get_evsips: %s', iplist)
|
|
return iplist
|
|
|
|
def _get_fsid(self, cmd, ip0, user, pw, fslabel):
|
|
"""Gets the FSID for the named filesystem."""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, 'evsfs', 'list',
|
|
check_exit_code=True)
|
|
LOG.debug('get_fsid: out %s', out)
|
|
|
|
lines = out.split('\n')
|
|
for line in lines:
|
|
inf = line.split()
|
|
if fslabel in line and fslabel == inf[1]:
|
|
LOG.debug('get_fsid: %s', line)
|
|
return inf[0]
|
|
|
|
LOG.warning(_LW('get_fsid: %(out)s -- No info for %(fslabel)s'),
|
|
{'out': out, 'fslabel': fslabel})
|
|
return 0
|
|
|
|
def get_nfs_info(self, cmd, ip0, user, pw):
|
|
"""Gets information on each NFS export.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:returns: formated string
|
|
"""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw,
|
|
'for-each-evs', '-q',
|
|
'nfs-export', 'list',
|
|
check_exit_code=True)
|
|
|
|
lines = out.split('\n')
|
|
newout = ""
|
|
export = ""
|
|
path = ""
|
|
for line in lines:
|
|
inf = line.split()
|
|
if 'Export name' in line:
|
|
export = inf[2]
|
|
if 'Export path' in line:
|
|
path = inf[2]
|
|
if 'File system info' in line:
|
|
fs = ""
|
|
if 'File system label' in line:
|
|
fs = inf[3]
|
|
if 'Transfer setting' in line and fs != "":
|
|
fsid = self._get_fsid(cmd, ip0, user, pw, fs)
|
|
evsid = self._get_evs(cmd, ip0, user, pw, fsid)
|
|
ips = self._get_evsips(cmd, ip0, user, pw, evsid)
|
|
newout += "Export: %s Path: %s HDP: %s FSID: %s \
|
|
EVS: %s IPS: %s\n" \
|
|
% (export, path, fs, fsid, evsid, ips)
|
|
fs = ""
|
|
|
|
LOG.debug('get_nfs_info: %(out)s -- %(err)s',
|
|
{'out': newout, 'err': err})
|
|
return newout
|
|
|
|
def create_lu(self, cmd, ip0, user, pw, hdp, size, name):
|
|
"""Creates a new Logical Unit.
|
|
|
|
If the operation can not be performed for some reason, utils.execute()
|
|
throws an error and aborts the operation. Used for iSCSI only
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param hdp: data Pool the logical unit will be created
|
|
:param size: Size (Mb) of the new logical unit
|
|
:param name: name of the logical unit
|
|
:returns: formated string with 'LUN %d HDP: %d size: %s MB, is
|
|
successfully created'
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-lu', 'add', "-e",
|
|
name, hdp,
|
|
'/.cinder/' + name + '.iscsi',
|
|
size + 'M',
|
|
check_exit_code=True)
|
|
|
|
out = "LUN %s HDP: %s size: %s MB, is successfully created" \
|
|
% (name, hdp, size)
|
|
|
|
LOG.debug('create_lu: %s', out)
|
|
return out
|
|
|
|
def delete_lu(self, cmd, ip0, user, pw, hdp, lun):
|
|
"""Delete an logical unit. Used for iSCSI only
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param hdp: data Pool of the logical unit
|
|
:param lun: id of the logical unit being deleted
|
|
:returns: formated string 'Logical unit deleted successfully.'
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-lu', 'del', '-d',
|
|
'-f', lun,
|
|
check_exit_code=True)
|
|
|
|
LOG.debug('delete_lu: %(out)s -- %(err)s', {'out': out, 'err': err})
|
|
return out
|
|
|
|
def create_dup(self, cmd, ip0, user, pw, src_lun, hdp, size, name):
|
|
"""Clones a volume
|
|
|
|
Clone primitive used to support all iSCSI snapshot/cloning functions.
|
|
Used for iSCSI only.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param hdp: data Pool of the logical unit
|
|
:param src_lun: id of the logical unit being deleted
|
|
:param size: size of the LU being cloned. Only for logging purposes
|
|
:returns: formated string
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-lu', 'clone', '-e',
|
|
src_lun, name,
|
|
'/.cinder/' + name + '.iscsi',
|
|
check_exit_code=True)
|
|
|
|
out = "LUN %s HDP: %s size: %s MB, is successfully created" \
|
|
% (name, hdp, size)
|
|
|
|
LOG.debug('create_dup: %(out)s -- %(err)s', {'out': out, 'err': err})
|
|
return out
|
|
|
|
def file_clone(self, cmd, ip0, user, pw, fslabel, src, name):
|
|
"""Clones NFS files to a new one named 'name'
|
|
|
|
Clone primitive used to support all NFS snapshot/cloning functions.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param fslabel: file system label of the new file
|
|
:param src: source file
|
|
:param name: target path of the new created file
|
|
:returns: formated string
|
|
"""
|
|
|
|
_fsid = self._get_fsid(cmd, ip0, user, pw, fslabel)
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, _fsid)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'file-clone-create', '-f', fslabel,
|
|
src, name,
|
|
check_exit_code=True)
|
|
|
|
out = "LUN %s HDP: %s Clone: %s -> %s" % (name, _fsid, src, name)
|
|
|
|
LOG.debug('file_clone: %(out)s -- %(err)s', {'out': out, 'err': err})
|
|
return out
|
|
|
|
def extend_vol(self, cmd, ip0, user, pw, hdp, lun, new_size, name):
|
|
"""Extend a iSCSI volume.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param hdp: data Pool of the logical unit
|
|
:param lun: id of the logical unit being extended
|
|
:param new_size: new size of the LU
|
|
:param name: formated string
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-lu', 'expand',
|
|
name, new_size + 'M',
|
|
check_exit_code=True)
|
|
|
|
out = ("LUN: %s successfully extended to %s MB" % (name, new_size))
|
|
|
|
LOG.debug('extend_vol: %s', out)
|
|
return out
|
|
|
|
def add_iscsi_conn(self, cmd, ip0, user, pw, lun, hdp,
|
|
port, iqn, initiator):
|
|
"""Setup the lun on on the specified target port
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param lun: id of the logical unit being extended
|
|
:param hdp: data pool of the logical unit
|
|
:param port: iSCSI port
|
|
:param iqn: iSCSI qualified name
|
|
:param initiator: initiator address
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'list', iqn,
|
|
check_exit_code=True)
|
|
|
|
# even though ssc uses the target alias, need to return the full iqn
|
|
fulliqn = ""
|
|
lines = out.split('\n')
|
|
for line in lines:
|
|
if 'Globally unique name' in line:
|
|
fulliqn = line.split()[3]
|
|
|
|
# find first free hlun
|
|
hlun = 0
|
|
for line in lines:
|
|
if line.startswith(' '):
|
|
lunline = line.split()[0]
|
|
vol = line.split()[1]
|
|
if lunline[0].isdigit():
|
|
# see if already mounted
|
|
if vol[:29] == lun[:29]:
|
|
LOG.info(_LI('lun: %(lun)s already mounted %(lline)s'),
|
|
{'lun': lun, 'lline': lunline})
|
|
conn = (int(lunline), lun, initiator, hlun, fulliqn,
|
|
hlun, hdp, port)
|
|
out = "H-LUN: %d alreadymapped LUN: %s, iSCSI \
|
|
Initiator: %s @ index: %d, and Target: %s \
|
|
@ index %d is successfully paired @ CTL: \
|
|
%s, Port: %s" % conn
|
|
LOG.debug('add_iscsi_conn: returns %s', out)
|
|
return out
|
|
|
|
if int(lunline) == hlun:
|
|
hlun += 1
|
|
if int(lunline) > hlun:
|
|
# found a hole
|
|
break
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'addlu',
|
|
iqn, lun, six.text_type(hlun),
|
|
check_exit_code=True)
|
|
|
|
conn = (int(hlun), lun, initiator, int(hlun), fulliqn, int(hlun),
|
|
hdp, 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
|
|
|
|
LOG.debug('add_iscsi_conn: returns %s', out)
|
|
return out
|
|
|
|
def del_iscsi_conn(self, cmd, ip0, user, pw, evsid, iqn, hlun):
|
|
"""Remove the lun on on the specified target port
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param evsid: EVSID for the file system
|
|
:param iqn: iSCSI qualified name
|
|
:param hlun: logical unit id
|
|
:return: formated string
|
|
"""
|
|
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", evsid,
|
|
'iscsi-target', 'list', iqn,
|
|
check_exit_code=True)
|
|
|
|
lines = out.split('\n')
|
|
out = ("H-LUN: %d already deleted from target %s" % (int(hlun), iqn))
|
|
# see if lun is already detached
|
|
for line in lines:
|
|
if line.startswith(' '):
|
|
lunline = line.split()[0]
|
|
if lunline[0].isdigit() and lunline == hlun:
|
|
out = ""
|
|
break
|
|
|
|
if out != "":
|
|
# hlun wasn't found
|
|
LOG.info(_LI('del_iscsi_conn: hlun not found %s'), out)
|
|
return out
|
|
|
|
# remove the LU from the target
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", evsid,
|
|
'iscsi-target', 'dellu',
|
|
'-f', iqn, hlun,
|
|
check_exit_code=True)
|
|
|
|
out = "H-LUN: %d successfully deleted from target %s" \
|
|
% (int(hlun), iqn)
|
|
|
|
LOG.debug('del_iscsi_conn: %s', out)
|
|
return out
|
|
|
|
def get_targetiqn(self, cmd, ip0, user, pw, targetalias, hdp, secret):
|
|
"""Obtain the targets full iqn
|
|
|
|
Return the target's full iqn rather than its alias.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param targetalias: alias of the target
|
|
:param hdp: data pool of the logical unit
|
|
:param secret: CHAP secret of the target
|
|
:return: string with full IQN
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'list', targetalias,
|
|
check_exit_code=True)
|
|
|
|
if "does not exist" in out:
|
|
if secret == "":
|
|
secret = '""'
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'add',
|
|
targetalias, secret,
|
|
check_exit_code=True)
|
|
else:
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'add',
|
|
targetalias, secret,
|
|
check_exit_code=True)
|
|
if "success" in out:
|
|
return targetalias
|
|
|
|
lines = out.split('\n')
|
|
# returns the first iqn
|
|
for line in lines:
|
|
if 'Alias' in line:
|
|
fulliqn = line.split()[2]
|
|
return fulliqn
|
|
|
|
def set_targetsecret(self, cmd, ip0, user, pw, targetalias, hdp, secret):
|
|
"""Sets the chap secret for the specified target.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param targetalias: alias of the target
|
|
:param hdp: data pool of the logical unit
|
|
:param secret: CHAP secret of the target
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'list',
|
|
targetalias,
|
|
check_exit_code=False)
|
|
|
|
if "does not exist" in out:
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'add',
|
|
targetalias, secret,
|
|
check_exit_code=True)
|
|
else:
|
|
LOG.info(_LI('targetlist: %s'), targetalias)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'mod',
|
|
'-s', secret, '-a', 'enable',
|
|
targetalias,
|
|
check_exit_code=True)
|
|
|
|
def get_targetsecret(self, cmd, ip0, user, pw, targetalias, hdp):
|
|
"""Returns the chap secret for the specified target.
|
|
|
|
:param ip0: string IP address of controller
|
|
:param user: string user authentication for array
|
|
:param pw: string password authentication for array
|
|
:param targetalias: alias of the target
|
|
:param hdp: data pool of the logical unit
|
|
:return secret: CHAP secret of the target
|
|
"""
|
|
|
|
_evsid = self._get_evs(cmd, ip0, user, pw, hdp)
|
|
out, err = self.run_cmd(cmd, ip0, user, pw, "console-context",
|
|
"--evs", _evsid,
|
|
'iscsi-target', 'list', targetalias,
|
|
check_exit_code=True)
|
|
|
|
enabled = ""
|
|
secret = ""
|
|
lines = out.split('\n')
|
|
for line in lines:
|
|
if 'Secret' in line:
|
|
if len(line.split()) > 2:
|
|
secret = line.split()[2]
|
|
if 'Authentication' in line:
|
|
enabled = line.split()[2]
|
|
|
|
if enabled == 'Enabled':
|
|
return secret
|
|
else:
|
|
return ""
|