Do not validate driver on changing non-driver fields

This prevents setting maintenance on nodes with a broken driver.

Change-Id: Ibd94d9d8ad5467f8430f77673a34507feb83da84
This commit is contained in:
Dmitry Tantsur 2020-07-07 12:25:18 +02:00
parent 3c47122f36
commit 217e354a2d
3 changed files with 55 additions and 1 deletions

View File

@ -209,6 +209,7 @@ class ConductorManager(base_manager.BaseConductorManager):
"updated unless it is in one of allowed "
"(%(allowed)s) states or in maintenance mode.")
updating_driver = 'driver' in delta
check_interfaces = updating_driver
for iface in drivers_base.ALL_INTERFACES:
interface_field = '%s_interface' % iface
if interface_field not in delta:
@ -224,7 +225,10 @@ class ConductorManager(base_manager.BaseConductorManager):
'allowed': ', '.join(allowed_update_states),
'field': interface_field})
driver_factory.check_and_update_node_interfaces(node_obj)
check_interfaces = True
if check_interfaces:
driver_factory.check_and_update_node_interfaces(node_obj)
# NOTE(dtantsur): if we're updating the driver from an invalid value,
# loading the old driver may be impossible. Since we only need to

View File

@ -960,6 +960,51 @@ class UpdateNodeTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):
self.assertIsNone(node.instance_uuid)
self.assertIsNone(node.allocation_id)
def test_update_node_maintenance_with_broken_interface(self):
# Updates of non-driver fields are possible with a broken driver
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
power_interface='foobar',
extra={'test': 'one'})
node.maintenance = True
res = self.service.update_node(self.context, node)
self.assertTrue(res.maintenance)
node.refresh()
self.assertTrue(node.maintenance)
self.assertEqual('foobar', node.power_interface)
def test_update_node_interface_field_with_broken_interface(self):
# Updates of driver fields are NOT possible with a broken driver,
# unless they're fixing the breakage.
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
power_interface='foobar',
deploy_interface='fake',
extra={'test': 'one'})
node.deploy_interface = 'iscsi'
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.service.update_node,
self.context, node)
self.assertEqual(exception.InterfaceNotFoundInEntrypoint,
exc.exc_info[0])
node.refresh()
self.assertEqual('foobar', node.power_interface)
self.assertEqual('fake', node.deploy_interface)
def test_update_node_fix_broken_interface(self):
# Updates of non-driver fields are possible with a broken driver
node = obj_utils.create_test_node(self.context, driver='fake-hardware',
power_interface='foobar',
extra={'test': 'one'})
node.power_interface = 'fake'
self.service.update_node(self.context, node)
node.refresh()
self.assertEqual('fake', node.power_interface)
@mgr_utils.mock_record_keepalive
class VendorPassthruTestCase(mgr_utils.ServiceSetUpMixin, db_base.DbTestCase):

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixes updating driver fields for nodes with a broken driver. This is
required to be able to set maintenance for such nodes.