From c0872500481007b318844bbb1d1b7dcd4cd54601 Mon Sep 17 00:00:00 2001 From: Shuangtai Tian Date: Thu, 17 Oct 2013 11:04:06 +0800 Subject: [PATCH] Extends V3 servers api for pci support All pci passthrough code is merged into nova, but the API does not support. this patch extends the servers to show PCI information for instance and compute node. This is a part of PCI APIs, for more information see the blueprint. Partially implement blueprint pci-api-support Change-Id: I99eeeca67983c49433ab0079f490a454d250f5e0 --- .../all_extensions/server-get-resp.json | 7 +- .../all_extensions/server-get-resp.xml | 5 +- .../all_extensions/servers-details-resp.json | 7 +- .../all_extensions/servers-details-resp.xml | 7 +- .../api_samples/os-pci/server-get-resp.json | 60 +++++++++ doc/v3/api_samples/os-pci/server-get-resp.xml | 22 ++++ .../api_samples/os-pci/server-post-req.json | 16 +++ doc/v3/api_samples/os-pci/server-post-req.xml | 19 +++ .../api_samples/os-pci/server-post-resp.json | 16 +++ .../api_samples/os-pci/server-post-resp.xml | 6 + .../os-pci/servers-detail-resp.json | 62 +++++++++ .../os-pci/servers-detail-resp.xml | 24 ++++ etc/nova/policy.json | 2 + nova/api/openstack/compute/plugins/v3/pci.py | 95 ++++++++++++++ .../openstack/compute/plugins/v3/test_pci.py | 121 ++++++++++++++++++ nova/tests/fake_network.py | 11 ++ nova/tests/fake_policy.py | 1 + .../all_extensions/server-get-resp.json.tpl | 1 + .../all_extensions/server-get-resp.xml.tpl | 5 +- .../servers-details-resp.json.tpl | 1 + .../servers-details-resp.xml.tpl | 5 +- .../os-pci/server-get-resp.json.tpl | 60 +++++++++ .../os-pci/server-get-resp.xml.tpl | 22 ++++ .../os-pci/server-post-req.json.tpl | 16 +++ .../os-pci/server-post-req.xml.tpl | 19 +++ .../os-pci/server-post-resp.json.tpl | 16 +++ .../os-pci/server-post-resp.xml.tpl | 6 + .../os-pci/servers-detail-resp.json.tpl | 62 +++++++++ .../os-pci/servers-detail-resp.xml.tpl | 24 ++++ nova/tests/integrated/v3/test_pci.py | 39 ++++++ setup.cfg | 1 + 31 files changed, 751 insertions(+), 7 deletions(-) create mode 100644 doc/v3/api_samples/os-pci/server-get-resp.json create mode 100644 doc/v3/api_samples/os-pci/server-get-resp.xml create mode 100644 doc/v3/api_samples/os-pci/server-post-req.json create mode 100644 doc/v3/api_samples/os-pci/server-post-req.xml create mode 100644 doc/v3/api_samples/os-pci/server-post-resp.json create mode 100644 doc/v3/api_samples/os-pci/server-post-resp.xml create mode 100644 doc/v3/api_samples/os-pci/servers-detail-resp.json create mode 100644 doc/v3/api_samples/os-pci/servers-detail-resp.xml create mode 100644 nova/api/openstack/compute/plugins/v3/pci.py create mode 100644 nova/tests/api/openstack/compute/plugins/v3/test_pci.py create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.xml.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-post-req.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-post-req.xml.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.xml.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.json.tpl create mode 100644 nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.xml.tpl create mode 100644 nova/tests/integrated/v3/test_pci.py diff --git a/doc/v3/api_samples/all_extensions/server-get-resp.json b/doc/v3/api_samples/all_extensions/server-get-resp.json index 568bdabacdd2..130d5cf14162 100644 --- a/doc/v3/api_samples/all_extensions/server-get-resp.json +++ b/doc/v3/api_samples/all_extensions/server-get-resp.json @@ -59,6 +59,11 @@ "os-extended-status:task_state": null, "os-extended-status:vm_state": "active", "os-extended-volumes:volumes_attached": [], + "os-pci:pci_devices": [ + { + "id": 1 + } + ], "os-server-usage:launched_at": "2013-09-23T13:37:00.880302", "os-server-usage:terminated_at": null, "progress": 0, @@ -69,7 +74,7 @@ ], "status": "ACTIVE", "tenant_id": "openstack", - "updated": "2013-09-23T13:37:00Z", + "updated": "2013-10-31T07:31:30Z", "user_id": "fake" } } diff --git a/doc/v3/api_samples/all_extensions/server-get-resp.xml b/doc/v3/api_samples/all_extensions/server-get-resp.xml index 815ce4568cb5..b795c7f561e1 100644 --- a/doc/v3/api_samples/all_extensions/server-get-resp.xml +++ b/doc/v3/api_samples/all_extensions/server-get-resp.xml @@ -1,5 +1,5 @@ - + @@ -16,6 +16,9 @@ + + + diff --git a/doc/v3/api_samples/all_extensions/servers-details-resp.json b/doc/v3/api_samples/all_extensions/servers-details-resp.json index c7b8f75076b9..6f4a4e97a48c 100644 --- a/doc/v3/api_samples/all_extensions/servers-details-resp.json +++ b/doc/v3/api_samples/all_extensions/servers-details-resp.json @@ -60,6 +60,11 @@ "os-extended-status:task_state": null, "os-extended-status:vm_state": "active", "os-extended-volumes:volumes_attached": [], + "os-pci:pci_devices": [ + { + "id": 1 + } + ], "os-server-usage:launched_at": "2013-09-23T13:53:12.774549", "os-server-usage:terminated_at": null, "progress": 0, @@ -70,7 +75,7 @@ ], "status": "ACTIVE", "tenant_id": "openstack", - "updated": "2013-09-23T13:53:12Z", + "updated": "2013-10-31T06:32:32Z", "user_id": "fake" } ] diff --git a/doc/v3/api_samples/all_extensions/servers-details-resp.xml b/doc/v3/api_samples/all_extensions/servers-details-resp.xml index ebd3044d37c6..713e274b13a2 100644 --- a/doc/v3/api_samples/all_extensions/servers-details-resp.xml +++ b/doc/v3/api_samples/all_extensions/servers-details-resp.xml @@ -1,6 +1,6 @@ - - + + @@ -17,6 +17,9 @@ + + + diff --git a/doc/v3/api_samples/os-pci/server-get-resp.json b/doc/v3/api_samples/os-pci/server-get-resp.json new file mode 100644 index 000000000000..a58574e62858 --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-get-resp.json @@ -0,0 +1,60 @@ +{ + "server": { + "addresses": { + "private": [ + { + "addr": "192.168.0.3", + "mac_addr": "aa:bb:cc:dd:ee:ff", + "type": "fixed", + "version": 4 + } + ] + }, + "created": "2013-11-25T03:45:54Z", + "flavor": { + "id": "1", + "links": [ + { + "href": "http://openstack.example.com/flavors/1", + "rel": "bookmark" + } + ] + }, + "host_id": "b7e88944272df30c113572778bcf5527f02e9c2a745221214536c1a2", + "id": "9dafa6bc-7a9f-45b2-8177-11800ceb7224", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://glance.openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v3/servers/9dafa6bc-7a9f-45b2-8177-11800ceb7224", + "rel": "self" + }, + { + "href": "http://openstack.example.com/servers/9dafa6bc-7a9f-45b2-8177-11800ceb7224", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-pci:pci_devices": [ + { + "id": 1 + } + ], + "progress": 0, + "status": "ACTIVE", + "tenant_id": "openstack", + "updated": "2013-11-25T03:45:54Z", + "user_id": "fake" + } +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/server-get-resp.xml b/doc/v3/api_samples/os-pci/server-get-resp.xml new file mode 100644 index 000000000000..e7e4b841dfe4 --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-get-resp.xml @@ -0,0 +1,22 @@ + + + + + + + + + + Apache1 + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/server-post-req.json b/doc/v3/api_samples/os-pci/server-post-req.json new file mode 100644 index 000000000000..30851df41a56 --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-post-req.json @@ -0,0 +1,16 @@ +{ + "server" : { + "name" : "new-server-test", + "image_ref" : "http://glance.openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b", + "flavor_ref" : "http://openstack.example.com/flavors/1", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality" : [ + { + "path" : "/etc/banner.txt", + "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ] + } +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/server-post-req.xml b/doc/v3/api_samples/os-pci/server-post-req.xml new file mode 100644 index 000000000000..24eabe8533ba --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-post-req.xml @@ -0,0 +1,19 @@ + + + + Apache1 + + + + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + + + \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/server-post-resp.json b/doc/v3/api_samples/os-pci/server-post-resp.json new file mode 100644 index 000000000000..6b9ad18047c8 --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-post-resp.json @@ -0,0 +1,16 @@ +{ + "server": { + "admin_password": "8C5KEgw2cQxu", + "id": "fb947804-6a43-499d-9526-3eac8adf7271", + "links": [ + { + "href": "http://openstack.example.com/v3/servers/fb947804-6a43-499d-9526-3eac8adf7271", + "rel": "self" + }, + { + "href": "http://openstack.example.com/servers/fb947804-6a43-499d-9526-3eac8adf7271", + "rel": "bookmark" + } + ] + } +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/server-post-resp.xml b/doc/v3/api_samples/os-pci/server-post-resp.xml new file mode 100644 index 000000000000..ab85d11b5683 --- /dev/null +++ b/doc/v3/api_samples/os-pci/server-post-resp.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/servers-detail-resp.json b/doc/v3/api_samples/os-pci/servers-detail-resp.json new file mode 100644 index 000000000000..f38922f3d112 --- /dev/null +++ b/doc/v3/api_samples/os-pci/servers-detail-resp.json @@ -0,0 +1,62 @@ +{ + "servers": [ + { + "addresses": { + "private": [ + { + "addr": "192.168.0.3", + "mac_addr": "aa:bb:cc:dd:ee:ff", + "type": "fixed", + "version": 4 + } + ] + }, + "created": "2013-11-25T03:45:54Z", + "flavor": { + "id": "1", + "links": [ + { + "href": "http://openstack.example.com/flavors/1", + "rel": "bookmark" + } + ] + }, + "host_id": "416f83c758ea0f9271018b278a9dcedb91b1190deaa598704b87219b", + "id": "ef440f98-04e8-46ea-ae74-e24d437040ea", + "image": { + "id": "70a599e0-31e7-49b7-b260-868f441e862b", + "links": [ + { + "href": "http://glance.openstack.example.com/images/70a599e0-31e7-49b7-b260-868f441e862b", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "http://openstack.example.com/v3/servers/ef440f98-04e8-46ea-ae74-e24d437040ea", + "rel": "self" + }, + { + "href": "http://openstack.example.com/servers/ef440f98-04e8-46ea-ae74-e24d437040ea", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-pci:pci_devices": [ + { + "id": 1 + } + ], + "progress": 0, + "status": "ACTIVE", + "tenant_id": "openstack", + "updated": "2013-11-25T03:45:54Z", + "user_id": "fake" + } + ] +} \ No newline at end of file diff --git a/doc/v3/api_samples/os-pci/servers-detail-resp.xml b/doc/v3/api_samples/os-pci/servers-detail-resp.xml new file mode 100644 index 000000000000..a327335f7377 --- /dev/null +++ b/doc/v3/api_samples/os-pci/servers-detail-resp.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + Apache1 + + + + + + + + + + + + + \ No newline at end of file diff --git a/etc/nova/policy.json b/etc/nova/policy.json index 4ccb4a4f0092..cbe165c274fc 100644 --- a/etc/nova/policy.json +++ b/etc/nova/policy.json @@ -178,6 +178,8 @@ "compute_extension:networks": "rule:admin_api", "compute_extension:networks:view": "", "compute_extension:networks_associate": "rule:admin_api", + "compute_extension:v3:os-pci:pci_servers": "", + "compute_extension:v3:os-pci:discoverable": "", "compute_extension:quotas:show": "", "compute_extension:quotas:update": "rule:admin_api", "compute_extension:quotas:delete": "rule:admin_api", diff --git a/nova/api/openstack/compute/plugins/v3/pci.py b/nova/api/openstack/compute/plugins/v3/pci.py new file mode 100644 index 000000000000..a2a193dca5bf --- /dev/null +++ b/nova/api/openstack/compute/plugins/v3/pci.py @@ -0,0 +1,95 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Intel Corporation +# 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 nova.api.openstack import extensions +from nova.api.openstack import wsgi +from nova.api.openstack import xmlutil + + +ALIAS = 'os-pci' +instance_authorize = extensions.soft_extension_authorizer( + 'compute', 'v3:' + ALIAS + ':pci_servers') + + +def make_server(elem): + pci_devices = xmlutil.TemplateElement('%s:pci_devices' % Pci.alias, + colon_ns=True) + elem.append(pci_devices) + device = xmlutil.SubTemplateElement(pci_devices, + '%s:pci_device' % Pci.alias, + selector='%s:pci_devices' % Pci.alias, + colon_ns=True) + device.set('id') + + +class PciServerTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('server', selector='server') + make_server(root) + return xmlutil.SlaveTemplate(root, 1, nsmap={Pci.alias: Pci.namespace}) + + +class PciServersTemplate(xmlutil.TemplateBuilder): + def construct(self): + root = xmlutil.TemplateElement('servers') + elem = xmlutil.SubTemplateElement(root, 'server', selector='servers') + make_server(elem) + return xmlutil.SlaveTemplate(root, 1, nsmap={Pci.alias: Pci.namespace}) + + +class PciServerController(wsgi.Controller): + def _extend_server(self, server, instance): + dev_id = [] + for dev in instance.pci_devices: + dev_id.append({'id': dev['id']}) + server['%s:pci_devices' % Pci.alias] = dev_id + + @wsgi.extends + def show(self, req, resp_obj, id): + context = req.environ['nova.context'] + if instance_authorize(context): + resp_obj.attach(xml=PciServerTemplate()) + server = resp_obj.obj['server'] + instance = req.get_db_instance(server['id']) + self._extend_server(server, instance) + + @wsgi.extends + def detail(self, req, resp_obj): + context = req.environ['nova.context'] + if instance_authorize(context): + resp_obj.attach(xml=PciServersTemplate()) + servers = list(resp_obj.obj['servers']) + for server in servers: + instance = req.get_db_instance(server['id']) + self._extend_server(server, instance) + + +class Pci(extensions.V3APIExtensionBase): + """Pci access support.""" + name = "PCIAccess" + alias = ALIAS + namespace = "http://docs.openstack.org/compute/ext/%s/api/v3" % ALIAS + version = 1 + + def get_resources(self): + return [] + + def get_controller_extensions(self): + server_extension = extensions.ControllerExtension( + self, 'servers', PciServerController()) + return [server_extension] diff --git a/nova/tests/api/openstack/compute/plugins/v3/test_pci.py b/nova/tests/api/openstack/compute/plugins/v3/test_pci.py new file mode 100644 index 000000000000..12955582f31b --- /dev/null +++ b/nova/tests/api/openstack/compute/plugins/v3/test_pci.py @@ -0,0 +1,121 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Intel Corp. +# +# 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 nova.api.openstack.compute.plugins.v3 import pci +from nova.api.openstack import wsgi +from nova import context +from nova import db +from nova.objects import instance +from nova.objects import pci_device +from nova import test +from nova.tests.api.openstack import fakes +from nova.tests.objects import test_pci_device + + +class FakeResponse(wsgi.ResponseObject): + pass + + +class PciServerTemplateTest(test.NoDBTestCase): + def test_pci_server_serializer(self): + fake_server = {"server": {'os-pci:pci_devices': [{"id": 1}]}} + expected = ("\n" + '' + '' + ) + serializer = pci.PciServerTemplate() + text = serializer.serialize(fake_server) + self.assertEqual(expected, text) + + def test_pci_servers_serializer(self): + fake_servers = {"servers": [{'os-pci:pci_devices': [{"id": 1}]}, + {'os-pci:pci_devices': [{"id": 2}]}]} + expected = ("\n" + '' + '' + '' + '' + '' + ) + serializer = pci.PciServersTemplate() + text = serializer.serialize(fake_servers) + self.assertEqual(expected, text) + + +class PciServerControllerTest(test.NoDBTestCase): + def setUp(self): + super(PciServerControllerTest, self).setUp() + self.controller = pci.PciServerController() + self.fake_obj = {'server': {'addresses': {}, + 'id': 'fb08', + 'name': 'a3', + 'status': 'ACTIVE', + 'tenant_id': '9a3af784c', + 'user_id': 'e992080ac0', + }} + self.fake_list = {'servers': [{'addresses': {}, + 'id': 'fb08', + 'name': 'a3', + 'status': 'ACTIVE', + 'tenant_id': '9a3af784c', + 'user_id': 'e992080ac', + }]} + self._create_fake_instance() + self._create_fake_pci_device() + self.pci_device.claim(self.inst) + self.pci_device.allocate(self.inst) + + def _create_fake_instance(self): + self.inst = instance.Instance() + self.inst.uuid = 'fake-inst-uuid' + self.inst.pci_devices = pci_device.PciDeviceList() + + def _create_fake_pci_device(self): + def fake_pci_device_get_by_addr(ctxt, id, addr): + return test_pci_device.fake_db_dev + + ctxt = context.get_admin_context() + self.stubs.Set(db, 'pci_device_get_by_addr', + fake_pci_device_get_by_addr) + self.pci_device = pci_device.PciDevice.get_by_dev_addr(ctxt, 1, 'a') + + def test_show(self): + def fake_get_db_instance(id): + return self.inst + + resp = FakeResponse(self.fake_obj, '') + req = fakes.HTTPRequestV3.blank('/os-pci/1', use_admin_context=True) + self.stubs.Set(req, 'get_db_instance', fake_get_db_instance) + self.controller.show(req, resp, '1') + self.assertEqual([{'id': 1}], + resp.obj['server']['os-pci:pci_devices']) + + def test_detail(self): + def fake_get_db_instance(id): + return self.inst + + resp = FakeResponse(self.fake_list, '') + req = fakes.HTTPRequestV3.blank('/os-pci/detail', + use_admin_context=True) + self.stubs.Set(req, 'get_db_instance', fake_get_db_instance) + self.controller.detail(req, resp) + self.assertEqual([{'id': 1}], + resp.obj['servers'][0]['os-pci:pci_devices']) diff --git a/nova/tests/fake_network.py b/nova/tests/fake_network.py index ebf78a82dde5..95a81fee5871 100644 --- a/nova/tests/fake_network.py +++ b/nova/tests/fake_network.py @@ -29,8 +29,10 @@ from nova.network import nova_ipam_lib from nova.network import rpcapi as network_rpcapi from nova.objects import base as obj_base from nova.objects import instance_info_cache +from nova.objects import pci_device from nova.openstack.common import jsonutils from nova.tests.objects import test_instance_info_cache +from nova.tests.objects import test_pci_device from nova.virt.libvirt import config as libvirt_config @@ -435,6 +437,10 @@ def stub_compute_with_ips(stubs): def fake_create(*args, **kwargs): return _create_instances_with_cached_ips(orig_create, *args, **kwargs) + def fake_pci_device_get_by_addr(context, node_id, dev_addr): + return test_pci_device.fake_db_dev + + stubs.Set(db, 'pci_device_get_by_addr', fake_pci_device_get_by_addr) stubs.Set(compute_api.API, 'get', fake_get) stubs.Set(compute_api.API, 'get_all', fake_get_all) stubs.Set(compute_api.API, 'create', fake_create) @@ -469,6 +475,7 @@ def _get_instances_with_cached_ips(orig_func, *args, **kwargs): """ instances = orig_func(*args, **kwargs) context = args[0] + fake_device = pci_device.PciDevice.get_by_dev_addr(context, 1, 'a') def _info_cache_for(instance): info_cache = dict(test_instance_info_cache.fake_info_cache, @@ -485,8 +492,12 @@ def _get_instances_with_cached_ips(orig_func, *args, **kwargs): if isinstance(instances, (list, obj_base.ObjectListBase)): for instance in instances: _info_cache_for(instance) + fake_device.claim(instance) + fake_device.allocate(instance) else: _info_cache_for(instances) + fake_device.claim(instances) + fake_device.allocate(instances) return instances diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index 30d89181c6d9..679c60e77016 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -234,6 +234,7 @@ policy_data = """ "compute_extension:networks:view": "", "compute_extension:networks_associate": "", "compute_extension:os-tenant-networks": "", + "compute_extension:v3:os-pci:pci_servers": "", "compute_extension:quotas:show": "", "compute_extension:quotas:update": "", "compute_extension:quotas:delete": "", diff --git a/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.json.tpl b/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.json.tpl index da7d8c68dfd2..6141fc530f7f 100644 --- a/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.json.tpl +++ b/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.json.tpl @@ -59,6 +59,7 @@ "os-extended-status:task_state": null, "os-extended-status:vm_state": "active", "os-extended-volumes:volumes_attached": [], + "os-pci:pci_devices": [{"id": 1}], "os-server-usage:launched_at": "%(timestamp)s", "os-server-usage:terminated_at": null, "progress": 0, diff --git a/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.xml.tpl b/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.xml.tpl index 15b3b89fdc0e..fb4eb79e13ab 100644 --- a/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.xml.tpl +++ b/nova/tests/integrated/v3/api_samples/all_extensions/server-get-resp.xml.tpl @@ -1,5 +1,5 @@ - + @@ -16,6 +16,9 @@ + + + diff --git a/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.json.tpl b/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.json.tpl index 4d226bba8f6e..b9470a1a0828 100644 --- a/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.json.tpl +++ b/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.json.tpl @@ -60,6 +60,7 @@ "os-extended-status:task_state": null, "os-extended-status:vm_state": "active", "os-extended-volumes:volumes_attached": [], + "os-pci:pci_devices": [{"id": 1}], "os-server-usage:launched_at": "%(timestamp)s", "os-server-usage:terminated_at": null, "progress": 0, diff --git a/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.xml.tpl b/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.xml.tpl index 19eb3dc7c5cb..ed1fdbd13341 100644 --- a/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.xml.tpl +++ b/nova/tests/integrated/v3/api_samples/all_extensions/servers-details-resp.xml.tpl @@ -1,5 +1,5 @@ - + @@ -17,6 +17,9 @@ + + + diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.json.tpl new file mode 100644 index 000000000000..02eff6699f5d --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.json.tpl @@ -0,0 +1,60 @@ +{ + "server": { + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "mac_addr": "aa:bb:cc:dd:ee:ff", + "type": "fixed", + "version": 4 + } + ] + }, + "created": "%(timestamp)s", + "flavor": { + "id": "1", + "links": [ + { + "href": "%(host)s/flavors/1", + "rel": "bookmark" + } + ] + }, + "host_id": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(glance_host)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(host)s/v3/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(host)s/servers/%(uuid)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-pci:pci_devices": [ + { + "id": 1 + } + ], + "progress": 0, + "status": "ACTIVE", + "tenant_id": "openstack", + "updated": "%(timestamp)s", + "user_id": "fake" + } +} diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.xml.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.xml.tpl new file mode 100644 index 000000000000..5ab0ccae9987 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-get-resp.xml.tpl @@ -0,0 +1,22 @@ + + + + + + + + + + Apache1 + + + + + + + + + + + + diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.json.tpl new file mode 100644 index 000000000000..e6c046ceb4e9 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.json.tpl @@ -0,0 +1,16 @@ +{ + "server" : { + "name" : "new-server-test", + "image_ref" : "%(glance_host)s/images/%(image_id)s", + "flavor_ref" : "%(host)s/flavors/1", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality" : [ + { + "path" : "/etc/banner.txt", + "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ] + } +} diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.xml.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.xml.tpl new file mode 100644 index 000000000000..31892a3c1f4d --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-post-req.xml.tpl @@ -0,0 +1,19 @@ + + + + Apache1 + + + + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + + + diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.json.tpl new file mode 100644 index 000000000000..eb3f76ebe6d3 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.json.tpl @@ -0,0 +1,16 @@ +{ + "server": { + "admin_password": "%(password)s", + "id": "%(id)s", + "links": [ + { + "href": "%(host)s/v3/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(host)s/servers/%(uuid)s", + "rel": "bookmark" + } + ] + } +} diff --git a/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.xml.tpl b/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.xml.tpl new file mode 100644 index 000000000000..59e7ae5a99ff --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/server-post-resp.xml.tpl @@ -0,0 +1,6 @@ + + + + + + diff --git a/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.json.tpl b/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.json.tpl new file mode 100644 index 000000000000..221460ddfede --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.json.tpl @@ -0,0 +1,62 @@ +{ + "servers": [ + { + "addresses": { + "private": [ + { + "addr": "%(ip)s", + "mac_addr": "aa:bb:cc:dd:ee:ff", + "type": "fixed", + "version": 4 + } + ] + }, + "created": "%(timestamp)s", + "flavor": { + "id": "1", + "links": [ + { + "href": "%(host)s/flavors/1", + "rel": "bookmark" + } + ] + }, + "host_id": "%(hostid)s", + "id": "%(id)s", + "image": { + "id": "%(uuid)s", + "links": [ + { + "href": "%(glance_host)s/images/%(uuid)s", + "rel": "bookmark" + } + ] + }, + "key_name": null, + "links": [ + { + "href": "%(host)s/v3/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(host)s/servers/%(uuid)s", + "rel": "bookmark" + } + ], + "metadata": { + "My Server Name": "Apache1" + }, + "name": "new-server-test", + "os-pci:pci_devices": [ + { + "id": 1 + } + ], + "progress": 0, + "status": "ACTIVE", + "tenant_id": "openstack", + "updated": "%(timestamp)s", + "user_id": "fake" + } + ] +} diff --git a/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.xml.tpl b/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.xml.tpl new file mode 100644 index 000000000000..4ba01ff8cef2 --- /dev/null +++ b/nova/tests/integrated/v3/api_samples/os-pci/servers-detail-resp.xml.tpl @@ -0,0 +1,24 @@ + + + + + + + + + + + Apache1 + + + + + + + + + + + + + diff --git a/nova/tests/integrated/v3/test_pci.py b/nova/tests/integrated/v3/test_pci.py new file mode 100644 index 000000000000..e016f51336cd --- /dev/null +++ b/nova/tests/integrated/v3/test_pci.py @@ -0,0 +1,39 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright 2013 Intel. +# +# 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 nova.tests.integrated.v3 import test_servers + + +class ExtendedServerPciSampleJsonTest(test_servers.ServersSampleBase): + extension_name = "os-pci" + + def test_show(self): + uuid = self._post_server() + response = self._do_get('servers/%s' % uuid) + subs = self._get_regexes() + subs['hostid'] = '[a-f0-9]+' + self._verify_response('server-get-resp', subs, response, 200) + + def test_detail(self): + self._post_server() + response = self._do_get('servers/detail') + subs = self._get_regexes() + subs['hostid'] = '[a-f0-9]+' + self._verify_response('servers-detail-resp', subs, response, 200) + + +class ExtendedServerPciSampleXmlTest(ExtendedServerPciSampleJsonTest): + ctype = 'xml' diff --git a/setup.cfg b/setup.cfg index 4d5defa4411e..4f63e840d365 100644 --- a/setup.cfg +++ b/setup.cfg @@ -93,6 +93,7 @@ nova.api.v3.extensions = migrations = nova.api.openstack.compute.plugins.v3.migrations:Migrations multinic = nova.api.openstack.compute.plugins.v3.multinic:Multinic multiple_create = nova.api.openstack.compute.plugins.v3.multiple_create:MultipleCreate + pci = nova.api.openstack.compute.plugins.v3.pci:Pci quota_classes = nova.api.openstack.compute.plugins.v3.quota_classes:QuotaClasses quota_sets = nova.api.openstack.compute.plugins.v3.quota_sets:QuotaSets remote_consoles = nova.api.openstack.compute.plugins.v3.remote_consoles:RemoteConsoles