Add requested_networks field to RequestSpec object
Since we want to support routed networks in Nova, we need to provide the needed networks to the scheduler, hence the new field which won't be persisted. Change-Id: I03fcf9d64a750e3e8a71c1862d3e2ceb84aaffd2 Related-Implements: blueprint routed-networks-scheduling
This commit is contained in:
parent
fefd984fd1
commit
edaaac6aaf
|
@ -34,7 +34,8 @@ REQUEST_SPEC_OPTIONAL_ATTRS = ['requested_destination',
|
|||
'security_groups',
|
||||
'network_metadata',
|
||||
'requested_resources',
|
||||
'request_level_params']
|
||||
'request_level_params',
|
||||
'requested_networks']
|
||||
|
||||
|
||||
@base.NovaObjectRegistry.register
|
||||
|
@ -53,7 +54,8 @@ class RequestSpec(base.NovaObject):
|
|||
# Version 1.11: Added is_bfv
|
||||
# Version 1.12: Added requested_resources
|
||||
# Version 1.13: Added request_level_params
|
||||
VERSION = '1.13'
|
||||
# Version 1.14: Added requested_networks
|
||||
VERSION = '1.14'
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(),
|
||||
|
@ -108,11 +110,15 @@ class RequestSpec(base.NovaObject):
|
|||
default=None),
|
||||
# NOTE(efried): This field won't be persisted.
|
||||
'request_level_params': fields.ObjectField('RequestLevelParams'),
|
||||
# NOTE(sbauza); This field won't be persisted.
|
||||
'requested_networks': fields.ObjectField('NetworkRequestList')
|
||||
}
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
super(RequestSpec, self).obj_make_compatible(primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if target_version < (1, 14) and 'requested_networks' in primitive:
|
||||
del primitive['requested_networks']
|
||||
if target_version < (1, 13) and 'request_level_params' in primitive:
|
||||
del primitive['request_level_params']
|
||||
if target_version < (1, 12):
|
||||
|
@ -152,6 +158,10 @@ class RequestSpec(base.NovaObject):
|
|||
self.request_level_params = RequestLevelParams()
|
||||
return
|
||||
|
||||
if attrname == 'requested_networks':
|
||||
self.requested_networks = objects.NetworkRequestList(objects=[])
|
||||
return
|
||||
|
||||
# NOTE(sbauza): In case the primitive was not providing that field
|
||||
# because of a previous RequestSpec version, we want to default
|
||||
# that field in order to have the same behaviour.
|
||||
|
@ -563,7 +573,8 @@ class RequestSpec(base.NovaObject):
|
|||
if key in ['id', 'instance_uuid']:
|
||||
setattr(spec, key, db_spec[key])
|
||||
elif key in ('requested_destination', 'requested_resources',
|
||||
'network_metadata', 'request_level_params'):
|
||||
'network_metadata', 'request_level_params',
|
||||
'requested_networks'):
|
||||
# Do not override what we already have in the object as this
|
||||
# field is not persisted. If save() is called after
|
||||
# one of these fields is populated, it will reset the field to
|
||||
|
@ -653,6 +664,10 @@ class RequestSpec(base.NovaObject):
|
|||
# no need for it after scheduling
|
||||
if 'network_metadata' in spec and spec.network_metadata:
|
||||
del spec.network_metadata
|
||||
# NOTE(sbauza): Don't persist requested_networks since we have
|
||||
# no need for it after scheduling
|
||||
if 'requested_networks' in spec and spec.requested_networks:
|
||||
del spec.requested_networks
|
||||
|
||||
db_updates = {'spec': jsonutils.dumps(spec.obj_to_primitive())}
|
||||
if 'instance_uuid' in updates:
|
||||
|
|
|
@ -1124,7 +1124,7 @@ object_data = {
|
|||
'QuotasNoOp': '1.3-d1593cf969c81846bc8192255ea95cce',
|
||||
'RequestGroup': '1.3-0458d350a8ec9d0673f9be5640a990ce',
|
||||
'RequestLevelParams': '1.0-1e5c8c18bd44cd233c8b32509c99d06f',
|
||||
'RequestSpec': '1.13-e1aa38b2bf3f8547474ee9e4c0aa2745',
|
||||
'RequestSpec': '1.14-2cdbda368ca07e10905dc5fe96908a58',
|
||||
'Resource': '1.0-d8a2abbb380da583b995fd118f6a8953',
|
||||
'ResourceList': '1.0-4a53826625cc280e15fae64a575e0879',
|
||||
'ResourceMetadata': '1.0-77509ea1ea0dd750d5864b9bd87d3f9d',
|
||||
|
|
|
@ -308,7 +308,7 @@ class _TestRequestSpecObject(object):
|
|||
mock_limits.assert_called_once_with({})
|
||||
# Make sure that all fields are set using that helper method
|
||||
skip = ['id', 'security_groups', 'network_metadata', 'is_bfv',
|
||||
'request_level_params']
|
||||
'request_level_params', 'requested_networks']
|
||||
for field in [f for f in spec.obj_fields if f not in skip]:
|
||||
self.assertTrue(spec.obj_attr_is_set(field),
|
||||
'Field: %s is not set' % field)
|
||||
|
@ -339,7 +339,8 @@ class _TestRequestSpecObject(object):
|
|||
filter_properties, instance_group, instance.availability_zone,
|
||||
objects.SecurityGroupList())
|
||||
# Make sure that all fields are set using that helper method
|
||||
skip = ['id', 'network_metadata', 'is_bfv', 'request_level_params']
|
||||
skip = ['id', 'network_metadata', 'is_bfv', 'request_level_params',
|
||||
'requested_networks']
|
||||
for field in [f for f in spec.obj_fields if f not in skip]:
|
||||
self.assertTrue(spec.obj_attr_is_set(field),
|
||||
'Field: %s is not set' % field)
|
||||
|
@ -664,6 +665,8 @@ class _TestRequestSpecObject(object):
|
|||
objects.ComputeNode(host='host2', hypervisor_hostname='node2'),
|
||||
]))
|
||||
req_obj.retry = expected_retry
|
||||
nr = objects.NetworkRequest()
|
||||
req_obj.requested_networks = objects.NetworkRequestList(objects=[nr])
|
||||
|
||||
orig_create_in_db = request_spec.RequestSpec._create_in_db
|
||||
with mock.patch.object(request_spec.RequestSpec, '_create_in_db') \
|
||||
|
@ -677,18 +680,21 @@ class _TestRequestSpecObject(object):
|
|||
# 2. requested_destination
|
||||
# 3. requested_resources
|
||||
# 4. retry
|
||||
# 5. requested_networks
|
||||
data = jsonutils.loads(updates['spec'])['nova_object.data']
|
||||
self.assertNotIn('network_metadata', data)
|
||||
self.assertIsNone(data['requested_destination'])
|
||||
self.assertIsNone(data['requested_resources'])
|
||||
self.assertIsNone(data['retry'])
|
||||
self.assertIsNotNone(data['instance_uuid'])
|
||||
self.assertNotIn('requested_networks', data)
|
||||
|
||||
# also we expect that the following fields are not reset after create
|
||||
# 1. network_metadata
|
||||
# 2. requested_destination
|
||||
# 3. requested_resources
|
||||
# 4. retry
|
||||
# 5. requested_networks
|
||||
self.assertIsNotNone(req_obj.network_metadata)
|
||||
self.assertJsonEqual(expected_network_metadata.obj_to_primitive(),
|
||||
req_obj.network_metadata.obj_to_primitive())
|
||||
|
@ -701,6 +707,9 @@ class _TestRequestSpecObject(object):
|
|||
self.assertIsNotNone(req_obj.retry)
|
||||
self.assertJsonEqual(expected_retry.obj_to_primitive(),
|
||||
req_obj.retry.obj_to_primitive())
|
||||
self.assertIsNotNone(req_obj.requested_networks)
|
||||
self.assertJsonEqual(nr.obj_to_primitive(),
|
||||
req_obj.requested_networks[0].obj_to_primitive())
|
||||
|
||||
def test_save_does_not_persist_requested_fields(self):
|
||||
req_obj = fake_request_spec.fake_spec_obj(remove_id=True)
|
||||
|
@ -722,6 +731,8 @@ class _TestRequestSpecObject(object):
|
|||
req_obj.retry = expected_retry
|
||||
req_obj.num_instances = 2
|
||||
req_obj.ignore_hosts = [uuids.ignored_host]
|
||||
nr = objects.NetworkRequest()
|
||||
req_obj.requested_networks = objects.NetworkRequestList(objects=[nr])
|
||||
|
||||
orig_save_in_db = request_spec.RequestSpec._save_in_db
|
||||
with mock.patch.object(request_spec.RequestSpec, '_save_in_db') \
|
||||
|
@ -736,6 +747,7 @@ class _TestRequestSpecObject(object):
|
|||
# 3. requested_resources
|
||||
# 4. retry
|
||||
# 5. ignore_hosts
|
||||
# 6. requested_networks
|
||||
data = jsonutils.loads(updates['spec'])['nova_object.data']
|
||||
self.assertNotIn('network_metadata', data)
|
||||
self.assertIsNone(data['requested_destination'])
|
||||
|
@ -743,6 +755,7 @@ class _TestRequestSpecObject(object):
|
|||
self.assertIsNone(data['retry'])
|
||||
self.assertIsNone(data['ignore_hosts'])
|
||||
self.assertIsNotNone(data['instance_uuid'])
|
||||
self.assertNotIn('requested_networks', data)
|
||||
|
||||
# also we expect that the following fields are not reset after save
|
||||
# 1. network_metadata
|
||||
|
@ -750,6 +763,7 @@ class _TestRequestSpecObject(object):
|
|||
# 3. requested_resources
|
||||
# 4. retry
|
||||
# 5. ignore_hosts
|
||||
# 6. requested_networks
|
||||
self.assertIsNotNone(req_obj.network_metadata)
|
||||
self.assertJsonEqual(expected_network_metadata.obj_to_primitive(),
|
||||
req_obj.network_metadata.obj_to_primitive())
|
||||
|
@ -764,6 +778,9 @@ class _TestRequestSpecObject(object):
|
|||
req_obj.retry.obj_to_primitive())
|
||||
self.assertIsNotNone(req_obj.ignore_hosts)
|
||||
self.assertEqual([uuids.ignored_host], req_obj.ignore_hosts)
|
||||
self.assertIsNotNone(req_obj.requested_networks)
|
||||
self.assertJsonEqual(nr.obj_to_primitive(),
|
||||
req_obj.requested_networks[0].obj_to_primitive())
|
||||
|
||||
def test_save(self):
|
||||
req_obj = fake_request_spec.fake_spec_obj()
|
||||
|
@ -871,6 +888,17 @@ class _TestRequestSpecObject(object):
|
|||
self.assertNotIn('requested_resources', primitive)
|
||||
self.assertIn('instance_uuid', primitive)
|
||||
|
||||
def test_compat_requested_networks(self):
|
||||
req_obj = objects.RequestSpec(
|
||||
requested_networks=objects.NetworkRequestList(objects=[]),
|
||||
instance_uuid=uuids.instance)
|
||||
versions = ovo_base.obj_tree_get_versions('RequestSpec')
|
||||
primitive = req_obj.obj_to_primitive(target_version='1.13',
|
||||
version_manifest=versions)
|
||||
primitive = primitive['nova_object.data']
|
||||
self.assertNotIn('requested_networks', primitive)
|
||||
self.assertIn('instance_uuid', primitive)
|
||||
|
||||
def test_default_requested_destination(self):
|
||||
req_obj = objects.RequestSpec()
|
||||
self.assertIsNone(req_obj.requested_destination)
|
||||
|
@ -889,6 +917,13 @@ class _TestRequestSpecObject(object):
|
|||
objects.NetworkMetadata)
|
||||
self.assertIn('network_metadata', req_obj)
|
||||
|
||||
def test_requested_networks_load(self):
|
||||
req_obj = objects.RequestSpec()
|
||||
self.assertNotIn('requested_networks', req_obj)
|
||||
self.assertIsInstance(req_obj.requested_networks,
|
||||
objects.NetworkRequestList)
|
||||
self.assertIn('requested_networks', req_obj)
|
||||
|
||||
def test_create_raises_on_unchanged_object(self):
|
||||
ctxt = context.RequestContext(uuids.user_id, uuids.project_id)
|
||||
req_obj = request_spec.RequestSpec(context=ctxt)
|
||||
|
|
Loading…
Reference in New Issue