summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ironic/common/driver_factory.py4
-rw-r--r--ironic/common/neutron.py2
-rw-r--r--ironic/drivers/modules/boot_mode_utils.py4
-rw-r--r--ironic/drivers/modules/deploy_utils.py4
-rw-r--r--ironic/drivers/modules/inspector.py4
-rw-r--r--ironic/drivers/modules/ramdisk.py3
-rw-r--r--ironic/drivers/modules/redfish/boot.py2
-rw-r--r--ironic/drivers/modules/redfish/raid.py2
-rw-r--r--ironic/objects/node.py6
-rw-r--r--ironic/tests/unit/objects/test_node.py11
-rw-r--r--releasenotes/notes/instance-info-interface-override-fix-043df41199529892.yaml7
11 files changed, 36 insertions, 13 deletions
diff --git a/ironic/common/driver_factory.py b/ironic/common/driver_factory.py
index 298a4962d..d989f075e 100644
--- a/ironic/common/driver_factory.py
+++ b/ironic/common/driver_factory.py
@@ -69,9 +69,7 @@ def _attach_interfaces_to_driver(bare_driver, node, hw_type):
the requested implementation is not compatible with it.
"""
for iface in _INTERFACE_LOADERS:
- iface_name = '%s_interface' % iface
- impl_name = node.instance_info.get(iface_name,
- getattr(node, iface_name))
+ impl_name = node.get_interface(iface)
impl = get_interface(hw_type, iface, impl_name)
setattr(bare_driver, iface, impl)
diff --git a/ironic/common/neutron.py b/ironic/common/neutron.py
index 03e78ef35..3ab23424b 100644
--- a/ironic/common/neutron.py
+++ b/ironic/common/neutron.py
@@ -712,7 +712,7 @@ def validate_port_info(node, port):
# Subnet Manager.
if port.extra.get('client-id'):
return True
- if (node.network_interface == 'neutron'
+ if (node.get_interface('network') == 'neutron'
and not port.local_link_connection):
LOG.warning("The local_link_connection is required for "
"'neutron' network interface and is not present "
diff --git a/ironic/drivers/modules/boot_mode_utils.py b/ironic/drivers/modules/boot_mode_utils.py
index 6150a71bf..c6a08d913 100644
--- a/ironic/drivers/modules/boot_mode_utils.py
+++ b/ironic/drivers/modules/boot_mode_utils.py
@@ -309,7 +309,7 @@ def configure_secure_boot_if_needed(task):
'management interface %(driver)s does not support it. '
'This warning will become an error in a future release.',
{'node': task.node.uuid,
- 'driver': task.node.management_interface})
+ 'driver': task.node.get_interface('management')})
except Exception as exc:
with excutils.save_and_reraise_exception():
LOG.error('Failed to configure secure boot for node %(node)s: '
@@ -335,7 +335,7 @@ def deconfigure_secure_boot_if_needed(task):
LOG.debug('Secure boot was requested for node %(node)s but its '
'management interface %(driver)s does not support it.',
{'node': task.node.uuid,
- 'driver': task.node.management_interface})
+ 'driver': task.node.get_interface('management')})
except Exception as exc:
with excutils.save_and_reraise_exception():
LOG.error('Failed to deconfigure secure boot for node %(node)s: '
diff --git a/ironic/drivers/modules/deploy_utils.py b/ironic/drivers/modules/deploy_utils.py
index 50e78051b..a22b4ff2d 100644
--- a/ironic/drivers/modules/deploy_utils.py
+++ b/ironic/drivers/modules/deploy_utils.py
@@ -628,7 +628,7 @@ def get_boot_option(node):
# option it supports.
def is_ramdisk_deploy(node):
- return node.deploy_interface == 'ramdisk'
+ return node.get_interface('deploy') == 'ramdisk'
def is_anaconda_deploy(node):
@@ -638,7 +638,7 @@ def is_anaconda_deploy(node):
:returns: A boolean value of True when Anaconda deploy interface is in use
otherwise False
"""
- if node.deploy_interface == 'anaconda':
+ if node.get_interface('deploy') == 'anaconda':
return True
return False
diff --git a/ironic/drivers/modules/inspector.py b/ironic/drivers/modules/inspector.py
index 1b866d0d5..af935717d 100644
--- a/ironic/drivers/modules/inspector.py
+++ b/ironic/drivers/modules/inspector.py
@@ -153,7 +153,7 @@ def _ironic_manages_boot(task, raise_exc=False):
'not support managed boot for in-band inspection or '
'the required options are not populated: %(exc)s',
{'node': task.node.uuid,
- 'iface': task.node.boot_interface,
+ 'iface': task.node.get_interface('boot'),
'exc': e})
if raise_exc:
raise
@@ -166,7 +166,7 @@ def _ironic_manages_boot(task, raise_exc=False):
'not support managed boot for in-band inspection or '
'the required options are not populated: %(exc)s',
{'node': task.node.uuid,
- 'iface': task.node.network_interface,
+ 'iface': task.node.get_interface('network'),
'exc': e})
if raise_exc:
raise
diff --git a/ironic/drivers/modules/ramdisk.py b/ironic/drivers/modules/ramdisk.py
index 9fbffebc1..125541bac 100644
--- a/ironic/drivers/modules/ramdisk.py
+++ b/ironic/drivers/modules/ramdisk.py
@@ -60,7 +60,8 @@ class RamdiskDeploy(agent_base.AgentBaseMixin, agent_base.HeartbeatMixin,
'deployment request of node %(node)s with boot '
'interface %(drv)s. The configuration drive will be '
'ignored for this deployment.',
- {'node': task.node, 'drv': task.node.boot_interface})
+ {'node': task.node,
+ 'drv': task.node.get_interface('boot')})
manager_utils.node_power_action(task, states.POWER_OFF)
# Tenant neworks must enable connectivity to the boot
# location, as reboot() can otherwise be very problematic.
diff --git a/ironic/drivers/modules/redfish/boot.py b/ironic/drivers/modules/redfish/boot.py
index dfc0d5d38..49928acdf 100644
--- a/ironic/drivers/modules/redfish/boot.py
+++ b/ironic/drivers/modules/redfish/boot.py
@@ -417,7 +417,7 @@ class RedfishVirtualMediaBoot(base.BootInterface):
_("The %(iface)s boot interface is not suitable for node "
"%(node)s with vendor %(vendor)s, use "
"idrac-redfish-virtual-media instead")
- % {'iface': task.node.boot_interface,
+ % {'iface': task.node.get_interface('boot'),
'node': task.node.uuid, 'vendor': vendor})
def validate(self, task):
diff --git a/ironic/drivers/modules/redfish/raid.py b/ironic/drivers/modules/redfish/raid.py
index 33a7853ea..a7a510811 100644
--- a/ironic/drivers/modules/redfish/raid.py
+++ b/ironic/drivers/modules/redfish/raid.py
@@ -709,7 +709,7 @@ class RedfishRAID(base.RAIDInterface):
raise exception.InvalidParameterValue(
_("The %(iface)s raid interface is not suitable for node "
"%(node)s with vendor %(vendor)s, use idrac-redfish instead")
- % {'iface': task.node.raid_interface,
+ % {'iface': task.node.get_interface('raid'),
'node': task.node.uuid, 'vendor': vendor})
def validate(self, task):
diff --git a/ironic/objects/node.py b/ironic/objects/node.py
index d8a919f2c..cc8479b8c 100644
--- a/ironic/objects/node.py
+++ b/ironic/objects/node.py
@@ -544,6 +544,12 @@ class Node(base.IronicObject, object_base.VersionedObjectDictCompat):
node = cls._from_db_object(context, cls(), db_node)
return node
+ def get_interface(self, iface):
+ iface_name = '%s_interface' % iface
+ impl_name = self.instance_info.get(iface_name,
+ getattr(self, iface_name))
+ return impl_name
+
def _convert_deploy_step_field(self, target_version,
remove_unavailable_fields=True):
# NOTE(rloo): Typically we set the value to None. However,
diff --git a/ironic/tests/unit/objects/test_node.py b/ironic/tests/unit/objects/test_node.py
index 06996c591..146120644 100644
--- a/ironic/tests/unit/objects/test_node.py
+++ b/ironic/tests/unit/objects/test_node.py
@@ -559,6 +559,17 @@ class TestNodeObject(db_base.DbTestCase, obj_utils.SchemasTestMixIn):
def test_payload_schemas(self):
self._check_payload_schemas(objects.node, objects.Node.fields)
+ def test_get_interface(self):
+ node = obj_utils.get_test_node(self.ctxt, **self.fake_node)
+ node.deploy_interface = 'direct'
+ self.assertEqual('direct', node.get_interface('deploy'))
+
+ def test_get_interface_overriden(self):
+ node = obj_utils.get_test_node(self.ctxt, **self.fake_node)
+ node.deploy_interface = 'direct'
+ node.instance_info = {'deploy_interface': 'ramdisk'}
+ self.assertEqual('ramdisk', node.get_interface('deploy'))
+
class TestConvertToVersion(db_base.DbTestCase):
diff --git a/releasenotes/notes/instance-info-interface-override-fix-043df41199529892.yaml b/releasenotes/notes/instance-info-interface-override-fix-043df41199529892.yaml
new file mode 100644
index 000000000..014d94274
--- /dev/null
+++ b/releasenotes/notes/instance-info-interface-override-fix-043df41199529892.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fixes issue with a node's instance_info interface override caused when
+ Ironic uses the interface attribute directly. Does so by adding a
+ `get_interface` method to a node, and updating the Ironic code to use it
+ where needed.