Revert baremetal v3 API extension
Baremetal is scheduled to be deprecated in Nova soon. Since the V3 API is experimental in Havana, we should revert the extension to avoid maintenance of the extension and its tests for no real gain. Things have changed enough since it was added that a simple git-revert won't work. This reverts the following changes:5de5ae1b5d
92c9975bd2
2382186311
Mailing list discussion: http://lists.openstack.org/pipermail/openstack-dev/2013-September/014614.html Change-Id: I3bdc7234f91eb4f9078ee24d7ab093b28f9930c9
This commit is contained in:
parent
3119dafeb5
commit
eef8473fa8
@ -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": "",
|
||||
|
@ -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 []
|
@ -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)
|
@ -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": "",
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user