Transfer RequestLevelParams from ports to scheduling
The new format of the resource_request field of the Neutron port allows expressing not just request groups but also request global parameters for the allocation candidate query. This patch adapts the neutron client in nova to parse such parameters. Then transfer this information to the scheduler to include it in the allocation candidate request. It relies on previous patches that already extended the RequestLevelParams ovo and the allocation candidate query generation. Change-Id: Icb91f6429050a161f577d0ed94d4cd906d3da461 blueprint: qos-minimum-guaranteed-packet-rate
This commit is contained in:
+14
-9
@@ -1063,7 +1063,7 @@ class API:
|
|||||||
result = self.network_api.create_resource_requests(
|
result = self.network_api.create_resource_requests(
|
||||||
context, requested_networks, pci_request_info,
|
context, requested_networks, pci_request_info,
|
||||||
affinity_policy=pci_numa_affinity_policy)
|
affinity_policy=pci_numa_affinity_policy)
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, req_lvl_params = result
|
||||||
|
|
||||||
self._check_support_vnic_accelerator(context, requested_networks)
|
self._check_support_vnic_accelerator(context, requested_networks)
|
||||||
|
|
||||||
@@ -1103,7 +1103,9 @@ class API:
|
|||||||
'pci_requests': pci_request_info,
|
'pci_requests': pci_request_info,
|
||||||
'numa_topology': numa_topology,
|
'numa_topology': numa_topology,
|
||||||
'system_metadata': system_metadata,
|
'system_metadata': system_metadata,
|
||||||
'port_resource_requests': port_resource_requests}
|
'port_resource_requests': port_resource_requests,
|
||||||
|
'request_level_params': req_lvl_params,
|
||||||
|
}
|
||||||
|
|
||||||
options_from_image = self._inherit_properties_from_image(
|
options_from_image = self._inherit_properties_from_image(
|
||||||
boot_meta, auto_disk_config)
|
boot_meta, auto_disk_config)
|
||||||
@@ -1295,6 +1297,7 @@ class API:
|
|||||||
security_groups = security_group_api.populate_security_groups(
|
security_groups = security_group_api.populate_security_groups(
|
||||||
security_groups)
|
security_groups)
|
||||||
port_resource_requests = base_options.pop('port_resource_requests')
|
port_resource_requests = base_options.pop('port_resource_requests')
|
||||||
|
req_lvl_params = base_options.pop('request_level_params')
|
||||||
instances_to_build = []
|
instances_to_build = []
|
||||||
# We could be iterating over several instances with several BDMs per
|
# We could be iterating over several instances with several BDMs per
|
||||||
# instance and those BDMs could be using a lot of the same images so
|
# instance and those BDMs could be using a lot of the same images so
|
||||||
@@ -1324,13 +1327,15 @@ class API:
|
|||||||
# RequestSpec before the instance is created.
|
# RequestSpec before the instance is created.
|
||||||
instance_uuid = uuidutils.generate_uuid()
|
instance_uuid = uuidutils.generate_uuid()
|
||||||
# Store the RequestSpec that will be used for scheduling.
|
# Store the RequestSpec that will be used for scheduling.
|
||||||
req_spec = objects.RequestSpec.from_components(context,
|
req_spec = objects.RequestSpec.from_components(
|
||||||
instance_uuid, boot_meta, flavor,
|
context,
|
||||||
base_options['numa_topology'],
|
instance_uuid, boot_meta, flavor,
|
||||||
base_options['pci_requests'], filter_properties,
|
base_options['numa_topology'],
|
||||||
instance_group, base_options['availability_zone'],
|
base_options['pci_requests'], filter_properties,
|
||||||
security_groups=security_groups,
|
instance_group, base_options['availability_zone'],
|
||||||
port_resource_requests=port_resource_requests)
|
security_groups=security_groups,
|
||||||
|
port_resource_requests=port_resource_requests,
|
||||||
|
request_level_params=req_lvl_params)
|
||||||
|
|
||||||
if block_device_mapping:
|
if block_device_mapping:
|
||||||
# Record whether or not we are a BFV instance
|
# Record whether or not we are a BFV instance
|
||||||
|
|||||||
+14
-5
@@ -7643,6 +7643,7 @@ class ComputeManager(manager.Manager):
|
|||||||
instance: 'objects.Instance',
|
instance: 'objects.Instance',
|
||||||
pci_reqs: 'objects.InstancePCIRequests',
|
pci_reqs: 'objects.InstancePCIRequests',
|
||||||
request_groups: ty.List['objects.RequestGroup'],
|
request_groups: ty.List['objects.RequestGroup'],
|
||||||
|
request_level_params: 'objects.RequestLevelParams',
|
||||||
) -> ty.Tuple[ty.Optional[ty.Dict[str, ty.List[str]]],
|
) -> ty.Tuple[ty.Optional[ty.Dict[str, ty.List[str]]],
|
||||||
ty.Optional[ty.Dict[str, ty.Dict[str, ty.Dict[str, int]]]]]:
|
ty.Optional[ty.Dict[str, ty.Dict[str, ty.Dict[str, int]]]]]:
|
||||||
"""Allocate resources for the request in placement
|
"""Allocate resources for the request in placement
|
||||||
@@ -7654,6 +7655,8 @@ class ComputeManager(manager.Manager):
|
|||||||
needed PCI devices
|
needed PCI devices
|
||||||
:param request_groups: A list of RequestGroup objects describing the
|
:param request_groups: A list of RequestGroup objects describing the
|
||||||
resources the port requests from placement
|
resources the port requests from placement
|
||||||
|
:param request_level_params: A RequestLevelParams object describing the
|
||||||
|
non group specific request of the port.
|
||||||
:raises InterfaceAttachResourceAllocationFailed: if we failed to
|
:raises InterfaceAttachResourceAllocationFailed: if we failed to
|
||||||
allocate resource in placement for the request
|
allocate resource in placement for the request
|
||||||
:returns: A tuple of provider mappings and allocated resources or
|
:returns: A tuple of provider mappings and allocated resources or
|
||||||
@@ -7682,7 +7685,8 @@ class ComputeManager(manager.Manager):
|
|||||||
# NOTE(gibi): when support is added for attaching a cyborg based
|
# NOTE(gibi): when support is added for attaching a cyborg based
|
||||||
# smart NIC the ResourceRequest could be extended to handle multiple
|
# smart NIC the ResourceRequest could be extended to handle multiple
|
||||||
# request groups.
|
# request groups.
|
||||||
rr = scheduler_utils.ResourceRequest.from_request_group(request_group)
|
rr = scheduler_utils.ResourceRequest.from_request_group(
|
||||||
|
request_group, request_level_params)
|
||||||
res = self.reportclient.get_allocation_candidates(context, rr)
|
res = self.reportclient.get_allocation_candidates(context, rr)
|
||||||
alloc_reqs, provider_sums, version = res
|
alloc_reqs, provider_sums, version = res
|
||||||
|
|
||||||
@@ -7805,9 +7809,14 @@ class ComputeManager(manager.Manager):
|
|||||||
instance.flavor, instance.image_meta)
|
instance.flavor, instance.image_meta)
|
||||||
pci_reqs = objects.InstancePCIRequests(
|
pci_reqs = objects.InstancePCIRequests(
|
||||||
requests=[], instance_uuid=instance.uuid)
|
requests=[], instance_uuid=instance.uuid)
|
||||||
_, request_groups = self.network_api.create_resource_requests(
|
_, request_groups, req_lvl_params = (
|
||||||
context, requested_networks, pci_reqs,
|
self.network_api.create_resource_requests(
|
||||||
affinity_policy=pci_numa_affinity_policy)
|
context,
|
||||||
|
requested_networks,
|
||||||
|
pci_reqs,
|
||||||
|
affinity_policy=pci_numa_affinity_policy
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# We only support one port per attach request so we at most have one
|
# We only support one port per attach request so we at most have one
|
||||||
# pci request
|
# pci request
|
||||||
@@ -7816,7 +7825,7 @@ class ComputeManager(manager.Manager):
|
|||||||
requested_networks[0].pci_request_id = pci_req.request_id
|
requested_networks[0].pci_request_id = pci_req.request_id
|
||||||
|
|
||||||
result = self._allocate_port_resource_for_instance(
|
result = self._allocate_port_resource_for_instance(
|
||||||
context, instance, pci_reqs, request_groups)
|
context, instance, pci_reqs, request_groups, req_lvl_params)
|
||||||
provider_mappings, resources = result
|
provider_mappings, resources = result
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|||||||
+16
-7
@@ -2050,13 +2050,15 @@ class API:
|
|||||||
:type affinity_policy: nova.objects.fields.PCINUMAAffinityPolicy
|
:type affinity_policy: nova.objects.fields.PCINUMAAffinityPolicy
|
||||||
:raises ExtendedResourceRequestNotSupported: if the
|
:raises ExtendedResourceRequestNotSupported: if the
|
||||||
extended-resource-request Neutron API extension is enabled.
|
extended-resource-request Neutron API extension is enabled.
|
||||||
:returns: A tuple with an instance of ``objects.NetworkMetadata`` for
|
|
||||||
use by the scheduler or None and a list of RequestGroup
|
:returns: A three tuple with an instance of ``objects.NetworkMetadata``
|
||||||
objects representing the resource needs of each requested
|
for use by the scheduler or None, a list of RequestGroup
|
||||||
port
|
objects representing the resource needs of each requested port and
|
||||||
|
a RequestLevelParam object that contains global scheduling
|
||||||
|
instructions not specific to any of the RequestGroups
|
||||||
"""
|
"""
|
||||||
if not requested_networks or requested_networks.no_allocate:
|
if not requested_networks or requested_networks.no_allocate:
|
||||||
return None, []
|
return None, [], None
|
||||||
|
|
||||||
if not self.support_create_with_resource_request(context):
|
if not self.support_create_with_resource_request(context):
|
||||||
raise exception.ExtendedResourceRequestNotSupported()
|
raise exception.ExtendedResourceRequestNotSupported()
|
||||||
@@ -2068,6 +2070,7 @@ class API:
|
|||||||
has_extended_resource_request_extension = (
|
has_extended_resource_request_extension = (
|
||||||
self._has_extended_resource_request_extension(context, neutron))
|
self._has_extended_resource_request_extension(context, neutron))
|
||||||
resource_requests = []
|
resource_requests = []
|
||||||
|
request_level_params = objects.RequestLevelParams()
|
||||||
|
|
||||||
for request_net in requested_networks:
|
for request_net in requested_networks:
|
||||||
physnet = None
|
physnet = None
|
||||||
@@ -2122,6 +2125,9 @@ class API:
|
|||||||
objects.RequestGroup.from_extended_port_request(
|
objects.RequestGroup.from_extended_port_request(
|
||||||
context=None,
|
context=None,
|
||||||
port_resource_request=resource_request))
|
port_resource_request=resource_request))
|
||||||
|
request_level_params.extend_with(
|
||||||
|
objects.RequestLevelParams.from_port_request(
|
||||||
|
port_resource_request=resource_request))
|
||||||
else:
|
else:
|
||||||
# keep supporting the old format of the
|
# keep supporting the old format of the
|
||||||
# resource_request
|
# resource_request
|
||||||
@@ -2183,8 +2189,11 @@ class API:
|
|||||||
# Add pci_request_id into the requested network
|
# Add pci_request_id into the requested network
|
||||||
request_net.pci_request_id = pci_request_id
|
request_net.pci_request_id = pci_request_id
|
||||||
|
|
||||||
return (objects.NetworkMetadata(physnets=physnets, tunneled=tunneled),
|
return (
|
||||||
resource_requests)
|
objects.NetworkMetadata(physnets=physnets, tunneled=tunneled),
|
||||||
|
resource_requests,
|
||||||
|
request_level_params
|
||||||
|
)
|
||||||
|
|
||||||
def _can_auto_allocate_network(self, context, neutron):
|
def _can_auto_allocate_network(self, context, neutron):
|
||||||
"""Helper method to determine if we can auto-allocate networks
|
"""Helper method to determine if we can auto-allocate networks
|
||||||
|
|||||||
@@ -474,10 +474,12 @@ class RequestSpec(base.NovaObject):
|
|||||||
return filt_props
|
return filt_props
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_components(cls, context, instance_uuid, image, flavor,
|
def from_components(
|
||||||
numa_topology, pci_requests, filter_properties, instance_group,
|
cls, context, instance_uuid, image, flavor,
|
||||||
availability_zone, security_groups=None, project_id=None,
|
numa_topology, pci_requests, filter_properties, instance_group,
|
||||||
user_id=None, port_resource_requests=None):
|
availability_zone, security_groups=None, project_id=None,
|
||||||
|
user_id=None, port_resource_requests=None, request_level_params=None
|
||||||
|
):
|
||||||
"""Returns a new RequestSpec object hydrated by various components.
|
"""Returns a new RequestSpec object hydrated by various components.
|
||||||
|
|
||||||
This helper is useful in creating the RequestSpec from the various
|
This helper is useful in creating the RequestSpec from the various
|
||||||
@@ -503,6 +505,7 @@ class RequestSpec(base.NovaObject):
|
|||||||
:param port_resource_requests: a list of RequestGroup objects
|
:param port_resource_requests: a list of RequestGroup objects
|
||||||
representing the resource needs of the
|
representing the resource needs of the
|
||||||
neutron ports
|
neutron ports
|
||||||
|
:param request_level_params: a RequestLevelParams object
|
||||||
"""
|
"""
|
||||||
spec_obj = cls(context)
|
spec_obj = cls(context)
|
||||||
spec_obj.num_instances = 1
|
spec_obj.num_instances = 1
|
||||||
@@ -536,10 +539,11 @@ class RequestSpec(base.NovaObject):
|
|||||||
if port_resource_requests:
|
if port_resource_requests:
|
||||||
spec_obj.requested_resources.extend(port_resource_requests)
|
spec_obj.requested_resources.extend(port_resource_requests)
|
||||||
|
|
||||||
# NOTE(efried): We don't need to handle request_level_params here yet
|
# NOTE(gibi): later the scheduler adds more request level params but
|
||||||
# because they're set dynamically by the scheduler. That could change
|
# never overrides existing ones so we can initialize them here.
|
||||||
# in the future.
|
if request_level_params is None:
|
||||||
# TODO(gibi): handle same_subtree here coming from the neutron ports
|
request_level_params = objects.RequestLevelParams()
|
||||||
|
spec_obj.request_level_params = request_level_params
|
||||||
|
|
||||||
# NOTE(sbauza): Default the other fields that are not part of the
|
# NOTE(sbauza): Default the other fields that are not part of the
|
||||||
# original contract
|
# original contract
|
||||||
|
|||||||
@@ -202,9 +202,13 @@ class ResourceRequest(object):
|
|||||||
def from_request_group(
|
def from_request_group(
|
||||||
cls,
|
cls,
|
||||||
request_group: 'objects.RequestGroup',
|
request_group: 'objects.RequestGroup',
|
||||||
|
request_level_params: 'objects.RequestLevelParams',
|
||||||
) -> 'ResourceRequest':
|
) -> 'ResourceRequest':
|
||||||
"""Create a new instance of ResourceRequest from a RequestGroup."""
|
"""Create a new instance of ResourceRequest from a RequestGroup."""
|
||||||
res_req = cls()
|
res_req = cls()
|
||||||
|
res_req._root_required = request_level_params.root_required
|
||||||
|
res_req._root_forbidden = request_level_params.root_forbidden
|
||||||
|
res_req._same_subtree = request_level_params.same_subtree
|
||||||
res_req._add_request_group(request_group)
|
res_req._add_request_group(request_group)
|
||||||
res_req.strip_zeros()
|
res_req.strip_zeros()
|
||||||
return res_req
|
return res_req
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ def stub_out_nw_api(test, cls=None, private=None, publics=None):
|
|||||||
def create_resource_requests(
|
def create_resource_requests(
|
||||||
self, context, requested_networks,
|
self, context, requested_networks,
|
||||||
pci_requests=None, affinity_policy=None):
|
pci_requests=None, affinity_policy=None):
|
||||||
return None, []
|
return None, [], objects.RequestLevelParams()
|
||||||
|
|
||||||
if cls is None:
|
if cls is None:
|
||||||
cls = Fake
|
cls = Fake
|
||||||
|
|||||||
@@ -223,9 +223,11 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
objects=[objects.NetworkRequest(address=address,
|
objects=[objects.NetworkRequest(address=address,
|
||||||
port_id=port)])
|
port_id=port)])
|
||||||
|
|
||||||
with mock.patch.object(self.compute_api.network_api,
|
with mock.patch.object(
|
||||||
'create_resource_requests',
|
self.compute_api.network_api,
|
||||||
return_value=(None, [])):
|
'create_resource_requests',
|
||||||
|
return_value=(None, [], mock.sentinel.req_lvl_params)
|
||||||
|
):
|
||||||
self.compute_api.create(self.context, flavor, 'image_id',
|
self.compute_api.create(self.context, flavor, 'image_id',
|
||||||
requested_networks=requested_networks,
|
requested_networks=requested_networks,
|
||||||
max_count=None)
|
max_count=None)
|
||||||
@@ -4888,7 +4890,10 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
'user_data': None,
|
'user_data': None,
|
||||||
'numa_topology': None,
|
'numa_topology': None,
|
||||||
'pci_requests': None,
|
'pci_requests': None,
|
||||||
'port_resource_requests': None}
|
'port_resource_requests': None,
|
||||||
|
'request_level_params':
|
||||||
|
objects.RequestLevelParams(),
|
||||||
|
}
|
||||||
security_groups = {}
|
security_groups = {}
|
||||||
block_device_mapping = objects.BlockDeviceMappingList(
|
block_device_mapping = objects.BlockDeviceMappingList(
|
||||||
objects=[objects.BlockDeviceMapping(
|
objects=[objects.BlockDeviceMapping(
|
||||||
@@ -5059,10 +5064,12 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
'properties': {'mappings': []},
|
'properties': {'mappings': []},
|
||||||
'status': 'fake-status',
|
'status': 'fake-status',
|
||||||
'location': 'far-away'}
|
'location': 'far-away'}
|
||||||
|
numa_topology = objects.InstanceNUMATopology()
|
||||||
|
pci_requests = objects.InstancePCIRequests()
|
||||||
base_options = {'image_ref': 'fake-ref',
|
base_options = {'image_ref': 'fake-ref',
|
||||||
'display_name': 'fake-name',
|
'display_name': 'fake-name',
|
||||||
'project_id': 'fake-project',
|
'project_id': 'fake-project',
|
||||||
'availability_zone': None,
|
'availability_zone': 'fake-az',
|
||||||
'metadata': {},
|
'metadata': {},
|
||||||
'access_ip_v4': None,
|
'access_ip_v4': None,
|
||||||
'access_ip_v6': None,
|
'access_ip_v6': None,
|
||||||
@@ -5073,9 +5080,13 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
'ramdisk_id': None,
|
'ramdisk_id': None,
|
||||||
'root_device_name': None,
|
'root_device_name': None,
|
||||||
'user_data': None,
|
'user_data': None,
|
||||||
'numa_topology': None,
|
'numa_topology': numa_topology,
|
||||||
'pci_requests': None,
|
'pci_requests': pci_requests,
|
||||||
'port_resource_requests': None}
|
'port_resource_requests':
|
||||||
|
mock.sentinel.resource_reqs,
|
||||||
|
'request_level_params':
|
||||||
|
mock.sentinel.req_lvl_params,
|
||||||
|
}
|
||||||
security_groups = {}
|
security_groups = {}
|
||||||
block_device_mappings = objects.BlockDeviceMappingList(
|
block_device_mappings = objects.BlockDeviceMappingList(
|
||||||
objects=[objects.BlockDeviceMapping(
|
objects=[objects.BlockDeviceMapping(
|
||||||
@@ -5112,6 +5123,18 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
block_device_mappings, {}, mock_get_volumes.return_value,
|
block_device_mappings, {}, mock_get_volumes.return_value,
|
||||||
False)] * max_count)
|
False)] * max_count)
|
||||||
|
|
||||||
|
mock_req_spec_from_components.assert_has_calls(
|
||||||
|
[
|
||||||
|
mock.call(
|
||||||
|
ctxt, mock.ANY, boot_meta, flavor, numa_topology,
|
||||||
|
pci_requests, filter_properties, instance_group,
|
||||||
|
'fake-az', security_groups=mock.ANY,
|
||||||
|
port_resource_requests=mock.sentinel.resource_reqs,
|
||||||
|
request_level_params=mock.sentinel.req_lvl_params
|
||||||
|
),
|
||||||
|
] * 2
|
||||||
|
)
|
||||||
|
|
||||||
for rs, br, im in instances_to_build:
|
for rs, br, im in instances_to_build:
|
||||||
self.assertIsInstance(br.instance, objects.Instance)
|
self.assertIsInstance(br.instance, objects.Instance)
|
||||||
self.assertTrue(uuidutils.is_uuid_like(br.instance.uuid))
|
self.assertTrue(uuidutils.is_uuid_like(br.instance.uuid))
|
||||||
@@ -5165,7 +5188,10 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
'user_data': None,
|
'user_data': None,
|
||||||
'numa_topology': None,
|
'numa_topology': None,
|
||||||
'pci_requests': None,
|
'pci_requests': None,
|
||||||
'port_resource_requests': None}
|
'port_resource_requests': None,
|
||||||
|
'request_level_params':
|
||||||
|
objects.RequestLevelParams(),
|
||||||
|
}
|
||||||
security_groups = {}
|
security_groups = {}
|
||||||
block_device_mapping = objects.BlockDeviceMappingList(
|
block_device_mapping = objects.BlockDeviceMappingList(
|
||||||
objects=[objects.BlockDeviceMapping(
|
objects=[objects.BlockDeviceMapping(
|
||||||
@@ -5262,7 +5288,11 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
'user_data': None,
|
'user_data': None,
|
||||||
'numa_topology': None,
|
'numa_topology': None,
|
||||||
'pci_requests': None,
|
'pci_requests': None,
|
||||||
'port_resource_requests': None}
|
'port_resource_requests': None,
|
||||||
|
'request_level_params':
|
||||||
|
objects.RequestLevelParams(),
|
||||||
|
}
|
||||||
|
|
||||||
security_groups = {}
|
security_groups = {}
|
||||||
block_device_mapping = objects.BlockDeviceMappingList(
|
block_device_mapping = objects.BlockDeviceMappingList(
|
||||||
objects=[objects.BlockDeviceMapping(
|
objects=[objects.BlockDeviceMapping(
|
||||||
@@ -5328,7 +5358,9 @@ class _ComputeAPIUnitTestMixIn(object):
|
|||||||
mock_objects.RequestSpec.from_components.assert_called_once_with(
|
mock_objects.RequestSpec.from_components.assert_called_once_with(
|
||||||
mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY, mock.ANY,
|
||||||
mock.ANY, mock.ANY, mock.ANY,
|
mock.ANY, mock.ANY, mock.ANY,
|
||||||
security_groups=secgroups, port_resource_requests=mock.ANY)
|
security_groups=secgroups, port_resource_requests=mock.ANY,
|
||||||
|
request_level_params=mock.ANY
|
||||||
|
)
|
||||||
test()
|
test()
|
||||||
|
|
||||||
def _test_rescue(self, vm_state=vm_states.ACTIVE, rescue_password=None,
|
def _test_rescue(self, vm_state=vm_states.ACTIVE, rescue_password=None,
|
||||||
|
|||||||
@@ -8692,11 +8692,13 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
objects=[objects.NetworkRequest(port_id=uuids.port_instance)])
|
objects=[objects.NetworkRequest(port_id=uuids.port_instance)])
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(self.compute_api.compute_task_api,
|
mock.patch.object(
|
||||||
'schedule_and_build_instances'),
|
self.compute_api.compute_task_api,
|
||||||
mock.patch.object(self.compute_api.network_api,
|
'schedule_and_build_instances'),
|
||||||
'create_resource_requests',
|
mock.patch.object(
|
||||||
return_value=(None, [])),
|
self.compute_api.network_api,
|
||||||
|
'create_resource_requests',
|
||||||
|
return_value=(None, [], objects.RequestLevelParams())),
|
||||||
) as (mock_sbi, _mock_create_resreqs):
|
) as (mock_sbi, _mock_create_resreqs):
|
||||||
self.compute_api.create(
|
self.compute_api.create(
|
||||||
self.context,
|
self.context,
|
||||||
@@ -10195,7 +10197,8 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
"_claim_pci_device_for_interface_attach",
|
"_claim_pci_device_for_interface_attach",
|
||||||
return_value=None)
|
return_value=None)
|
||||||
) as (cap, mock_lock, mock_create_resource_req, mock_claim_pci):
|
) as (cap, mock_lock, mock_create_resource_req, mock_claim_pci):
|
||||||
mock_create_resource_req.return_value = (None, [])
|
mock_create_resource_req.return_value = (
|
||||||
|
None, [], mock.sentinel.req_lvl_params)
|
||||||
vif = self.compute.attach_interface(self.context,
|
vif = self.compute.attach_interface(self.context,
|
||||||
instance,
|
instance,
|
||||||
network_id,
|
network_id,
|
||||||
@@ -10255,7 +10258,8 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
mock_allocate_res
|
mock_allocate_res
|
||||||
):
|
):
|
||||||
request_groups = [objects.RequestGroup]
|
request_groups = [objects.RequestGroup]
|
||||||
mock_create_resource_req.return_value = (None, request_groups)
|
mock_create_resource_req.return_value = (
|
||||||
|
None, request_groups, mock.sentinel.req_lvl_params)
|
||||||
mock_allocate_res.return_value = (
|
mock_allocate_res.return_value = (
|
||||||
mock.sentinel.provider_mappings, mock.sentinel.resources)
|
mock.sentinel.provider_mappings, mock.sentinel.resources)
|
||||||
vif = self.compute.attach_interface(
|
vif = self.compute.attach_interface(
|
||||||
@@ -10300,7 +10304,9 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
# as this port has resource request we need to call
|
# as this port has resource request we need to call
|
||||||
# _allocate_port_resource_for_instance for it
|
# _allocate_port_resource_for_instance for it
|
||||||
mock_allocate_res.assert_called_once_with(
|
mock_allocate_res.assert_called_once_with(
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
mock.sentinel.req_lvl_params
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
||||||
def test_attach_sriov_interface(self, mock_notify):
|
def test_attach_sriov_interface(self, mock_notify):
|
||||||
@@ -10337,7 +10343,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
# Simulate that the requested port is an SRIOV port
|
# Simulate that the requested port is an SRIOV port
|
||||||
pci_requests.requests.append(pci_req)
|
pci_requests.requests.append(pci_req)
|
||||||
# without resource request
|
# without resource request
|
||||||
return None, []
|
return None, [], mock.sentinel.req_lvl_params
|
||||||
|
|
||||||
mock_create_resource_req.side_effect = create_resource_req
|
mock_create_resource_req.side_effect = create_resource_req
|
||||||
|
|
||||||
@@ -10413,7 +10419,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
# Simulate that the requested port is an SRIOV port
|
# Simulate that the requested port is an SRIOV port
|
||||||
pci_requests.requests.append(pci_req)
|
pci_requests.requests.append(pci_req)
|
||||||
# with resource request
|
# with resource request
|
||||||
return None, request_groups
|
return None, request_groups, mock.sentinel.req_lvl_params
|
||||||
|
|
||||||
mock_create_resource_req.side_effect = create_resource_req
|
mock_create_resource_req.side_effect = create_resource_req
|
||||||
|
|
||||||
@@ -10464,9 +10470,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
self.assertIn(pci_device, instance.pci_devices.objects)
|
self.assertIn(pci_device, instance.pci_devices.objects)
|
||||||
|
|
||||||
# ensure that we called _allocate_port_resource_for_instance as it has
|
# ensure that we called _allocate_port_resource_for_instance as it has
|
||||||
# resource reques
|
# resource request
|
||||||
mock_allocate_res.assert_called_once_with(
|
mock_allocate_res.assert_called_once_with(
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
mock.sentinel.req_lvl_params
|
||||||
|
)
|
||||||
|
|
||||||
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
@mock.patch.object(compute_utils, 'notify_about_instance_action')
|
||||||
def test_interface_tagged_attach(self, mock_notify):
|
def test_interface_tagged_attach(self, mock_notify):
|
||||||
@@ -10487,7 +10495,8 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
'_claim_pci_device_for_interface_attach',
|
'_claim_pci_device_for_interface_attach',
|
||||||
return_value=None)
|
return_value=None)
|
||||||
) as (mock_capabilities, mock_create_resource_req, mock_claim_pci):
|
) as (mock_capabilities, mock_create_resource_req, mock_claim_pci):
|
||||||
mock_create_resource_req.return_value = (None, [])
|
mock_create_resource_req.return_value = (
|
||||||
|
None, [], mock.sentinel.req_lvl_params)
|
||||||
vif = self.compute.attach_interface(self.context,
|
vif = self.compute.attach_interface(self.context,
|
||||||
instance,
|
instance,
|
||||||
network_id,
|
network_id,
|
||||||
@@ -10563,7 +10572,8 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
|
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
|
||||||
mock_dict, mock_create_resource_req, mock_claim_pci):
|
mock_dict, mock_create_resource_req, mock_claim_pci):
|
||||||
|
|
||||||
mock_create_resource_req.return_value = (None, [])
|
mock_create_resource_req.return_value = (
|
||||||
|
None, [], mock.sentinel.req_lvl_params)
|
||||||
mock_allocate.return_value = nwinfo
|
mock_allocate.return_value = nwinfo
|
||||||
mock_attach.side_effect = exception.NovaException("attach_failed")
|
mock_attach.side_effect = exception.NovaException("attach_failed")
|
||||||
self.assertRaises(exception.InterfaceAttachFailed,
|
self.assertRaises(exception.InterfaceAttachFailed,
|
||||||
@@ -10641,7 +10651,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
pci_requests=None, affinity_policy=None):
|
pci_requests=None, affinity_policy=None):
|
||||||
# Simulate that the requested port is an SRIOV port
|
# Simulate that the requested port is an SRIOV port
|
||||||
pci_requests.requests.append(pci_req)
|
pci_requests.requests.append(pci_req)
|
||||||
return None, []
|
return None, [], mock.sentinel.req_lvl_params
|
||||||
|
|
||||||
mock_create_resource_req.side_effect = create_resource_req
|
mock_create_resource_req.side_effect = create_resource_req
|
||||||
mock_allocate.return_value = nwinfo
|
mock_allocate.return_value = nwinfo
|
||||||
@@ -10716,7 +10726,7 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
pci_requests=None, affinity_policy=None):
|
pci_requests=None, affinity_policy=None):
|
||||||
# Simulate that the requested port is an SRIOV port
|
# Simulate that the requested port is an SRIOV port
|
||||||
pci_requests.requests.append(pci_req)
|
pci_requests.requests.append(pci_req)
|
||||||
return None, request_groups
|
return None, request_groups, mock.sentinel.req_lvl_params
|
||||||
|
|
||||||
mock_create_resource_req.side_effect = create_resource_req
|
mock_create_resource_req.side_effect = create_resource_req
|
||||||
mock_allocate_res.return_value = (
|
mock_allocate_res.return_value = (
|
||||||
@@ -10741,7 +10751,12 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
self.assertNotIn(pci_req, instance.pci_requests.requests)
|
self.assertNotIn(pci_req, instance.pci_requests.requests)
|
||||||
|
|
||||||
mock_allocate_res.assert_called_once_with(
|
mock_allocate_res.assert_called_once_with(
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context,
|
||||||
|
instance,
|
||||||
|
pci_reqs,
|
||||||
|
request_groups,
|
||||||
|
mock.sentinel.req_lvl_params
|
||||||
|
)
|
||||||
mock_remove_res.assert_called_once_with(
|
mock_remove_res.assert_called_once_with(
|
||||||
self.context, instance.uuid, mock.sentinel.resources)
|
self.context, instance.uuid, mock.sentinel.resources)
|
||||||
|
|
||||||
@@ -10753,6 +10768,10 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
resources={"CUSTOM_FOO": 13},
|
resources={"CUSTOM_FOO": 13},
|
||||||
requester_id=uuids.requester_id)
|
requester_id=uuids.requester_id)
|
||||||
]
|
]
|
||||||
|
req_lvl_params = objects.RequestLevelParams(
|
||||||
|
root_required={"CUSTOM_BLUE"},
|
||||||
|
same_subtree=[[uuids.group1, uuids.group2]]
|
||||||
|
)
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||||
@@ -10781,7 +10800,9 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
alloc_reqs, mock.sentinel.provider_sums, mock.sentinel.version)
|
alloc_reqs, mock.sentinel.provider_sums, mock.sentinel.version)
|
||||||
|
|
||||||
res = self.compute._allocate_port_resource_for_instance(
|
res = self.compute._allocate_port_resource_for_instance(
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
req_lvl_params
|
||||||
|
)
|
||||||
provider_mappings, resources = res
|
provider_mappings, resources = res
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -10797,6 +10818,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
request_groups[0].requester_id)
|
request_groups[0].requester_id)
|
||||||
self.assertEqual(request_groups[0], actual_rg)
|
self.assertEqual(request_groups[0], actual_rg)
|
||||||
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
||||||
|
self.assertEqual({"CUSTOM_BLUE"}, resource_request._root_required)
|
||||||
|
self.assertEqual(
|
||||||
|
[[uuids.group1, uuids.group2]],
|
||||||
|
resource_request._same_subtree
|
||||||
|
)
|
||||||
mock_add_res.assert_called_once_with(
|
mock_add_res.assert_called_once_with(
|
||||||
self.context, instance.uuid, mock.sentinel.resources)
|
self.context, instance.uuid, mock.sentinel.resources)
|
||||||
mock_update_pci.assert_called_once_with(
|
mock_update_pci.assert_called_once_with(
|
||||||
@@ -10811,6 +10837,10 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
resources={"CUSTOM_FOO": 13},
|
resources={"CUSTOM_FOO": 13},
|
||||||
requester_id=uuids.requester_id)
|
requester_id=uuids.requester_id)
|
||||||
]
|
]
|
||||||
|
req_lvl_params = objects.RequestLevelParams(
|
||||||
|
root_required={"CUSTOM_BLUE"},
|
||||||
|
same_subtree=[[uuids.group1, uuids.group2]]
|
||||||
|
)
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||||
@@ -10836,7 +10866,9 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InterfaceAttachResourceAllocationFailed,
|
exception.InterfaceAttachResourceAllocationFailed,
|
||||||
self.compute._allocate_port_resource_for_instance,
|
self.compute._allocate_port_resource_for_instance,
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
req_lvl_params,
|
||||||
|
)
|
||||||
|
|
||||||
mock_get_nodename.assert_called_once_with(
|
mock_get_nodename.assert_called_once_with(
|
||||||
self.context, instance.node)
|
self.context, instance.node)
|
||||||
@@ -10851,6 +10883,10 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
resources={"CUSTOM_FOO": 13},
|
resources={"CUSTOM_FOO": 13},
|
||||||
requester_id=uuids.requester_id)
|
requester_id=uuids.requester_id)
|
||||||
]
|
]
|
||||||
|
req_lvl_params = objects.RequestLevelParams(
|
||||||
|
root_required={"CUSTOM_BLUE"},
|
||||||
|
same_subtree=[[uuids.group1, uuids.group2]]
|
||||||
|
)
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||||
@@ -10885,7 +10921,9 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InterfaceAttachResourceAllocationFailed,
|
exception.InterfaceAttachResourceAllocationFailed,
|
||||||
self.compute._allocate_port_resource_for_instance,
|
self.compute._allocate_port_resource_for_instance,
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
req_lvl_params
|
||||||
|
)
|
||||||
|
|
||||||
mock_get_nodename.assert_called_once_with(
|
mock_get_nodename.assert_called_once_with(
|
||||||
self.context, instance.node)
|
self.context, instance.node)
|
||||||
@@ -10896,6 +10934,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
request_groups[0].requester_id)
|
request_groups[0].requester_id)
|
||||||
self.assertEqual(request_groups[0], actual_rg)
|
self.assertEqual(request_groups[0], actual_rg)
|
||||||
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
||||||
|
self.assertEqual({"CUSTOM_BLUE"}, resource_request._root_required)
|
||||||
|
self.assertEqual(
|
||||||
|
[[uuids.group1, uuids.group2]],
|
||||||
|
resource_request._same_subtree
|
||||||
|
)
|
||||||
mock_add_res.assert_called_once_with(
|
mock_add_res.assert_called_once_with(
|
||||||
self.context, instance.uuid, mock.sentinel.resources)
|
self.context, instance.uuid, mock.sentinel.resources)
|
||||||
|
|
||||||
@@ -10907,6 +10950,10 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
resources={"CUSTOM_FOO": 13},
|
resources={"CUSTOM_FOO": 13},
|
||||||
requester_id=uuids.requester_id)
|
requester_id=uuids.requester_id)
|
||||||
]
|
]
|
||||||
|
req_lvl_params = objects.RequestLevelParams(
|
||||||
|
root_required={"CUSTOM_BLUE"},
|
||||||
|
same_subtree=[[uuids.group1, uuids.group2]]
|
||||||
|
)
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||||
@@ -10943,7 +10990,9 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.AmbiguousResourceProviderForPCIRequest,
|
exception.AmbiguousResourceProviderForPCIRequest,
|
||||||
self.compute._allocate_port_resource_for_instance,
|
self.compute._allocate_port_resource_for_instance,
|
||||||
self.context, instance, pci_reqs, request_groups)
|
self.context, instance, pci_reqs, request_groups,
|
||||||
|
req_lvl_params
|
||||||
|
)
|
||||||
|
|
||||||
mock_get_nodename.assert_called_once_with(
|
mock_get_nodename.assert_called_once_with(
|
||||||
self.context, instance.node)
|
self.context, instance.node)
|
||||||
@@ -10954,6 +11003,11 @@ class ComputeAPITestCase(BaseTestCase):
|
|||||||
request_groups[0].requester_id)
|
request_groups[0].requester_id)
|
||||||
self.assertEqual(request_groups[0], actual_rg)
|
self.assertEqual(request_groups[0], actual_rg)
|
||||||
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
self.assertEqual(uuids.compute_node, actual_rg.in_tree)
|
||||||
|
self.assertEqual({"CUSTOM_BLUE"}, resource_request._root_required)
|
||||||
|
self.assertEqual(
|
||||||
|
[[uuids.group1, uuids.group2]],
|
||||||
|
resource_request._same_subtree
|
||||||
|
)
|
||||||
mock_add_res.assert_called_once_with(
|
mock_add_res.assert_called_once_with(
|
||||||
self.context, instance.uuid, mock.sentinel.resources)
|
self.context, instance.uuid, mock.sentinel.resources)
|
||||||
mock_update_pci.assert_called_once_with(
|
mock_update_pci.assert_called_once_with(
|
||||||
|
|||||||
@@ -2600,7 +2600,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
def do_test(
|
def do_test(
|
||||||
update, meth, add_fault, notify, event, mock_claim_pci,
|
update, meth, add_fault, notify, event, mock_claim_pci,
|
||||||
mock_create_resource_req):
|
mock_create_resource_req):
|
||||||
mock_create_resource_req.return_value = None, []
|
mock_create_resource_req.return_value = (
|
||||||
|
None, [], mock.sentinel.req_lvl_params)
|
||||||
self.assertRaises(exception.InterfaceAttachFailed,
|
self.assertRaises(exception.InterfaceAttachFailed,
|
||||||
self.compute.attach_interface,
|
self.compute.attach_interface,
|
||||||
self.context, f_instance, uuids.network_id,
|
self.context, f_instance, uuids.network_id,
|
||||||
|
|||||||
@@ -5789,7 +5789,7 @@ class TestAPI(TestAPIBase):
|
|||||||
|
|
||||||
result = api.create_resource_requests(
|
result = api.create_resource_requests(
|
||||||
self.context, requested_networks, pci_requests)
|
self.context, requested_networks, pci_requests)
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, _ = result
|
||||||
|
|
||||||
self.assertFalse(mock_get_client.called)
|
self.assertFalse(mock_get_client.called)
|
||||||
self.assertIsNone(network_metadata)
|
self.assertIsNone(network_metadata)
|
||||||
@@ -5816,7 +5816,7 @@ class TestAPI(TestAPIBase):
|
|||||||
|
|
||||||
result = api.create_resource_requests(
|
result = api.create_resource_requests(
|
||||||
self.context, requested_networks, pci_requests)
|
self.context, requested_networks, pci_requests)
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, _ = result
|
||||||
|
|
||||||
mock_get_physnet_tunneled_info.assert_not_called()
|
mock_get_physnet_tunneled_info.assert_not_called()
|
||||||
self.assertEqual(set(), network_metadata.physnets)
|
self.assertEqual(set(), network_metadata.physnets)
|
||||||
@@ -5875,7 +5875,7 @@ class TestAPI(TestAPIBase):
|
|||||||
|
|
||||||
result = api.create_resource_requests(
|
result = api.create_resource_requests(
|
||||||
self.context, requested_networks, pci_requests)
|
self.context, requested_networks, pci_requests)
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, _ = result
|
||||||
|
|
||||||
self.assertEqual([
|
self.assertEqual([
|
||||||
mock.sentinel.request_group1,
|
mock.sentinel.request_group1,
|
||||||
@@ -5982,7 +5982,7 @@ class TestAPI(TestAPIBase):
|
|||||||
result = self.api.create_resource_requests(
|
result = self.api.create_resource_requests(
|
||||||
self.context, requested_networks, pci_requests=None)
|
self.context, requested_networks, pci_requests=None)
|
||||||
|
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, _ = result
|
||||||
mock_get_dp_group.assert_called_once_with('smat_nic')
|
mock_get_dp_group.assert_called_once_with('smat_nic')
|
||||||
mock_get_physnet_tunneled_info.assert_called_once_with(
|
mock_get_physnet_tunneled_info.assert_called_once_with(
|
||||||
self.context, mock.ANY, 'netN')
|
self.context, mock.ANY, 'netN')
|
||||||
@@ -6046,6 +6046,12 @@ class TestAPI(TestAPIBase):
|
|||||||
@mock.patch.object(
|
@mock.patch.object(
|
||||||
neutronapi.API, '_has_extended_resource_request_extension',
|
neutronapi.API, '_has_extended_resource_request_extension',
|
||||||
return_value=True)
|
return_value=True)
|
||||||
|
@mock.patch(
|
||||||
|
'nova.objects.request_spec.RequestLevelParams.extend_with'
|
||||||
|
)
|
||||||
|
@mock.patch(
|
||||||
|
'nova.objects.request_spec.RequestLevelParams.from_port_request'
|
||||||
|
)
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
'nova.objects.request_spec.RequestGroup.from_extended_port_request')
|
'nova.objects.request_spec.RequestGroup.from_extended_port_request')
|
||||||
@mock.patch.object(neutronapi.API, '_get_physnet_tunneled_info')
|
@mock.patch.object(neutronapi.API, '_get_physnet_tunneled_info')
|
||||||
@@ -6054,6 +6060,7 @@ class TestAPI(TestAPIBase):
|
|||||||
def test_create_resource_request_extended(
|
def test_create_resource_request_extended(
|
||||||
self, getclient, mock_get_port_vnic_info,
|
self, getclient, mock_get_port_vnic_info,
|
||||||
mock_get_physnet_tunneled_info, mock_from_port_request,
|
mock_get_physnet_tunneled_info, mock_from_port_request,
|
||||||
|
mock_req_lvl_param, mock_extened_req_lvl_param,
|
||||||
mock_has_extended_res_req
|
mock_has_extended_res_req
|
||||||
):
|
):
|
||||||
requested_networks = objects.NetworkRequestList(
|
requested_networks = objects.NetworkRequestList(
|
||||||
@@ -6088,10 +6095,15 @@ class TestAPI(TestAPIBase):
|
|||||||
mock.sentinel.port2_request_group2,
|
mock.sentinel.port2_request_group2,
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
|
# also both port1 and port2 has same subtree params
|
||||||
|
mock_req_lvl_param.side_effect = [
|
||||||
|
mock.sentinel.port1_req_lvl_param,
|
||||||
|
mock.sentinel.port2_req_lvl_param,
|
||||||
|
]
|
||||||
|
|
||||||
result = api.create_resource_requests(
|
result = api.create_resource_requests(
|
||||||
self.context, requested_networks, pci_requests)
|
self.context, requested_networks, pci_requests)
|
||||||
network_metadata, port_resource_requests = result
|
network_metadata, port_resource_requests, req_lvl_param = result
|
||||||
|
|
||||||
# assert that all the request groups are collected from both ports
|
# assert that all the request groups are collected from both ports
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -6102,6 +6114,23 @@ class TestAPI(TestAPIBase):
|
|||||||
mock.sentinel.port2_request_group2,
|
mock.sentinel.port2_request_group2,
|
||||||
],
|
],
|
||||||
port_resource_requests)
|
port_resource_requests)
|
||||||
|
# the same subtree requests are combined from the two ports
|
||||||
|
mock_req_lvl_param.assert_has_calls(
|
||||||
|
[
|
||||||
|
mock.call(
|
||||||
|
port_resource_request=mock.sentinel.resource_request1),
|
||||||
|
mock.call(
|
||||||
|
port_resource_request=mock.sentinel.resource_request2),
|
||||||
|
]
|
||||||
|
|
||||||
|
)
|
||||||
|
mock_extened_req_lvl_param.assert_has_calls(
|
||||||
|
[
|
||||||
|
mock.call(mock.sentinel.port1_req_lvl_param),
|
||||||
|
mock.call(mock.sentinel.port2_req_lvl_param),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.assertIsInstance(req_lvl_param, objects.RequestLevelParams)
|
||||||
|
|
||||||
mock_from_port_request.assert_has_calls([
|
mock_from_port_request.assert_has_calls([
|
||||||
mock.call(
|
mock.call(
|
||||||
|
|||||||
@@ -412,13 +412,17 @@ class _TestRequestSpecObject(object):
|
|||||||
filter_properties = {'fake': 'property'}
|
filter_properties = {'fake': 'property'}
|
||||||
|
|
||||||
rg = request_spec.RequestGroup()
|
rg = request_spec.RequestGroup()
|
||||||
|
req_lvl_params = request_spec.RequestLevelParams()
|
||||||
|
|
||||||
spec = objects.RequestSpec.from_components(ctxt, instance.uuid, image,
|
spec = objects.RequestSpec.from_components(
|
||||||
flavor, instance.numa_topology, instance.pci_requests,
|
ctxt, instance.uuid, image,
|
||||||
filter_properties, None, instance.availability_zone,
|
flavor, instance.numa_topology, instance.pci_requests,
|
||||||
port_resource_requests=[rg])
|
filter_properties, None, instance.availability_zone,
|
||||||
|
port_resource_requests=[rg], request_level_params=req_lvl_params
|
||||||
|
)
|
||||||
|
|
||||||
self.assertListEqual([rg], spec.requested_resources)
|
self.assertListEqual([rg], spec.requested_resources)
|
||||||
|
self.assertEqual(req_lvl_params, spec.request_level_params)
|
||||||
|
|
||||||
def test_get_scheduler_hint(self):
|
def test_get_scheduler_hint(self):
|
||||||
spec_obj = objects.RequestSpec(scheduler_hints={'foo_single': ['1'],
|
spec_obj = objects.RequestSpec(scheduler_hints={'foo_single': ['1'],
|
||||||
|
|||||||
@@ -1346,8 +1346,13 @@ class TestUtils(TestUtilsBase):
|
|||||||
"CUSTOM_VNIC_TYPE_NORMAL"]
|
"CUSTOM_VNIC_TYPE_NORMAL"]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
req_lvl_params = objects.RequestLevelParams(
|
||||||
|
root_required={"CUSTOM_BLUE"},
|
||||||
|
root_forbidden={"CUSTOM_DIRTY"},
|
||||||
|
same_subtree=[[uuids.group1]],
|
||||||
|
)
|
||||||
|
|
||||||
rr = utils.ResourceRequest.from_request_group(rg)
|
rr = utils.ResourceRequest.from_request_group(rg, req_lvl_params)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
f'limit=1000&'
|
f'limit=1000&'
|
||||||
@@ -1356,7 +1361,9 @@ class TestUtils(TestUtilsBase):
|
|||||||
f'CUSTOM_VNIC_TYPE_NORMAL&'
|
f'CUSTOM_VNIC_TYPE_NORMAL&'
|
||||||
f'resources{uuids.port_id}='
|
f'resources{uuids.port_id}='
|
||||||
f'NET_BW_EGR_KILOBIT_PER_SEC%3A1000%2C'
|
f'NET_BW_EGR_KILOBIT_PER_SEC%3A1000%2C'
|
||||||
f'NET_BW_IGR_KILOBIT_PER_SEC%3A1000',
|
f'NET_BW_IGR_KILOBIT_PER_SEC%3A1000&'
|
||||||
|
f'root_required=CUSTOM_BLUE%2C%21CUSTOM_DIRTY&'
|
||||||
|
f'same_subtree={uuids.group1}',
|
||||||
rr.to_querystring())
|
rr.to_querystring())
|
||||||
|
|
||||||
def test_resource_request_add_group_inserts_the_group(self):
|
def test_resource_request_add_group_inserts_the_group(self):
|
||||||
|
|||||||
Reference in New Issue
Block a user