Pci Device DB support
Add a new table to store information about available PCI devices on compute nodes and related APIs to fetch and update these devices information. Add a summary PCI device column to compute node table so that scheduler doesn't need joinload to get the PCI information. Co-authored-by: Boris Pavlovic <boris@pavlovic.me> bp:pci-passthrough-base Change-Id:I9ca8fe689a7ef1c4f22dec8640a018c0adff773c
This commit is contained in:
@@ -1471,6 +1471,38 @@ instance_type_extra_specs_update_or_create = \
|
||||
####################
|
||||
|
||||
|
||||
def pci_device_get_by_addr(context, node_id, dev_addr):
|
||||
"""Get PCI device by address."""
|
||||
return IMPL.pci_device_get_by_addr(context, node_id, dev_addr)
|
||||
|
||||
|
||||
def pci_device_get_by_id(context, id):
|
||||
"""Get PCI device by id."""
|
||||
return IMPL.pci_device_get_by_id(context, id)
|
||||
|
||||
|
||||
def pci_device_get_all_by_node(context, node_id):
|
||||
"""Get all PCI devices for one host."""
|
||||
return IMPL.pci_device_get_all_by_node(context, node_id)
|
||||
|
||||
|
||||
def pci_device_get_all_by_instance_uuid(context, instance_uuid):
|
||||
"""Get PCI devices allocated to instance."""
|
||||
return IMPL.pci_device_get_all_by_instance_uuid(context, instance_uuid)
|
||||
|
||||
|
||||
def pci_device_destroy(context, node_id, address):
|
||||
"""Delete a PCI device record."""
|
||||
return IMPL.pci_device_destroy(context, node_id, address)
|
||||
|
||||
|
||||
def pci_device_update(context, node_id, address, value):
|
||||
"""Update a pci device."""
|
||||
return IMPL.pci_device_update(context, node_id, address, value)
|
||||
|
||||
|
||||
###################
|
||||
|
||||
def cell_create(context, values):
|
||||
"""Create a new child Cell entry."""
|
||||
return IMPL.cell_create(context, values)
|
||||
|
||||
@@ -1668,11 +1668,18 @@ def _instances_fill_metadata(context, instances, manual_joins=None):
|
||||
for row in _instance_system_metadata_get_multi(context, uuids):
|
||||
sys_meta[row['instance_uuid']].append(row)
|
||||
|
||||
pcidevs = collections.defaultdict(list)
|
||||
if 'pci_devices' in manual_joins:
|
||||
for row in _instance_pcidevs_get_multi(context, uuids):
|
||||
pcidevs[row['instance_uuid']].append(row)
|
||||
|
||||
filled_instances = []
|
||||
for inst in instances:
|
||||
inst = dict(inst.iteritems())
|
||||
inst['system_metadata'] = sys_meta[inst['uuid']]
|
||||
inst['metadata'] = meta[inst['uuid']]
|
||||
if 'pci_devices' in manual_joins:
|
||||
inst['pci_devices'] = pcidevs[inst['uuid']]
|
||||
filled_instances.append(inst)
|
||||
|
||||
return filled_instances
|
||||
@@ -1680,7 +1687,7 @@ def _instances_fill_metadata(context, instances, manual_joins=None):
|
||||
|
||||
def _manual_join_columns(columns_to_join):
|
||||
manual_joins = []
|
||||
for column in ('metadata', 'system_metadata'):
|
||||
for column in ('metadata', 'system_metadata', 'pci_devices'):
|
||||
if column in columns_to_join:
|
||||
columns_to_join.remove(column)
|
||||
manual_joins.append(column)
|
||||
@@ -5774,3 +5781,74 @@ def instance_group_policies_get(context, group_uuid):
|
||||
base_model=models.InstanceGroupPolicy).\
|
||||
filter_by(group_id=id).all()
|
||||
return [policy[0] for policy in policies]
|
||||
|
||||
|
||||
####################
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def pci_device_get_by_addr(context, node_id, dev_addr):
|
||||
pci_dev_ref = model_query(context, models.PciDevice).\
|
||||
filter_by(compute_node_id=node_id).\
|
||||
filter_by(address=dev_addr).\
|
||||
first()
|
||||
if not pci_dev_ref:
|
||||
raise exception.PciDeviceNotFound(node_id=node_id, address=dev_addr)
|
||||
return pci_dev_ref
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def pci_device_get_by_id(context, id):
|
||||
pci_dev_ref = model_query(context, models.PciDevice).\
|
||||
filter_by(id=id).\
|
||||
first()
|
||||
if not pci_dev_ref:
|
||||
raise exception.PciDeviceNotFoundById(id=id)
|
||||
return pci_dev_ref
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def pci_device_get_all_by_node(context, node_id):
|
||||
return model_query(context, models.PciDevice).\
|
||||
filter_by(compute_node_id=node_id).\
|
||||
all()
|
||||
|
||||
|
||||
@require_context
|
||||
def pci_device_get_all_by_instance_uuid(context, instance_uuid):
|
||||
return model_query(context, models.PciDevice).\
|
||||
filter_by(status='allocated').\
|
||||
filter_by(instance_uuid=instance_uuid).\
|
||||
all()
|
||||
|
||||
|
||||
def _instance_pcidevs_get_multi(context, instance_uuids, session=None):
|
||||
return model_query(context, models.PciDevice, session=session).\
|
||||
filter_by(status='allocated').\
|
||||
filter(models.PciDevice.instance_uuid.in_(instance_uuids))
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def pci_device_destroy(context, node_id, address):
|
||||
result = model_query(context, models.PciDevice).\
|
||||
filter_by(compute_node_id=node_id).\
|
||||
filter_by(address=address).\
|
||||
soft_delete()
|
||||
if not result:
|
||||
raise exception.PciDeviceNotFound(node_id=node_id, address=address)
|
||||
|
||||
|
||||
@require_admin_context
|
||||
def pci_device_update(context, node_id, address, values):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
device = model_query(context, models.PciDevice, session=session,
|
||||
read_deleted="no").\
|
||||
filter_by(compute_node_id=node_id).\
|
||||
filter_by(address=address).\
|
||||
first()
|
||||
if not device:
|
||||
device = models.PciDevice()
|
||||
device.update(values)
|
||||
session.add(device)
|
||||
return device
|
||||
|
||||
108
nova/db/sqlalchemy/migrate_repo/versions/213_add_pci_devices.py
Normal file
108
nova/db/sqlalchemy/migrate_repo/versions/213_add_pci_devices.py
Normal file
@@ -0,0 +1,108 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2013 OpenStack Foundation
|
||||
# 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.
|
||||
# @author: Boris Pavlovic, Mirantis Inc
|
||||
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import DateTime
|
||||
from sqlalchemy import Index
|
||||
from sqlalchemy import Integer
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Table
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import UniqueConstraint
|
||||
|
||||
from nova.db.sqlalchemy import api
|
||||
from nova.db.sqlalchemy import utils
|
||||
from nova.openstack.common.gettextutils import _
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData(bind=migrate_engine)
|
||||
|
||||
pci_devices_uc_name = 'uniq_pci_devices0compute_node_id0address0deleted'
|
||||
pci_devices = Table('pci_devices', meta,
|
||||
Column('created_at', DateTime(timezone=False)),
|
||||
Column('updated_at', DateTime(timezone=False)),
|
||||
Column('deleted_at', DateTime(timezone=False)),
|
||||
Column('deleted', Integer, default=0, nullable=False),
|
||||
Column('id', Integer, primary_key=True),
|
||||
Column('compute_node_id', Integer, nullable=False),
|
||||
Column('address', String(12), nullable=False),
|
||||
Column('product_id', String(4)),
|
||||
Column('vendor_id', String(4)),
|
||||
Column('dev_type', String(8)),
|
||||
Column('dev_id', String(255)),
|
||||
Column('label', String(255), nullable=False),
|
||||
Column('status', String(36), nullable=False),
|
||||
Column('extra_info', Text, nullable=True),
|
||||
Column('instance_uuid', String(36), nullable=True),
|
||||
Index('ix_pci_devices_compute_node_id_deleted',
|
||||
'compute_node_id', 'deleted'),
|
||||
Index('ix_pci_devices_instance_uuid_deleted',
|
||||
'instance_uuid', 'deleted'),
|
||||
UniqueConstraint('compute_node_id',
|
||||
'address', 'deleted',
|
||||
name=pci_devices_uc_name),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8')
|
||||
|
||||
try:
|
||||
pci_devices.create()
|
||||
utils.create_shadow_table(migrate_engine, table=pci_devices)
|
||||
except Exception:
|
||||
LOG.exception(_("Exception while creating table 'pci_devices'."))
|
||||
raise
|
||||
|
||||
try:
|
||||
compute_nodes = utils.get_table(migrate_engine, 'compute_nodes')
|
||||
pci_stats = Column('pci_stats', Text, nullable=True)
|
||||
compute_nodes.create_column(pci_stats)
|
||||
shadow_compute_nodes = utils.get_table(
|
||||
migrate_engine, api._SHADOW_TABLE_PREFIX + 'compute_nodes')
|
||||
shadow_compute_nodes.create_column(pci_stats.copy())
|
||||
except Exception:
|
||||
LOG.exception(_("Exception for adding pci stats to compute node."))
|
||||
raise
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData(bind=migrate_engine)
|
||||
|
||||
try:
|
||||
pci_device = Table('pci_devices', meta, autoload=True)
|
||||
pci_device.drop()
|
||||
shadow_pci_device = Table(api._SHADOW_TABLE_PREFIX + 'pci_devices',
|
||||
meta, autoload=True)
|
||||
shadow_pci_device.drop()
|
||||
except Exception:
|
||||
LOG.exception(_("Exception while dropping 'pci_devices' tables."))
|
||||
raise
|
||||
|
||||
try:
|
||||
compute_nodes = utils.get_table(migrate_engine, 'compute_nodes')
|
||||
compute_nodes.drop_column('pci_stats')
|
||||
shadow_compute_nodes = utils.get_table(
|
||||
migrate_engine, api._SHADOW_TABLE_PREFIX + 'compute_nodes')
|
||||
shadow_compute_nodes.drop_column('pci_stats')
|
||||
except Exception:
|
||||
LOG.exception(_("Exception for dropping pci stats from compute node."))
|
||||
raise
|
||||
@@ -112,6 +112,10 @@ class ComputeNode(BASE, NovaBase):
|
||||
host_ip = Column(types.IPAddress())
|
||||
supported_instances = Column(Text)
|
||||
|
||||
# Note(yongli): json string PCI Stats
|
||||
# '{"vendor_id":"8086", "product_id":"1234", "count":3 }'
|
||||
pci_stats = Column(Text, nullable=True)
|
||||
|
||||
|
||||
class ComputeNodeStat(BASE, NovaBase):
|
||||
"""Stats related to the current workload of a compute host that are
|
||||
@@ -1365,3 +1369,46 @@ class InstanceGroup(BASE, NovaBase):
|
||||
@property
|
||||
def members(self):
|
||||
return [m.instance_id for m in self._members]
|
||||
|
||||
|
||||
class PciDevice(BASE, NovaBase):
|
||||
"""
|
||||
Represents a PCI host device that can be passed through to instances.
|
||||
"""
|
||||
__tablename__ = 'pci_devices'
|
||||
__table_args__ = (
|
||||
Index('ix_pci_devices_compute_node_id_deleted',
|
||||
'compute_node_id', 'deleted'),
|
||||
Index('ix_pci_devices_instance_uuid_deleted',
|
||||
'instance_uuid', 'deleted'),
|
||||
schema.UniqueConstraint(
|
||||
"compute_node_id", "address", "deleted",
|
||||
name="uniq_pci_devices0compute_node_id0address0deleted")
|
||||
)
|
||||
id = Column(Integer, primary_key=True)
|
||||
|
||||
compute_node_id = Column(Integer, ForeignKey('compute_nodes.id'),
|
||||
nullable=False)
|
||||
|
||||
# physical address of device domain:bus:slot.func (0000:09:01.1)
|
||||
address = Column(String(12), nullable=False)
|
||||
|
||||
vendor_id = Column(String(4), nullable=False)
|
||||
product_id = Column(String(4), nullable=False)
|
||||
dev_type = Column(String(8), nullable=False)
|
||||
dev_id = Column(String(255), nullable=True)
|
||||
|
||||
# label is abstract device name, that is used to unify devices with the
|
||||
# same functionality with different addresses or host.
|
||||
label = Column(String(255), nullable=False)
|
||||
|
||||
status = Column(String(36), nullable=False)
|
||||
|
||||
extra_info = Column(Text, nullable=True)
|
||||
|
||||
instance_uuid = Column(String(36), nullable=True)
|
||||
instance = relationship(Instance, backref="pci_devices",
|
||||
foreign_keys=instance_uuid,
|
||||
primaryjoin='and_('
|
||||
'PciDevice.instance_uuid == Instance.uuid,'
|
||||
'PciDevice.deleted == 0)')
|
||||
|
||||
@@ -1368,3 +1368,11 @@ class ImageDownloadModuleConfigurationError(ImageDownloadModuleError):
|
||||
|
||||
class PciDeviceWrongAddressFormat(NovaException):
|
||||
msg_fmt = _("The PCI address %(address)s has an incorrect format.")
|
||||
|
||||
|
||||
class PciDeviceNotFoundById(NotFound):
|
||||
msg_fmt = _("PCI device %(id)s not found")
|
||||
|
||||
|
||||
class PciDeviceNotFound(NovaException):
|
||||
msg_fmt = _("PCI Device %(node_id)s:%(address)s not found.")
|
||||
|
||||
@@ -1564,7 +1564,8 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
result = db.instance_get_all_by_filters(self.ctxt, {})
|
||||
self._assertEqualListsOfObjects([inst1, inst2], result,
|
||||
ignored_keys=['metadata', 'system_metadata',
|
||||
'deleted', 'deleted_at', 'info_cache'])
|
||||
'deleted', 'deleted_at', 'info_cache',
|
||||
'pci_devices'])
|
||||
|
||||
def test_instance_get_all_by_filters_deleted_and_soft_deleted(self):
|
||||
inst1 = self.create_instance_with_args()
|
||||
@@ -1575,7 +1576,8 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
{'deleted': True})
|
||||
self._assertEqualListsOfObjects([inst1, inst2], result,
|
||||
ignored_keys=['metadata', 'system_metadata',
|
||||
'deleted', 'deleted_at', 'info_cache'])
|
||||
'deleted', 'deleted_at', 'info_cache',
|
||||
'pci_devices'])
|
||||
|
||||
def test_instance_get_all_by_filters_deleted_no_soft_deleted(self):
|
||||
inst1 = self.create_instance_with_args()
|
||||
@@ -1587,7 +1589,7 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
'soft_deleted': False})
|
||||
self._assertEqualListsOfObjects([inst1], result,
|
||||
ignored_keys=['deleted', 'deleted_at', 'metadata',
|
||||
'system_metadata', 'info_cache'])
|
||||
'system_metadata', 'info_cache', 'pci_devices'])
|
||||
|
||||
def test_instance_get_all_by_filters_alive_and_soft_deleted(self):
|
||||
inst1 = self.create_instance_with_args()
|
||||
@@ -1632,7 +1634,7 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
results = db.instance_get_all_hung_in_rebooting(self.ctxt, 10)
|
||||
self._assertEqualListsOfObjects([instance], results,
|
||||
ignored_keys=['task_state', 'info_cache', 'security_groups',
|
||||
'metadata', 'system_metadata'])
|
||||
'metadata', 'system_metadata', 'pci_devices'])
|
||||
db.instance_update(self.ctxt, instance['uuid'], {"task_state": None})
|
||||
|
||||
# Ensure the newly rebooted instance is not returned.
|
||||
@@ -3312,7 +3314,8 @@ class FixedIPTestCase(BaseInstanceTypeTestCase):
|
||||
# Instance check here
|
||||
instance_data = db.instance_get_by_uuid(self.ctxt, instance_uuid)
|
||||
ignored_keys = ['info_cache', 'system_metadata',
|
||||
'security_groups', 'metadata'] # HOW ????
|
||||
'security_groups', 'metadata',
|
||||
'pci_devices'] # HOW ????
|
||||
self._assertEqualObjects(instance_data, fixed_ip_data[2], ignored_keys)
|
||||
|
||||
def test_fixed_ip_update_not_found_for_address(self):
|
||||
@@ -5106,7 +5109,8 @@ class ComputeNodeTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
disk_available_least=100,
|
||||
hypervisor_hostname='abracadabra104',
|
||||
host_ip='127.0.0.1',
|
||||
supported_instances='')
|
||||
supported_instances='',
|
||||
pci_stats='')
|
||||
# add some random stats
|
||||
self.stats = dict(num_instances=3, num_proj_12345=2,
|
||||
num_proj_23456=2, num_vm_building=3)
|
||||
@@ -6513,3 +6517,169 @@ class InstanceGroupPoliciesDBApiTestCase(InstanceGroupDBApiTestCase):
|
||||
self.assertRaises(exception.InstanceGroupPolicyNotFound,
|
||||
db.instance_group_policy_delete,
|
||||
self.context, id, 'invalid_policy')
|
||||
|
||||
|
||||
class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
|
||||
def setUp(self):
|
||||
super(PciDeviceDBApiTestCase, self).setUp()
|
||||
self.user_id = 'fake_user'
|
||||
self.project_id = 'fake_project'
|
||||
self.context = context.RequestContext(self.user_id, self.project_id)
|
||||
self.admin_context = context.get_admin_context()
|
||||
self.ignored_keys = ['id', 'deleted', 'deleted_at', 'updated_at',
|
||||
'created_at']
|
||||
|
||||
def _get_fake_pci_devs(self):
|
||||
return {'id': 3353,
|
||||
'compute_node_id': 1,
|
||||
'address': '0000:0f:08:07',
|
||||
'vendor_id': '8086',
|
||||
'product_id': '1520',
|
||||
'dev_type': 'type-VF',
|
||||
'dev_id': 'pci_0000:0f:08:07',
|
||||
'extra_info': None,
|
||||
'label': 'label_8086_1520',
|
||||
'status': 'available',
|
||||
'instance_uuid': '00000000-0000-0000-0000-000000000010',
|
||||
}, {'id': 3356,
|
||||
'compute_node_id': 1,
|
||||
'address': '0000:0f:03:07',
|
||||
'vendor_id': '8083',
|
||||
'product_id': '1523',
|
||||
'dev_type': 'type-VF',
|
||||
'dev_id': 'pci_0000:0f:08:07',
|
||||
'extra_info': None,
|
||||
'label': 'label_8086_1520',
|
||||
'status': 'available',
|
||||
'instance_uuid': '00000000-0000-0000-0000-000000000010',
|
||||
}
|
||||
|
||||
def _create_fake_pci_devs(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
db.pci_device_update(self.admin_context, v2['compute_node_id'],
|
||||
v2['address'], v2)
|
||||
return (v1, v2)
|
||||
|
||||
def test_pci_device_get_by_addr(self):
|
||||
v1, v2 = self._create_fake_pci_devs()
|
||||
result = db.pci_device_get_by_addr(self.admin_context, 1,
|
||||
'0000:0f:08:07')
|
||||
self._assertEqualObjects(v1, result, self.ignored_keys)
|
||||
|
||||
def test_pci_device_get_by_addr_not_found(self):
|
||||
self._create_fake_pci_devs()
|
||||
self.assertRaises(exception.PciDeviceNotFound,
|
||||
db.pci_device_get_by_addr, self.admin_context,
|
||||
1, '0000:0f:08:09')
|
||||
|
||||
def test_pci_device_get_by_addr_low_priv(self):
|
||||
self._create_fake_pci_devs()
|
||||
self.assertRaises(exception.AdminRequired,
|
||||
db.pci_device_get_by_addr,
|
||||
self.context, 1, '0000:0f:08:07')
|
||||
|
||||
def test_pci_device_get_by_id(self):
|
||||
v1, v2 = self._create_fake_pci_devs()
|
||||
result = db.pci_device_get_by_id(self.admin_context, 3353)
|
||||
ignored_keys = ['id', 'deleted', 'deleted_at', 'updated_at',
|
||||
'created_at']
|
||||
self._assertEqualObjects(v1, result, self.ignored_keys)
|
||||
|
||||
def test_pci_device_get_by_id_not_found(self):
|
||||
self._create_fake_pci_devs()
|
||||
self.assertRaises(exception.PciDeviceNotFoundById,
|
||||
db.pci_device_get_by_id,
|
||||
self.admin_context, 3354)
|
||||
|
||||
def test_pci_device_get_by_id_low_priv(self):
|
||||
self._create_fake_pci_devs()
|
||||
self.assertRaises(exception.AdminRequired,
|
||||
db.pci_device_get_by_id,
|
||||
self.context, 3553)
|
||||
|
||||
def test_pci_device_get_all_by_node(self):
|
||||
v1, v2 = self._create_fake_pci_devs()
|
||||
results = db.pci_device_get_all_by_node(self.admin_context, 1)
|
||||
self._assertEqualListsOfObjects(results, [v1, v2], self.ignored_keys)
|
||||
|
||||
def test_pci_device_get_all_by_node_empty(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
results = db.pci_device_get_all_by_node(self.admin_context, 9)
|
||||
self.assertEqual(len(results), 0)
|
||||
|
||||
def test_pci_device_get_all_by_node_low_priv(self):
|
||||
self._create_fake_pci_devs()
|
||||
self.assertRaises(exception.AdminRequired,
|
||||
db.pci_device_get_all_by_node,
|
||||
self.context, 1)
|
||||
|
||||
def test_pci_device_get_by_instance_uuid(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
v1['status'] = 'allocated'
|
||||
v2['status'] = 'allocated'
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
db.pci_device_update(self.admin_context, v2['compute_node_id'],
|
||||
v2['address'], v2)
|
||||
results = db.pci_device_get_all_by_instance_uuid(
|
||||
self.context,
|
||||
'00000000-0000-0000-0000-000000000010')
|
||||
self._assertEqualListsOfObjects(results, [v1, v2], self.ignored_keys)
|
||||
|
||||
def test_pci_device_get_by_instance_uuid_check_status(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
v1['status'] = 'allocated'
|
||||
v2['status'] = 'claimed'
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
db.pci_device_update(self.admin_context, v2['compute_node_id'],
|
||||
v2['address'], v2)
|
||||
results = db.pci_device_get_all_by_instance_uuid(
|
||||
self.context,
|
||||
'00000000-0000-0000-0000-000000000010')
|
||||
self._assertEqualListsOfObjects(results, [v1], self.ignored_keys)
|
||||
|
||||
def test_pci_device_update(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
v1['status'] = 'allocated'
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
result = db.pci_device_get_by_addr(
|
||||
self.admin_context, 1, '0000:0f:08:07')
|
||||
self._assertEqualObjects(v1, result, self.ignored_keys)
|
||||
|
||||
v1['status'] = 'claimed'
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
result = db.pci_device_get_by_addr(
|
||||
self.admin_context, 1, '0000:0f:08:07')
|
||||
self._assertEqualObjects(v1, result, self.ignored_keys)
|
||||
|
||||
def test_pci_device_update_low_priv(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
self.assertRaises(exception.AdminRequired,
|
||||
db.pci_device_update, self.context,
|
||||
v1['compute_node_id'], v1['address'], v1)
|
||||
|
||||
def test_pci_device_destroy(self):
|
||||
v1, v2 = self._create_fake_pci_devs()
|
||||
results = db.pci_device_get_all_by_node(self.admin_context, 1)
|
||||
self._assertEqualListsOfObjects(results, [v1, v2], self.ignored_keys)
|
||||
db.pci_device_destroy(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'])
|
||||
results = db.pci_device_get_all_by_node(self.admin_context, 1)
|
||||
self._assertEqualListsOfObjects(results, [v2], self.ignored_keys)
|
||||
|
||||
def test_pci_device_destroy_exception(self):
|
||||
v1, v2 = self._get_fake_pci_devs()
|
||||
db.pci_device_update(self.admin_context, v1['compute_node_id'],
|
||||
v1['address'], v1)
|
||||
results = db.pci_device_get_all_by_node(self.admin_context, 1)
|
||||
self._assertEqualListsOfObjects(results, [v1], self.ignored_keys)
|
||||
self.assertRaises(exception.PciDeviceNotFound,
|
||||
db.pci_device_destroy,
|
||||
self.admin_context,
|
||||
v2['compute_node_id'],
|
||||
v2['address'])
|
||||
|
||||
@@ -2835,6 +2835,53 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn):
|
||||
if engine.name == 'mysql':
|
||||
self._212(engine)
|
||||
|
||||
def _pre_upgrade_213(self, engine):
|
||||
self.assertRaises(sqlalchemy.exc.NoSuchTableError,
|
||||
db_utils.get_table, engine,
|
||||
'pci_devices')
|
||||
|
||||
def _check_213(self, engine, data):
|
||||
fake_pci = {'id': 3353,
|
||||
'compute_node_id': 1,
|
||||
'dev_id': 'pci_0000:0f:08:07',
|
||||
'address': '0000:0f:08:7',
|
||||
'product_id': '8086',
|
||||
'vendor_id': '1520',
|
||||
'dev_type': 'type-VF',
|
||||
'label': 'label_8086_1520',
|
||||
'status': 'available',
|
||||
'extra_info': None,
|
||||
'deleted': 0,
|
||||
'instance_uuid': '00000000-0000-0000-0000-000000000010',
|
||||
}
|
||||
devs = db_utils.get_table(engine, 'pci_devices')
|
||||
engine.execute(devs.insert(), fake_pci)
|
||||
result = devs.select().execute().fetchall()
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0]['vendor_id'], '1520')
|
||||
fake_node = dict(vcpus=2, memory_mb=1024, local_gb=2048,
|
||||
vcpus_used=0, memory_mb_used=0,
|
||||
local_gb_used=0, free_ram_mb=1024,
|
||||
free_disk_gb=2048, hypervisor_type="xen",
|
||||
hypervisor_version=1, cpu_info="",
|
||||
running_vms=0, current_workload=0,
|
||||
service_id=1,
|
||||
disk_available_least=100,
|
||||
hypervisor_hostname='abracadabra104',
|
||||
host_ip='127.0.0.1',
|
||||
supported_instances='')
|
||||
nodes = db_utils.get_table(engine, 'compute_nodes')
|
||||
engine.execute(nodes.insert(), fake_node)
|
||||
result = nodes.select().execute().fetchall()
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0]['pci_stats'], None)
|
||||
|
||||
def _post_downgrade_213(self, engine):
|
||||
# check that groups does not exist
|
||||
self.assertRaises(sqlalchemy.exc.NoSuchTableError,
|
||||
db_utils.get_table, engine,
|
||||
'pci_devices')
|
||||
|
||||
|
||||
class TestBaremetalMigrations(BaseMigrationTestCase, CommonTestsMixIn):
|
||||
"""Test sqlalchemy-migrate migrations."""
|
||||
|
||||
Reference in New Issue
Block a user