Merge "Transfer RequestLevelParams from ports to scheduling"
This commit is contained in:
commit
982d459c65
nova
compute
network
objects
scheduler
tests/unit
api/openstack
compute
network
objects
scheduler
@ -1064,7 +1064,7 @@ class API:
|
||||
result = self.network_api.create_resource_requests(
|
||||
context, requested_networks, pci_request_info,
|
||||
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)
|
||||
|
||||
@ -1104,7 +1104,9 @@ class API:
|
||||
'pci_requests': pci_request_info,
|
||||
'numa_topology': numa_topology,
|
||||
'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(
|
||||
boot_meta, auto_disk_config)
|
||||
@ -1296,6 +1298,7 @@ class API:
|
||||
security_groups = security_group_api.populate_security_groups(
|
||||
security_groups)
|
||||
port_resource_requests = base_options.pop('port_resource_requests')
|
||||
req_lvl_params = base_options.pop('request_level_params')
|
||||
instances_to_build = []
|
||||
# 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
|
||||
@ -1325,13 +1328,15 @@ class API:
|
||||
# RequestSpec before the instance is created.
|
||||
instance_uuid = uuidutils.generate_uuid()
|
||||
# Store the RequestSpec that will be used for scheduling.
|
||||
req_spec = objects.RequestSpec.from_components(context,
|
||||
instance_uuid, boot_meta, flavor,
|
||||
base_options['numa_topology'],
|
||||
base_options['pci_requests'], filter_properties,
|
||||
instance_group, base_options['availability_zone'],
|
||||
security_groups=security_groups,
|
||||
port_resource_requests=port_resource_requests)
|
||||
req_spec = objects.RequestSpec.from_components(
|
||||
context,
|
||||
instance_uuid, boot_meta, flavor,
|
||||
base_options['numa_topology'],
|
||||
base_options['pci_requests'], filter_properties,
|
||||
instance_group, base_options['availability_zone'],
|
||||
security_groups=security_groups,
|
||||
port_resource_requests=port_resource_requests,
|
||||
request_level_params=req_lvl_params)
|
||||
|
||||
if block_device_mapping:
|
||||
# Record whether or not we are a BFV instance
|
||||
|
@ -7627,6 +7627,7 @@ class ComputeManager(manager.Manager):
|
||||
instance: 'objects.Instance',
|
||||
pci_reqs: 'objects.InstancePCIRequests',
|
||||
request_groups: ty.List['objects.RequestGroup'],
|
||||
request_level_params: 'objects.RequestLevelParams',
|
||||
) -> ty.Tuple[ty.Optional[ty.Dict[str, ty.List[str]]],
|
||||
ty.Optional[ty.Dict[str, ty.Dict[str, ty.Dict[str, int]]]]]:
|
||||
"""Allocate resources for the request in placement
|
||||
@ -7638,6 +7639,8 @@ class ComputeManager(manager.Manager):
|
||||
needed PCI devices
|
||||
:param request_groups: A list of RequestGroup objects describing the
|
||||
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
|
||||
allocate resource in placement for the request
|
||||
:returns: A tuple of provider mappings and allocated resources or
|
||||
@ -7666,7 +7669,8 @@ class ComputeManager(manager.Manager):
|
||||
# NOTE(gibi): when support is added for attaching a cyborg based
|
||||
# smart NIC the ResourceRequest could be extended to handle multiple
|
||||
# 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)
|
||||
alloc_reqs, provider_sums, version = res
|
||||
|
||||
@ -7789,12 +7793,17 @@ class ComputeManager(manager.Manager):
|
||||
instance.flavor, instance.image_meta)
|
||||
pci_reqs = objects.InstancePCIRequests(
|
||||
requests=[], instance_uuid=instance.uuid)
|
||||
_, request_groups = self.network_api.create_resource_requests(
|
||||
context, requested_networks, pci_reqs,
|
||||
affinity_policy=pci_numa_affinity_policy)
|
||||
_, request_groups, req_lvl_params = (
|
||||
self.network_api.create_resource_requests(
|
||||
context,
|
||||
requested_networks,
|
||||
pci_reqs,
|
||||
affinity_policy=pci_numa_affinity_policy
|
||||
)
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
try:
|
||||
|
@ -2050,13 +2050,15 @@ class API:
|
||||
:type affinity_policy: nova.objects.fields.PCINUMAAffinityPolicy
|
||||
:raises ExtendedResourceRequestNotSupported: if the
|
||||
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
|
||||
objects representing the resource needs of each requested
|
||||
port
|
||||
|
||||
:returns: A three tuple with an instance of ``objects.NetworkMetadata``
|
||||
for use by the scheduler or None, a list of RequestGroup
|
||||
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:
|
||||
return None, []
|
||||
return None, [], None
|
||||
|
||||
if not self.support_create_with_resource_request(context):
|
||||
raise exception.ExtendedResourceRequestNotSupported()
|
||||
@ -2068,6 +2070,7 @@ class API:
|
||||
has_extended_resource_request_extension = (
|
||||
self._has_extended_resource_request_extension(context, neutron))
|
||||
resource_requests = []
|
||||
request_level_params = objects.RequestLevelParams()
|
||||
|
||||
for request_net in requested_networks:
|
||||
physnet = None
|
||||
@ -2122,6 +2125,9 @@ class API:
|
||||
objects.RequestGroup.from_extended_port_request(
|
||||
context=None,
|
||||
port_resource_request=resource_request))
|
||||
request_level_params.extend_with(
|
||||
objects.RequestLevelParams.from_port_request(
|
||||
port_resource_request=resource_request))
|
||||
else:
|
||||
# keep supporting the old format of the
|
||||
# resource_request
|
||||
@ -2183,8 +2189,11 @@ class API:
|
||||
# Add pci_request_id into the requested network
|
||||
request_net.pci_request_id = pci_request_id
|
||||
|
||||
return (objects.NetworkMetadata(physnets=physnets, tunneled=tunneled),
|
||||
resource_requests)
|
||||
return (
|
||||
objects.NetworkMetadata(physnets=physnets, tunneled=tunneled),
|
||||
resource_requests,
|
||||
request_level_params
|
||||
)
|
||||
|
||||
def _can_auto_allocate_network(self, context, neutron):
|
||||
"""Helper method to determine if we can auto-allocate networks
|
||||
|
@ -474,10 +474,12 @@ class RequestSpec(base.NovaObject):
|
||||
return filt_props
|
||||
|
||||
@classmethod
|
||||
def from_components(cls, context, instance_uuid, image, flavor,
|
||||
numa_topology, pci_requests, filter_properties, instance_group,
|
||||
availability_zone, security_groups=None, project_id=None,
|
||||
user_id=None, port_resource_requests=None):
|
||||
def from_components(
|
||||
cls, context, instance_uuid, image, flavor,
|
||||
numa_topology, pci_requests, filter_properties, instance_group,
|
||||
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.
|
||||
|
||||
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
|
||||
representing the resource needs of the
|
||||
neutron ports
|
||||
:param request_level_params: a RequestLevelParams object
|
||||
"""
|
||||
spec_obj = cls(context)
|
||||
spec_obj.num_instances = 1
|
||||
@ -536,10 +539,11 @@ class RequestSpec(base.NovaObject):
|
||||
if port_resource_requests:
|
||||
spec_obj.requested_resources.extend(port_resource_requests)
|
||||
|
||||
# NOTE(efried): We don't need to handle request_level_params here yet
|
||||
# because they're set dynamically by the scheduler. That could change
|
||||
# in the future.
|
||||
# TODO(gibi): handle same_subtree here coming from the neutron ports
|
||||
# NOTE(gibi): later the scheduler adds more request level params but
|
||||
# never overrides existing ones so we can initialize them here.
|
||||
if request_level_params is None:
|
||||
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
|
||||
# original contract
|
||||
|
@ -202,9 +202,13 @@ class ResourceRequest(object):
|
||||
def from_request_group(
|
||||
cls,
|
||||
request_group: 'objects.RequestGroup',
|
||||
request_level_params: 'objects.RequestLevelParams',
|
||||
) -> 'ResourceRequest':
|
||||
"""Create a new instance of ResourceRequest from a RequestGroup."""
|
||||
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.strip_zeros()
|
||||
return res_req
|
||||
|
@ -184,7 +184,7 @@ def stub_out_nw_api(test, cls=None, private=None, publics=None):
|
||||
def create_resource_requests(
|
||||
self, context, requested_networks,
|
||||
pci_requests=None, affinity_policy=None):
|
||||
return None, []
|
||||
return None, [], objects.RequestLevelParams()
|
||||
|
||||
if cls is None:
|
||||
cls = Fake
|
||||
|
@ -226,9 +226,11 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
objects=[objects.NetworkRequest(address=address,
|
||||
port_id=port)])
|
||||
|
||||
with mock.patch.object(self.compute_api.network_api,
|
||||
'create_resource_requests',
|
||||
return_value=(None, [])):
|
||||
with mock.patch.object(
|
||||
self.compute_api.network_api,
|
||||
'create_resource_requests',
|
||||
return_value=(None, [], mock.sentinel.req_lvl_params)
|
||||
):
|
||||
self.compute_api.create(self.context, flavor, 'image_id',
|
||||
requested_networks=requested_networks,
|
||||
max_count=None)
|
||||
@ -4891,7 +4893,10 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
'user_data': None,
|
||||
'numa_topology': None,
|
||||
'pci_requests': None,
|
||||
'port_resource_requests': None}
|
||||
'port_resource_requests': None,
|
||||
'request_level_params':
|
||||
objects.RequestLevelParams(),
|
||||
}
|
||||
security_groups = {}
|
||||
block_device_mapping = objects.BlockDeviceMappingList(
|
||||
objects=[objects.BlockDeviceMapping(
|
||||
@ -5062,10 +5067,12 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
'properties': {'mappings': []},
|
||||
'status': 'fake-status',
|
||||
'location': 'far-away'}
|
||||
numa_topology = objects.InstanceNUMATopology()
|
||||
pci_requests = objects.InstancePCIRequests()
|
||||
base_options = {'image_ref': 'fake-ref',
|
||||
'display_name': 'fake-name',
|
||||
'project_id': 'fake-project',
|
||||
'availability_zone': None,
|
||||
'availability_zone': 'fake-az',
|
||||
'metadata': {},
|
||||
'access_ip_v4': None,
|
||||
'access_ip_v6': None,
|
||||
@ -5076,9 +5083,13 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
'ramdisk_id': None,
|
||||
'root_device_name': None,
|
||||
'user_data': None,
|
||||
'numa_topology': None,
|
||||
'pci_requests': None,
|
||||
'port_resource_requests': None}
|
||||
'numa_topology': numa_topology,
|
||||
'pci_requests': pci_requests,
|
||||
'port_resource_requests':
|
||||
mock.sentinel.resource_reqs,
|
||||
'request_level_params':
|
||||
mock.sentinel.req_lvl_params,
|
||||
}
|
||||
security_groups = {}
|
||||
block_device_mappings = objects.BlockDeviceMappingList(
|
||||
objects=[objects.BlockDeviceMapping(
|
||||
@ -5115,6 +5126,18 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
block_device_mappings, {}, mock_get_volumes.return_value,
|
||||
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:
|
||||
self.assertIsInstance(br.instance, objects.Instance)
|
||||
self.assertTrue(uuidutils.is_uuid_like(br.instance.uuid))
|
||||
@ -5168,7 +5191,10 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
'user_data': None,
|
||||
'numa_topology': None,
|
||||
'pci_requests': None,
|
||||
'port_resource_requests': None}
|
||||
'port_resource_requests': None,
|
||||
'request_level_params':
|
||||
objects.RequestLevelParams(),
|
||||
}
|
||||
security_groups = {}
|
||||
block_device_mapping = objects.BlockDeviceMappingList(
|
||||
objects=[objects.BlockDeviceMapping(
|
||||
@ -5265,7 +5291,11 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
'user_data': None,
|
||||
'numa_topology': None,
|
||||
'pci_requests': None,
|
||||
'port_resource_requests': None}
|
||||
'port_resource_requests': None,
|
||||
'request_level_params':
|
||||
objects.RequestLevelParams(),
|
||||
}
|
||||
|
||||
security_groups = {}
|
||||
block_device_mapping = objects.BlockDeviceMappingList(
|
||||
objects=[objects.BlockDeviceMapping(
|
||||
@ -5331,7 +5361,9 @@ class _ComputeAPIUnitTestMixIn(object):
|
||||
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,
|
||||
security_groups=secgroups, port_resource_requests=mock.ANY)
|
||||
security_groups=secgroups, port_resource_requests=mock.ANY,
|
||||
request_level_params=mock.ANY
|
||||
)
|
||||
test()
|
||||
|
||||
def _test_rescue(self, vm_state=vm_states.ACTIVE, rescue_password=None,
|
||||
|
@ -8703,11 +8703,13 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
objects=[objects.NetworkRequest(port_id=uuids.port_instance)])
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(self.compute_api.compute_task_api,
|
||||
'schedule_and_build_instances'),
|
||||
mock.patch.object(self.compute_api.network_api,
|
||||
'create_resource_requests',
|
||||
return_value=(None, [])),
|
||||
mock.patch.object(
|
||||
self.compute_api.compute_task_api,
|
||||
'schedule_and_build_instances'),
|
||||
mock.patch.object(
|
||||
self.compute_api.network_api,
|
||||
'create_resource_requests',
|
||||
return_value=(None, [], objects.RequestLevelParams())),
|
||||
) as (mock_sbi, _mock_create_resreqs):
|
||||
self.compute_api.create(
|
||||
self.context,
|
||||
@ -10206,7 +10208,8 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
"_claim_pci_device_for_interface_attach",
|
||||
return_value=None)
|
||||
) 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,
|
||||
instance,
|
||||
network_id,
|
||||
@ -10266,7 +10269,8 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
mock_allocate_res
|
||||
):
|
||||
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.sentinel.provider_mappings, mock.sentinel.resources)
|
||||
vif = self.compute.attach_interface(
|
||||
@ -10311,7 +10315,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
# as this port has resource request we need to call
|
||||
# _allocate_port_resource_for_instance for it
|
||||
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')
|
||||
def test_attach_sriov_interface(self, mock_notify):
|
||||
@ -10348,7 +10354,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
# Simulate that the requested port is an SRIOV port
|
||||
pci_requests.requests.append(pci_req)
|
||||
# without resource request
|
||||
return None, []
|
||||
return None, [], mock.sentinel.req_lvl_params
|
||||
|
||||
mock_create_resource_req.side_effect = create_resource_req
|
||||
|
||||
@ -10424,7 +10430,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
# Simulate that the requested port is an SRIOV port
|
||||
pci_requests.requests.append(pci_req)
|
||||
# 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
|
||||
|
||||
@ -10475,9 +10481,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertIn(pci_device, instance.pci_devices.objects)
|
||||
|
||||
# ensure that we called _allocate_port_resource_for_instance as it has
|
||||
# resource reques
|
||||
# resource request
|
||||
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')
|
||||
def test_interface_tagged_attach(self, mock_notify):
|
||||
@ -10498,7 +10506,8 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
'_claim_pci_device_for_interface_attach',
|
||||
return_value=None)
|
||||
) 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,
|
||||
instance,
|
||||
network_id,
|
||||
@ -10574,7 +10583,8 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
) as (mock_notify, mock_attach, mock_allocate, mock_deallocate,
|
||||
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_attach.side_effect = exception.NovaException("attach_failed")
|
||||
self.assertRaises(exception.InterfaceAttachFailed,
|
||||
@ -10652,7 +10662,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
pci_requests=None, affinity_policy=None):
|
||||
# Simulate that the requested port is an SRIOV port
|
||||
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_allocate.return_value = nwinfo
|
||||
@ -10727,7 +10737,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
pci_requests=None, affinity_policy=None):
|
||||
# Simulate that the requested port is an SRIOV port
|
||||
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_allocate_res.return_value = (
|
||||
@ -10752,7 +10762,12 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertNotIn(pci_req, instance.pci_requests.requests)
|
||||
|
||||
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(
|
||||
self.context, instance.uuid, mock.sentinel.resources)
|
||||
|
||||
@ -10764,6 +10779,10 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
resources={"CUSTOM_FOO": 13},
|
||||
requester_id=uuids.requester_id)
|
||||
]
|
||||
req_lvl_params = objects.RequestLevelParams(
|
||||
root_required={"CUSTOM_BLUE"},
|
||||
same_subtree=[[uuids.group1, uuids.group2]]
|
||||
)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||
@ -10792,7 +10811,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
alloc_reqs, mock.sentinel.provider_sums, mock.sentinel.version)
|
||||
|
||||
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
|
||||
|
||||
self.assertEqual(
|
||||
@ -10808,6 +10829,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
request_groups[0].requester_id)
|
||||
self.assertEqual(request_groups[0], actual_rg)
|
||||
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(
|
||||
self.context, instance.uuid, mock.sentinel.resources)
|
||||
mock_update_pci.assert_called_once_with(
|
||||
@ -10822,6 +10848,10 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
resources={"CUSTOM_FOO": 13},
|
||||
requester_id=uuids.requester_id)
|
||||
]
|
||||
req_lvl_params = objects.RequestLevelParams(
|
||||
root_required={"CUSTOM_BLUE"},
|
||||
same_subtree=[[uuids.group1, uuids.group2]]
|
||||
)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||
@ -10847,7 +10877,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertRaises(
|
||||
exception.InterfaceAttachResourceAllocationFailed,
|
||||
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(
|
||||
self.context, instance.node)
|
||||
@ -10862,6 +10894,10 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
resources={"CUSTOM_FOO": 13},
|
||||
requester_id=uuids.requester_id)
|
||||
]
|
||||
req_lvl_params = objects.RequestLevelParams(
|
||||
root_required={"CUSTOM_BLUE"},
|
||||
same_subtree=[[uuids.group1, uuids.group2]]
|
||||
)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||
@ -10896,7 +10932,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertRaises(
|
||||
exception.InterfaceAttachResourceAllocationFailed,
|
||||
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(
|
||||
self.context, instance.node)
|
||||
@ -10907,6 +10945,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
request_groups[0].requester_id)
|
||||
self.assertEqual(request_groups[0], actual_rg)
|
||||
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(
|
||||
self.context, instance.uuid, mock.sentinel.resources)
|
||||
|
||||
@ -10918,6 +10961,10 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
resources={"CUSTOM_FOO": 13},
|
||||
requester_id=uuids.requester_id)
|
||||
]
|
||||
req_lvl_params = objects.RequestLevelParams(
|
||||
root_required={"CUSTOM_BLUE"},
|
||||
same_subtree=[[uuids.group1, uuids.group2]]
|
||||
)
|
||||
|
||||
with test.nested(
|
||||
mock.patch.object(objects.ComputeNode, 'get_by_nodename'),
|
||||
@ -10954,7 +11001,9 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
self.assertRaises(
|
||||
exception.AmbiguousResourceProviderForPCIRequest,
|
||||
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(
|
||||
self.context, instance.node)
|
||||
@ -10965,6 +11014,11 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
request_groups[0].requester_id)
|
||||
self.assertEqual(request_groups[0], actual_rg)
|
||||
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(
|
||||
self.context, instance.uuid, mock.sentinel.resources)
|
||||
mock_update_pci.assert_called_once_with(
|
||||
|
@ -2627,7 +2627,8 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
||||
def do_test(
|
||||
update, meth, add_fault, notify, event, mock_claim_pci,
|
||||
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.compute.attach_interface,
|
||||
self.context, f_instance, uuids.network_id,
|
||||
|
@ -5789,7 +5789,7 @@ class TestAPI(TestAPIBase):
|
||||
|
||||
result = api.create_resource_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.assertIsNone(network_metadata)
|
||||
@ -5816,7 +5816,7 @@ class TestAPI(TestAPIBase):
|
||||
|
||||
result = api.create_resource_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()
|
||||
self.assertEqual(set(), network_metadata.physnets)
|
||||
@ -5875,7 +5875,7 @@ class TestAPI(TestAPIBase):
|
||||
|
||||
result = api.create_resource_requests(
|
||||
self.context, requested_networks, pci_requests)
|
||||
network_metadata, port_resource_requests = result
|
||||
network_metadata, port_resource_requests, _ = result
|
||||
|
||||
self.assertEqual([
|
||||
mock.sentinel.request_group1,
|
||||
@ -5982,7 +5982,7 @@ class TestAPI(TestAPIBase):
|
||||
result = self.api.create_resource_requests(
|
||||
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_physnet_tunneled_info.assert_called_once_with(
|
||||
self.context, mock.ANY, 'netN')
|
||||
@ -6046,6 +6046,12 @@ class TestAPI(TestAPIBase):
|
||||
@mock.patch.object(
|
||||
neutronapi.API, '_has_extended_resource_request_extension',
|
||||
return_value=True)
|
||||
@mock.patch(
|
||||
'nova.objects.request_spec.RequestLevelParams.extend_with'
|
||||
)
|
||||
@mock.patch(
|
||||
'nova.objects.request_spec.RequestLevelParams.from_port_request'
|
||||
)
|
||||
@mock.patch(
|
||||
'nova.objects.request_spec.RequestGroup.from_extended_port_request')
|
||||
@mock.patch.object(neutronapi.API, '_get_physnet_tunneled_info')
|
||||
@ -6054,6 +6060,7 @@ class TestAPI(TestAPIBase):
|
||||
def test_create_resource_request_extended(
|
||||
self, getclient, mock_get_port_vnic_info,
|
||||
mock_get_physnet_tunneled_info, mock_from_port_request,
|
||||
mock_req_lvl_param, mock_extened_req_lvl_param,
|
||||
mock_has_extended_res_req
|
||||
):
|
||||
requested_networks = objects.NetworkRequestList(
|
||||
@ -6088,10 +6095,15 @@ class TestAPI(TestAPIBase):
|
||||
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(
|
||||
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
|
||||
self.assertEqual(
|
||||
@ -6102,6 +6114,23 @@ class TestAPI(TestAPIBase):
|
||||
mock.sentinel.port2_request_group2,
|
||||
],
|
||||
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.call(
|
||||
|
@ -412,13 +412,17 @@ class _TestRequestSpecObject(object):
|
||||
filter_properties = {'fake': 'property'}
|
||||
|
||||
rg = request_spec.RequestGroup()
|
||||
req_lvl_params = request_spec.RequestLevelParams()
|
||||
|
||||
spec = objects.RequestSpec.from_components(ctxt, instance.uuid, image,
|
||||
flavor, instance.numa_topology, instance.pci_requests,
|
||||
filter_properties, None, instance.availability_zone,
|
||||
port_resource_requests=[rg])
|
||||
spec = objects.RequestSpec.from_components(
|
||||
ctxt, instance.uuid, image,
|
||||
flavor, instance.numa_topology, instance.pci_requests,
|
||||
filter_properties, None, instance.availability_zone,
|
||||
port_resource_requests=[rg], request_level_params=req_lvl_params
|
||||
)
|
||||
|
||||
self.assertListEqual([rg], spec.requested_resources)
|
||||
self.assertEqual(req_lvl_params, spec.request_level_params)
|
||||
|
||||
def test_get_scheduler_hint(self):
|
||||
spec_obj = objects.RequestSpec(scheduler_hints={'foo_single': ['1'],
|
||||
|
@ -1369,8 +1369,13 @@ class TestUtils(TestUtilsBase):
|
||||
"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(
|
||||
f'limit=1000&'
|
||||
@ -1379,7 +1384,9 @@ class TestUtils(TestUtilsBase):
|
||||
f'CUSTOM_VNIC_TYPE_NORMAL&'
|
||||
f'resources{uuids.port_id}='
|
||||
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())
|
||||
|
||||
def test_resource_request_add_group_inserts_the_group(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user