Allow associate an instance independent of the node power state

When updating the instance_uuid field of a node Ironic would check the
power state to see if the node was powered off, otherwise the update
would fail. This patch is removing that check and leaving it to the
drivers to ensure that the node is in whatever power state it needs to
be as part of the deployment.

Closes-Bug: #1413296
(cherry picked from commit 7da9dd7f30)

Conflicts:
	ironic/conductor/manager.py

Change-Id: Ic18f49a89f18ddfa3006ba3f2ee4a22ad69c4d4d
This commit is contained in:
Lucas Alvares Gomes 2015-01-21 17:09:12 +00:00 committed by Tom Cammann
parent 7da4990875
commit 7776b84c0c
2 changed files with 16 additions and 47 deletions

View File

@ -249,8 +249,7 @@ class ConductorManager(periodic_task.PeriodicTasks):
@messaging.expected_exceptions(exception.InvalidParameterValue,
exception.MissingParameterValue,
exception.NodeLocked,
exception.NodeInWrongPowerState)
exception.NodeLocked)
def update_node(self, context, node_obj):
"""Update a node with the supplied data.
@ -272,24 +271,10 @@ class ConductorManager(periodic_task.PeriodicTasks):
driver_name = node_obj.driver if 'driver' in delta else None
with task_manager.acquire(context, node_id, shared=False,
driver_name=driver_name) as task:
# TODO(deva): Determine what value will be passed by API when
# instance_uuid needs to be unset, and handle it.
if 'instance_uuid' in delta:
task.driver.power.validate(task)
node_obj.power_state = \
task.driver.power.get_power_state(task)
if node_obj.power_state != states.POWER_OFF:
raise exception.NodeInWrongPowerState(
node=node_id,
pstate=node_obj.power_state)
# update any remaining parameters, then save
driver_name=driver_name):
node_obj.save()
return node_obj
return node_obj
def _power_state_error_handler(self, e, node, power_state):
"""Set the node's power states if error occurs.

View File

@ -412,41 +412,25 @@ class UpdateNodeTestCase(_ServiceSetUpMixin, tests_db_base.DbTestCase):
res = objects.Node.get_by_uuid(self.context, node['uuid'])
self.assertEqual({'test': 'one'}, res['extra'])
def test_associate_node_invalid_state(self):
node = obj_utils.create_test_node(self.context, driver='fake',
extra={'test': 'one'},
instance_uuid=None,
power_state=states.POWER_ON)
# check that it fails because state is POWER_ON
node.instance_uuid = 'fake-uuid'
exc = self.assertRaises(messaging.rpc.ExpectedException,
self.service.update_node,
self.context,
node)
# Compare true exception hidden by @messaging.expected_exceptions
self.assertEqual(exception.NodeInWrongPowerState, exc.exc_info[0])
# verify change did not happen
node.refresh()
self.assertIsNone(node.instance_uuid)
def test_associate_node_valid_state(self):
@mock.patch('ironic.drivers.modules.fake.FakePower.get_power_state')
def _test_associate_node(self, power_state, mock_get_power_state):
mock_get_power_state.return_value = power_state
node = obj_utils.create_test_node(self.context, driver='fake',
instance_uuid=None,
power_state=states.NOSTATE)
node.instance_uuid = 'fake-uuid'
self.service.update_node(self.context, node)
with mock.patch('ironic.drivers.modules.fake.FakePower.'
'get_power_state') as mock_get_power_state:
# Check if the change was applied
node.instance_uuid = 'meow'
node.refresh()
self.assertEqual('fake-uuid', node.instance_uuid)
mock_get_power_state.return_value = states.POWER_OFF
node.instance_uuid = 'fake-uuid'
self.service.update_node(self.context, node)
def test_associate_node_powered_off(self):
self._test_associate_node(states.POWER_OFF)
# Check if the change was applied
node.instance_uuid = 'meow'
node.refresh()
self.assertEqual('fake-uuid', node.instance_uuid)
def test_associate_node_powered_on(self):
self._test_associate_node(states.POWER_ON)
def test_update_node_invalid_driver(self):
existing_driver = 'fake'