From 81ac0b4115633437a53da99cd73ac6663e0b98e4 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Mon, 11 Sep 2017 16:08:33 +0200 Subject: [PATCH] Remove assumption that a valid IPMI channel cannot follow an invalid one It seems to be incorrect at least for some iLO machines. Also harden the code against invalid output from ipmitool. Change-Id: I733785e9c7d86eadca963f0776910504bf91bcfe Closes-Bug: #1714944 (cherry picked from commit d6ff5116f4a5586238d44a196ec89d844b151f9d) --- ironic_python_agent/hardware.py | 21 ++++++++++++------- .../tests/unit/test_hardware.py | 4 ++++ ...ipmi-address-channel-b6b8010c41d05c1b.yaml | 6 ++++++ 3 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 releasenotes/notes/ipmi-address-channel-b6b8010c41d05c1b.yaml diff --git a/ironic_python_agent/hardware.py b/ironic_python_agent/hardware.py index 568d5bf49..30549dbc0 100644 --- a/ironic_python_agent/hardware.py +++ b/ironic_python_agent/hardware.py @@ -21,6 +21,7 @@ import time from ironic_lib import disk_utils from ironic_lib import utils as il_utils +import netaddr from oslo_concurrency import processutils from oslo_config import cfg from oslo_log import log @@ -944,14 +945,20 @@ class GenericHardwareManager(HardwareManager): out, e = utils.execute( "ipmitool lan print {} | awk '/IP Address[[:space:]]*:/" " {{print $4}}'".format(channel), shell=True) - # Invalid channel cannot be followed by a valid one, so we can - # safely break here if e.startswith("Invalid channel"): - break - # In case we get empty IP or 0.0.0.0 on a valid channel, - # we need to keep querying - if out.strip() not in ('', '0.0.0.0'): - return out.strip() + continue + out = out.strip() + + try: + netaddr.IPAddress(out) + except netaddr.AddrFormatError: + LOG.warning('Invalid IP address: %s', out) + continue + + # In case we get 0.0.0.0 on a valid channel, we need to keep + # querying + if out != '0.0.0.0': + return out except (processutils.ProcessExecutionError, OSError) as e: # Not error, because it's normal in virtual environment diff --git a/ironic_python_agent/tests/unit/test_hardware.py b/ironic_python_agent/tests/unit/test_hardware.py index 216f9776e..901bae2d0 100644 --- a/ironic_python_agent/tests/unit/test_hardware.py +++ b/ironic_python_agent/tests/unit/test_hardware.py @@ -1564,7 +1564,11 @@ class TestGenericHardwareManager(base.IronicAgentTest): # and for any other we return a correct IP address def side_effect(*args, **kwargs): if args[0].startswith("ipmitool lan print 1"): + return '', 'Invalid channel 1\n' + elif args[0].startswith("ipmitool lan print 2"): return '0.0.0.0\n', '' + elif args[0].startswith("ipmitool lan print 3"): + return 'meow', '' else: return '192.1.2.3\n', '' mocked_execute.side_effect = side_effect diff --git a/releasenotes/notes/ipmi-address-channel-b6b8010c41d05c1b.yaml b/releasenotes/notes/ipmi-address-channel-b6b8010c41d05c1b.yaml new file mode 100644 index 000000000..64e34d0f2 --- /dev/null +++ b/releasenotes/notes/ipmi-address-channel-b6b8010c41d05c1b.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes incorrect assumption that a valid channel cannot follow an invalid + one in IPMI (`bug 1714944 + `_).