Add VirtCPUModel nova objects
The VirtCPUModel is to present the guest cpu modelling. As this is a quite new object, no from/to_dict function is needed. The VirtCPUModel object has limitation to the arch and mode, but not for model or features, so that no update needed when new CPU model or features are released. Co-authored: Daniel P. Berrange <berrange@redhat.com> Change-Id: Ied869f587981804fa23f6b705b5da98a509790e2 Implements: blueprint resource-objects
This commit is contained in:
parent
1a5dff21da
commit
e948aebda7
45
nova/compute/cpumodel.py
Normal file
45
nova/compute/cpumodel.py
Normal file
@ -0,0 +1,45 @@
|
||||
# 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.
|
||||
|
||||
POLICY_FORCE = 'force'
|
||||
POLICY_REQUIRE = 'require'
|
||||
POLICY_OPTIONAL = 'optional'
|
||||
POLICY_DISABLE = 'disable'
|
||||
POLICY_FORBID = 'forbid'
|
||||
|
||||
ALL_POLICIES = [
|
||||
POLICY_FORCE,
|
||||
POLICY_REQUIRE,
|
||||
POLICY_OPTIONAL,
|
||||
POLICY_DISABLE,
|
||||
POLICY_FORBID,
|
||||
]
|
||||
|
||||
MODE_CUSTOM = 'custom'
|
||||
MODE_HOST_MODEL = 'host-model'
|
||||
MODE_HOST_PASSTHROUGH = 'host-passthrough'
|
||||
|
||||
ALL_CPUMODES = [
|
||||
MODE_CUSTOM,
|
||||
MODE_HOST_MODEL,
|
||||
MODE_HOST_PASSTHROUGH,
|
||||
]
|
||||
|
||||
MATCH_MINIMUM = 'minimum'
|
||||
MATCH_EXACT = 'exact'
|
||||
MATCH_STRICT = 'strict'
|
||||
|
||||
ALL_MATCHES = [
|
||||
MATCH_MINIMUM,
|
||||
MATCH_EXACT,
|
||||
MATCH_STRICT,
|
||||
]
|
@ -55,5 +55,6 @@ def register_all():
|
||||
__import__('nova.objects.security_group')
|
||||
__import__('nova.objects.security_group_rule')
|
||||
__import__('nova.objects.service')
|
||||
__import__('nova.objects.vcpu_model')
|
||||
__import__('nova.objects.virt_cpu_topology')
|
||||
__import__('nova.objects.virtual_interface')
|
||||
|
75
nova/objects/vcpu_model.py
Normal file
75
nova/objects/vcpu_model.py
Normal file
@ -0,0 +1,75 @@
|
||||
# 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 oslo.serialization import jsonutils
|
||||
|
||||
from nova.compute import arch
|
||||
from nova.compute import cpumodel
|
||||
from nova import db
|
||||
from nova.objects import base
|
||||
from nova.objects import fields
|
||||
|
||||
|
||||
class VirtCPUModel(base.NovaObject):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
fields = {
|
||||
'arch': fields.EnumField(nullable=True,
|
||||
valid_values=arch.ALL),
|
||||
'vendor': fields.StringField(nullable=True),
|
||||
'topology': fields.ObjectField('VirtCPUTopology',
|
||||
nullable=True),
|
||||
'features': fields.ListOfObjectsField("VirtCPUFeature",
|
||||
default=[]),
|
||||
'mode': fields.EnumField(nullable=True,
|
||||
valid_values=cpumodel.ALL_CPUMODES),
|
||||
'model': fields.StringField(nullable=True),
|
||||
'match': fields.EnumField(nullable=True,
|
||||
valid_values=cpumodel.ALL_MATCHES),
|
||||
}
|
||||
|
||||
obj_relationships = {
|
||||
'topology': [('1.0', '1.0')],
|
||||
'features': [('1.0', '1.0')],
|
||||
}
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
setattr(self, attrname, None)
|
||||
|
||||
def to_json(self):
|
||||
return jsonutils.dumps(self.obj_to_primitive())
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, jsonstr):
|
||||
return cls.obj_from_primitive(jsonutils.loads(jsonstr))
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_instance_uuid(cls, context, instance_uuid):
|
||||
db_extra = db.instance_extra_get_by_instance_uuid(
|
||||
context, instance_uuid, columns=['vcpu_model'])
|
||||
if not db_extra or not db_extra['vcpu_model']:
|
||||
return None
|
||||
return cls.obj_from_primitive(jsonutils.loads(db_extra['vcpu_model']))
|
||||
|
||||
|
||||
class VirtCPUFeature(base.NovaObject):
|
||||
VERSION = VirtCPUModel.VERSION
|
||||
|
||||
fields = {
|
||||
'policy': fields.EnumField(nullable=True,
|
||||
valid_values=cpumodel.ALL_POLICIES),
|
||||
'name': fields.StringField(nullable=False),
|
||||
}
|
||||
|
||||
def obj_load_attr(self, attrname):
|
||||
setattr(self, attrname, None)
|
@ -1182,6 +1182,8 @@ object_data = {
|
||||
'TestSubclassedObject': '1.6-87177ccbefd7a740a9e261f958e15b00',
|
||||
'VirtualInterface': '1.0-10fdac4c704102b6d57d6936d6d790d2',
|
||||
'VirtualInterfaceList': '1.0-accbf02628a8063c1d885077a2bf49b6',
|
||||
'VirtCPUFeature': '1.0-3cac8c77d84a632ba79da01a4b87afb9',
|
||||
'VirtCPUModel': '1.0-ae051080026849eddf7179e353673756',
|
||||
'VirtCPUTopology': '1.0-fc694de72e20298f7c6bab1083fd4563',
|
||||
}
|
||||
|
||||
@ -1205,7 +1207,8 @@ object_relationships = {
|
||||
'MyObj': {'MyOwnedObject': '1.0'},
|
||||
'SecurityGroupRule': {'SecurityGroup': '1.1'},
|
||||
'Service': {'ComputeNode': '1.10'},
|
||||
'TestSubclassedObject': {'MyOwnedObject': '1.0'}
|
||||
'TestSubclassedObject': {'MyOwnedObject': '1.0'},
|
||||
'VirtCPUModel': {'VirtCPUTopology': '1.0'},
|
||||
}
|
||||
|
||||
|
||||
|
102
nova/tests/unit/objects/test_vcpu_model.py
Normal file
102
nova/tests/unit/objects/test_vcpu_model.py
Normal file
@ -0,0 +1,102 @@
|
||||
# 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.compute import arch
|
||||
from nova.compute import cpumodel
|
||||
from nova import objects
|
||||
from nova.tests.unit.objects import test_objects
|
||||
|
||||
fake_cpu_model_feature = {
|
||||
'policy': cpumodel.POLICY_REQUIRE,
|
||||
'name': 'sse2',
|
||||
}
|
||||
|
||||
fake_cpu_model_feature_obj = objects.VirtCPUFeature(
|
||||
**fake_cpu_model_feature)
|
||||
|
||||
fake_vcpumodel_dict = {
|
||||
'arch': arch.I686,
|
||||
'vendor': 'fake-vendor',
|
||||
'match': cpumodel.MATCH_EXACT,
|
||||
'topology': objects.VirtCPUTopology(sockets=1, cores=1, threads=1),
|
||||
'features': [fake_cpu_model_feature_obj],
|
||||
'mode': cpumodel.MODE_HOST_MODEL,
|
||||
'model': 'fake-model',
|
||||
}
|
||||
fake_vcpumodel = objects.VirtCPUModel(**fake_vcpumodel_dict)
|
||||
|
||||
|
||||
class _TestVirtCPUFeatureObj(object):
|
||||
def test_policy_limitation(self):
|
||||
obj = objects.VirtCPUFeature()
|
||||
self.assertRaises(ValueError, setattr, obj, 'policy', 'foo')
|
||||
|
||||
|
||||
class TestVirtCPUFeatureObj(test_objects._LocalTest,
|
||||
_TestVirtCPUFeatureObj):
|
||||
pass
|
||||
|
||||
|
||||
class TestRemoteVirtCPUFeatureObj(test_objects._LocalTest,
|
||||
_TestVirtCPUFeatureObj):
|
||||
pass
|
||||
|
||||
|
||||
class _TestVirtCPUModel(object):
|
||||
def test_create(self):
|
||||
model = objects.VirtCPUModel(**fake_vcpumodel_dict)
|
||||
self.assertEqual(fake_vcpumodel_dict['model'], model.model)
|
||||
self.assertEqual(fake_vcpumodel_dict['topology']['sockets'],
|
||||
model.topology.sockets)
|
||||
feature = model.features[0]
|
||||
self.assertEqual(fake_cpu_model_feature['policy'],
|
||||
feature.policy)
|
||||
|
||||
def test_defaults(self):
|
||||
model = objects.VirtCPUModel()
|
||||
self.assertIsNone(model.mode)
|
||||
self.assertIsNone(model.model)
|
||||
self.assertIsNone(model.vendor)
|
||||
self.assertIsNone(model.arch)
|
||||
self.assertIsNone(model.match)
|
||||
self.assertEqual([], model.features)
|
||||
self.assertIsNone(model.topology)
|
||||
|
||||
def test_arch_field(self):
|
||||
model = objects.VirtCPUModel(**fake_vcpumodel_dict)
|
||||
self.assertRaises(ValueError, setattr, model, 'arch', 'foo')
|
||||
|
||||
def test_serialize(self):
|
||||
modelin = objects.VirtCPUModel(**fake_vcpumodel_dict)
|
||||
modelout = objects.VirtCPUModel.from_json(modelin.to_json())
|
||||
|
||||
self.assertEqual(modelin.mode, modelout.mode)
|
||||
self.assertEqual(modelin.model, modelout.model)
|
||||
self.assertEqual(modelin.vendor, modelout.vendor)
|
||||
self.assertEqual(modelin.arch, modelout.arch)
|
||||
self.assertEqual(modelin.match, modelout.match)
|
||||
self.assertEqual(modelin.features[0].policy,
|
||||
modelout.features[0].policy)
|
||||
self.assertEqual(modelin.features[0].name, modelout.features[0].name)
|
||||
self.assertEqual(modelin.topology.sockets, modelout.topology.sockets)
|
||||
self.assertEqual(modelin.topology.cores, modelout.topology.cores)
|
||||
self.assertEqual(modelin.topology.threads, modelout.topology.threads)
|
||||
|
||||
|
||||
class TestVirtCPUModel(test_objects._LocalTest,
|
||||
_TestVirtCPUModel):
|
||||
pass
|
||||
|
||||
|
||||
class TestRemoteVirtCPUModel(test_objects._LocalTest,
|
||||
_TestVirtCPUModel):
|
||||
pass
|
Loading…
Reference in New Issue
Block a user