TgtAdm: Don't change CHAP username/password on live migration

As tgtd doesn't update CHAP username/password while the initiator is
connected, CHAP username/password must not be changed while a Nova
instance are performing live-migration; otherwise the compute node
which the instance migrates to cannot login to the volume and the
migration process is aborted.

This fixes TgtAdm implementation not to regenerate random
username/password every time initialize_connection is called.
Also, it enables CHAP auth in unit tests of TargetAdmin helpers.

Change-Id: I48729a33fada62a7c8e4fe500b1e39533d898701
Closes-Bug: #1383509
This commit is contained in:
Tomoki Sekiyama 2014-10-20 14:32:55 -04:00
parent c105259736
commit c22038b900
3 changed files with 58 additions and 9 deletions

View File

@ -23,6 +23,8 @@ import re
import stat
import time
import six
from cinder.brick import exception
from cinder.brick import executor
from cinder.i18n import _
@ -47,6 +49,10 @@ class TargetAdmin(executor.Executor):
def _run(self, *args, **kwargs):
self._execute(self._cmd, *args, run_as_root=True, **kwargs)
def _get_target_chap_auth(self, volume_id):
"""Get the current chap auth username and password."""
return None
def create_iscsi_target(self, name, tid, lun, path,
chap_auth=None, **kwargs):
"""Create an iSCSI target and logical unit."""
@ -159,6 +165,25 @@ class TgtAdm(TargetAdmin):
"id:%(vol_id)s: %(e)s")
% {'vol_id': name, 'e': e})
def _get_target_chap_auth(self, name):
volumes_dir = self.volumes_dir
vol_id = name.split(':')[1]
volume_path = os.path.join(volumes_dir, vol_id)
try:
with open(volume_path, 'r') as f:
volume_conf = f.read()
except Exception as e:
LOG.debug('Failed to open config for %(vol_id)s: %(e)s'
% {'vol_id': vol_id, 'e': six.text_type(e)})
return None
m = re.search('incominguser (\w+) (\w+)', volume_conf)
if m:
return (m.group(1), m.group(2))
LOG.debug('Failed to find CHAP auth from config for %s' % vol_id)
return None
def create_iscsi_target(self, name, tid, lun, path,
chap_auth=None, **kwargs):
# Note(jdg) tid and lun aren't used by TgtAdm but remain for
@ -496,10 +521,6 @@ class LioAdm(TargetAdmin):
LOG.info(_('Creating iscsi_target for volume: %s') % vol_id)
# rtstool requires chap_auth, but unit tests don't provide it
chap_auth_userid = 'test_id'
chap_auth_password = 'test_pass'
if chap_auth is not None:
(chap_auth_userid, chap_auth_password) = chap_auth.split(' ')[1:]

View File

@ -34,6 +34,8 @@ class TargetAdminTestCase(object):
self.path = '/foo'
self.vol_id = 'blaa'
self.vol_name = 'volume-blaa'
self.chap_username = 'test_id'
self.chap_password = 'test_pass'
self.write_cache = 'off'
self.db = {}
@ -66,7 +68,9 @@ class TargetAdminTestCase(object):
return {'tid': self.tid,
'target_name': self.target_name,
'lun': self.lun,
'path': self.path}
'path': self.path,
'username': self.chap_username,
'password': self.chap_password}
def get_script(self):
return self.script_template % self.get_script_params()
@ -78,10 +82,14 @@ class TargetAdminTestCase(object):
def clear_cmds(self):
self.cmds = []
def verify_config(self):
pass
def verify_cmds(self, cmds):
self.assertEqual(len(cmds), len(self.cmds))
for cmd in self.cmds:
self.assertTrue(cmd in cmds)
self.verify_config()
def verify(self):
script = self.get_script()
@ -95,8 +103,11 @@ class TargetAdminTestCase(object):
def run_commands(self):
target_helper = self.driver.get_target_helper(self.db)
target_helper.set_execute(self.fake_execute)
chap_auth = target_helper._iscsi_authentication('IncomingUser',
self.chap_username,
self.chap_password)
target_helper.create_iscsi_target(self.target_name, self.tid,
self.lun, self.path,
self.lun, self.path, chap_auth,
write_cache=self.write_cache)
target_helper.show_target(self.tid, iqn=self.target_name)
target_helper.remove_iscsi_target(self.tid, self.lun, self.vol_id,
@ -128,6 +139,11 @@ class TgtAdmTestCase(test.TestCase, TargetAdminTestCase):
'--delete %(target_name)s',
'tgtadm --lld iscsi --op show --mode target'])
def verify_config(self):
target_helper = self.driver.get_target_helper(self.db)
self.assertEqual(target_helper._get_target_chap_auth(self.target_name),
(self.chap_username, self.chap_password))
class IetAdmTestCase(test.TestCase, TargetAdminTestCase):
@ -139,6 +155,8 @@ class IetAdmTestCase(test.TestCase, TargetAdminTestCase):
'ietadm --op new --tid=%(tid)s --params Name=%(target_name)s',
'ietadm --op new --tid=%(tid)s --lun=%(lun)s '
'--params Path=%(path)s,Type=fileio',
'ietadm --op new --tid=%(tid)s --user '
'--params=IncomingUser=%(username)s,Password=%(password)s',
'ietadm --op show --tid=%(tid)s',
'ietadm --op delete --tid=%(tid)s --lun=%(lun)s',
'ietadm --op delete --tid=%(tid)s'])
@ -155,6 +173,8 @@ class IetAdmBlockIOTestCase(test.TestCase, TargetAdminTestCase):
'ietadm --op new --tid=%(tid)s --params Name=%(target_name)s',
'ietadm --op new --tid=%(tid)s --lun=%(lun)s '
'--params Path=%(path)s,Type=blockio',
'ietadm --op new --tid=%(tid)s --user '
'--params=IncomingUser=%(username)s,Password=%(password)s',
'ietadm --op show --tid=%(tid)s',
'ietadm --op delete --tid=%(tid)s --lun=%(lun)s',
'ietadm --op delete --tid=%(tid)s'])
@ -171,6 +191,8 @@ class IetAdmFileIOTestCase(test.TestCase, TargetAdminTestCase):
'ietadm --op new --tid=%(tid)s --params Name=%(target_name)s',
'ietadm --op new --tid=%(tid)s --lun=%(lun)s '
'--params Path=%(path)s,Type=fileio',
'ietadm --op new --tid=%(tid)s --user '
'--params=IncomingUser=%(username)s,Password=%(password)s',
'ietadm --op show --tid=%(tid)s',
'ietadm --op delete --tid=%(tid)s --lun=%(lun)s',
'ietadm --op delete --tid=%(tid)s'])
@ -188,6 +210,8 @@ class IetAdmAutoIOTestCase(test.TestCase, TargetAdminTestCase):
'ietadm --op new --tid=%(tid)s --params Name=%(target_name)s',
'ietadm --op new --tid=%(tid)s --lun=%(lun)s '
'--params Path=%(path)s,Type=blockio',
'ietadm --op new --tid=%(tid)s --user '
'--params=IncomingUser=%(username)s,Password=%(password)s',
'ietadm --op show --tid=%(tid)s',
'ietadm --op delete --tid=%(tid)s --lun=%(lun)s',
'ietadm --op delete --tid=%(tid)s'])
@ -201,7 +225,7 @@ class LioAdmTestCase(test.TestCase, TargetAdminTestCase):
self.flags(iscsi_helper='lioadm')
self.script_template = "\n".join([
'cinder-rtstool create '
'%(path)s %(target_name)s test_id test_pass',
'%(path)s %(target_name)s %(username)s %(password)s',
'cinder-rtstool delete %(target_name)s'])

View File

@ -41,8 +41,12 @@ class _ExportMixin(object):
volume,
max_targets)
chap_username = utils.generate_username()
chap_password = utils.generate_password()
current_chap_auth = self._get_target_chap_auth(iscsi_name)
if current_chap_auth:
(chap_username, chap_password) = current_chap_auth
else:
chap_username = utils.generate_username()
chap_password = utils.generate_password()
chap_auth = self._iscsi_authentication('IncomingUser',
chap_username,
chap_password)