diff options
author | Adam Gandelman <adamg@ubuntu.com> | 2014-07-23 11:46:31 -0400 |
---|---|---|
committer | Adam Gandelman <adamg@ubuntu.com> | 2014-07-24 15:25:56 -0400 |
commit | 35c11d4057849fb2e40c73dbcd2640d9e3637c92 (patch) | |
tree | a0777104c3c03798fde7a08f8ae88e96cc8bc24f | |
parent | 036c79e38f994121022a69a0bc76917e0048fd63 (diff) | |
download | ironic-35c11d4057849fb2e40c73dbcd2640d9e3637c92.tar.gz |
Generalize exception handling in Nova driver
We need to ensure nodes get unprovisioned and disassociated from instances upon
all failure cases, not only the specific exceptions being caught now. This
removes the catching of those specific exceptions during instance spawn and
performs required cleanup and re-raising.
Change-Id: I9461139400d7aa0a339550cf89f3d49e3a8cb2c0
-rw-r--r-- | ironic/nova/tests/virt/ironic/test_driver.py | 33 | ||||
-rw-r--r-- | ironic/nova/virt/ironic/driver.py | 19 |
2 files changed, 41 insertions, 11 deletions
diff --git a/ironic/nova/tests/virt/ironic/test_driver.py b/ironic/nova/tests/virt/ironic/test_driver.py index 1699fd525..2bdbaed41 100644 --- a/ironic/nova/tests/virt/ironic/test_driver.py +++ b/ironic/nova/tests/virt/ironic/test_driver.py @@ -631,7 +631,7 @@ class IronicDriverTestCase(test.NoDBTestCase): mock_node.get.return_value = node mock_node.validate.return_value = ironic_utils.get_test_validation() mock_node.set_provision_state.side_effect = ironic_exception.BadRequest - self.assertRaises(exception.InstanceDeployFailure, + self.assertRaises(ironic_exception.BadRequest, self.driver.spawn, self.ctx, instance, None, [], None) @@ -642,6 +642,37 @@ class IronicDriverTestCase(test.NoDBTestCase): mock_cleanup_deploy.assert_called_once_with(node, instance, None) @mock.patch.object(loopingcall, 'FixedIntervalLoopingCall') + @mock.patch.object(FAKE_CLIENT, 'node') + @mock.patch.object(flavor_obj.Flavor, 'get_by_id') + @mock.patch.object(ironic_driver.IronicDriver, '_start_firewall') + @mock.patch.object(ironic_driver.IronicDriver, '_plug_vifs') + @mock.patch.object(ironic_driver.IronicDriver, 'destroy') + def test_spawn_node_trigger_deploy_fail3(self, mock_destroy, + mock_pvifs, mock_sf, + mock_flavor, mock_node, + mock_looping): + node_uuid = 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' + fake_net_info = utils.get_test_network_info() + node = ironic_utils.get_test_node(driver='fake', uuid=node_uuid) + instance = fake_instance.fake_instance_obj(self.ctx, node=node_uuid) + fake_flavor = {'ephemeral_gb': 0} + mock_flavor.return_value = fake_flavor + + mock_node.get.return_value = node + mock_node.validate.return_value = ironic_utils.get_test_validation() + + fake_looping_call = FakeLoopingCall() + mock_looping.return_value = fake_looping_call + + fake_looping_call.wait.side_effect = ironic_exception.BadRequest + fake_net_info = utils.get_test_network_info() + self.assertRaises(ironic_exception.BadRequest, + self.driver.spawn, + self.ctx, instance, None, [], None, fake_net_info) + mock_destroy.assert_called_once_with(self.ctx, instance, + fake_net_info) + + @mock.patch.object(loopingcall, 'FixedIntervalLoopingCall') @mock.patch.object(instance_obj.Instance, 'save') @mock.patch.object(FAKE_CLIENT, 'node') @mock.patch.object(flavor_obj.Flavor, 'get_by_id') diff --git a/ironic/nova/virt/ironic/driver.py b/ironic/nova/virt/ironic/driver.py index 1ac7d4eb0..8f71f0a81 100644 --- a/ironic/nova/virt/ironic/driver.py +++ b/ironic/nova/virt/ironic/driver.py @@ -549,21 +549,20 @@ class IronicDriver(virt_driver.ComputeDriver): try: icli.call("node.set_provision_state", node_uuid, ironic_states.ACTIVE) - except (exception.NovaException, # Retry failed - ironic_exception.InternalServerError, # Validations - ironic_exception.BadRequest) as e: # Maintenance - msg = (_("Failed to request Ironic to provision instance " - "%(inst)s: %(reason)s") % {'inst': instance['uuid'], - 'reason': str(e)}) - LOG.error(msg) - self._cleanup_deploy(node, instance, network_info) - raise exception.InstanceDeployFailure(msg) + except Exception as e: + with excutils.save_and_reraise_exception(): + msg = (_("Failed to request Ironic to provision instance " + "%(inst)s: %(reason)s") % {'inst': instance['uuid'], + 'reason': str(e)}) + LOG.error(msg) + self._cleanup_deploy(node, instance, network_info) timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_active, icli, instance) + try: timer.start(interval=CONF.ironic.api_retry_interval).wait() - except exception.InstanceDeployFailure: + except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error deploying instance %(instance)s on " "baremetal node %(node)s.") % |