diff options
author | Devananda van der Veen <devananda.vdv@gmail.com> | 2013-02-21 13:56:25 -0800 |
---|---|---|
committer | Devananda van der Veen <devananda.vdv@gmail.com> | 2013-02-22 07:20:38 -0800 |
commit | 3aace2a610d8b5e7027ef141970e23cddba0294d (patch) | |
tree | 461f32463e3a5836938bcc331debc1c700ddcdf0 | |
parent | fc4ede9bb69896992e5fafc2623f1083cc8d19cd (diff) | |
download | nova-3aace2a610d8b5e7027ef141970e23cddba0294d.tar.gz nova-3aace2a610d8b5e7027ef141970e23cddba0294d.tar.xz nova-3aace2a610d8b5e7027ef141970e23cddba0294d.zip |
Fix exception handling in baremetal API.
In patch ab9f8667c63d901f37d1662c5204fb2938be44fe, several
baremetal/db/api methods' exceptions were changed from InstanceNotFound
to NodeNotFound. The API extension for baremetal was not updated to
catch these, and this was not caught by unit testing. This resulted in
unhandled exceptions within nova-api if any baremetal node lacked an
associated interface.
While fixing that bug, a few other unit tests for the baremetal API
were added, and a missing exception was added to db/api bm_node_destroy.
Fixes bug 1131430.
Change-Id: I15f7624723754f9d7b217b609663a2d709acb056
-rw-r--r-- | nova/api/openstack/compute/contrib/baremetal_nodes.py | 10 | ||||
-rw-r--r-- | nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py | 30 | ||||
-rw-r--r-- | nova/virt/baremetal/db/sqlalchemy/api.py | 9 |
3 files changed, 39 insertions, 10 deletions
diff --git a/nova/api/openstack/compute/contrib/baremetal_nodes.py b/nova/api/openstack/compute/contrib/baremetal_nodes.py index 38d66d2ae..70bb6e8a0 100644 --- a/nova/api/openstack/compute/contrib/baremetal_nodes.py +++ b/nova/api/openstack/compute/contrib/baremetal_nodes.py @@ -104,7 +104,7 @@ class BareMetalNodeController(wsgi.Controller): try: ifs = db.bm_interface_get_all_by_bm_node_id( context, node_from_db['id']) - except exception.InstanceNotFound: + except exception.NodeNotFound: ifs = [] node = _node_dict(node_from_db) node['interfaces'] = [_interface_dict(i) for i in ifs] @@ -117,11 +117,11 @@ class BareMetalNodeController(wsgi.Controller): authorize(context) try: node = db.bm_node_get(context, id) - except exception.InstanceNotFound: + except exception.NodeNotFound: raise webob.exc.HTTPNotFound try: ifs = db.bm_interface_get_all_by_bm_node_id(context, id) - except exception.InstanceNotFound: + except exception.NodeNotFound: ifs = [] node = _node_dict(node) node['interfaces'] = [_interface_dict(i) for i in ifs] @@ -141,14 +141,14 @@ class BareMetalNodeController(wsgi.Controller): authorize(context) try: db.bm_node_destroy(context, id) - except exception.InstanceNotFound: + except exception.NodeNotFound: raise webob.exc.HTTPNotFound return webob.Response(status_int=202) def _check_node_exists(self, context, node_id): try: db.bm_node_get(context, node_id) - except exception.InstanceNotFound: + except exception.NodeNotFound: raise webob.exc.HTTPNotFound @wsgi.serializers(xml=InterfaceTemplate) diff --git a/nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py b/nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py index 381d452a7..fc4ae8122 100644 --- a/nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py +++ b/nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py @@ -67,6 +67,17 @@ class BareMetalNodesTest(test.TestCase): self.mox.ReplayAll() self.controller.delete(self.request, 1) + def test_delete_node_not_found(self): + self.mox.StubOutWithMock(db, 'bm_node_destroy') + db.bm_node_destroy(self.context, 1).\ + AndRaise(exception.NodeNotFound(node_id=1)) + self.mox.ReplayAll() + self.assertRaises( + exc.HTTPNotFound, + self.controller.delete, + self.request, + 1) + def test_index(self): nodes = [{'id': 1}, {'id': 2}, @@ -78,7 +89,7 @@ class BareMetalNodesTest(test.TestCase): self.mox.StubOutWithMock(db, 'bm_interface_get_all_by_bm_node_id') db.bm_node_get_all(self.context).AndReturn(nodes) db.bm_interface_get_all_by_bm_node_id(self.context, 1).\ - AndRaise(exception.InstanceNotFound(instance_id=1)) + AndRaise(exception.NodeNotFound(node_id=1)) db.bm_interface_get_all_by_bm_node_id(self.context, 2).\ AndReturn(interfaces) self.mox.ReplayAll() @@ -103,6 +114,19 @@ class BareMetalNodesTest(test.TestCase): self.assertEqual(node_id, res_dict['node']['id']) self.assertEqual(2, len(res_dict['node']['interfaces'])) + def test_show_no_interfaces(self): + node_id = 1 + node = {'id': node_id} + self.mox.StubOutWithMock(db, 'bm_node_get') + self.mox.StubOutWithMock(db, 'bm_interface_get_all_by_bm_node_id') + db.bm_node_get(self.context, node_id).AndReturn(node) + db.bm_interface_get_all_by_bm_node_id(self.context, node_id).\ + AndRaise(exception.NodeNotFound(node_id=node_id)) + self.mox.ReplayAll() + res_dict = self.controller.show(self.request, node_id) + self.assertEqual(node_id, res_dict['node']['id']) + self.assertEqual(0, len(res_dict['node']['interfaces'])) + def test_add_interface(self): node_id = 1 address = '11:22:33:44:55:66' @@ -174,7 +198,7 @@ class BareMetalNodesTest(test.TestCase): node_id = 1 self.mox.StubOutWithMock(db, 'bm_node_get') db.bm_node_get(self.context, node_id).\ - AndRaise(exception.InstanceNotFound(instance_id=node_id)) + AndRaise(exception.NodeNotFound(node_id=node_id)) self.mox.ReplayAll() body = {'add_interface': {'address': '11:11:11:11:11:11'}} self.assertRaises(exc.HTTPNotFound, @@ -187,7 +211,7 @@ class BareMetalNodesTest(test.TestCase): node_id = 1 self.mox.StubOutWithMock(db, 'bm_node_get') db.bm_node_get(self.context, node_id).\ - AndRaise(exception.InstanceNotFound(instance_id=node_id)) + AndRaise(exception.NodeNotFound(node_id=node_id)) self.mox.ReplayAll() body = {'remove_interface': {'address': '11:11:11:11:11:11'}} self.assertRaises(exc.HTTPNotFound, diff --git a/nova/virt/baremetal/db/sqlalchemy/api.py b/nova/virt/baremetal/db/sqlalchemy/api.py index bbfc17a35..d64bc4872 100644 --- a/nova/virt/baremetal/db/sqlalchemy/api.py +++ b/nova/virt/baremetal/db/sqlalchemy/api.py @@ -222,15 +222,20 @@ def bm_node_associate_and_update(context, node_uuid, values): def bm_node_destroy(context, bm_node_id): # First, delete all interfaces belonging to the node. # Delete physically since these have unique columns. - model_query(context, models.BareMetalInterface, read_deleted="no").\ + session = db_session.get_session() + with session.begin(): + model_query(context, models.BareMetalInterface, read_deleted="no").\ filter_by(bm_node_id=bm_node_id).\ delete() - model_query(context, models.BareMetalNode).\ + rows = model_query(context, models.BareMetalNode, read_deleted="no").\ filter_by(id=bm_node_id).\ update({'deleted': True, 'deleted_at': timeutils.utcnow(), 'updated_at': literal_column('updated_at')}) + if not rows: + raise exception.NodeNotFound(node_id=bm_node_id) + @sqlalchemy_api.require_admin_context def bm_pxe_ip_get_all(context): |