Add pci_device_pools to ComputeNode object
The compute_nodes table has a field called pci_stats that is used to pass pci device availability to the scheduler. The pci device data is obtained by the virt drivers and passed to the resource tracker in the available resource data. The resource tracker creates pci device pools to track the number of similar devices as a resource. The pci_stats field contains the pci pool data. A new object versioned called PciDevicePool has been created for the pci device pool data. The pci_device_pools field is added to the ComputeNode object as a PciDevicePoolList object. The type of the field is: ObjectField('PciDevicePoolList') The format that the PciDevicePool object uses to store data in the database is made backward compatible with the existing format. There was an alternative patch by yjiang5 that does not version the data in the field, this patch replaces that one. The original can be found here Ifde89b209f2fcc2283894195b1e7e866cf28dccb Co-Authored-By: Paul Murray <pmurray@hp.com> Co-Authored-By: yunhong-jiang <yunhong-jiang@intel.com> Co-Authored-By: Ed Leafe <ed@leafe.com> Change-Id: I625f13061fddfb0cdb16c8e36336656b40696447
This commit is contained in:
parent
fec5ff1294
commit
6fbf84b8a4
|
@ -49,6 +49,7 @@ def register_all():
|
|||
__import__('nova.objects.network_request')
|
||||
__import__('nova.objects.numa')
|
||||
__import__('nova.objects.pci_device')
|
||||
__import__('nova.objects.pci_device_pool')
|
||||
__import__('nova.objects.tag')
|
||||
__import__('nova.objects.quotas')
|
||||
__import__('nova.objects.security_group')
|
||||
|
|
|
@ -19,6 +19,7 @@ from nova import exception
|
|||
from nova import objects
|
||||
from nova.objects import base
|
||||
from nova.objects import fields
|
||||
from nova.objects import pci_device_pool
|
||||
from nova import utils
|
||||
|
||||
|
||||
|
@ -32,7 +33,8 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
# Version 1.6: Added supported_hv_specs
|
||||
# Version 1.7: Added host field
|
||||
# Version 1.8: Added get_by_host_and_nodename()
|
||||
VERSION = '1.8'
|
||||
# Version 1.9: Added pci_device_pools
|
||||
VERSION = '1.9'
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(read_only=True),
|
||||
|
@ -60,9 +62,14 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
# NOTE(pmurray): the supported_hv_specs field maps to the
|
||||
# supported_instances field in the database
|
||||
'supported_hv_specs': fields.ListOfObjectsField('HVSpec'),
|
||||
# NOTE(pmurray): the pci_device_pools field maps to the
|
||||
# pci_stats field in the database
|
||||
'pci_device_pools': fields.ObjectField('PciDevicePoolList',
|
||||
nullable=True),
|
||||
}
|
||||
|
||||
obj_relationships = {
|
||||
'pci_device_pools': [('1.9', '1.0')],
|
||||
'supported_hv_specs': [('1.6', '1.0')],
|
||||
}
|
||||
|
||||
|
@ -110,9 +117,13 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
|
||||
@staticmethod
|
||||
def _from_db_object(context, compute, db_compute):
|
||||
|
||||
fields = set(compute.fields) - set(['stats', 'supported_hv_specs',
|
||||
'host'])
|
||||
special_cases = set([
|
||||
'stats',
|
||||
'supported_hv_specs',
|
||||
'host',
|
||||
'pci_device_pools',
|
||||
])
|
||||
fields = set(compute.fields) - special_cases
|
||||
for key in fields:
|
||||
compute[key] = db_compute[key]
|
||||
|
||||
|
@ -127,6 +138,8 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
for hv_spec in hv_specs]
|
||||
compute['supported_hv_specs'] = hv_specs
|
||||
|
||||
pci_stats = db_compute.get('pci_stats')
|
||||
compute.pci_device_pools = pci_device_pool.from_pci_stats(pci_stats)
|
||||
compute._context = context
|
||||
|
||||
# Make sure that we correctly set the host field depending on either
|
||||
|
@ -165,22 +178,31 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
db_compute['host'] = service.host
|
||||
return cls._from_db_object(context, cls(), db_compute)
|
||||
|
||||
def _convert_stats_to_db_format(self, updates):
|
||||
@staticmethod
|
||||
def _convert_stats_to_db_format(updates):
|
||||
stats = updates.pop('stats', None)
|
||||
if stats is not None:
|
||||
updates['stats'] = jsonutils.dumps(stats)
|
||||
|
||||
def _convert_host_ip_to_db_format(self, updates):
|
||||
@staticmethod
|
||||
def _convert_host_ip_to_db_format(updates):
|
||||
host_ip = updates.pop('host_ip', None)
|
||||
if host_ip:
|
||||
updates['host_ip'] = str(host_ip)
|
||||
|
||||
def _convert_supported_instances_to_db_format(selfself, updates):
|
||||
@staticmethod
|
||||
def _convert_supported_instances_to_db_format(updates):
|
||||
hv_specs = updates.pop('supported_hv_specs', None)
|
||||
if hv_specs is not None:
|
||||
hv_specs = [hv_spec.to_list() for hv_spec in hv_specs]
|
||||
updates['supported_instances'] = jsonutils.dumps(hv_specs)
|
||||
|
||||
@staticmethod
|
||||
def _convert_pci_stats_to_db_format(updates):
|
||||
pools = updates.pop('pci_device_pools', None)
|
||||
if pools:
|
||||
updates['pci_stats'] = jsonutils.dumps(pools.obj_to_primitive())
|
||||
|
||||
@base.remotable
|
||||
def create(self, context):
|
||||
if self.obj_attr_is_set('id'):
|
||||
|
@ -190,6 +212,7 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
self._convert_stats_to_db_format(updates)
|
||||
self._convert_host_ip_to_db_format(updates)
|
||||
self._convert_supported_instances_to_db_format(updates)
|
||||
self._convert_pci_stats_to_db_format(updates)
|
||||
|
||||
db_compute = db.compute_node_create(context, updates)
|
||||
self._from_db_object(context, self, db_compute)
|
||||
|
@ -203,6 +226,7 @@ class ComputeNode(base.NovaPersistentObject, base.NovaObject):
|
|||
self._convert_stats_to_db_format(updates)
|
||||
self._convert_host_ip_to_db_format(updates)
|
||||
self._convert_supported_instances_to_db_format(updates)
|
||||
self._convert_pci_stats_to_db_format(updates)
|
||||
|
||||
db_compute = db.compute_node_update(context, self.id, updates)
|
||||
self._from_db_object(context, self, db_compute)
|
||||
|
@ -230,7 +254,8 @@ class ComputeNodeList(base.ObjectListBase, base.NovaObject):
|
|||
# Version 1.6 ComputeNode version 1.6
|
||||
# Version 1.7 ComputeNode version 1.7
|
||||
# Version 1.8 ComputeNode version 1.8 + add get_all_by_host()
|
||||
VERSION = '1.8'
|
||||
# Version 1.9 ComputeNode version 1.9
|
||||
VERSION = '1.9'
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('ComputeNode'),
|
||||
}
|
||||
|
@ -245,6 +270,7 @@ class ComputeNodeList(base.ObjectListBase, base.NovaObject):
|
|||
'1.6': '1.6',
|
||||
'1.7': '1.7',
|
||||
'1.8': '1.8',
|
||||
'1.9': '1.9',
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
# 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
|
||||
|
||||
from oslo.serialization import jsonutils
|
||||
import six
|
||||
|
||||
from nova import objects
|
||||
from nova.objects import base
|
||||
from nova.objects import fields
|
||||
|
||||
|
||||
class PciDevicePool(base.NovaObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'product_id': fields.StringField(),
|
||||
'vendor_id': fields.StringField(),
|
||||
'tags': fields.DictOfNullableStringsField(),
|
||||
'count': fields.IntegerField(),
|
||||
}
|
||||
|
||||
# NOTE(pmurray): before this object existed the pci device pool data was
|
||||
# stored as a dict. For backward compatibility we need to be able to read
|
||||
# it in from a dict
|
||||
@classmethod
|
||||
def from_dict(cls, value):
|
||||
pool_dict = copy.copy(value)
|
||||
pool = cls()
|
||||
pool.vendor_id = pool_dict.pop("vendor_id")
|
||||
pool.product_id = pool_dict.pop("product_id")
|
||||
pool.count = pool_dict.pop("count")
|
||||
pool.tags = {}
|
||||
pool.tags.update(pool_dict)
|
||||
return pool
|
||||
|
||||
|
||||
class PciDevicePoolList(base.ObjectListBase, base.NovaObject):
|
||||
# Version 1.0: Initial verison
|
||||
# PciDevicePool <= 1.0
|
||||
VERSION = '1.0'
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('PciDevicePool'),
|
||||
}
|
||||
child_versions = {
|
||||
'1.0': '1.0',
|
||||
}
|
||||
|
||||
|
||||
def from_pci_stats(pci_stats):
|
||||
"""Create and return a PciDevicePoolList from the data stored in the db,
|
||||
which can be either the serialized object, or, prior to the creation of the
|
||||
device pool objects, a simple dict or a list of such dicts.
|
||||
"""
|
||||
pools = None
|
||||
if isinstance(pci_stats, six.string_types):
|
||||
try:
|
||||
pci_stats = jsonutils.loads(pci_stats)
|
||||
except (ValueError, TypeError):
|
||||
pci_stats = None
|
||||
if pci_stats:
|
||||
# Check for object-ness, or old-style storage format.
|
||||
if 'nova_object.namespace' in pci_stats:
|
||||
pools = objects.PciDevicePoolList.obj_from_primitive(pci_stats)
|
||||
else:
|
||||
# This can be either a dict or a list of dicts
|
||||
if isinstance(pci_stats, list):
|
||||
pool_list = [objects.PciDevicePool.from_dict(stat)
|
||||
for stat in pci_stats]
|
||||
else:
|
||||
pool_list = [objects.PciDevicePool.from_dict(pci_stats)]
|
||||
pools = objects.PciDevicePoolList(objects=pool_list)
|
||||
return pools
|
|
@ -33,7 +33,8 @@ class Service(base.NovaPersistentObject, base.NovaObject):
|
|||
# Version 1.5: ComputeNode version 1.6
|
||||
# Version 1.6: ComputeNode version 1.7
|
||||
# Version 1.7: ComputeNode version 1.8
|
||||
VERSION = '1.7'
|
||||
# Version 1.8: ComputeNode version 1.9
|
||||
VERSION = '1.8'
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(read_only=True),
|
||||
|
@ -49,7 +50,7 @@ class Service(base.NovaPersistentObject, base.NovaObject):
|
|||
|
||||
obj_relationships = {
|
||||
'compute_node': [('1.1', '1.4'), ('1.3', '1.5'), ('1.5', '1.6'),
|
||||
('1.7', '1.8')],
|
||||
('1.7', '1.8'), ('1.8', '1.9')],
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
@ -143,7 +144,8 @@ class ServiceList(base.ObjectListBase, base.NovaObject):
|
|||
# Version 1.3: Service version 1.5
|
||||
# Version 1.4: Service version 1.6
|
||||
# Version 1.5: Service version 1.7
|
||||
VERSION = '1.5'
|
||||
# Version 1.6: Service version 1.8
|
||||
VERSION = '1.6'
|
||||
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('Service'),
|
||||
|
@ -156,6 +158,7 @@ class ServiceList(base.ObjectListBase, base.NovaObject):
|
|||
'1.3': '1.5',
|
||||
'1.4': '1.6',
|
||||
'1.5': '1.7',
|
||||
'1.6': '1.8',
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright 2014 IBM Corp.
|
||||
# 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.objects import pci_device_pool
|
||||
|
||||
|
||||
# This represents the format that PCI device pool info was stored in the DB
|
||||
# before this info was made into objects.
|
||||
fake_pool_dict = {
|
||||
'product_id': 'fake-product',
|
||||
'vendor_id': 'fake-vendor',
|
||||
't1': 'v1',
|
||||
't2': 'v2',
|
||||
'count': 2,
|
||||
}
|
||||
|
||||
fake_pool = pci_device_pool.PciDevicePool(count=5,
|
||||
product_id='foo',
|
||||
vendor_id='bar',
|
||||
tags={'t1': 'v1', 't2': 'v2'})
|
||||
fake_pool_primitive = fake_pool.obj_to_primitive()
|
||||
|
||||
fake_pool_list = pci_device_pool.PciDevicePoolList(objects=[fake_pool])
|
||||
fake_pool_list_primitive = fake_pool_list.obj_to_primitive()
|
|
@ -22,6 +22,7 @@ from nova import objects
|
|||
from nova.objects import compute_node
|
||||
from nova.objects import hv_spec
|
||||
from nova.objects import service
|
||||
from nova.tests.unit import fake_pci_device_pools
|
||||
from nova.tests.unit.objects import test_objects
|
||||
|
||||
NOW = timeutils.utcnow().replace(microsecond=0)
|
||||
|
@ -41,6 +42,7 @@ fake_supported_hv_specs = [fake_hv_spec]
|
|||
# for backward compatibility, each supported instance object
|
||||
# is stored as a list in the database
|
||||
fake_supported_hv_specs_db_format = jsonutils.dumps([fake_hv_spec.to_list()])
|
||||
fake_pci = jsonutils.dumps(fake_pci_device_pools.fake_pool_list_primitive)
|
||||
fake_compute_node = {
|
||||
'created_at': NOW,
|
||||
'updated_at': None,
|
||||
|
@ -69,6 +71,7 @@ fake_compute_node = {
|
|||
'host_ip': fake_host_ip,
|
||||
'numa_topology': fake_numa_topology_db_format,
|
||||
'supported_instances': fake_supported_hv_specs_db_format,
|
||||
'pci_stats': fake_pci,
|
||||
}
|
||||
# FIXME(sbauza) : For compatibility checking, to be removed once we are sure
|
||||
# that all computes are running latest DB version with host field in it.
|
||||
|
@ -81,13 +84,26 @@ class _TestComputeNodeObject(object):
|
|||
obj_val = [inst.to_list() for inst in obj_val]
|
||||
self.json_comparator(expected, obj_val)
|
||||
|
||||
def pci_device_pools_comparator(self, expected, obj_val):
|
||||
obj_val = obj_val.obj_to_primitive()
|
||||
self.json_loads_comparator(expected, obj_val)
|
||||
|
||||
def json_loads_comparator(self, expected, obj_val):
|
||||
# NOTE(edleafe): This is necessary because the dumps() version of the
|
||||
# PciDevicePoolList doesn't maintain ordering, so the output string
|
||||
# doesn't always match.
|
||||
self.assertEqual(jsonutils.loads(expected), obj_val)
|
||||
|
||||
def comparators(self):
|
||||
return {'stats': self.json_comparator,
|
||||
'host_ip': self.str_comparator,
|
||||
'supported_hv_specs': self.supported_hv_specs_comparator}
|
||||
'supported_hv_specs': self.supported_hv_specs_comparator,
|
||||
'pci_device_pools': self.pci_device_pools_comparator,
|
||||
}
|
||||
|
||||
def subs(self):
|
||||
return {'supported_hv_specs': 'supported_instances'}
|
||||
return {'supported_hv_specs': 'supported_instances',
|
||||
'pci_device_pools': 'pci_stats'}
|
||||
|
||||
def test_get_by_id(self):
|
||||
self.mox.StubOutWithMock(db, 'compute_node_get')
|
||||
|
@ -325,6 +341,12 @@ class _TestComputeNodeObject(object):
|
|||
primitive = compute.obj_to_primitive(target_version='1.6')
|
||||
self.assertNotIn('host', primitive)
|
||||
|
||||
def test_compat_pci_device_pools(self):
|
||||
compute = compute_node.ComputeNode()
|
||||
compute.pci_device_pools = fake_pci_device_pools.fake_pool_list
|
||||
primitive = compute.obj_to_primitive(target_version='1.8')
|
||||
self.assertNotIn('pci_device_pools', primitive)
|
||||
|
||||
|
||||
class TestComputeNodeObject(test_objects._LocalTest,
|
||||
_TestComputeNodeObject):
|
||||
|
|
|
@ -1095,8 +1095,8 @@ object_data = {
|
|||
'BandwidthUsageList': '1.2-5b564cbfd5ae6e106443c086938e7602',
|
||||
'BlockDeviceMapping': '1.5-9968ffe513e7672484b0f528b034cd0f',
|
||||
'BlockDeviceMappingList': '1.6-ee2ed2eb3f3f2f54d573ccea0ff2eeaa',
|
||||
'ComputeNode': '1.8-117273c242796142ef637d39a9270a6a',
|
||||
'ComputeNodeList': '1.8-c22863c12a4d6f5edca61d2d62ed5896',
|
||||
'ComputeNode': '1.9-d59bebd3176d86f0f7ea02086732a0d4',
|
||||
'ComputeNodeList': '1.9-4fdeaf7dce98f5736f0ed239c9265c65',
|
||||
'DNSDomain': '1.0-5bdc288d7c3b723ce86ede998fd5c9ba',
|
||||
'DNSDomainList': '1.0-cfb3e7e82be661501c31099523154db4',
|
||||
'EC2InstanceMapping': '1.0-627baaf4b12c9067200979bdc4558a99',
|
||||
|
@ -1140,6 +1140,8 @@ object_data = {
|
|||
'NUMATopology': '1.2-790f6bdff85bf6e5677f409f3a4f1c6a',
|
||||
'PciDevice': '1.2-29e35c3199f3b98ce66e5d1212612818',
|
||||
'PciDeviceList': '1.1-2896df4f5b06579e5f35adba5fcae9db',
|
||||
'PciDevicePool': '1.0-d6ed1abe611c9947345a44155abe6f11',
|
||||
'PciDevicePoolList': '1.0-d31e08e0ff620a4df7cc2014b6c50da8',
|
||||
'Quotas': '1.2-36098cf2143e6535873c3fa3d6fe56f7',
|
||||
'QuotasNoOp': '1.2-164c628906b170fd946a7672e85e4935',
|
||||
'S3ImageMapping': '1.0-9225943a44a91ad0349b9fd8bd3f3ce2',
|
||||
|
@ -1149,9 +1151,11 @@ object_data = {
|
|||
'SecurityGroupRuleList': '1.1-667fca3a9928f23d2d10e61962c55f3c',
|
||||
'Service': '1.7-82bbfd46a744a9c89bc44b47a1b81683',
|
||||
'ServiceList': '1.5-f137850fbd69933a69a03eae572b05f0',
|
||||
'TestSubclassedObject': '1.6-87177ccbefd7a740a9e261f958e15b00',
|
||||
'Service': '1.8-82bbfd46a744a9c89bc44b47a1b81683',
|
||||
'ServiceList': '1.6-f8bd332b71ff1c3a86b88b6070072fd4',
|
||||
'Tag': '1.0-a11531f4e4e3166eef6243d6d58a18bd',
|
||||
'TagList': '1.0-e89bf8c8055f1f1d654fb44f0abf1f53',
|
||||
'TestSubclassedObject': '1.6-87177ccbefd7a740a9e261f958e15b00',
|
||||
'VirtualInterface': '1.0-10fdac4c704102b6d57d6936d6d790d2',
|
||||
'VirtualInterfaceList': '1.0-accbf02628a8063c1d885077a2bf49b6',
|
||||
'VirtCPUTopology': '1.0-fc694de72e20298f7c6bab1083fd4563',
|
||||
|
@ -1160,6 +1164,7 @@ object_data = {
|
|||
|
||||
object_relationships = {
|
||||
'BlockDeviceMapping': {'Instance': '1.17'},
|
||||
'ComputeNode': {'PciDevicePoolList': '1.0'},
|
||||
'FixedIP': {'Instance': '1.17', 'Network': '1.2',
|
||||
'VirtualInterface': '1.0',
|
||||
'FloatingIPList': '1.7'},
|
||||
|
@ -1174,7 +1179,7 @@ object_relationships = {
|
|||
'InstanceNUMACell': {'VirtCPUTopology': '1.0'},
|
||||
'MyObj': {'MyOwnedObject': '1.0'},
|
||||
'SecurityGroupRule': {'SecurityGroup': '1.1'},
|
||||
'Service': {'ComputeNode': '1.8'},
|
||||
'Service': {'ComputeNode': '1.9'},
|
||||
'TestSubclassedObject': {'MyOwnedObject': '1.0'}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
# 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
|
||||
|
||||
from nova import objects
|
||||
from nova.objects import pci_device_pool
|
||||
from nova import test
|
||||
from nova.tests.unit import fake_pci_device_pools as fake_pci
|
||||
from nova.tests.unit.objects import test_objects
|
||||
|
||||
|
||||
class _TestPciDevicePoolObject(object):
|
||||
|
||||
def test_pci_pool_from_dict_not_distructive(self):
|
||||
test_dict = copy.copy(fake_pci.fake_pool_dict)
|
||||
objects.PciDevicePool.from_dict(test_dict)
|
||||
self.assertEqual(fake_pci.fake_pool_dict, test_dict)
|
||||
|
||||
def test_pci_pool_from_dict(self):
|
||||
pool_obj = objects.PciDevicePool.from_dict(fake_pci.fake_pool_dict)
|
||||
self.assertEqual(pool_obj.product_id, 'fake-product')
|
||||
self.assertEqual(pool_obj.vendor_id, 'fake-vendor')
|
||||
self.assertEqual(pool_obj.tags, {'t1': 'v1', 't2': 'v2'})
|
||||
self.assertEqual(pool_obj.count, 2)
|
||||
|
||||
def test_pci_pool_from_dict_no_tags(self):
|
||||
dict_notag = copy.copy(fake_pci.fake_pool_dict)
|
||||
dict_notag.pop('t1')
|
||||
dict_notag.pop('t2')
|
||||
pool_obj = objects.PciDevicePool.from_dict(dict_notag)
|
||||
self.assertEqual(pool_obj.tags, {})
|
||||
|
||||
|
||||
class TestPciDevicePoolObject(test_objects._LocalTest,
|
||||
_TestPciDevicePoolObject):
|
||||
pass
|
||||
|
||||
|
||||
class TestRemotePciDevicePoolObject(test_objects._RemoteTest,
|
||||
_TestPciDevicePoolObject):
|
||||
pass
|
||||
|
||||
|
||||
class TestConvertPciStats(test.NoDBTestCase):
|
||||
def test_from_pci_stats_obj(self):
|
||||
prim = fake_pci.fake_pool_list_primitive
|
||||
pools = pci_device_pool.from_pci_stats(prim)
|
||||
self.assertIsInstance(pools, pci_device_pool.PciDevicePoolList)
|
||||
self.assertEqual(len(pools), 1)
|
||||
|
||||
def test_from_pci_stats_dict(self):
|
||||
prim = fake_pci.fake_pool_dict
|
||||
pools = pci_device_pool.from_pci_stats(prim)
|
||||
self.assertIsInstance(pools, pci_device_pool.PciDevicePoolList)
|
||||
self.assertEqual(len(pools), 1)
|
||||
|
||||
def test_from_pci_stats_list_of_dicts(self):
|
||||
prim = fake_pci.fake_pool_dict
|
||||
pools = pci_device_pool.from_pci_stats([prim, prim])
|
||||
self.assertIsInstance(pools, pci_device_pool.PciDevicePoolList)
|
||||
self.assertEqual(len(pools), 2)
|
||||
|
||||
def test_from_pci_stats_bad(self):
|
||||
prim = "not a valid json string for an object"
|
||||
pools = pci_device_pool.from_pci_stats(prim)
|
||||
self.assertIsNone(pools)
|
|
@ -13,6 +13,7 @@
|
|||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo.serialization import jsonutils
|
||||
from oslo.utils import timeutils
|
||||
|
||||
from nova import db
|
||||
|
@ -45,13 +46,25 @@ class _TestServiceObject(object):
|
|||
obj_val = [inst.to_list() for inst in obj_val]
|
||||
self.json_comparator(expected, obj_val)
|
||||
|
||||
def pci_device_pools_comparator(self, expected, obj_val):
|
||||
obj_val = obj_val.obj_to_primitive()
|
||||
self.json_loads_comparator(expected, obj_val)
|
||||
|
||||
def json_loads_comparator(self, expected, obj_val):
|
||||
# NOTE(edleafe): This is necessary because the dumps() version of the
|
||||
# PciDevicePoolList doesn't maintain ordering, so the output string
|
||||
# doesn't always match.
|
||||
self.assertEqual(jsonutils.loads(expected), obj_val)
|
||||
|
||||
def comparators(self):
|
||||
return {'stats': self.json_comparator,
|
||||
'host_ip': self.str_comparator,
|
||||
'supported_hv_specs': self.supported_hv_specs_comparator}
|
||||
'supported_hv_specs': self.supported_hv_specs_comparator,
|
||||
'pci_device_pools': self.pci_device_pools_comparator}
|
||||
|
||||
def subs(self):
|
||||
return {'supported_hv_specs': 'supported_instances'}
|
||||
return {'supported_hv_specs': 'supported_instances',
|
||||
'pci_device_pools': 'pci_stats'}
|
||||
|
||||
def _test_query(self, db_method, obj_method, *args, **kwargs):
|
||||
self.mox.StubOutWithMock(db, db_method)
|
||||
|
|
Loading…
Reference in New Issue