Merge "Add persistent volumes for tgtd."

This commit is contained in:
Jenkins
2012-08-07 04:09:00 +00:00
committed by Gerrit Code Review
4 changed files with 111 additions and 79 deletions

View File

@@ -14,6 +14,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import os.path
import string import string
from cinder import test from cinder import test
@@ -28,9 +29,12 @@ class TargetAdminTestCase(object):
self.tid = 1 self.tid = 1
self.target_name = 'iqn.2011-09.org.foo.bar:blaa' self.target_name = 'iqn.2011-09.org.foo.bar:blaa'
self.lun = 10 self.lun = 10
self.path = '/foo/bar/blaa' self.path = '/foo'
self.vol_id = 'blaa'
self.script_template = None self.script_template = None
self.stubs.Set(os.path, 'isfile', lambda _: True)
self.stubs.Set(os, 'unlink', lambda _: '')
def get_script_params(self): def get_script_params(self):
return {'tid': self.tid, return {'tid': self.tid,
@@ -65,11 +69,10 @@ class TargetAdminTestCase(object):
def run_commands(self): def run_commands(self):
tgtadm = iscsi.get_target_admin() tgtadm = iscsi.get_target_admin()
tgtadm.set_execute(self.fake_execute) tgtadm.set_execute(self.fake_execute)
tgtadm.new_target(self.target_name, self.tid) tgtadm.create_iscsi_target(self.target_name, self.tid,
self.lun, self.path)
tgtadm.show_target(self.tid) tgtadm.show_target(self.tid)
tgtadm.new_logicalunit(self.tid, self.lun, self.path) tgtadm.remove_iscsi_target(self.tid, self.lun, self.vol_id)
tgtadm.delete_logicalunit(self.tid, self.lun)
tgtadm.delete_target(self.tid)
def test_target_admin(self): def test_target_admin(self):
self.clear_cmds() self.clear_cmds()
@@ -83,22 +86,11 @@ class TgtAdmTestCase(test.TestCase, TargetAdminTestCase):
super(TgtAdmTestCase, self).setUp() super(TgtAdmTestCase, self).setUp()
TargetAdminTestCase.setUp(self) TargetAdminTestCase.setUp(self)
self.flags(iscsi_helper='tgtadm') self.flags(iscsi_helper='tgtadm')
self.flags(volumes_dir="./")
self.script_template = "\n".join([ self.script_template = "\n".join([
"tgtadm --op new --lld=iscsi --mode=target --tid=%(tid)s " "tgt-admin --execute --conf ./blaa --update blaa",
"--targetname=%(target_name)s", "tgtadm --op show --lld=iscsi --mode=target --tid=1",
"tgtadm --op bind --lld=iscsi --mode=target --initiator-address=ALL " "tgt-admin --delete iqn.2010-10.org.openstack:volume-blaa"])
"--tid=%(tid)s",
"tgtadm --op show --lld=iscsi --mode=target --tid=%(tid)s",
"tgtadm --op new --lld=iscsi --mode=logicalunit --tid=%(tid)s "
"--lun=%(lun)d --backing-store=%(path)s",
"tgtadm --op delete --lld=iscsi --mode=logicalunit --tid=%(tid)s "
"--lun=%(lun)d",
"tgtadm --op delete --lld=iscsi --mode=target --tid=%(tid)s"])
def get_script_params(self):
params = super(TgtAdmTestCase, self).get_script_params()
params['lun'] += 1
return params
class IetAdmTestCase(test.TestCase, TargetAdminTestCase): class IetAdmTestCase(test.TestCase, TargetAdminTestCase):
@@ -109,8 +101,8 @@ class IetAdmTestCase(test.TestCase, TargetAdminTestCase):
self.flags(iscsi_helper='ietadm') self.flags(iscsi_helper='ietadm')
self.script_template = "\n".join([ self.script_template = "\n".join([
"ietadm --op new --tid=%(tid)s --params Name=%(target_name)s", "ietadm --op new --tid=%(tid)s --params Name=%(target_name)s",
"ietadm --op show --tid=%(tid)s", "ietadm --op new --tid=%(tid)s --lun=%(lun)s "
"ietadm --op new --tid=%(tid)s --lun=%(lun)d "
"--params Path=%(path)s,Type=fileio", "--params Path=%(path)s,Type=fileio",
"ietadm --op delete --tid=%(tid)s --lun=%(lun)d", "ietadm --op show --tid=%(tid)s",
"ietadm --op delete --tid=%(tid)s"]) "ietadm --op delete --tid=%(tid)s",
"ietadm --op delete --tid=%(tid)s --lun=%(lun)s"])

View File

@@ -274,9 +274,8 @@ class ISCSIDriver(VolumeDriver):
iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name']) iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name']) volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name'])
self.tgtadm.new_target(iscsi_name, iscsi_target, check_exit_code=False) self.tgtadm.create_iscsi_target(iscsi_name, iscsi_target,
self.tgtadm.new_logicalunit(iscsi_target, 0, volume_path, 0, volume_path, check_exit_code=False)
check_exit_code=False)
def _ensure_iscsi_targets(self, context, host): def _ensure_iscsi_targets(self, context, host):
"""Ensure that target ids have been created in datastore.""" """Ensure that target ids have been created in datastore."""
@@ -297,8 +296,8 @@ class ISCSIDriver(VolumeDriver):
iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name']) iscsi_name = "%s%s" % (FLAGS.iscsi_target_prefix, volume['name'])
volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name']) volume_path = "/dev/%s/%s" % (FLAGS.volume_group, volume['name'])
self.tgtadm.new_target(iscsi_name, iscsi_target) self.tgtadm.create_iscsi_target(iscsi_name, iscsi_target,
self.tgtadm.new_logicalunit(iscsi_target, 0, volume_path) 0, volume_path)
model_update = {} model_update = {}
if FLAGS.iscsi_helper == 'tgtadm': if FLAGS.iscsi_helper == 'tgtadm':
@@ -328,8 +327,7 @@ class ISCSIDriver(VolumeDriver):
"is presently exported for volume: %s"), volume['id']) "is presently exported for volume: %s"), volume['id'])
return return
self.tgtadm.delete_logicalunit(iscsi_target, 0) self.tgtadm.remove_iscsi_target(iscsi_target, 0, volume['id'])
self.tgtadm.delete_target(iscsi_target)
def _do_iscsi_discovery(self, volume): def _do_iscsi_discovery(self, volume):
#TODO(justinsb): Deprecate discovery and use stored info #TODO(justinsb): Deprecate discovery and use stored info

View File

@@ -19,18 +19,27 @@
Helper code for the iSCSI volume driver. Helper code for the iSCSI volume driver.
""" """
import os
from cinder import exception
from cinder import flags from cinder import flags
from cinder.openstack.common import cfg from cinder.openstack.common import cfg
from cinder.openstack.common import log as logging
from cinder import utils from cinder import utils
LOG = logging.getLogger(__name__)
iscsi_helper_opt = cfg.StrOpt('iscsi_helper', iscsi_helper_opt = [
default='ietadm', cfg.StrOpt('iscsi_helper',
help='iscsi target user-land tool to use') default='tgtadm',
help='iscsi target user-land tool to use'),
cfg.StrOpt('volumes_dir',
default='$state_path/volumes',
help='Volume configfuration file storage directory'),
]
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
FLAGS.register_opt(iscsi_helper_opt) FLAGS.register_opts(iscsi_helper_opt)
class TargetAdmin(object): class TargetAdmin(object):
@@ -50,23 +59,31 @@ class TargetAdmin(object):
def _run(self, *args, **kwargs): def _run(self, *args, **kwargs):
self._execute(self._cmd, *args, run_as_root=True, **kwargs) self._execute(self._cmd, *args, run_as_root=True, **kwargs)
def new_target(self, name, tid, **kwargs): def create_iscsi_target(self, name, tid, lun, path, **kwargs):
"""Create a iSCSI target and logical unit"""
raise NotImplementedError()
def remove_iscsi_target(self, tid, lun, vol_id, **kwargs):
"""Remove a iSCSI target and logical unit"""
raise NotImplementedError()
def _new_target(self, name, tid, **kwargs):
"""Create a new iSCSI target.""" """Create a new iSCSI target."""
raise NotImplementedError() raise NotImplementedError()
def delete_target(self, tid, **kwargs): def _delete_target(self, tid, **kwargs):
"""Delete a target.""" """Delete a target."""
raise NotImplementedError() raise NotImplementedError()
def show_target(self, tid, **kwargs): def _show_target(self, tid, **kwargs):
"""Query the given target ID.""" """Query the given target ID."""
raise NotImplementedError() raise NotImplementedError()
def new_logicalunit(self, tid, lun, path, **kwargs): def _new_logicalunit(self, tid, lun, path, **kwargs):
"""Create a new LUN on a target using the supplied path.""" """Create a new LUN on a target using the supplied path."""
raise NotImplementedError() raise NotImplementedError()
def delete_logicalunit(self, tid, lun, **kwargs): def _delete_logicalunit(self, tid, lun, **kwargs):
"""Delete a logical unit from a target.""" """Delete a logical unit from a target."""
raise NotImplementedError() raise NotImplementedError()
@@ -77,23 +94,53 @@ class TgtAdm(TargetAdmin):
def __init__(self, execute=utils.execute): def __init__(self, execute=utils.execute):
super(TgtAdm, self).__init__('tgtadm', execute) super(TgtAdm, self).__init__('tgtadm', execute)
def new_target(self, name, tid, **kwargs): def create_iscsi_target(self, name, tid, lun, path, **kwargs):
self._run('--op', 'new', try:
'--lld=iscsi', '--mode=target', if not os.path.exists(FLAGS.volumes_dir):
'--tid=%s' % tid, os.makedirs(FLAGS.volumes_dir)
'--targetname=%s' % name,
**kwargs)
self._run('--op', 'bind',
'--lld=iscsi', '--mode=target',
'--initiator-address=ALL',
'--tid=%s' % tid,
**kwargs)
def delete_target(self, tid, **kwargs): # grab the volume id
self._run('--op', 'delete', vol_id = name.split(':')[1]
'--lld=iscsi', '--mode=target',
'--tid=%s' % tid, volume_conf = """
**kwargs) <target %s>
backing-store %s
</target>
""" % (name, path)
LOG.info(_('Creating volume: %s') % vol_id)
volume_path = os.path.join(FLAGS.volumes_dir, vol_id)
if not os.path.isfile(volume_path):
f = open(volume_path, 'w+')
f.write(volume_conf)
f.close()
self._execute('tgt-admin', '--execute',
'--conf %s' % volume_path,
'--update %s' % vol_id, run_as_root=True)
except Exception as ex:
LOG.exception(ex)
raise exception.Error(_('Failed to create volume: %s')
% vol_id)
def remove_iscsi_target(self, tid, lun, vol_id, **kwargs):
try:
LOG.info(_('Removing volume: %s') % vol_id)
vol_uuid_file = 'volume-%s' % vol_id
volume_path = os.path.join(FLAGS.volumes_dir, vol_uuid_file)
if os.path.isfile(volume_path):
delete_file = '%s%s' % (FLAGS.iscsi_target_prefix,
vol_uuid_file)
self._execute('tgt-admin',
'--delete',
delete_file,
run_as_root=True)
os.unlink(volume_path)
except Exception as ex:
LOG.exception(ex)
raise exception.Error(_('Failed to remove volume: %s')
% vol_id)
def show_target(self, tid, **kwargs): def show_target(self, tid, **kwargs):
self._run('--op', 'show', self._run('--op', 'show',
@@ -101,21 +148,6 @@ class TgtAdm(TargetAdmin):
'--tid=%s' % tid, '--tid=%s' % tid,
**kwargs) **kwargs)
def new_logicalunit(self, tid, lun, path, **kwargs):
self._run('--op', 'new',
'--lld=iscsi', '--mode=logicalunit',
'--tid=%s' % tid,
'--lun=%d' % (lun + 1), # lun0 is reserved
'--backing-store=%s' % path,
**kwargs)
def delete_logicalunit(self, tid, lun, **kwargs):
self._run('--op', 'delete',
'--lld=iscsi', '--mode=logicalunit',
'--tid=%s' % tid,
'--lun=%d' % (lun + 1),
**kwargs)
class IetAdm(TargetAdmin): class IetAdm(TargetAdmin):
"""iSCSI target administration using ietadm.""" """iSCSI target administration using ietadm."""
@@ -123,13 +155,22 @@ class IetAdm(TargetAdmin):
def __init__(self, execute=utils.execute): def __init__(self, execute=utils.execute):
super(IetAdm, self).__init__('ietadm', execute) super(IetAdm, self).__init__('ietadm', execute)
def new_target(self, name, tid, **kwargs): def create_iscsi_target(self, name, tid, lun, path, **kwargs):
self._run('--op', 'new', self._new_target(name, tid, **kwargs)
'--tid=%s' % tid, self._new_logicalunit(tid, lun, path, **kwargs)
'--params', 'Name=%s' % name,
**kwargs)
def delete_target(self, tid, **kwargs): def remove_iscsi_target(self, tid, lun, vol_id, **kwargs):
LOG.info(_('Removing volume: %s') % vol_id)
self._delete_target(tid, **kwargs)
self._delete_logicalunit(tid, lun, **kwargs)
def _new_target(self, name, tid, **kwargs):
self._run('--op', 'new',
'--tid=%s' % tid,
'--params', 'Name=%s' % name,
**kwargs)
def _delete_target(self, tid, **kwargs):
self._run('--op', 'delete', self._run('--op', 'delete',
'--tid=%s' % tid, '--tid=%s' % tid,
**kwargs) **kwargs)
@@ -139,14 +180,14 @@ class IetAdm(TargetAdmin):
'--tid=%s' % tid, '--tid=%s' % tid,
**kwargs) **kwargs)
def new_logicalunit(self, tid, lun, path, **kwargs): def _new_logicalunit(self, tid, lun, path, **kwargs):
self._run('--op', 'new', self._run('--op', 'new',
'--tid=%s' % tid, '--tid=%s' % tid,
'--lun=%d' % lun, '--lun=%d' % lun,
'--params', 'Path=%s,Type=fileio' % path, '--params', 'Path=%s,Type=fileio' % path,
**kwargs) **kwargs)
def delete_logicalunit(self, tid, lun, **kwargs): def _delete_logicalunit(self, tid, lun, **kwargs):
self._run('--op', 'delete', self._run('--op', 'delete',
'--tid=%s' % tid, '--tid=%s' % tid,
'--lun=%d' % lun, '--lun=%d' % lun,

View File

@@ -5,6 +5,7 @@
# nova/volume/iscsi.py: iscsi_helper '--op' ... # nova/volume/iscsi.py: iscsi_helper '--op' ...
ietadm: CommandFilter, /usr/sbin/ietadm, root ietadm: CommandFilter, /usr/sbin/ietadm, root
tgtadm: CommandFilter, /usr/sbin/tgtadm, root tgtadm: CommandFilter, /usr/sbin/tgtadm, root
tgt-admin: CommandFilter, /usr/sbin/tgt-admin, root
# nova/volume/driver.py: 'vgs', '--noheadings', '-o', 'name' # nova/volume/driver.py: 'vgs', '--noheadings', '-o', 'name'
vgs: CommandFilter, /sbin/vgs, root vgs: CommandFilter, /sbin/vgs, root