From 1e105d61f72edb2d1cb75a29dce2964618fa41e3 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Thu, 11 Aug 2011 07:44:38 -0400 Subject: [PATCH] Allow the user to choose either ietadm or tgtadm (lp:819997) Also, refactor ietadm/tgtadm calls out into helper classes. Add a new TargetAdmin abstract base class and implement it using ietadm and tgtadm. This cleans up the code greatly and gets us some code reuse. (Based on a patch by Chuck Short ) Change-Id: I1c0064e5d35483a6c4059cfc61a484f5f576b2da --- nova/tests/test_iscsi.py | 116 ++++++++++++++++++++++++++++++++++++++ nova/tests/test_volume.py | 16 ++---- 2 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 nova/tests/test_iscsi.py diff --git a/nova/tests/test_iscsi.py b/nova/tests/test_iscsi.py new file mode 100644 index 00000000..d7aed0fb --- /dev/null +++ b/nova/tests/test_iscsi.py @@ -0,0 +1,116 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Red Hat, Inc. +# +# 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 string + +from nova import test +from nova.volume import iscsi + + +class TargetAdminTestCase(object): + + def setUp(self): + self.cmds = [] + + self.tid = 1 + self.target_name = 'iqn.2011-09.org.foo.bar:blaa' + self.lun = 10 + self.path = '/foo/bar/blaa' + + self.script_template = None + + def get_script_params(self): + return {'tid': self.tid, + 'target_name': self.target_name, + 'lun': self.lun, + 'path': self.path} + + def get_script(self): + return self.script_template % self.get_script_params() + + def fake_execute(self, *cmd, **kwargs): + self.cmds.append(string.join(cmd)) + return "", None + + def clear_cmds(self): + cmds = [] + + def verify_cmds(self, cmds): + self.assertEqual(len(cmds), len(self.cmds)) + for a, b in zip(cmds, self.cmds): + self.assertEqual(a, b) + + def verify(self): + script = self.get_script() + cmds = [] + for line in script.split('\n'): + if not line.strip(): + continue + cmds.append(line) + self.verify_cmds(cmds) + + def run_commands(self): + tgtadm = iscsi.get_target_admin() + tgtadm.set_execute(self.fake_execute) + tgtadm.new_target(self.target_name, self.tid) + tgtadm.show_target(self.tid) + tgtadm.new_logicalunit(self.tid, self.lun, self.path) + tgtadm.delete_logicalunit(self.tid, self.lun) + tgtadm.delete_target(self.tid) + + def test_target_admin(self): + self.clear_cmds() + self.run_commands() + self.verify() + + +class TgtAdmTestCase(test.TestCase, TargetAdminTestCase): + + def setUp(self): + super(TgtAdmTestCase, self).setUp() + TargetAdminTestCase.setUp(self) + self.flags(iscsi_helper='tgtadm') + self.script_template = """ +tgtadm --op new --lld=iscsi --mode=target --tid=%(tid)s \ +--targetname=%(target_name)s +tgtadm --op bind --lld=iscsi --mode=target --initiator-address=ALL \ +--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): + + def setUp(self): + super(IetAdmTestCase, self).setUp() + TargetAdminTestCase.setUp(self) + self.flags(iscsi_helper='ietadm') + self.script_template = """ +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)d --params Path=%(path)s,Type=fileio +ietadm --op delete --tid=%(tid)s --lun=%(lun)d +ietadm --op delete --tid=%(tid)s +""" diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index d1b11aaf..588b7a32 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -270,7 +270,7 @@ class DriverTestCase(test.TestCase): def _fake_execute(_command, *_args, **_kwargs): """Fake _execute.""" return self.output, None - self.volume.driver._execute = _fake_execute + self.volume.driver.set_execute(_fake_execute) log = logging.getLogger() self.stream = cStringIO.StringIO() @@ -333,12 +333,10 @@ class ISCSITestCase(DriverTestCase): """No log message when all the processes are running.""" volume_id_list = self._attach_volume() - self.mox.StubOutWithMock(self.volume.driver, '_execute') + self.mox.StubOutWithMock(self.volume.driver.tgtadm, 'show_target') for i in volume_id_list: tid = db.volume_get_iscsi_target_num(self.context, i) - self.volume.driver._execute("ietadm", "--op", "show", - "--tid=%(tid)d" % locals(), - run_as_root=True) + self.volume.driver.tgtadm.show_target(tid) self.stream.truncate(0) self.mox.ReplayAll() @@ -354,11 +352,9 @@ class ISCSITestCase(DriverTestCase): volume_id_list = self._attach_volume() tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0]) - self.mox.StubOutWithMock(self.volume.driver, '_execute') - self.volume.driver._execute("ietadm", "--op", "show", - "--tid=%(tid)d" % locals(), - run_as_root=True).AndRaise( - exception.ProcessExecutionError()) + self.mox.StubOutWithMock(self.volume.driver.tgtadm, 'show_target') + self.volume.driver.tgtadm.show_target(tid).AndRaise( + exception.ProcessExecutionError()) self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError,