Merge "Add numa_node to PCIDevice"

This commit is contained in:
Jenkins 2015-01-16 22:02:45 +00:00 committed by Gerrit Code Review
commit 83178d91df
15 changed files with 156 additions and 11 deletions

View File

@ -0,0 +1,41 @@
# Copyright 2014 Intel Corporation
# 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.
#
# See blueprint backportable-db-migrations-icehouse
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
from sqlalchemy import MetaData, Table, Column, Integer
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
# Add a new column to store PCI device numa node
pci_devices = Table('pci_devices', meta, autoload=True)
shadow_pci_devices = Table('shadow_pci_devices', meta, autoload=True)
numa_node = Column('numa_node', Integer, default=None)
pci_devices.create_column(numa_node)
shadow_pci_devices.create_column(numa_node.copy())
def downgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
# Remove the numa_node column
pci_devices = Table('pci_devices', meta, autoload=True)
shadow_pci_devices = Table('shadow_pci_devices', meta, autoload=True)
pci_devices.drop_column('numa_node')
shadow_pci_devices.drop_column('numa_node')

View File

@ -1413,6 +1413,9 @@ class PciDevice(BASE, NovaBase):
extra_info = Column(Text)
instance_uuid = Column(String(36))
numa_node = Column(Integer, nullable=True)
instance = orm.relationship(Instance, backref="pci_devices",
foreign_keys=instance_uuid,
primaryjoin='and_('

View File

@ -71,7 +71,8 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject,
# Version 1.0: Initial version
# Version 1.1: String attributes updated to support unicode
# Version 1.2: added request_id field
VERSION = '1.2'
# Version 1.3: Added field to represent PCI device NUMA node
VERSION = '1.3'
fields = {
'id': fields.IntegerField(),
@ -88,6 +89,7 @@ class PciDevice(base.NovaPersistentObject, base.NovaObject,
'instance_uuid': fields.StringField(nullable=True),
'request_id': fields.StringField(nullable=True),
'extra_info': fields.DictOfStringsField(),
'numa_node': fields.IntegerField(nullable=True),
}
def obj_make_compatible(self, primitive, target_version):
@ -188,6 +190,7 @@ class PciDeviceList(base.ObjectListBase, base.NovaObject):
'1.0': '1.1',
# NOTE(danms): PciDevice was at 1.1 before we added this
'1.1': '1.2',
'1.2': '1.3',
}
def __init__(self, *args, **kwargs):

View File

@ -29,6 +29,7 @@ fake_db_dev_1 = {
'compute_node_id': 1,
'address': '0000:04:10.0',
'vendor_id': '8086',
'numa_node': 0,
'product_id': '1520',
'dev_type': 'type-VF',
'status': 'available',
@ -48,6 +49,7 @@ fake_db_dev_2 = {
'compute_node_id': 1,
'address': '0000:04:10.1',
'vendor_id': '8086',
'numa_node': 1,
'product_id': '1520',
'dev_type': 'type-VF',
'status': 'available',

View File

@ -7663,6 +7663,7 @@ class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
'address': '0000:0f:08.7',
'vendor_id': '8086',
'product_id': '1520',
'numa_node': 1,
'dev_type': 'type-VF',
'dev_id': 'pci_0000:0f:08.7',
'extra_info': None,
@ -7675,6 +7676,7 @@ class PciDeviceDBApiTestCase(test.TestCase, ModelsObjectComparatorMixin):
'address': '0000:0f:03.7',
'vendor_id': '8083',
'product_id': '1523',
'numa_node': 0,
'dev_type': 'type-VF',
'dev_id': 'pci_0000:0f:08.7',
'extra_info': None,

View File

@ -561,6 +561,24 @@ class NovaMigrationsCheckers(test_migrations.WalkVersionsMixin):
self.assertColumnNotExists(engine, 'compute_nodes', 'host')
self.assertColumnNotExists(engine, 'shadow_compute_nodes', 'host')
def _check_269(self, engine, data):
self.assertColumnExists(engine, 'pci_devices', 'numa_node')
self.assertColumnExists(engine, 'shadow_pci_devices', 'numa_node')
pci_devices = oslodbutils.get_table(engine, 'pci_devices')
shadow_pci_devices = oslodbutils.get_table(
engine, 'shadow_pci_devices')
self.assertIsInstance(pci_devices.c.numa_node.type,
sqlalchemy.types.Integer)
self.assertTrue(pci_devices.c.numa_node.nullable)
self.assertIsInstance(shadow_pci_devices.c.numa_node.type,
sqlalchemy.types.Integer)
self.assertTrue(shadow_pci_devices.c.numa_node.nullable)
def _post_downgrade_269(self, engine):
self.assertColumnNotExists(engine, 'pci_devices', 'numa_node')
self.assertColumnNotExists(engine, 'shadow_pci_devices', 'numa_node')
class TestNovaMigrationsSQLite(NovaMigrationsCheckers,
test_base.DbTestCase):

View File

@ -606,6 +606,7 @@ class _TestInstanceObject(object):
'compute_node_id': 1,
'address': 'a1',
'vendor_id': 'v1',
'numa_node': 0,
'product_id': 'p1',
'dev_type': 't',
'status': 'allocated',
@ -623,6 +624,7 @@ class _TestInstanceObject(object):
'compute_node_id': 1,
'address': 'a',
'vendor_id': 'v',
'numa_node': 1,
'product_id': 'p',
'dev_type': 't',
'status': 'allocated',

View File

@ -1160,8 +1160,8 @@ object_data = {
'NUMACell': '1.2-cb9c3b08cc1c418d021492f788d04173',
'NUMAPagesTopology': '1.0-97d93f70a68625b5f29ff63a40a4f612',
'NUMATopology': '1.2-790f6bdff85bf6e5677f409f3a4f1c6a',
'PciDevice': '1.2-29e35c3199f3b98ce66e5d1212612818',
'PciDeviceList': '1.1-2896df4f5b06579e5f35adba5fcae9db',
'PciDevice': '1.3-e059641df10e85d464672c5183a9473b',
'PciDeviceList': '1.1-38cbe2d3c23b9e46f7a74b486abcad85',
'PciDevicePool': '1.0-d6ed1abe611c9947345a44155abe6f11',
'PciDevicePoolList': '1.0-d31e08e0ff620a4df7cc2014b6c50da8',
'Quotas': '1.2-36098cf2143e6535873c3fa3d6fe56f7',

View File

@ -26,6 +26,7 @@ dev_dict = {
'address': 'a',
'product_id': 'p',
'vendor_id': 'v',
'numa_node': 0,
'status': 'available'}
@ -39,6 +40,7 @@ fake_db_dev = {
'address': 'a',
'vendor_id': 'v',
'product_id': 'p',
'numa_node': 0,
'dev_type': 't',
'status': 'available',
'dev_id': 'i',
@ -59,6 +61,7 @@ fake_db_dev_1 = {
'address': 'a1',
'vendor_id': 'v1',
'product_id': 'p1',
'numa_node': 1,
'dev_type': 't',
'status': 'available',
'dev_id': 'i',
@ -87,7 +90,7 @@ class _TestPciDeviceObject(object):
self.assertEqual(self.pci_device.product_id, 'p')
self.assertEqual(self.pci_device.obj_what_changed(),
set(['compute_node_id', 'product_id', 'vendor_id',
'status', 'address', 'extra_info']))
'numa_node', 'status', 'address', 'extra_info']))
def test_pci_device_extra_info(self):
self.dev_dict = copy.copy(dev_dict)
@ -99,7 +102,8 @@ class _TestPciDeviceObject(object):
self.assertEqual(set(extra_value.keys()), set(('k1', 'k2')))
self.assertEqual(self.pci_device.obj_what_changed(),
set(['compute_node_id', 'address', 'product_id',
'vendor_id', 'status', 'extra_info']))
'vendor_id', 'numa_node', 'status',
'extra_info']))
def test_update_device(self):
self.pci_device = pci_device.PciDevice.create(dev_dict)
@ -199,6 +203,15 @@ class _TestPciDeviceObject(object):
self.pci_device.save(ctxt)
self.assertEqual(self.called, False)
def test_update_numa_node(self):
self.pci_device = pci_device.PciDevice.create(dev_dict)
self.assertEqual(0, self.pci_device.numa_node)
self.dev_dict = copy.copy(dev_dict)
self.dev_dict['numa_node'] = '1'
self.pci_device = pci_device.PciDevice.create(self.dev_dict)
self.assertEqual(1, self.pci_device.numa_node)
class TestPciDeviceObject(test_objects._LocalTest,
_TestPciDeviceObject):

View File

@ -30,6 +30,7 @@ dev_dict = {
'address': 'a',
'vendor_id': 'v',
'product_id': 'p',
'numa_node': 1,
'dev_type': 't',
'status': 'available',
'dev_id': 'i',

View File

@ -52,6 +52,7 @@ fake_db_dev = {
'address': '0000:00:00.1',
'vendor_id': 'v',
'product_id': 'p',
'numa_node': 1,
'dev_type': 't',
'status': 'available',
'dev_id': 'i',

View File

@ -1974,6 +1974,7 @@ class LibvirtConfigNodeDevicePciCapTest(LibvirtConfigBaseTest):
self.assertEqual(obj.product_id, 0x10bd)
self.assertEqual(obj.vendor, "Intel Inc.")
self.assertEqual(obj.vendor_id, 0x8086)
self.assertIsNone(obj.numa_node)
self.assertIsInstance(obj.fun_capability[0],
config.LibvirtConfigNodeDevicePciSubFunctionCap)
@ -1991,6 +1992,7 @@ class LibvirtConfigNodeDevicePciCapTest(LibvirtConfigBaseTest):
<function>5</function>
<product id="0x10bd">Intel 10 Gigabit Ethernet</product>
<vendor id="0x8086">Intel Inc.</vendor>
<numa node='0'/>
<capability type="virt_functions">
<address domain="0000" bus="0x0a" slot="0x1" function="0x1"/>
<address domain="0001" bus="0x0a" slot="0x02" function="0x03"/>
@ -2010,6 +2012,7 @@ class LibvirtConfigNodeDevicePciCapTest(LibvirtConfigBaseTest):
self.assertEqual(obj.product_id, 0x10bd)
self.assertEqual(obj.vendor, "Intel Inc.")
self.assertEqual(obj.vendor_id, 0x8086)
self.assertEqual(0, obj.numa_node)
self.assertIsInstance(obj.fun_capability[0],
config.LibvirtConfigNodeDevicePciSubFunctionCap)

View File

@ -140,7 +140,8 @@ _fake_NodeDevXml = \
<bus>4</bus>
<slot>16</slot>
<function>7</function>
<product id='0x1520'>I350 Ethernet Controller Virtual Function</product>
<product id='0x1520'>I350 Ethernet Controller Virtual Function
</product>
<vendor id='0x8086'>Intel Corporation</vendor>
<capability type='phys_function'>
<address domain='0x0000' bus='0x04' slot='0x00' function='0x3'/>
@ -148,6 +149,29 @@ _fake_NodeDevXml = \
<capability type='virt_functions'>
</capability>
</capability>
</device>""",
"pci_0000_04_11_7": """
<device>
<name>pci_0000_04_11_7</name>
<parent>pci_0000_00_01_1</parent>
<driver>
<name>igbvf</name>
</driver>
<capability type='pci'>
<domain>0</domain>
<bus>4</bus>
<slot>17</slot>
<function>7</function>
<product id='0x1520'>I350 Ethernet Controller Virtual Function
</product>
<vendor id='0x8086'>Intel Corporation</vendor>
<numa node='0'/>
<capability type='phys_function'>
<address domain='0x0000' bus='0x04' slot='0x00' function='0x3'/>
</capability>
<capability type='virt_functions'>
</capability>
</capability>
</device>"""}
@ -8838,24 +8862,38 @@ class LibvirtConnTestCase(test.NoDBTestCase):
"dev_id": "pci_0000_04_00_3",
"address": "0000:04:00.3",
"product_id": '1521',
"numa_node": None,
"vendor_id": '8086',
"label": 'label_8086_1521',
"dev_type": 'type-PF',
}
self.assertEqual(actualvf, expect_vf)
self.assertEqual(expect_vf, actualvf)
actualvf = conn._get_pcidev_info("pci_0000_04_10_7")
expect_vf = {
"dev_id": "pci_0000_04_10_7",
"address": "0000:04:10.7",
"product_id": '1520',
"numa_node": None,
"vendor_id": '8086',
"label": 'label_8086_1520',
"dev_type": 'type-VF',
"phys_function": '0000:04:00.3',
}
self.assertEqual(expect_vf, actualvf)
actualvf = conn._get_pcidev_info("pci_0000_04_11_7")
expect_vf = {
"dev_id": "pci_0000_04_11_7",
"address": "0000:04:11.7",
"product_id": '1520',
"vendor_id": '8086',
"numa_node": 0,
"label": 'label_8086_1520',
"dev_type": 'type-VF',
"phys_function": '0000:04:00.3',
}
self.assertEqual(actualvf, expect_vf)
self.assertEqual(expect_vf, actualvf)
def test_list_devices_not_supported(self):
conn = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
@ -8889,9 +8927,11 @@ class LibvirtConnTestCase(test.NoDBTestCase):
def test_get_pci_passthrough_devices(self):
def fakelistDevices(caps, fakeargs=0):
return ['pci_0000_04_00_3', 'pci_0000_04_10_7']
return ['pci_0000_04_00_3', 'pci_0000_04_10_7',
'pci_0000_04_11_7']
self.mox.StubOutWithMock(libvirt_driver.LibvirtDriver, '_conn')
libvirt_driver.LibvirtDriver._conn.listDevices = fakelistDevices
def fake_nodeDeviceLookupByName(name):
@ -8909,13 +8949,24 @@ class LibvirtConnTestCase(test.NoDBTestCase):
"product_id": '1521',
"vendor_id": '8086',
"dev_type": 'type-PF',
"phys_function": None},
"phys_function": None,
"numa_node": None},
{
"dev_id": "pci_0000_04_10_7",
"domain": 0,
"address": "0000:04:10.7",
"product_id": '1520',
"vendor_id": '8086',
"numa_node": None,
"dev_type": 'type-VF',
"phys_function": [('0x0000', '0x04', '0x00', '0x3')]},
{
"dev_id": "pci_0000_04_11_7",
"domain": 0,
"address": "0000:04:11.7",
"product_id": '1520',
"vendor_id": '8086',
"numa_node": 0,
"dev_type": 'type-VF',
"phys_function": [('0x0000', '0x04', '0x00', '0x3')],
}
@ -8925,7 +8976,7 @@ class LibvirtConnTestCase(test.NoDBTestCase):
for dev in range(len(actualvfs)):
for key in actualvfs[dev].keys():
if key not in ['phys_function', 'virt_functions', 'label']:
self.assertEqual(actualvfs[dev][key], expectvfs[dev][key])
self.assertEqual(expectvfs[dev][key], actualvfs[dev][key])
def _fake_caps_numa_topology(self):
topology = vconfig.LibvirtConfigCapsNUMATopology()

View File

@ -2004,6 +2004,7 @@ class LibvirtConfigNodeDevicePciCap(LibvirtConfigObject):
self.product_id = None
self.vendor = None
self.vendor_id = None
self.numa_node = None
self.fun_capability = list()
def parse_dom(self, xmldoc):
@ -2024,6 +2025,8 @@ class LibvirtConfigNodeDevicePciCap(LibvirtConfigObject):
elif c.tag == "vendor":
self.vendor = c.text
self.vendor_id = int(c.get('id'), 16)
elif c.tag == "numa":
self.numa_node = int(c.get('node'))
elif c.tag == "capability" and c.get('type') in \
('virt_functions', 'phys_function'):
funcap = LibvirtConfigNodeDevicePciSubFunctionCap()

View File

@ -4719,6 +4719,8 @@ class LibvirtDriver(driver.ComputeDriver):
"vendor_id": "%04x" % cfgdev.pci_capability.vendor_id,
}
device["numa_node"] = cfgdev.pci_capability.numa_node
# requirement by DataBase Model
device['label'] = 'label_%(vendor_id)s_%(product_id)s' % device
device.update(_get_device_type(cfgdev))