diff --git a/etc/nova/policy.json b/etc/nova/policy.json index e2e0e0337269..5cbefb200dde 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -61,8 +61,6 @@ "compute_extension:v3:os-attach-interfaces": "", "compute_extension:v3:os-attach-interfaces:discoverable": "", "compute_extension:baremetal_nodes": "rule:admin_api", - "compute_extension:v3:os-baremetal-nodes": "rule:admin_api", - "compute_extension:v3:os-baremetal-nodes:discoverable": "", "compute_extension:cells": "rule:admin_api", "compute_extension:v3:os-cells": "rule:admin_api", "compute_extension:v3:os-cells:discoverable": "", diff --git a/nova/api/openstack/compute/plugins/v3/baremetal_nodes.py b/nova/api/openstack/compute/plugins/v3/baremetal_nodes.py deleted file mode 100644 index bebdd3ab8a7f..000000000000 --- a/nova/api/openstack/compute/plugins/v3/baremetal_nodes.py +++ /dev/null @@ -1,231 +0,0 @@ -# Copyright (c) 2013 NTT DOCOMO, INC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -"""The bare-metal admin extension.""" - -import webob - -from nova.api.openstack import extensions -from nova.api.openstack import wsgi -from nova.api.openstack import xmlutil -from nova import exception -from nova.openstack.common.gettextutils import _ -from nova.virt.baremetal import db - -ALIAS = 'os-baremetal-nodes' -authorize = extensions.extension_authorizer('compute', - 'v3:' + ALIAS) - -node_fields = ['id', 'cpus', 'local_gb', 'memory_mb', 'pm_address', - 'pm_user', - 'service_host', 'terminal_port', 'instance_uuid', - ] - -interface_fields = ['id', 'address', 'datapath_id', 'port_no'] - - -def _node_dict(node_ref): - d = {} - for f in node_fields: - d[f] = node_ref.get(f) - return d - - -def _interface_dict(interface_ref): - d = {} - for f in interface_fields: - d[f] = interface_ref.get(f) - return d - - -def _make_node_elem(elem): - for f in node_fields: - elem.set(f) - - -def _make_interface_elem(elem): - for f in interface_fields: - elem.set(f) - - -class NodeTemplate(xmlutil.TemplateBuilder): - def construct(self): - node_elem = xmlutil.TemplateElement('node', selector='node') - _make_node_elem(node_elem) - ifs_elem = xmlutil.TemplateElement('interfaces') - if_elem = xmlutil.SubTemplateElement(ifs_elem, 'interface', - selector='interfaces') - _make_interface_elem(if_elem) - node_elem.append(ifs_elem) - return xmlutil.MasterTemplate(node_elem, 1) - - -class NodesTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('nodes') - node_elem = xmlutil.SubTemplateElement(root, 'node', selector='nodes') - _make_node_elem(node_elem) - ifs_elem = xmlutil.TemplateElement('interfaces') - if_elem = xmlutil.SubTemplateElement(ifs_elem, 'interface', - selector='interfaces') - _make_interface_elem(if_elem) - node_elem.append(ifs_elem) - return xmlutil.MasterTemplate(root, 1) - - -class InterfaceTemplate(xmlutil.TemplateBuilder): - def construct(self): - root = xmlutil.TemplateElement('interface', selector='interface') - _make_interface_elem(root) - return xmlutil.MasterTemplate(root, 1) - - -class BareMetalNodeController(wsgi.Controller): - """The Bare-Metal Node API controller for the OpenStack API.""" - - @extensions.expected_errors(()) - @wsgi.serializers(xml=NodesTemplate) - def index(self, req): - context = req.environ['nova.context'] - authorize(context) - nodes_from_db = db.bm_node_get_all(context) - nodes = [] - for node_from_db in nodes_from_db: - try: - ifs = db.bm_interface_get_all_by_bm_node_id( - context, node_from_db['id']) - except exception.NodeNotFound: - ifs = [] - node = _node_dict(node_from_db) - node['interfaces'] = [_interface_dict(i) for i in ifs] - nodes.append(node) - return {'nodes': nodes} - - @extensions.expected_errors(404) - @wsgi.serializers(xml=NodeTemplate) - def show(self, req, id): - context = req.environ['nova.context'] - authorize(context) - try: - node = db.bm_node_get(context, id) - except exception.NodeNotFound as e: - raise webob.exc.HTTPNotFound(explanation=e.format_message()) - try: - ifs = db.bm_interface_get_all_by_bm_node_id(context, id) - except exception.NodeNotFound: - ifs = [] - node = _node_dict(node) - node['interfaces'] = [_interface_dict(i) for i in ifs] - return {'node': node} - - @extensions.expected_errors(()) - @wsgi.serializers(xml=NodeTemplate) - @wsgi.response(201) - def create(self, req, body): - context = req.environ['nova.context'] - authorize(context) - values = body['node'].copy() - prov_mac_address = values.pop('prov_mac_address', None) - node = db.bm_node_create(context, values) - node = _node_dict(node) - if prov_mac_address: - if_id = db.bm_interface_create(context, - bm_node_id=node['id'], - address=prov_mac_address, - datapath_id=None, - port_no=None) - if_ref = db.bm_interface_get(context, if_id) - node['interfaces'] = [_interface_dict(if_ref)] - else: - node['interfaces'] = [] - return {'node': node} - - @extensions.expected_errors(404) - def delete(self, req, id): - context = req.environ['nova.context'] - authorize(context) - try: - db.bm_node_destroy(context, id) - except exception.NodeNotFound as e: - raise webob.exc.HTTPNotFound(explanation=e.format_message()) - return webob.Response(status_int=202) - - def _check_node_exists(self, context, node_id): - try: - db.bm_node_get(context, node_id) - except exception.NodeNotFound as e: - raise webob.exc.HTTPNotFound(explanation=e.format_message()) - - @extensions.expected_errors(404) - @wsgi.serializers(xml=InterfaceTemplate) - @wsgi.action('add_interface') - def _add_interface(self, req, id, body): - context = req.environ['nova.context'] - authorize(context) - self._check_node_exists(context, id) - body = body['add_interface'] - address = body['address'] - datapath_id = body.get('datapath_id') - port_no = body.get('port_no') - if_id = db.bm_interface_create(context, - bm_node_id=id, - address=address, - datapath_id=datapath_id, - port_no=port_no) - if_ref = db.bm_interface_get(context, if_id) - return {'interface': _interface_dict(if_ref)} - - @extensions.expected_errors((400, 404)) - @wsgi.response(202) - @wsgi.action('remove_interface') - def _remove_interface(self, req, id, body): - context = req.environ['nova.context'] - authorize(context) - self._check_node_exists(context, id) - body = body['remove_interface'] - if_id = body.get('id') - address = body.get('address') - if not if_id and not address: - raise webob.exc.HTTPBadRequest( - explanation=_("Must specify id or address")) - ifs = db.bm_interface_get_all_by_bm_node_id(context, id) - for i in ifs: - if if_id and if_id != i['id']: - continue - if address and address != i['address']: - continue - db.bm_interface_destroy(context, i['id']) - return - raise webob.exc.HTTPNotFound() - - -class BaremetalNodes(extensions.V3APIExtensionBase): - """Admin-only bare-metal node administration.""" - - name = "BareMetalNodes" - alias = ALIAS - namespace = "http://docs.openstack.org/compute/ext/baremetal_nodes/api/v3" - version = 1 - - def get_resources(self): - resources = [] - res = extensions.ResourceExtension(ALIAS, - BareMetalNodeController(), - member_actions={"action": "POST", }) - resources.append(res) - return resources - - def get_controller_extensions(self): - return [] diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_baremetal_nodes.py b/nova/tests/api/openstack/compute/plugins/v3/test_baremetal_nodes.py deleted file mode 100644 index 0ab5097946b6..000000000000 --- a/nova/tests/api/openstack/compute/plugins/v3/test_baremetal_nodes.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (c) 2013 NTT DOCOMO, INC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from webob import exc - -from nova.api.openstack.compute.plugins.v3 import baremetal_nodes -from nova import context -from nova import exception -from nova import test -from nova.virt.baremetal import db - - -class FakeRequest(object): - - def __init__(self, context): - self.environ = {"nova.context": context} - - -class BareMetalNodesTest(test.TestCase): - - def setUp(self): - super(BareMetalNodesTest, self).setUp() - - self.context = context.get_admin_context() - self.controller = baremetal_nodes.BareMetalNodeController() - self.request = FakeRequest(self.context) - - def test_create(self): - node = { - 'service_host': "host", - 'cpus': 8, - 'memory_mb': 8192, - 'local_gb': 128, - 'pm_address': "10.1.2.3", - 'pm_user': "pm_user", - 'pm_password': "pm_pass", - 'terminal_port': 8000, - 'interfaces': [], - } - response = node.copy() - response['id'] = 100 - del response['pm_password'] - response['instance_uuid'] = None - self.mox.StubOutWithMock(db, 'bm_node_create') - db.bm_node_create(self.context, node).AndReturn(response) - self.mox.ReplayAll() - res_dict = self.controller.create(self.request, {'node': node}) - self.assertEqual({'node': response}, res_dict) - self.assertEqual(self.controller.create.wsgi_code, 201) - - def test_delete(self): - self.mox.StubOutWithMock(db, 'bm_node_destroy') - db.bm_node_destroy(self.context, 1) - 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}, - ] - interfaces = [{'id': 1, 'address': '11:11:11:11:11:11'}, - {'id': 2, 'address': '22:22:22:22:22:22'}, - ] - self.mox.StubOutWithMock(db, 'bm_node_get_all') - 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.NodeNotFound(node_id=1)) - db.bm_interface_get_all_by_bm_node_id(self.context, 2).\ - AndReturn(interfaces) - self.mox.ReplayAll() - res_dict = self.controller.index(self.request) - self.assertEqual(2, len(res_dict['nodes'])) - self.assertEqual([], res_dict['nodes'][0]['interfaces']) - self.assertEqual(2, len(res_dict['nodes'][1]['interfaces'])) - - def test_show(self): - node_id = 1 - node = {'id': node_id} - interfaces = [{'id': 1, 'address': '11:11:11:11:11:11'}, - {'id': 2, 'address': '22:22:22:22:22:22'}, - ] - 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).\ - AndReturn(interfaces) - self.mox.ReplayAll() - res_dict = self.controller.show(self.request, node_id) - 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' - body = {'add_interface': {'address': address}} - self.mox.StubOutWithMock(db, 'bm_node_get') - self.mox.StubOutWithMock(db, 'bm_interface_create') - self.mox.StubOutWithMock(db, 'bm_interface_get') - db.bm_node_get(self.context, node_id) - db.bm_interface_create(self.context, - bm_node_id=node_id, - address=address, - datapath_id=None, - port_no=None).\ - AndReturn(12345) - db.bm_interface_get(self.context, 12345).\ - AndReturn({'id': 12345, 'address': address}) - self.mox.ReplayAll() - res_dict = self.controller._add_interface(self.request, node_id, body) - self.assertEqual(12345, res_dict['interface']['id']) - self.assertEqual(address, res_dict['interface']['address']) - - def test_remove_interface(self): - node_id = 1 - interfaces = [{'id': 1}, - {'id': 2}, - {'id': 3}, - ] - body = {'remove_interface': {'id': 2}} - self.mox.StubOutWithMock(db, 'bm_node_get') - self.mox.StubOutWithMock(db, 'bm_interface_get_all_by_bm_node_id') - self.mox.StubOutWithMock(db, 'bm_interface_destroy') - db.bm_node_get(self.context, node_id) - db.bm_interface_get_all_by_bm_node_id(self.context, node_id).\ - AndReturn(interfaces) - db.bm_interface_destroy(self.context, 2) - self.mox.ReplayAll() - self.controller._remove_interface(self.request, node_id, body) - - def test_remove_interface_by_address(self): - node_id = 1 - interfaces = [{'id': 1, 'address': '11:11:11:11:11:11'}, - {'id': 2, 'address': '22:22:22:22:22:22'}, - {'id': 3, 'address': '33:33:33:33:33:33'}, - ] - self.mox.StubOutWithMock(db, 'bm_node_get') - self.mox.StubOutWithMock(db, 'bm_interface_get_all_by_bm_node_id') - self.mox.StubOutWithMock(db, 'bm_interface_destroy') - db.bm_node_get(self.context, node_id) - db.bm_interface_get_all_by_bm_node_id(self.context, node_id).\ - AndReturn(interfaces) - db.bm_interface_destroy(self.context, 2) - self.mox.ReplayAll() - body = {'remove_interface': {'address': '22:22:22:22:22:22'}} - self.controller._remove_interface(self.request, node_id, body) - - def test_remove_interface_no_id_no_address(self): - node_id = 1 - self.mox.StubOutWithMock(db, 'bm_node_get') - db.bm_node_get(self.context, node_id) - self.mox.ReplayAll() - body = {'remove_interface': {}} - self.assertRaises(exc.HTTPBadRequest, - self.controller._remove_interface, - self.request, - node_id, - body) - - def test_add_interface_node_not_found(self): - node_id = 1 - self.mox.StubOutWithMock(db, 'bm_node_get') - db.bm_node_get(self.context, 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, - self.controller._add_interface, - self.request, - node_id, - body) - - def test_remove_interface_node_not_found(self): - node_id = 1 - self.mox.StubOutWithMock(db, 'bm_node_get') - db.bm_node_get(self.context, 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, - self.controller._remove_interface, - self.request, - node_id, - body) diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index d5a4b81003b1..3d420c149180 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -135,7 +135,6 @@ policy_data = """ "compute_extension:attach_interfaces": "", "compute_extension:v3:os-attach-interfaces": "", "compute_extension:baremetal_nodes": "", - "compute_extension:v3:os-baremetal-nodes": "", "compute_extension:cells": "", "compute_extension:v3:os-cells": "", "compute_extension:certificates": "", diff --git a/setup.cfg b/setup.cfg index 8ad14b6139c6..830c2a713f03 100644 --- a/setup.cfg +++ b/setup.cfg @@ -62,7 +62,6 @@ nova.api.v3.extensions = aggregates = nova.api.openstack.compute.plugins.v3.aggregates:Aggregates attach_interfaces = nova.api.openstack.compute.plugins.v3.attach_interfaces:AttachInterfaces availability_zone = nova.api.openstack.compute.plugins.v3.availability_zone:AvailabilityZone - baremetal_nodes = nova.api.openstack.compute.plugins.v3.baremetal_nodes:BaremetalNodes block_device_mapping = nova.api.openstack.compute.plugins.v3.block_device_mapping:BlockDeviceMapping cells = nova.api.openstack.compute.plugins.v3.cells:Cells certificates = nova.api.openstack.compute.plugins.v3.certificates:Certificates