b3f0b7a2ca
This reverts commit 6338d4656c
Change-Id: I078217b96b2d5fcca78b57c8827883a4b15ef9f0
239 lines
6.4 KiB
Python
Executable File
239 lines
6.4 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, initiator_iqns=None):
|
|
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
|
|
|
|
rtslib.MappedLUN(acl_new, lun_new.lun, lun_new.lun)
|
|
|
|
if initiator_iqns:
|
|
initiator_iqns = initiator_iqns.strip(' ')
|
|
for i in initiator_iqns.split(','):
|
|
acl_new = rtslib.NodeACL(tpg_new, i, mode='create')
|
|
acl_new.chap_userid = userid
|
|
acl_new.chap_password = password
|
|
|
|
rtslib.MappedLUN(acl_new, lun_new.lun, lun_new.lun)
|
|
|
|
tpg_new.enable = 1
|
|
|
|
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 add_initiator(target_iqn, initiator_iqn, userid, password):
|
|
try:
|
|
rtsroot = rtslib.root.RTSRoot()
|
|
except rtslib.utils.RTSLibError:
|
|
print(_('Ensure that configfs is mounted at /sys/kernel/config.'))
|
|
raise
|
|
|
|
# Look for the target
|
|
target = None
|
|
for t in rtsroot.targets:
|
|
if t.dump()['wwn'] == target_iqn:
|
|
target = t
|
|
break
|
|
if target == None:
|
|
raise RtstoolError(_('Could not find target %s') % target_iqn)
|
|
|
|
tpg = target.tpgs.next() # get the first one
|
|
for acl in tpg.dump()['node_acls']:
|
|
# See if this ACL configuration already exists
|
|
if acl['node_wwn'] == initiator_iqn:
|
|
# No further action required
|
|
return
|
|
|
|
acl_new = rtslib.NodeACL(tpg, initiator_iqn, mode='create')
|
|
acl_new.chap_userid = userid
|
|
acl_new.chap_password = password
|
|
|
|
rtslib.MappedLUN(acl_new, 0, tpg_lun=0)
|
|
|
|
|
|
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]" +
|
|
" <initiator_iqn,iqn2,iqn3,...>")
|
|
print(sys.argv[0] +
|
|
" add-initiator [target_iqn] [userid] [password] [initiator_iqn]")
|
|
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()
|
|
|
|
if len(argv) > 7:
|
|
usage()
|
|
|
|
backing_device = argv[2]
|
|
name = argv[3]
|
|
userid = argv[4]
|
|
password = argv[5]
|
|
initiator_iqns = None
|
|
|
|
if len(argv) > 6:
|
|
initiator_iqns = argv[6]
|
|
|
|
create(backing_device, name, userid, password, initiator_iqns)
|
|
|
|
elif argv[1] == 'add-initiator':
|
|
if len(argv) < 6:
|
|
usage()
|
|
|
|
target_iqn = argv[2]
|
|
userid = argv[3]
|
|
password = argv[4]
|
|
initiator_iqn = argv[5]
|
|
|
|
add_initiator(target_iqn, initiator_iqn, 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())
|