Remove unused os-pci API

The os-pci API was never part of the v2.0 API and was added
to the v3 API, but when the v3 API turned into the v2.1 API
which is backward compatible with the v2.0 API, the os-pci
API was removed from v2.1. The original intent was to enable
it in a microversion but that never happened.

We should just delete this API since it has a number of issues
anyway:

1. It's not documented (which makes sense since it's not enabled).
2. The PciHypervisorController just takes the compute_nodes.pci_stats
   dict and dumps it to json out of the REST API with no control over
   the keys in the response. That means if we ever change the fields
   in the PciDevicePool object, we implicitly introduce a backward
   incompatible change in the REST API.
3. We don't want to be reporting host stats out of the API [1].
4. To make the os-hypervisors extension work in a multi-cell environment
   we'd have to add uuids to the PciDevices model and change the API to
   return and take in uuids to identify the devices for GET requests.
5. And last but not least, no one has asked for this in over two years.

As a result of removing this API we can also remove the join on the
pci_devices table when showing details about an instance or listing
instances, which were added years ago because of the PciServerController:

Id3c8a0b187e399ce2acecd4aaa37ac95e731d46c

Id3e60c3c56c2eb4209e8aca8a2c26881ca86b435

[1] https://docs.openstack.org/developer/nova/policies.html?#metrics-gathering

Closes-Bug: #1426241
Closes-Bug: #1673869

Change-Id: I9099744264eeec175672d10d04da69648dec1a9d
This commit is contained in:
Matt Riedemann 2017-04-18 21:14:43 -04:00
parent 4b37c38eaa
commit 75a7e6fc7d
26 changed files with 17 additions and 1249 deletions

View File

@ -1,40 +0,0 @@
{
"hypervisors": [
{
"cpu_info": "{\"arch\": \"x86_64\", \"model\": \"Nehalem\", \"vendor\": \"Intel\", \"features\": [\"pge\", \"clflush\"], \"topology\": {\"cores\": 1, \"threads\": 1, \"sockets\": 4}}",
"state": "up",
"status": "enabled",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
"hypervisor_type": "fake",
"hypervisor_version": 1000,
"id": 1,
"local_gb": 1028,
"local_gb_used": 0,
"memory_mb": 8192,
"memory_mb_used": 512,
"os-pci:pci_stats": [
{
"count": 5,
"key1": "value1",
"keya": "valuea",
"product_id": "1520",
"vendor_id": "8086",
"numa_node": 1
}
],
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
"id": 2,
"disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
}
]
}

View File

@ -1,38 +0,0 @@
{
"hypervisor": {
"cpu_info": "{\"arch\": \"x86_64\", \"model\": \"Nehalem\", \"vendor\": \"Intel\", \"features\": [\"pge\", \"clflush\"], \"topology\": {\"cores\": 1, \"threads\": 1, \"sockets\": 4}}",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "1.1.1.1",
"state": "up",
"status": "enabled",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
"hypervisor_type": "fake",
"hypervisor_version": 1000,
"id": 1,
"local_gb": 1028,
"local_gb_used": 0,
"memory_mb": 8192,
"memory_mb_used": 512,
"os-pci:pci_stats": [
{
"count": 5,
"key1": "value1",
"keya": "valuea",
"product_id": "1520",
"vendor_id": "8086",
"numa_node": 1
}
],
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
"id": 2,
"disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
}
}

View File

@ -1,36 +0,0 @@
{
"pci_devices": [
{
"address": "0000:04:10.0",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_0",
"dev_type": "type-VF",
"extra_info": {
"key1": "value1",
"key2": "value2"
},
"id": 1,
"server_uuid": "69ba1044-0766-4ec0-b60d-09595de034a1",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
},
{
"address": "0000:04:10.1",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_1",
"dev_type": "type-VF",
"extra_info": {
"key3": "value3",
"key4": "value4"
},
"id": 2,
"server_uuid": "d5b446a6-a1b4-4d01-b4f0-eac37b3a62fc",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
]
}

View File

@ -1,20 +0,0 @@
{
"pci_devices": [
{
"address": "0000:04:10.0",
"compute_node_id": 1,
"id": 1,
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
},
{
"address": "0000:04:10.1",
"compute_node_id": 1,
"id": 2,
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
]
}

View File

@ -1,18 +0,0 @@
{
"pci_device": {
"address": "0000:04:10.0",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_0",
"dev_type": "type-VF",
"extra_info": {
"key1": "value1",
"key2": "value2"
},
"id": 1,
"server_uuid": "69ba1044-0766-4ec0-b60d-09595de034a1",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
}

View File

@ -1,60 +0,0 @@
{
"server": {
"addresses": {
"private": [
{
"addr": "192.168.0.3",
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
"OS-EXT-IPS:type": "fixed",
"version": 4
}
]
},
"created": "2013-11-25T03:45:54Z",
"flavor": {
"id": "1",
"links": [
{
"href": "http://openstack.example.com/flavors/1",
"rel": "bookmark"
}
]
},
"hostId": "b7e88944272df30c113572778bcf5527f02e9c2a745221214536c1a2",
"id": "9dafa6bc-7a9f-45b2-8177-11800ceb7224",
"image": {
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
"links": [
{
"href": "http://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": "6f70656e737461636b20342065766572",
"updated": "2013-11-25T03:45:54Z",
"user_id": "fake"
}
}

View File

@ -1,62 +0,0 @@
{
"servers": [
{
"addresses": {
"private": [
{
"addr": "192.168.0.3",
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
"OS-EXT-IPS:type": "fixed",
"version": 4
}
]
},
"created": "2013-11-25T03:45:54Z",
"flavor": {
"id": "1",
"links": [
{
"href": "http://openstack.example.com/flavors/1",
"rel": "bookmark"
}
]
},
"hostId": "416f83c758ea0f9271018b278a9dcedb91b1190deaa598704b87219b",
"id": "ef440f98-04e8-46ea-ae74-e24d437040ea",
"image": {
"id": "70a599e0-31e7-49b7-b260-868f441e862b",
"links": [
{
"href": "http://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": "6f70656e737461636b20342065766572",
"updated": "2013-11-25T03:45:54Z",
"user_id": "fake"
}
]
}

View File

@ -1,150 +0,0 @@
# 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.
import webob.exc
from nova.api.openstack import extensions
from nova.api.openstack import wsgi
from nova import compute
from nova import exception
from nova import objects
from nova.policies import pci as pci_policies
ALIAS = 'os-pci'
PCI_ADMIN_KEYS = ['id', 'address', 'vendor_id', 'product_id', 'status',
'compute_node_id']
PCI_DETAIL_KEYS = ['dev_type', 'label', 'instance_uuid', 'dev_id',
'extra_info']
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 context.can(pci_policies.POLICY_ROOT % 'pci_servers', fatal=False):
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 context.can(pci_policies.POLICY_ROOT % 'pci_servers', fatal=False):
servers = list(resp_obj.obj['servers'])
for server in servers:
instance = req.get_db_instance(server['id'])
self._extend_server(server, instance)
class PciHypervisorController(wsgi.Controller):
def _extend_hypervisor(self, hypervisor, compute_node):
if compute_node.pci_device_pools is not None:
pci_pools = [pci_pool.to_dict()
for pci_pool in compute_node.pci_device_pools]
else:
pci_pools = []
hypervisor['%s:pci_stats' % Pci.alias] = pci_pools
@wsgi.extends
def show(self, req, resp_obj, id):
hypervisor = resp_obj.obj['hypervisor']
compute_node = req.get_db_compute_node(hypervisor['id'])
self._extend_hypervisor(hypervisor, compute_node)
@wsgi.extends
def detail(self, req, resp_obj):
hypervisors = list(resp_obj.obj['hypervisors'])
for hypervisor in hypervisors:
compute_node = req.get_db_compute_node(hypervisor['id'])
self._extend_hypervisor(hypervisor, compute_node)
class PciController(wsgi.Controller):
def __init__(self):
self.host_api = compute.HostAPI()
def _view_pcidevice(self, device, detail=False):
dev_dict = {}
for key in PCI_ADMIN_KEYS:
dev_dict[key] = getattr(device, key)
if detail:
for field in PCI_DETAIL_KEYS:
if field == 'instance_uuid':
dev_dict['server_uuid'] = getattr(device, field)
else:
dev_dict[field] = getattr(device, field)
return dev_dict
def _get_all_nodes_pci_devices(self, req, detail, action):
context = req.environ['nova.context']
context.can(pci_policies.POLICY_ROOT % action)
compute_nodes = self.host_api.compute_node_get_all(context)
results = []
for node in compute_nodes:
pci_devs = objects.PciDeviceList.get_by_compute_node(
context, node.id)
results.extend([self._view_pcidevice(dev, detail)
for dev in pci_devs])
return results
@extensions.expected_errors(())
def detail(self, req):
results = self._get_all_nodes_pci_devices(req, True, 'detail')
return dict(pci_devices=results)
@extensions.expected_errors(404)
def show(self, req, id):
context = req.environ['nova.context']
context.can(pci_policies.POLICY_ROOT % 'show')
try:
pci_dev = objects.PciDevice.get_by_dev_id(context, id)
except exception.PciDeviceNotFoundById as e:
raise webob.exc.HTTPNotFound(explanation=e.format_message())
result = self._view_pcidevice(pci_dev, True)
return dict(pci_device=result)
@extensions.expected_errors(())
def index(self, req):
results = self._get_all_nodes_pci_devices(req, False, 'index')
return dict(pci_devices=results)
class Pci(extensions.V21APIExtensionBase):
"""Pci access support."""
name = "PciAccess"
alias = ALIAS
version = 1
def get_resources(self):
resources = [extensions.ResourceExtension(ALIAS,
PciController(),
collection_actions={'detail': 'GET'})]
return resources
def get_controller_extensions(self):
server_extension = extensions.ControllerExtension(
self, 'servers', PciServerController())
compute_extension = extensions.ControllerExtension(
self, 'os-hypervisors', PciHypervisorController())
return [server_extension, compute_extension]

View File

@ -291,7 +291,7 @@ class ServersController(wsgi.Controller):
context, sort_keys, sort_dirs,
schema_servers.SERVER_LIST_IGNORE_SORT_KEY, ('host', 'node'))
expected_attrs = ['pci_devices']
expected_attrs = []
if is_detail:
expected_attrs.append('services')
if api_version_request.is_supported(req, '2.26'):
@ -333,7 +333,7 @@ class ServersController(wsgi.Controller):
:param is_detail: True if you plan on showing the details of the
instance in the response, False otherwise.
"""
expected_attrs = ['flavor', 'pci_devices', 'numa_topology']
expected_attrs = ['flavor', 'numa_topology']
if is_detail:
if api_version_request.is_supported(req, '2.26'):
expected_attrs.append("tags")

View File

@ -71,7 +71,6 @@ from nova.policies import multiple_create
from nova.policies import networks
from nova.policies import networks_associate
from nova.policies import pause_server
from nova.policies import pci
from nova.policies import quota_class_sets
from nova.policies import quota_sets
from nova.policies import remote_consoles
@ -161,7 +160,6 @@ def list_rules():
networks.list_rules(),
networks_associate.list_rules(),
pause_server.list_rules(),
pci.list_rules(),
quota_class_sets.list_rules(),
quota_sets.list_rules(),
remote_consoles.list_rules(),

View File

@ -1,44 +0,0 @@
# Copyright 2016 Cloudbase Solutions Srl
# 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 oslo_policy import policy
from nova.policies import base
POLICY_ROOT = 'os_compute_api:os-pci:%s'
pci_policies = [
policy.RuleDefault(
name=POLICY_ROOT % 'index',
check_str=base.RULE_ADMIN_API),
policy.RuleDefault(
name=POLICY_ROOT % 'detail',
check_str=base.RULE_ADMIN_API),
policy.RuleDefault(
name=POLICY_ROOT % 'pci_servers',
check_str=base.RULE_ADMIN_OR_OWNER),
policy.RuleDefault(
name=POLICY_ROOT % 'show',
check_str=base.RULE_ADMIN_API),
policy.RuleDefault(
name=POLICY_ROOT % 'discoverable',
check_str=base.RULE_ANY),
]
def list_rules():
return pci_policies

View File

@ -1,40 +0,0 @@
{
"hypervisors": [
{
"cpu_info": "{\"arch\": \"x86_64\", \"model\": \"Nehalem\", \"vendor\": \"Intel\", \"features\": [\"pge\", \"clflush\"], \"topology\": {\"cores\": 1, \"threads\": 1, \"sockets\": 4}}",
"state": "up",
"status": "enabled",
"current_workload": 0,
"disk_available_least": 0,
"host_ip": "%(ip)s",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
"hypervisor_type": "fake",
"hypervisor_version": 1000,
"id": 1,
"local_gb": 1028,
"local_gb_used": 0,
"memory_mb": 8192,
"memory_mb_used": 512,
"os-pci:pci_stats": [
{
"count": 5,
"key1": "value1",
"keya": "valuea",
"product_id": "1520",
"vendor_id": "8086",
"numa_node": 1
}
],
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
"id": 2,
"disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
}
]
}

View File

@ -1,38 +0,0 @@
{
"hypervisor": {
"cpu_info": "{\"arch\": \"x86_64\", \"model\": \"Nehalem\", \"vendor\": \"Intel\", \"features\": [\"pge\", \"clflush\"], \"topology\": {\"cores\": 1, \"threads\": 1, \"sockets\": 4}}",
"current_workload": 0,
"state": "up",
"status": "enabled",
"disk_available_least": 0,
"host_ip": "%(ip)s",
"free_disk_gb": 1028,
"free_ram_mb": 7680,
"hypervisor_hostname": "fake-mini",
"hypervisor_type": "fake",
"hypervisor_version": 1000,
"id": 1,
"local_gb": 1028,
"local_gb_used": 0,
"memory_mb": 8192,
"memory_mb_used": 512,
"os-pci:pci_stats": [
{
"count": 5,
"key1": "value1",
"keya": "valuea",
"product_id": "1520",
"vendor_id": "8086",
"numa_node": 1
}
],
"running_vms": 0,
"service": {
"host": "043b3cacf6f34c90a7245151fc8ebcda",
"id": 2,
"disabled_reason": null
},
"vcpus": 1,
"vcpus_used": 0
}
}

View File

@ -1,36 +0,0 @@
{
"pci_devices": [
{
"address": "0000:04:10.0",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_0",
"dev_type": "type-VF",
"extra_info": {
"key1": "value1",
"key2": "value2"
},
"id": 1,
"server_uuid": "69ba1044-0766-4ec0-b60d-09595de034a1",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
},
{
"address": "0000:04:10.1",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_1",
"dev_type": "type-VF",
"extra_info": {
"key3": "value3",
"key4": "value4"
},
"id": 2,
"server_uuid": "d5b446a6-a1b4-4d01-b4f0-eac37b3a62fc",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
]
}

View File

@ -1,20 +0,0 @@
{
"pci_devices": [
{
"address": "0000:04:10.0",
"compute_node_id": 1,
"id": 1,
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
},
{
"address": "0000:04:10.1",
"compute_node_id": 1,
"id": 2,
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
]
}

View File

@ -1,18 +0,0 @@
{
"pci_device": {
"address": "0000:04:10.0",
"compute_node_id": 1,
"dev_id": "pci_0000_04_10_0",
"dev_type": "type-VF",
"extra_info": {
"key1": "value1",
"key2": "value2"
},
"id": 1,
"server_uuid": "69ba1044-0766-4ec0-b60d-09595de034a1",
"label": "label_8086_1520",
"product_id": "1520",
"status": "available",
"vendor_id": "8086"
}
}

View File

@ -1,60 +0,0 @@
{
"server": {
"addresses": {
"private": [
{
"addr": "%(ip)s",
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
"OS-EXT-IPS:type": "fixed",
"version": 4
}
]
},
"created": "%(isotime)s",
"flavor": {
"id": "1",
"links": [
{
"href": "%(host)s/flavors/1",
"rel": "bookmark"
}
]
},
"hostId": "%(hostid)s",
"id": "%(id)s",
"image": {
"id": "%(uuid)s",
"links": [
{
"href": "%(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": "6f70656e737461636b20342065766572",
"updated": "%(isotime)s",
"user_id": "fake"
}
}

View File

@ -1,62 +0,0 @@
{
"servers": [
{
"addresses": {
"private": [
{
"addr": "%(ip)s",
"OS-EXT-IPS-MAC:mac_addr": "aa:bb:cc:dd:ee:ff",
"OS-EXT-IPS:type": "fixed",
"version": 4
}
]
},
"created": "%(isotime)s",
"flavor": {
"id": "1",
"links": [
{
"href": "%(host)s/flavors/1",
"rel": "bookmark"
}
]
},
"hostId": "%(hostid)s",
"id": "%(id)s",
"image": {
"id": "%(uuid)s",
"links": [
{
"href": "%(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": "6f70656e737461636b20342065766572",
"updated": "%(isotime)s",
"user_id": "fake"
}
]
}

View File

@ -1,201 +0,0 @@
# 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.
import collections
import mock
from oslo_serialization import jsonutils
import testtools
from nova import objects
from nova.objects import fields
from nova.objects import pci_device_pool
from nova.tests.functional.api_sample_tests import api_sample_base
from nova.tests.functional.api_sample_tests import test_servers
skip_msg = "Bug 1426241"
fake_db_dev_1 = {
'created_at': None,
'updated_at': None,
'deleted_at': None,
'deleted': None,
'id': 1,
'compute_node_id': 1,
'address': '0000:04:10.0',
'vendor_id': '8086',
'numa_node': 0,
'product_id': '1520',
'dev_type': fields.PciDeviceType.SRIOV_VF,
'status': 'available',
'dev_id': 'pci_0000_04_10_0',
'label': 'label_8086_1520',
'instance_uuid': '69ba1044-0766-4ec0-b60d-09595de034a1',
'request_id': None,
'extra_info': '{"key1": "value1", "key2": "value2"}'
}
fake_db_dev_2 = {
'created_at': None,
'updated_at': None,
'deleted_at': None,
'deleted': None,
'id': 2,
'compute_node_id': 1,
'address': '0000:04:10.1',
'vendor_id': '8086',
'numa_node': 1,
'product_id': '1520',
'dev_type': fields.PciDeviceType.SRIOV_VF,
'status': 'available',
'dev_id': 'pci_0000_04_10_1',
'label': 'label_8086_1520',
'instance_uuid': 'd5b446a6-a1b4-4d01-b4f0-eac37b3a62fc',
'request_id': None,
'extra_info': '{"key3": "value3", "key4": "value4"}'
}
class ExtendedServerPciSampleJsonTest(test_servers.ServersSampleBase):
sample_dir = "os-pci"
def setUp(self):
raise testtools.TestCase.skipException(skip_msg)
def test_show(self):
uuid = self._post_server()
response = self._do_get('servers/%s' % uuid)
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 = {'hostid': '[a-f0-9]+'}
self._verify_response('servers-detail-resp', subs, response, 200)
class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV21):
ADMIN_API = True
sample_dir = 'os-pci'
def setUp(self):
raise testtools.TestCase.skipException(skip_msg)
super(ExtendedHyervisorPciSampleJsonTest, self).setUp()
cpu_info = collections.OrderedDict([
('arch', 'x86_64'),
('model', 'Nehalem'),
('vendor', 'Intel'),
('features', ['pge', 'clflush']),
('topology', {
'cores': 1,
'threads': 1,
'sockets': 4,
}),
])
self.fake_compute_node = objects.ComputeNode(
cpu_info=jsonutils.dumps(cpu_info),
current_workload=0,
disk_available_least=0,
host_ip="1.1.1.1",
state="up",
status="enabled",
free_disk_gb=1028,
free_ram_mb=7680,
hypervisor_hostname="fake-mini",
hypervisor_type="fake",
hypervisor_version=1000,
id=1,
local_gb=1028,
local_gb_used=0,
memory_mb=8192,
memory_mb_used=512,
running_vms=0,
vcpus=1,
vcpus_used=0,
service_id=2,
host='043b3cacf6f34c90a7245151fc8ebcda',
pci_device_pools=pci_device_pool.from_pci_stats(
{"count": 5,
"vendor_id": "8086",
"product_id": "1520",
"keya": "valuea",
"key1": "value1",
"numa_node": 1}),)
self.fake_service = objects.Service(
id=2,
host='043b3cacf6f34c90a7245151fc8ebcda',
disabled=False,
disabled_reason=None)
@mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
@mock.patch("nova.objects.Service.get_by_compute_host")
@mock.patch("nova.objects.ComputeNode.get_by_id")
def test_pci_show(self, mock_obj, mock_svc_get, mock_service):
mock_obj.return_value = self.fake_compute_node
mock_svc_get.return_value = self.fake_service
hypervisor_id = 1
response = self._do_get('os-hypervisors/%s' % hypervisor_id)
subs = {
'hypervisor_id': hypervisor_id,
}
self._verify_response('hypervisors-pci-show-resp',
subs, response, 200)
@mock.patch("nova.servicegroup.API.service_is_up", return_value=True)
@mock.patch("nova.objects.Service.get_by_compute_host")
@mock.patch("nova.objects.ComputeNodeList.get_all")
def test_pci_detail(self, mock_obj, mock_svc_get, mock_service):
mock_obj.return_value = [self.fake_compute_node]
mock_svc_get.return_value = self.fake_service
hypervisor_id = 1
subs = {
'hypervisor_id': hypervisor_id
}
response = self._do_get('os-hypervisors/detail')
self._verify_response('hypervisors-pci-detail-resp',
subs, response, 200)
class PciSampleJsonTest(api_sample_base.ApiSampleTestBaseV21):
ADMIN_API = True
sample_dir = "os-pci"
def setUp(self):
raise testtools.TestCase.skipException(skip_msg)
def _fake_pci_device_get_by_id(self, context, id):
return fake_db_dev_1
def _fake_pci_device_get_all_by_node(self, context, id):
return [fake_db_dev_1, fake_db_dev_2]
def test_pci_show(self):
self.stub_out('nova.db.pci_device_get_by_id',
self._fake_pci_device_get_by_id)
response = self._do_get('os-pci/1')
self._verify_response('pci-show-resp', {}, response, 200)
def test_pci_index(self):
self.stub_out('nova.db.pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
response = self._do_get('os-pci')
self._verify_response('pci-index-resp', {}, response, 200)
def test_pci_detail(self):
self.stub_out('nova.db.pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
response = self._do_get('os-pci/detail')
self._verify_response('pci-detail-resp', {}, response, 200)

View File

@ -1,273 +0,0 @@
# 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.
import mock
from webob import exc
from nova.api.openstack.compute import pci
from nova.api.openstack import wsgi
from nova import context
from nova import exception
from nova import objects
from nova.objects import fields
from nova.objects import pci_device_pool
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.objects import test_pci_device
from nova.tests import uuidsentinel as uuids
pci_stats = [{"count": 3,
"vendor_id": "8086",
"product_id": "1520",
"numa_node": 1}]
fake_compute_node = objects.ComputeNode(
pci_device_pools=pci_device_pool.from_pci_stats(pci_stats))
class FakeResponse(wsgi.ResponseObject):
pass
class PciServerControllerTestV21(test.NoDBTestCase):
def setUp(self):
super(PciServerControllerTestV21, 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.uuid)
self.pci_device.allocate(self.inst)
def _create_fake_instance(self):
self.inst = objects.Instance()
self.inst.uuid = uuids.instance
self.inst.pci_devices = objects.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.stub_out('nova.db.pci_device_get_by_addr',
fake_pci_device_get_by_addr)
self.pci_device = objects.PciDevice.get_by_dev_addr(ctxt, 1, 'a')
def test_show(self):
resp = FakeResponse(self.fake_obj, '')
req = fakes.HTTPRequest.blank('/os-pci/1', use_admin_context=True)
with mock.patch.object(req, 'get_db_instance',
return_value=self.inst) as mock_get_db_inst:
self.controller.show(req, resp, '1')
self.assertEqual([{'id': 1}],
resp.obj['server']['os-pci:pci_devices'])
mock_get_db_inst.assert_called_once_with(
self.fake_obj['server']['id'])
def test_detail(self):
resp = FakeResponse(self.fake_list, '')
req = fakes.HTTPRequest.blank('/os-pci/detail',
use_admin_context=True)
with mock.patch.object(req, 'get_db_instance',
return_value=self.inst) as mock_get_db_inst:
self.controller.detail(req, resp)
self.assertEqual([{'id': 1}],
resp.obj['servers'][0]['os-pci:pci_devices'])
mock_get_db_inst.assert_called_once_with(
self.fake_list['servers'][0]['id'])
class PciHypervisorControllerTestV21(test.NoDBTestCase):
def setUp(self):
super(PciHypervisorControllerTestV21, self).setUp()
self.controller = pci.PciHypervisorController()
self.fake_objs = dict(hypervisors=[
dict(id=1,
service=dict(id=1, host="compute1"),
hypervisor_type="xen",
hypervisor_version=3,
hypervisor_hostname="hyper1")])
self.fake_obj = dict(hypervisor=dict(
id=1,
service=dict(id=1, host="compute1"),
hypervisor_type="xen",
hypervisor_version=3,
hypervisor_hostname="hyper1"))
def test_show(self):
req = fakes.HTTPRequest.blank('/os-hypervisors/1',
use_admin_context=True)
resp = FakeResponse(self.fake_obj, '')
with mock.patch.object(req, 'get_db_compute_node',
return_value=fake_compute_node
) as mock_get_db_node:
self.controller.show(req, resp, '1')
self.assertIn('os-pci:pci_stats', resp.obj['hypervisor'])
self.assertEqual(pci_stats[0],
resp.obj['hypervisor']['os-pci:pci_stats'][0])
mock_get_db_node.assert_called_once_with(
self.fake_obj['hypervisor']['id'])
def test_detail(self):
req = fakes.HTTPRequest.blank('/os-hypervisors/detail',
use_admin_context=True)
resp = FakeResponse(self.fake_objs, '')
with mock.patch.object(req, 'get_db_compute_node',
return_value=fake_compute_node
) as mock_get_db_node:
self.controller.detail(req, resp)
self.assertIn('os-pci:pci_stats', resp.obj['hypervisors'][0])
self.assertEqual(pci_stats[0],
resp.obj['hypervisors'][0]['os-pci:pci_stats'][0])
mock_get_db_node.assert_called_once_with(
self.fake_objs['hypervisors'][0]['id'])
class PciControlletestV21(test.NoDBTestCase):
def setUp(self):
super(PciControlletestV21, self).setUp()
self.controller = pci.PciController()
def test_show(self):
def fake_pci_device_get_by_id(context, id):
return test_pci_device.fake_db_dev
self.stub_out('nova.db.pci_device_get_by_id',
fake_pci_device_get_by_id)
req = fakes.HTTPRequest.blank('/os-pci/1', use_admin_context=True)
result = self.controller.show(req, '1')
dist = {'pci_device': {'address': 'a',
'compute_node_id': 1,
'dev_id': 'i',
'extra_info': {},
'dev_type': fields.PciDeviceType.STANDARD,
'id': 1,
'server_uuid': None,
'label': 'l',
'product_id': 'p',
'status': 'available',
'vendor_id': 'v'}}
self.assertEqual(dist, result)
def test_show_error_id(self):
def fake_pci_device_get_by_id(context, id):
raise exception.PciDeviceNotFoundById(id=id)
self.stub_out('nova.db.pci_device_get_by_id',
fake_pci_device_get_by_id)
req = fakes.HTTPRequest.blank('/os-pci/0', use_admin_context=True)
self.assertRaises(exc.HTTPNotFound, self.controller.show, req, '0')
def _fake_compute_node_get_all(self, context):
return [objects.ComputeNode(id=1,
service_id=1,
host='fake',
cpu_info='cpu_info',
disk_available_least=100)]
def _fake_pci_device_get_all_by_node(self, context, node):
return [test_pci_device.fake_db_dev, test_pci_device.fake_db_dev_1]
def test_index(self):
self.stub_out('nova.db.pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
with mock.patch.object(
self.controller.host_api, 'compute_node_get_all',
side_effect=self._fake_compute_node_get_all
) as mock_node_get_all:
req = fakes.HTTPRequest.blank('/os-pci', use_admin_context=True)
result = self.controller.index(req)
dist = {'pci_devices': [test_pci_device.fake_db_dev,
test_pci_device.fake_db_dev_1]}
for i in range(len(result['pci_devices'])):
self.assertEqual(dist['pci_devices'][i]['vendor_id'],
result['pci_devices'][i]['vendor_id'])
self.assertEqual(dist['pci_devices'][i]['id'],
result['pci_devices'][i]['id'])
self.assertEqual(dist['pci_devices'][i]['status'],
result['pci_devices'][i]['status'])
self.assertEqual(dist['pci_devices'][i]['address'],
result['pci_devices'][i]['address'])
self.assertEqual(1, mock_node_get_all.call_count)
def test_detail(self):
self.stub_out('nova.db.pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
with mock.patch.object(
self.controller.host_api, 'compute_node_get_all',
side_effect=self._fake_compute_node_get_all
) as mock_node_get_all:
req = fakes.HTTPRequest.blank('/os-pci/detail',
use_admin_context=True)
result = self.controller.detail(req)
dist = {'pci_devices': [test_pci_device.fake_db_dev,
test_pci_device.fake_db_dev_1]}
for i in range(len(result['pci_devices'])):
self.assertEqual(dist['pci_devices'][i]['vendor_id'],
result['pci_devices'][i]['vendor_id'])
self.assertEqual(dist['pci_devices'][i]['id'],
result['pci_devices'][i]['id'])
self.assertEqual(dist['pci_devices'][i]['label'],
result['pci_devices'][i]['label'])
self.assertEqual(dist['pci_devices'][i]['dev_id'],
result['pci_devices'][i]['dev_id'])
self.assertEqual(1, mock_node_get_all.call_count)
class PciControllerPolicyEnforcementV21(test.NoDBTestCase):
def setUp(self):
super(PciControllerPolicyEnforcementV21, self).setUp()
self.controller = pci.PciController()
self.req = fakes.HTTPRequest.blank('')
def _test_policy_failed(self, action, *args):
rule_name = "os_compute_api:os-pci:%s" % action
rule = {rule_name: "project:non_fake"}
self.policy.set_rules(rule)
exc = self.assertRaises(
exception.PolicyNotAuthorized, getattr(self.controller, action),
self.req, *args)
self.assertEqual(
"Policy doesn't allow %s to be performed." % rule_name,
exc.format_message())
def test_index_policy_failed(self):
self._test_policy_failed('index')
def test_detail_policy_failed(self):
self._test_policy_failed('detail')
def test_show_policy_failed(self):
self._test_policy_failed('show', 1)

View File

@ -136,7 +136,7 @@ class ServerActionsControllerTestV21(test.TestCase):
body=body_map.get(action))
mock_get.assert_called_once_with(self.context, uuid,
expected_attrs=['flavor', 'pci_devices', 'numa_topology'])
expected_attrs=['flavor', 'numa_topology'])
mock_method.assert_called_once_with(self.context, instance,
*args, **kwargs)

View File

@ -289,12 +289,12 @@ class ServersControllerTest(ControllerTest):
res_dict = self.controller.show(req, FAKE_UUID)
self.assertEqual(res_dict['server']['id'], FAKE_UUID)
def test_get_server_joins_pci_devices(self):
def test_get_server_joins(self):
def fake_get(_self, *args, **kwargs):
expected_attrs = kwargs['expected_attrs']
self.assertEqual(['flavor', 'info_cache', 'metadata',
'numa_topology', 'pci_devices'], expected_attrs)
'numa_topology'], expected_attrs)
ctxt = context.RequestContext('fake', 'fake')
return fake_instance.fake_instance_obj(
ctxt, expected_attrs=expected_attrs)
@ -1121,7 +1121,7 @@ class ServersControllerTest(ControllerTest):
self.assertIsNotNone(search_opts)
self.assertIn('name', search_opts)
self.assertEqual(search_opts['name'], 'whee.*')
self.assertEqual(['pci_devices'], expected_attrs)
self.assertEqual([], expected_attrs)
return objects.InstanceList(
objects=[fakes.stub_instance_obj(100, uuid=server_uuid)])
@ -1416,19 +1416,6 @@ class ServersControllerTest(ControllerTest):
self.assertEqual(s['hostId'], host_ids[i % 2])
self.assertEqual(s['name'], 'server%d' % (i + 1))
def test_get_servers_joins_pci_devices(self):
def fake_get_all(compute_self, context, search_opts=None,
limit=None, marker=None,
expected_attrs=None, sort_keys=None, sort_dirs=None):
self.assertEqual(['pci_devices'], expected_attrs)
return []
self.stubs.Set(compute_api.API, 'get_all', fake_get_all)
req = self.req('/fake/servers', use_admin_context=True)
self.assertIn('servers', self.controller.index(req))
def test_get_servers_joins_services(self):
def fake_get_all(compute_self, context, search_opts=None,
limit=None, marker=None,

View File

@ -78,10 +78,6 @@ policy_data = """
"os_compute_api:os-tenant-networks": "",
"os_compute_api:os-pause-server:pause": "",
"os_compute_api:os-pause-server:unpause": "",
"os_compute_api:os-pci:pci_servers": "",
"os_compute_api:os-pci:index": "",
"os_compute_api:os-pci:detail": "",
"os_compute_api:os-pci:show": "",
"os_compute_api:os-quota-sets:show": "",
"os_compute_api:os-quota-sets:update": "",
"os_compute_api:os-quota-sets:delete": "",

View File

@ -314,9 +314,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-migrate-server:migrate_live",
"os_compute_api:os-networks",
"os_compute_api:os-networks-associate",
"os_compute_api:os-pci:index",
"os_compute_api:os-pci:detail",
"os_compute_api:os-pci:show",
"os_compute_api:os-quota-sets:update",
"os_compute_api:os-quota-sets:delete",
"os_compute_api:os-quota-sets:detail",
@ -412,7 +409,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:limits",
"os_compute_api:os-multinic",
"os_compute_api:os-networks:view",
"os_compute_api:os-pci:pci_servers",
"os_compute_api:os-rescue",
"os_compute_api:os-security-groups",
"os_compute_api:os-server-password",
@ -497,7 +493,6 @@ class RealRolePolicyTestCase(test.NoDBTestCase):
"os_compute_api:os-networks:discoverable",
"os_compute_api:os-networks-associate:discoverable",
"os_compute_api:os-pause-server:discoverable",
"os_compute_api:os-pci:discoverable",
"os_compute_api:os-quota-sets:discoverable",
"os_compute_api:os-quota-class-sets:discoverable",
"os_compute_api:os-rescue:discoverable",

View File

@ -0,0 +1,11 @@
---
other:
- |
The disabled ``os-pci`` API has been removed. This API was originally added
to the v3 API which over time finally became the v2.1 API and the initial
microversion is backward compatible with the v2.0 API, where the
``os-pci`` extension did not exist. The ``os-pci`` API was never enabled
as a microversion in the v2.1 API and at this time no longer aligns with
Nova strategically and is therefore just technical debt, so it has been
removed. Since it was never enabled or exposed out of the compute REST API
endpoint there was no deprecation period for this.

View File

@ -125,9 +125,6 @@ nova.api.v21.extensions =
networks = nova.api.openstack.compute.networks:Networks
networks_associate = nova.api.openstack.compute.networks_associate:NetworksAssociate
pause_server = nova.api.openstack.compute.pause_server:PauseServer
# NOTE(cyeoh): this is intentionally disabled until microversions is active.
# See https://bugs.launchpad.net/nova/+bug/1426241
# pci = nova.api.openstack.compute.pci:Pci
quota_classes = nova.api.openstack.compute.quota_classes:QuotaClasses
quota_sets = nova.api.openstack.compute.quota_sets:QuotaSets
remote_consoles = nova.api.openstack.compute.remote_consoles:RemoteConsoles