Merge "Add V3 api for pci support"

This commit is contained in:
Jenkins 2014-02-20 20:12:50 +00:00 committed by Gerrit Code Review
commit e0f0f14fb6
11 changed files with 375 additions and 1 deletions

View File

@ -0,0 +1,36 @@
{
"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

@ -0,0 +1,20 @@
{
"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

@ -0,0 +1,18 @@
{
"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

@ -188,6 +188,9 @@
"compute_extension:v3:os-pause-server:unpause": "rule:admin_or_owner",
"compute_extension:v3:os-pci:pci_servers": "",
"compute_extension:v3:os-pci:discoverable": "",
"compute_extension:v3:os-pci:index": "rule:admin_api",
"compute_extension:v3:os-pci:detail": "rule:admin_api",
"compute_extension:v3:os-pci:show": "rule:admin_api",
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "rule:admin_api",
"compute_extension:quotas:delete": "rule:admin_api",

View File

@ -14,8 +14,13 @@
# 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.objects import pci_device
from nova.openstack.common import jsonutils
@ -23,6 +28,13 @@ ALIAS = 'os-pci'
instance_authorize = extensions.soft_extension_authorizer(
'compute', 'v3:' + ALIAS + ':pci_servers')
authorize = extensions.extension_authorizer('compute', 'v3:' + ALIAS)
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):
@ -68,6 +80,57 @@ class PciHypervisorController(wsgi.Controller):
self._extend_hypervisor(hypervisor, compute_node)
class PciController(object):
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] = device[key]
if detail:
for field in PCI_DETAIL_KEYS:
if field == 'instance_uuid':
dev_dict['server_uuid'] = device[field]
else:
dev_dict[field] = device[field]
return dev_dict
def _get_all_nodes_pci_devices(self, req, detail, action):
context = req.environ['nova.context']
authorize(context, action=action)
compute_nodes = self.host_api.compute_node_get_all(context)
results = []
for node in compute_nodes:
pci_devs = pci_device.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']
authorize(context, action='show')
try:
pci_dev = pci_device.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.V3APIExtensionBase):
"""Pci access support."""
name = "PCIAccess"
@ -75,7 +138,10 @@ class Pci(extensions.V3APIExtensionBase):
version = 1
def get_resources(self):
return []
resources = [extensions.ResourceExtension(ALIAS,
PciController(),
collection_actions={'detail': 'GET'})]
return resources
def get_controller_extensions(self):
server_extension = extensions.ControllerExtension(

View File

@ -13,10 +13,13 @@
# under the License.
from webob import exc
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 import exception
from nova.objects import instance
from nova.objects import pci_device
from nova.openstack.common import jsonutils
@ -148,3 +151,86 @@ class PciHypervisorControllerTest(test.NoDBTestCase):
self.assertIn('os-pci:pci_stats', resp.obj['hypervisors'][0])
self.assertEqual(fake_compute_node['pci_stats'][0],
resp.obj['hypervisors'][0]['os-pci:pci_stats'][0])
class PciControlletest(test.NoDBTestCase):
def setUp(self):
super(PciControlletest, 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.stubs.Set(db, 'pci_device_get_by_id', fake_pci_device_get_by_id)
req = fakes.HTTPRequestV3.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': 't',
'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.stubs.Set(db, 'pci_device_get_by_id', fake_pci_device_get_by_id)
req = fakes.HTTPRequestV3.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 [dict(id=1,
service_id=1,
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.stubs.Set(db, 'compute_node_get_all',
self._fake_compute_node_get_all)
self.stubs.Set(db, 'pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
req = fakes.HTTPRequestV3.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'])
def test_detail(self):
self.stubs.Set(db, 'compute_node_get_all',
self._fake_compute_node_get_all)
self.stubs.Set(db, 'pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
req = fakes.HTTPRequestV3.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'])

View File

@ -240,6 +240,9 @@ policy_data = """
"compute_extension:v3:os-pause-server:pause": "",
"compute_extension:v3:os-pause-server:unpause": "",
"compute_extension:v3:os-pci:pci_servers": "",
"compute_extension:v3:os-pci:index": "",
"compute_extension:v3:os-pci:detail": "",
"compute_extension:v3:os-pci:show": "",
"compute_extension:quotas:show": "",
"compute_extension:quotas:update": "",
"compute_extension:quotas:delete": "",

View File

@ -0,0 +1,36 @@
{
"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

@ -0,0 +1,20 @@
{
"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

@ -0,0 +1,18 @@
{
"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

@ -18,6 +18,43 @@ from nova.tests.integrated.v3 import api_sample_base
from nova.tests.integrated.v3 import test_servers
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',
'product_id': '1520',
'dev_type': 'type-VF',
'status': 'available',
'dev_id': 'pci_0000_04_10_0',
'label': 'label_8086_1520',
'instance_uuid': '69ba1044-0766-4ec0-b60d-09595de034a1',
'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',
'product_id': '1520',
'dev_type': 'type-VF',
'status': 'available',
'dev_id': 'pci_0000_04_10_1',
'label': 'label_8086_1520',
'instance_uuid': 'd5b446a6-a1b4-4d01-b4f0-eac37b3a62fc',
'extra_info': '{"key3": "value3", "key4": "value4"}'
}
class ExtendedServerPciSampleJsonTest(test_servers.ServersSampleBase):
extension_name = "os-pci"
@ -104,3 +141,34 @@ class ExtendedHyervisorPciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
subs.update(self._get_regexes())
self._verify_response('hypervisors-pci-detail-resp',
subs, response, 200)
class PciSampleJsonTest(api_sample_base.ApiSampleTestBaseV3):
extension_name = "os-pci"
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.stubs.Set(db, 'pci_device_get_by_id',
self._fake_pci_device_get_by_id)
response = self._do_get('os-pci/1')
subs = self._get_regexes()
self._verify_response('pci-show-resp', subs, response, 200)
def test_pci_index(self):
self.stubs.Set(db, 'pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
response = self._do_get('os-pci')
subs = self._get_regexes()
self._verify_response('pci-index-resp', subs, response, 200)
def test_pci_detail(self):
self.stubs.Set(db, 'pci_device_get_all_by_node',
self._fake_pci_device_get_all_by_node)
response = self._do_get('os-pci/detail')
subs = self._get_regexes()
self._verify_response('pci-detail-resp', subs, response, 200)