summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevananda van der Veen <devananda.vdv@gmail.com>2013-02-21 13:56:25 -0800
committerDevananda van der Veen <devananda.vdv@gmail.com>2013-02-22 07:20:38 -0800
commit3aace2a610d8b5e7027ef141970e23cddba0294d (patch)
tree461f32463e3a5836938bcc331debc1c700ddcdf0
parentfc4ede9bb69896992e5fafc2623f1083cc8d19cd (diff)
downloadnova-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.py10
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_baremetal_nodes.py30
-rw-r--r--nova/virt/baremetal/db/sqlalchemy/api.py9
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):