cinder/bin/cinder-rtstool
Eric Harney 1fc557561b Add LIO iSCSI backend support using python-rtslib
This patch enables LIO as an iSCSI backend for Cinder, using
python-rtslib.

To enable, set "iscsi_helper = lioadm" in cinder.conf.

This requires python-rtslib 2.1.fb27, which is available from pip.

Implements blueprint lio-iscsi-support
DocImpact

Change-Id: Ifb23de65f26a40997afd6148a1d0be39bcc8d196
2013-02-15 11:20:10 -05:00

178 lines
4.6 KiB
Python
Executable File

#!/usr/bin/env python
# vim: et tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2012 - 2013 Red Hat, 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.
import gettext
import re
import sys
import rtslib
gettext.install('cinder-rtstool', unicode=1)
class RtstoolError(Exception):
pass
class RtstoolImportError(RtstoolError):
pass
def create(backing_device, name, userid, password):
try:
rtsroot = rtslib.root.RTSRoot()
except rtslib.utils.RTSLibError:
print _('Ensure that configfs is mounted at /sys/kernel/config.')
raise
# Look to see if BlockStorageObject already exists
for x in rtsroot.storage_objects:
if x.dump()['name'] == name:
# Already exists, use this one
return
so_new = rtslib.BlockStorageObject(name=name,
dev=backing_device)
target_new = rtslib.Target(rtslib.FabricModule('iscsi'), name, 'create')
tpg_new = rtslib.TPG(target_new, mode='create')
tpg_new.set_attribute('authentication', '1')
lun_new = rtslib.LUN(tpg_new, storage_object=so_new)
initiator_name = None
name_file = '/etc/iscsi/initiatorname.iscsi'
try:
with open(name_file, 'r') as f:
for line in f:
m = re.match('InitiatorName=(.+)', line)
if m != None:
initiator_name = m.group(1)
break
except IOError:
raise RtstoolError(_('Could not open %s') % name_file)
if initiator_name == None:
raise RtstoolError(_('Could not read InitiatorName from %s') %
name_file)
acl_new = rtslib.NodeACL(tpg_new, initiator_name, mode='create')
acl_new.chap_userid = userid
acl_new.chap_password = password
tpg_new.enable = 1
m = rtslib.MappedLUN(acl_new, lun_new.lun, lun_new.lun)
try:
rtslib.NetworkPortal(tpg_new, '0.0.0.0', 3260, mode='any')
except rtslib.utils.RTSLibError:
print _('Error creating NetworkPortal: ensure port 3260 '
'is not in use by another service.')
raise
try:
rtslib.NetworkPortal(tpg_new, '::0', 3260, mode='any')
except rtslib.utils.RTSLibError:
# TODO(emh): Binding to IPv6 fails sometimes -- let pass for now.
pass
def get_targets():
rtsroot = rtslib.root.RTSRoot()
for x in rtsroot.targets:
print(x.dump()['wwn'])
def delete(iqn):
rtsroot = rtslib.root.RTSRoot()
for x in rtsroot.targets:
if x.dump()['wwn'] == iqn:
x.delete()
break
for x in rtsroot.storage_objects:
if x.dump()['name'] == iqn:
x.delete()
break
def verify_rtslib():
for member in ['BlockStorageObject', 'FabricModule', 'LUN',
'MappedLUN', 'NetworkPortal', 'NodeACL', 'root',
'Target', 'TPG']:
if not hasattr(rtslib, member):
raise RtstoolImportError(_("rtslib is missing member %s: "
"You may need a newer python-rtslib.") %
member)
def usage():
print "Usage:"
print sys.argv[0], "create [device] [name] [userid] [password]"
print sys.argv[0], "get-targets"
print sys.argv[0], "delete [iqn]"
print sys.argv[0], "verify"
sys.exit(1)
def main(argv=None):
if argv is None:
argv = sys.argv
if len(argv) < 2:
usage()
if argv[1] == 'create':
if len(argv) < 6:
usage()
backing_device = argv[2]
name = argv[3]
userid = argv[4]
password = argv[5]
create(backing_device, name, userid, password)
elif argv[1] == 'get-targets':
get_targets()
elif argv[1] == 'delete':
if len(argv) < 3:
usage()
iqn = argv[2]
delete(iqn)
elif argv[1] == 'verify':
# This is used to verify that this script can be called by cinder,
# and that rtslib is new enough to work.
verify_rtslib()
return 0
else:
usage()
return 0
if __name__ == '__main__':
sys.exit(main())