From 44955a1937ae25514bfe4ee5ccb561642681ab1c Mon Sep 17 00:00:00 2001 From: Dean Troyer Date: Tue, 13 Dec 2011 19:05:21 -0600 Subject: [PATCH] Fixes bug 887402 Change utils.execute to accept a list or a single integer in check_exit_code. In libvirt.disconnect_volume() return codes 0 and 255 are both valid for logout/delete, where 255 is returned if the volume is already disconnected. Also includes a fix by Dan Prince for a regression introduced by the above fix (bug 904560) Change-Id: Icffeb0fe8269a02d95ac6ed180ba0bb9f458a6ed --- nova/tests/test_utils.py | 6 ++++++ nova/utils.py | 17 ++++++++++++----- nova/virt/libvirt/volume.py | 12 ++++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 2c4c02b827a..15ac0dc2d5c 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -79,6 +79,12 @@ def test_unknown_kwargs_raises_error(self): utils.execute, '/bin/true', this_is_not_a_valid_kwarg=True) + def test_check_exit_code_boolean(self): + utils.execute('/bin/false', check_exit_code=False) + self.assertRaises(exception.ProcessExecutionError, + utils.execute, + '/bin/false', check_exit_code=True) + def test_no_retry_on_success(self): fd, tmpfilename = tempfile.mkstemp() _, tmpfilename2 = tempfile.mkstemp() diff --git a/nova/utils.py b/nova/utils.py index adf45debdf9..1139e101eb7 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -157,8 +157,9 @@ def execute(*cmd, **kwargs): :cmd Passed to subprocess.Popen. :process_input Send to opened process. - :check_exit_code Defaults to 0. Raise exception.ProcessExecutionError - unless program exits with this code. + :check_exit_code Single bool, int, or list of allowed exit codes. + Defaults to [0]. Raise exception.ProcessExecutionError + unless program exits with one of these code. :delay_on_retry True | False. Defaults to True. If set to True, wait a short amount of time before retrying. :attempts How many times to retry cmd. @@ -171,7 +172,13 @@ def execute(*cmd, **kwargs): """ process_input = kwargs.pop('process_input', None) - check_exit_code = kwargs.pop('check_exit_code', 0) + check_exit_code = kwargs.pop('check_exit_code', [0]) + ignore_exit_code = False + if type(check_exit_code) == int: + check_exit_code = [check_exit_code] + elif type(check_exit_code) == bool: + ignore_exit_code = not check_exit_code + check_exit_code = [0] delay_on_retry = kwargs.pop('delay_on_retry', True) attempts = kwargs.pop('attempts', 1) run_as_root = kwargs.pop('run_as_root', False) @@ -205,8 +212,8 @@ def execute(*cmd, **kwargs): _returncode = obj.returncode # pylint: disable=E1101 if _returncode: LOG.debug(_('Result was %s') % _returncode) - if type(check_exit_code) == types.IntType \ - and _returncode != check_exit_code: + if ignore_exit_code == False \ + and _returncode not in check_exit_code: (stdout, stderr) = result raise exception.ProcessExecutionError( exit_code=_returncode, diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index e5d73c08f67..352ba5115e1 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -87,11 +87,13 @@ def connect_volume(self, connection_info, mount_device): class LibvirtISCSIVolumeDriver(LibvirtVolumeDriver): """Driver to attach Network volumes to libvirt.""" - def _run_iscsiadm(self, iscsi_properties, iscsi_command): + def _run_iscsiadm(self, iscsi_properties, iscsi_command, **kwargs): + check_exit_code = kwargs.pop('check_exit_code', 0) (out, err) = utils.execute('iscsiadm', '-m', 'node', '-T', iscsi_properties['target_iqn'], '-p', iscsi_properties['target_portal'], - *iscsi_command, run_as_root=True) + *iscsi_command, run_as_root=True, + check_exit_code=check_exit_code) LOG.debug("iscsiadm %s: stdout=%s stderr=%s" % (iscsi_command, out, err)) return (out, err) @@ -170,5 +172,7 @@ def disconnect_volume(self, connection_info, mount_device): sup.disconnect_volume(connection_info, mount_device) iscsi_properties = connection_info['data'] self._iscsiadm_update(iscsi_properties, "node.startup", "manual") - self._run_iscsiadm(iscsi_properties, ("--logout",)) - self._run_iscsiadm(iscsi_properties, ('--op', 'delete')) + self._run_iscsiadm(iscsi_properties, ("--logout"), + check_exit_code=[0, 255]) + self._run_iscsiadm(iscsi_properties, ('--op', 'delete'), + check_exit_code=[0, 255])