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 6cf65cf79e88..72adc1c2b0ca 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 4a5d9463c147..362270b94fa2 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 c8503ebd1325..9332e8b6face 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