Extend RequestGroup object for mapping
This patch adds two new fields to the RequestGroup ovo, requester_id and provider_uuids. These two fields are needed to be able to hold and communicate the mapping between the requester of the RequestGroup (e.g. Neutron port) and the resource providers that are fulfilling the request (e.g. network device RPs). If the RequestGroup represents the un-numbered group then more than one RP can fulfill the request hence provider_uuids is a list. These new fields later in the series will be populated based on some logic in the nova-conductor. However in the long run we expect that these fields will be populated from the Placement allocation candidates response. blueprint bandwidth-resource-provider Change-Id: Ic4735f92542e5e0ca36b459874dc486f6b360317
This commit is contained in:
committed by
Matt Riedemann
parent
03bc8b6a6b
commit
b2a995f198
@@ -1983,6 +1983,7 @@ class API(base_api.NetworkAPI):
|
||||
resource_requests.append(
|
||||
objects.RequestGroup.from_port_request(
|
||||
context=None,
|
||||
port_uuid=request_net.port_id,
|
||||
port_resource_request=resource_request))
|
||||
|
||||
elif request_net.network_id and not request_net.auto_allocate:
|
||||
|
||||
@@ -1249,3 +1249,9 @@ class InstancePowerStateField(BaseEnumField):
|
||||
|
||||
class ListOfListsOfStringsField(fields.AutoTypedField):
|
||||
AUTO_TYPE = List(List(fields.String()))
|
||||
|
||||
|
||||
# TODO(mriedem): Replace this with the version from oslo.versiondobjects
|
||||
# when https://review.openstack.org/#/c/634700/ is released.
|
||||
class ListOfUUIDField(AutoTypedField):
|
||||
AUTO_TYPE = List(fields.UUID())
|
||||
|
||||
@@ -797,7 +797,9 @@ class RequestGroup(base.NovaObject):
|
||||
"""Versioned object based on the unversioned
|
||||
nova.api.openstack.placement.lib.RequestGroup object.
|
||||
"""
|
||||
VERSION = '1.0'
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: add requester_id and provider_uuids fields
|
||||
VERSION = '1.1'
|
||||
|
||||
fields = {
|
||||
'use_same_provider': fields.BooleanField(default=True),
|
||||
@@ -811,6 +813,13 @@ class RequestGroup(base.NovaObject):
|
||||
# member of the aggregate aggregate_UUID1 and member of the aggregate
|
||||
# aggregate_UUID2 or aggregate_UUID3 .
|
||||
'aggregates': fields.ListOfListsOfStringsField(default=[]),
|
||||
# The entity the request is coming from (e.g. the Neutron port uuid)
|
||||
# which may not always be a UUID.
|
||||
'requester_id': fields.StringField(nullable=True, default=None),
|
||||
# The resource provider UUIDs that together fulfill the request
|
||||
# NOTE(gibi): this can be more than one if this is the unnumbered
|
||||
# request group (i.e. use_same_provider=False)
|
||||
'provider_uuids': fields.ListOfUUIDField(default=[]),
|
||||
}
|
||||
|
||||
def __init__(self, context=None, **kwargs):
|
||||
@@ -818,10 +827,11 @@ class RequestGroup(base.NovaObject):
|
||||
self.obj_set_defaults()
|
||||
|
||||
@classmethod
|
||||
def from_port_request(cls, context, port_resource_request):
|
||||
def from_port_request(cls, context, port_uuid, port_resource_request):
|
||||
"""Init the group from the resource request of a neutron port
|
||||
|
||||
:param context: the request context
|
||||
:param port_uuid: the port requesting the resources
|
||||
:param port_resource_request: the resource_request attribute of the
|
||||
neutron port
|
||||
For example:
|
||||
@@ -845,6 +855,17 @@ class RequestGroup(base.NovaObject):
|
||||
use_same_provider=True,
|
||||
resources=port_resource_request['resources'],
|
||||
required_traits=set(port_resource_request.get(
|
||||
'required', [])))
|
||||
'required', [])),
|
||||
requester_id=port_uuid)
|
||||
obj.obj_set_defaults()
|
||||
return obj
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
super(RequestGroup, self).obj_make_compatible(
|
||||
primitive, target_version)
|
||||
target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if target_version < (1, 1):
|
||||
if 'requester_id' in primitive:
|
||||
del primitive['requester_id']
|
||||
if 'provider_uuids' in primitive:
|
||||
del primitive['provider_uuids']
|
||||
|
||||
@@ -5325,9 +5325,11 @@ class TestNeutronv2WithMock(_TestNeutronv2Common):
|
||||
mock_request_spec.assert_has_calls([
|
||||
mock.call(
|
||||
context=None,
|
||||
port_uuid=uuids.portid_2,
|
||||
port_resource_request=mock.sentinel.resource_request1),
|
||||
mock.call(
|
||||
context=None,
|
||||
port_uuid=uuids.trusted_port,
|
||||
port_resource_request=mock.sentinel.resource_request2),
|
||||
])
|
||||
|
||||
|
||||
@@ -1142,7 +1142,7 @@ object_data = {
|
||||
'PowerVMLiveMigrateData': '1.4-a745f4eda16b45e1bc5686a0c498f27e',
|
||||
'Quotas': '1.3-40fcefe522111dddd3e5e6155702cf4e',
|
||||
'QuotasNoOp': '1.3-347a039fc7cfee7b225b68b5181e0733',
|
||||
'RequestGroup': '1.0-5f694d4237c00c7b01136a4e4bcacd6d',
|
||||
'RequestGroup': '1.1-5a330f65df2d91356b1da19f10540ec8',
|
||||
'RequestSpec': '1.12-25010470f219af9b6163f2a457a513f5',
|
||||
'S3ImageMapping': '1.0-7dd7366a890d82660ed121de9092276e',
|
||||
'SchedulerLimits': '1.0-249c4bd8e62a9b327b7026b7f19cc641',
|
||||
|
||||
@@ -854,6 +854,8 @@ class TestRequestGroupObject(test.TestCase):
|
||||
self.assertEqual(set(), rg.required_traits)
|
||||
self.assertEqual(set(), rg.forbidden_traits)
|
||||
self.assertEqual([], rg.aggregates)
|
||||
self.assertIsNone(None, rg.requester_id)
|
||||
self.assertEqual([], rg.provider_uuids)
|
||||
|
||||
def test_from_port_request(self):
|
||||
port_resource_request = {
|
||||
@@ -864,7 +866,7 @@ class TestRequestGroupObject(test.TestCase):
|
||||
"CUSTOM_VNIC_TYPE_NORMAL"]
|
||||
}
|
||||
rg = request_spec.RequestGroup.from_port_request(
|
||||
self.context, port_resource_request)
|
||||
self.context, uuids.port_id, port_resource_request)
|
||||
|
||||
self.assertTrue(rg.use_same_provider)
|
||||
self.assertEqual(
|
||||
@@ -873,9 +875,11 @@ class TestRequestGroupObject(test.TestCase):
|
||||
rg.resources)
|
||||
self.assertEqual({"CUSTOM_PHYSNET_2", "CUSTOM_VNIC_TYPE_NORMAL"},
|
||||
rg.required_traits)
|
||||
self.assertEqual(uuids.port_id, rg.requester_id)
|
||||
# and the rest is defaulted
|
||||
self.assertEqual(set(), rg.forbidden_traits)
|
||||
self.assertEqual([], rg.aggregates)
|
||||
self.assertEqual([], rg.provider_uuids)
|
||||
|
||||
def test_from_port_request_without_traits(self):
|
||||
port_resource_request = {
|
||||
@@ -883,14 +887,28 @@ class TestRequestGroupObject(test.TestCase):
|
||||
"NET_BW_IGR_KILOBIT_PER_SEC": 1000,
|
||||
"NET_BW_EGR_KILOBIT_PER_SEC": 1000}}
|
||||
rg = request_spec.RequestGroup.from_port_request(
|
||||
self.context, port_resource_request)
|
||||
self.context, uuids.port_id, port_resource_request)
|
||||
|
||||
self.assertTrue(rg.use_same_provider)
|
||||
self.assertEqual(
|
||||
{"NET_BW_IGR_KILOBIT_PER_SEC": 1000,
|
||||
"NET_BW_EGR_KILOBIT_PER_SEC": 1000},
|
||||
rg.resources)
|
||||
self.assertEqual(uuids.port_id, rg.requester_id)
|
||||
# and the rest is defaulted
|
||||
self.assertEqual(set(), rg.required_traits)
|
||||
self.assertEqual(set(), rg.forbidden_traits)
|
||||
self.assertEqual([], rg.aggregates)
|
||||
self.assertEqual([], rg.provider_uuids)
|
||||
|
||||
def test_compat_requester_and_provider(self):
|
||||
req_obj = objects.RequestGroup(
|
||||
requester_id=uuids.requester, provider_uuids=[uuids.rp1],
|
||||
required_traits=set(['CUSTOM_PHYSNET_2']))
|
||||
versions = ovo_base.obj_tree_get_versions('RequestGroup')
|
||||
primitive = req_obj.obj_to_primitive(
|
||||
target_version='1.0',
|
||||
version_manifest=versions)['nova_object.data']
|
||||
self.assertNotIn('requester_id', primitive)
|
||||
self.assertNotIn('provider_uuids', primitive)
|
||||
self.assertIn('required_traits', primitive)
|
||||
|
||||
Reference in New Issue
Block a user