pci: Remove nova.pci.device module

This moves the module-level functions in nova.pci.device module to be
non-remotable object methods of nova.objects.PciDevice.

Change-Id: Iff31ec73548b99bc38e830d88089725c0fb4f105
This commit is contained in:
Jay Pipes 2015-08-15 19:32:01 -04:00
parent 3fdb7ac23e
commit ee2ecfc68a
8 changed files with 177 additions and 247 deletions

View File

@ -13,10 +13,13 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
from oslo_log import log as logging
from oslo_serialization import jsonutils
from nova import db
from nova import exception
from nova import objects
from nova.objects import base
from nova.objects import fields
@ -198,6 +201,79 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject):
self.address, updates)
self._from_db_object(self._context, self, db_pci)
def claim(self, instance):
if self.status != fields.PciDeviceStatus.AVAILABLE:
raise exception.PciDeviceInvalidStatus(
compute_node_id=self.compute_node_id,
address=self.address, status=self.status,
hopestatus=[fields.PciDeviceStatus.AVAILABLE])
self.status = fields.PciDeviceStatus.CLAIMED
self.instance_uuid = instance['uuid']
def allocate(self, instance):
ok_statuses = (fields.PciDeviceStatus.AVAILABLE,
fields.PciDeviceStatus.CLAIMED)
if self.status not in ok_statuses:
raise exception.PciDeviceInvalidStatus(
compute_node_id=self.compute_node_id,
address=self.address, status=self.status,
hopestatus=ok_statuses)
if (self.status == fields.PciDeviceStatus.CLAIMED and
self.instance_uuid != instance['uuid']):
raise exception.PciDeviceInvalidOwner(
compute_node_id=self.compute_node_id,
address=self.address, owner=self.instance_uuid,
hopeowner=instance['uuid'])
self.status = fields.PciDeviceStatus.ALLOCATED
self.instance_uuid = instance['uuid']
# Notes(yjiang5): remove this check when instance object for
# compute manager is finished
if isinstance(instance, dict):
if 'pci_devices' not in instance:
instance['pci_devices'] = []
instance['pci_devices'].append(copy.copy(self))
else:
instance.pci_devices.objects.append(copy.copy(self))
def remove(self):
if self.status != fields.PciDeviceStatus.AVAILABLE:
raise exception.PciDeviceInvalidStatus(
compute_node_id=self.compute_node_id,
address=self.address, status=self.status,
hopestatus=[fields.PciDeviceStatus.AVAILABLE])
self.status = fields.PciDeviceStatus.REMOVED
self.instance_uuid = None
self.request_id = None
def free(self, instance=None):
ok_statuses = (fields.PciDeviceStatus.ALLOCATED,
fields.PciDeviceStatus.CLAIMED)
if self.status not in ok_statuses:
raise exception.PciDeviceInvalidStatus(
compute_node_id=self.compute_node_id,
address=self.address, status=self.status,
hopestatus=ok_statuses)
if instance and self.instance_uuid != instance['uuid']:
raise exception.PciDeviceInvalidOwner(
compute_node_id=self.compute_node_id,
address=self.address, owner=self.instance_uuid,
hopeowner=instance['uuid'])
old_status = self.status
self.status = fields.PciDeviceStatus.AVAILABLE
self.instance_uuid = None
self.request_id = None
if old_status == fields.PciDeviceStatus.ALLOCATED and instance:
# Notes(yjiang5): remove this check when instance object for
# compute manager is finished
existed = next((dev for dev in instance['pci_devices']
if dev.id == self.id))
if isinstance(instance, dict):
instance['pci_devices'].remove(existed)
else:
instance.pci_devices.objects.remove(existed)
@base.NovaObjectRegistry.register
class PciDeviceList(base.ObjectListBase, base.NovaObject):

View File

@ -1,105 +0,0 @@
# Copyright 2014 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 copy
import functools
from nova import exception
from nova.objects import fields
def check_device_status(dev_status=None):
"""Decorator to check device status before changing it."""
if dev_status is not None and not isinstance(dev_status, set):
dev_status = set(dev_status)
def outer(f):
@functools.wraps(f)
def inner(devobj, instance=None):
if devobj.status not in dev_status:
raise exception.PciDeviceInvalidStatus(
compute_node_id=devobj.compute_node_id,
address=devobj.address, status=devobj.status,
hopestatus=dev_status)
if instance:
return f(devobj, instance)
else:
return f(devobj)
return inner
return outer
@check_device_status(dev_status=[fields.PciDeviceStatus.AVAILABLE])
def claim(devobj, instance):
devobj.status = fields.PciDeviceStatus.CLAIMED
devobj.instance_uuid = instance['uuid']
@check_device_status(dev_status=[
fields.PciDeviceStatus.AVAILABLE,
fields.PciDeviceStatus.CLAIMED
])
def allocate(devobj, instance):
if (devobj.status == fields.PciDeviceStatus.CLAIMED and
devobj.instance_uuid != instance['uuid']):
raise exception.PciDeviceInvalidOwner(
compute_node_id=devobj.compute_node_id,
address=devobj.address, owner=devobj.instance_uuid,
hopeowner=instance['uuid'])
devobj.status = fields.PciDeviceStatus.ALLOCATED
devobj.instance_uuid = instance['uuid']
# Notes(yjiang5): remove this check when instance object for
# compute manager is finished
if isinstance(instance, dict):
if 'pci_devices' not in instance:
instance['pci_devices'] = []
instance['pci_devices'].append(copy.copy(devobj))
else:
instance.pci_devices.objects.append(copy.copy(devobj))
@check_device_status(dev_status=[fields.PciDeviceStatus.AVAILABLE])
def remove(devobj):
devobj.status = fields.PciDeviceStatus.REMOVED
devobj.instance_uuid = None
devobj.request_id = None
@check_device_status(dev_status=[
fields.PciDeviceStatus.CLAIMED,
fields.PciDeviceStatus.ALLOCATED
])
def free(devobj, instance=None):
if instance and devobj.instance_uuid != instance['uuid']:
raise exception.PciDeviceInvalidOwner(
compute_node_id=devobj.compute_node_id,
address=devobj.address, owner=devobj.instance_uuid,
hopeowner=instance['uuid'])
old_status = devobj.status
devobj.status = fields.PciDeviceStatus.AVAILABLE
devobj.instance_uuid = None
devobj.request_id = None
if old_status == fields.PciDeviceStatus.ALLOCATED and instance:
# Notes(yjiang5): remove this check when instance object for
# compute manager is finished
existed = next((dev for dev in instance['pci_devices']
if dev.id == devobj.id))
if isinstance(instance, dict):
instance['pci_devices'].remove(existed)
else:
instance.pci_devices.objects.remove(existed)

View File

@ -24,7 +24,6 @@ from nova import exception
from nova.i18n import _LW
from nova import objects
from nova.objects import fields
from nova.pci import device
from nova.pci import stats
from nova.pci import whitelist
from nova.virt import hardware
@ -127,7 +126,7 @@ class PciDevTracker(object):
for existed in self.pci_devs:
if existed.address in exist_addrs - new_addrs:
try:
device.remove(existed)
existed.remove()
except exception.PciDeviceInvalidStatus as e:
LOG.warning(_LW("Trying to remove device with %(status)s "
"ownership %(instance_uuid)s because of "
@ -189,7 +188,7 @@ class PciDevTracker(object):
return None
for dev in devs:
device.claim(dev, instance)
dev.claim(instance)
if instance_numa_topology and any(
dev.numa_node is None for dev in devs):
LOG.warning(_LW("Assigning a pci device without numa affinity to"
@ -199,7 +198,7 @@ class PciDevTracker(object):
def _allocate_instance(self, instance, devs):
for dev in devs:
device.allocate(dev, instance)
dev.allocate(instance)
def allocate_instance(self, instance):
devs = self.claims.pop(instance['uuid'], [])
@ -218,7 +217,7 @@ class PciDevTracker(object):
return None
def _free_device(self, dev, instance=None):
device.free(dev, instance)
dev.free(instance)
stale = self.stale.pop(dev.address, None)
if stale:
dev.update_device(stale)

View File

@ -23,7 +23,6 @@ from nova import exception
from nova import objects
from nova.objects import fields
from nova.objects import pci_device_pool
from nova.pci import device
from nova import test
from nova.tests.unit.api.openstack import fakes
from nova.tests.unit.objects import test_pci_device
@ -62,8 +61,8 @@ class PciServerControllerTestV21(test.NoDBTestCase):
}]}
self._create_fake_instance()
self._create_fake_pci_device()
device.claim(self.pci_device, self.inst)
device.allocate(self.pci_device, self.inst)
self.pci_device.claim(self.inst)
self.pci_device.allocate(self.inst)
def _create_fake_instance(self):
self.inst = objects.Instance()

View File

@ -29,7 +29,6 @@ from nova.network import rpcapi as network_rpcapi
from nova import objects
from nova.objects import base as obj_base
from nova.objects import virtual_interface as vif_obj
from nova.pci import device as pci_device
from nova.tests.unit.objects import test_fixed_ip
from nova.tests.unit.objects import test_instance_info_cache
from nova.tests.unit.objects import test_pci_device
@ -442,12 +441,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)
pci_device.claim(fake_device, instance)
pci_device.allocate(fake_device, instance)
fake_device.claim(instance)
fake_device.allocate(instance)
else:
_info_cache_for(instances)
pci_device.claim(fake_device, instances)
pci_device.allocate(fake_device, instances)
fake_device.claim(instances)
fake_device.allocate(instances)
return instances

View File

@ -19,6 +19,7 @@ from oslo_utils import timeutils
from nova import context
from nova import db
from nova import exception
from nova.objects import fields
from nova.objects import instance
from nova.objects import pci_device
@ -245,6 +246,95 @@ class _TestPciDeviceObject(object):
pci_device2.instance_uuid = None
self.assertNotEqual(pci_device1, pci_device2)
def test_claim_device(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.claim(self.inst)
self.assertEqual(devobj.status,
fields.PciDeviceStatus.CLAIMED)
self.assertEqual(devobj.instance_uuid,
self.inst.uuid)
self.assertEqual(len(self.inst.pci_devices), 0)
def test_claim_device_fail(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.status = fields.PciDeviceStatus.ALLOCATED
self.assertRaises(exception.PciDeviceInvalidStatus,
devobj.claim, self.inst)
def test_allocate_device(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.claim(self.inst)
devobj.allocate(self.inst)
self.assertEqual(devobj.status,
fields.PciDeviceStatus.ALLOCATED)
self.assertEqual(devobj.instance_uuid, 'fake-inst-uuid')
self.assertEqual(len(self.inst.pci_devices), 1)
self.assertEqual(self.inst.pci_devices[0].vendor_id,
'v')
self.assertEqual(self.inst.pci_devices[0].status,
fields.PciDeviceStatus.ALLOCATED)
def test_allocate_device_fail_status(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.status = 'removed'
self.assertRaises(exception.PciDeviceInvalidStatus,
devobj.allocate, self.inst)
def test_allocate_device_fail_owner(self):
self._create_fake_instance()
inst_2 = instance.Instance()
inst_2.uuid = 'fake-inst-uuid-2'
devobj = pci_device.PciDevice.create(dev_dict)
devobj.claim(self.inst)
self.assertRaises(exception.PciDeviceInvalidOwner,
devobj.allocate, inst_2)
def test_free_claimed_device(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.claim(self.inst)
devobj.free(self.inst)
self.assertEqual(devobj.status,
fields.PciDeviceStatus.AVAILABLE)
self.assertIsNone(devobj.instance_uuid)
def test_free_allocated_device(self):
self._create_fake_instance()
ctx = context.get_admin_context()
devobj = pci_device.PciDevice._from_db_object(
ctx, pci_device.PciDevice(), fake_db_dev)
devobj.claim(self.inst)
devobj.allocate(self.inst)
self.assertEqual(len(self.inst.pci_devices), 1)
devobj.free(self.inst)
self.assertEqual(len(self.inst.pci_devices), 0)
self.assertEqual(devobj.status,
fields.PciDeviceStatus.AVAILABLE)
self.assertIsNone(devobj.instance_uuid)
def test_free_device_fail(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.status = fields.PciDeviceStatus.REMOVED
self.assertRaises(exception.PciDeviceInvalidStatus, devobj.free)
def test_remove_device(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.remove()
self.assertEqual(devobj.status, fields.PciDeviceStatus.REMOVED)
self.assertIsNone(devobj.instance_uuid)
def test_remove_device_fail(self):
self._create_fake_instance()
devobj = pci_device.PciDevice.create(dev_dict)
devobj.claim(self.inst)
self.assertRaises(exception.PciDeviceInvalidStatus, devobj.remove)
class TestPciDeviceObject(test_objects._LocalTest,
_TestPciDeviceObject):

View File

@ -1,127 +0,0 @@
# Copyright 2014 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 import context
from nova import exception
from nova import objects
from nova.objects import fields
from nova.pci import device
from nova import test
dev_dict = {
'created_at': None,
'updated_at': None,
'deleted_at': None,
'deleted': None,
'id': 1,
'compute_node_id': 1,
'address': 'a',
'vendor_id': 'v',
'product_id': 'p',
'numa_node': 1,
'dev_type': fields.PciDeviceType.STANDARD,
'status': fields.PciDeviceStatus.AVAILABLE,
'dev_id': 'i',
'label': 'l',
'instance_uuid': None,
'extra_info': '{}',
'request_id': None,
}
class PciDeviceTestCase(test.NoDBTestCase):
def setUp(self):
super(PciDeviceTestCase, self).setUp()
self.ctxt = context.get_admin_context()
self.inst = objects.Instance()
self.inst.uuid = 'fake-inst-uuid'
self.inst.pci_devices = objects.PciDeviceList()
self.devobj = objects.PciDevice._from_db_object(
self.ctxt,
objects.PciDevice(),
dev_dict)
def test_claim_device(self):
device.claim(self.devobj, self.inst)
self.assertEqual(self.devobj.status,
fields.PciDeviceStatus.CLAIMED)
self.assertEqual(self.devobj.instance_uuid,
self.inst.uuid)
self.assertEqual(len(self.inst.pci_devices), 0)
def test_claim_device_fail(self):
self.devobj.status = fields.PciDeviceStatus.ALLOCATED
self.assertRaises(exception.PciDeviceInvalidStatus,
device.claim, self.devobj, self.inst)
def test_allocate_device(self):
device.claim(self.devobj, self.inst)
device.allocate(self.devobj, self.inst)
self.assertEqual(self.devobj.status,
fields.PciDeviceStatus.ALLOCATED)
self.assertEqual(self.devobj.instance_uuid, 'fake-inst-uuid')
self.assertEqual(len(self.inst.pci_devices), 1)
self.assertEqual(self.inst.pci_devices[0].vendor_id,
'v')
self.assertEqual(self.inst.pci_devices[0].status,
fields.PciDeviceStatus.ALLOCATED)
def test_allocacte_device_fail_status(self):
self.devobj.status = 'removed'
self.assertRaises(exception.PciDeviceInvalidStatus,
device.allocate,
self.devobj,
self.inst)
def test_allocacte_device_fail_owner(self):
inst_2 = objects.Instance()
inst_2.uuid = 'fake-inst-uuid-2'
device.claim(self.devobj, self.inst)
self.assertRaises(exception.PciDeviceInvalidOwner,
device.allocate,
self.devobj, inst_2)
def test_free_claimed_device(self):
device.claim(self.devobj, self.inst)
device.free(self.devobj, self.inst)
self.assertEqual(self.devobj.status,
fields.PciDeviceStatus.AVAILABLE)
self.assertIsNone(self.devobj.instance_uuid)
def test_free_allocated_device(self):
device.claim(self.devobj, self.inst)
device.allocate(self.devobj, self.inst)
self.assertEqual(len(self.inst.pci_devices), 1)
device.free(self.devobj, self.inst)
self.assertEqual(len(self.inst.pci_devices), 0)
self.assertEqual(self.devobj.status,
fields.PciDeviceStatus.AVAILABLE)
self.assertIsNone(self.devobj.instance_uuid)
def test_free_device_fail(self):
self.devobj.status = 'removed'
self.assertRaises(exception.PciDeviceInvalidStatus,
device.free, self.devobj)
def test_remove_device(self):
device.remove(self.devobj)
self.assertEqual(self.devobj.status, 'removed')
self.assertIsNone(self.devobj.instance_uuid)
def test_remove_device_fail(self):
device.claim(self.devobj, self.inst)
self.assertRaises(exception.PciDeviceInvalidStatus,
device.remove, self.devobj)

View File

@ -24,7 +24,6 @@ from nova import context
from nova import db
from nova import objects
from nova.objects import fields
from nova.pci import device
from nova.pci import manager
from nova import test
from nova.tests.unit.api.openstack import fakes
@ -291,7 +290,7 @@ class PciDevTrackerTestCase(test.NoDBTestCase):
self.assertEqual(len(self.tracker.pci_devs), 3)
dev = self.tracker.pci_devs[0]
self.update_called = 0
device.remove(dev)
dev.remove()
self.tracker.save(self.fake_context)
self.assertEqual(len(self.tracker.pci_devs), 2)
self.assertEqual(self.destroy_called, 1)