Reject interface attach with QoS aware port

Attaching a port with minimum bandwidth policy would require to update
the allocation of the server. But for that nova would need to select the
proper networking resource provider under the compute resource provider
the server is running on.

For the first iteration of the feature we consider this out of scope. To
avoid resource allocation inconsistencies this patch propose to reject
such attach interface request. Rejecting such interface attach does not
break existing functionality as today only the SRIOV Neutron backend
supports the minimum bandwidth policy but Nova does not support
interface attach with SRIOV interfaces today.

A subsequent patch will handle attaching a network that has QoS policy.

Co-Authored-By: Elod Illes <elod.illes@ericsson.com>

Change-Id: Id8b5c48a6e8cf65dc0a7dc13a80a0a72684f70d9
blueprint: bandwidth-resource-provider
This commit is contained in:
Balazs Gibizer 2018-05-22 15:13:55 -07:00
parent dcdfec70f5
commit bd6f33070b
6 changed files with 88 additions and 1 deletions

View File

@ -4377,6 +4377,17 @@ class API(base.Base):
"""Use hotplug to add an network adapter to an instance."""
self._record_action_start(
context, instance, instance_actions.ATTACH_INTERFACE)
# NOTE(gibi): Checking if the requested port has resource request as
# such ports are currently not supported as they would at least
# need resource allocation manipulation in placement but might also
# need a new scheduling if resource on this host is not available.
if port_id:
port = self.network_api.show_port(context, port_id)
if port['port'].get('resource_request'):
raise exception.AttachInterfaceWithQoSPolicyNotSupported(
instance_uuid=instance.uuid)
return self.compute_rpcapi.attach_interface(context,
instance=instance, network_id=network_id, port_id=port_id,
requested_ip=requested_ip, tag=tag)

View File

@ -2143,6 +2143,11 @@ class AttachInterfaceNotSupported(Invalid):
"instance %(instance_uuid)s.")
class AttachInterfaceWithQoSPolicyNotSupported(AttachInterfaceNotSupported):
msg_fmt = _("Attaching interfaces with QoS policy is not supported for "
"instance %(instance_uuid)s.")
class InvalidReservedMemoryPagesOption(Invalid):
msg_fmt = _("The format of the option 'reserved_huge_pages' is invalid. "
"(found '%(conf)s') Please refer to the nova "

View File

@ -367,7 +367,7 @@ class ProviderUsageBaseTestCase(test.TestCase, InstanceHelperMixin):
super(ProviderUsageBaseTestCase, self).setUp()
self.useFixture(policy_fixture.RealPolicyFixture())
self.useFixture(nova_fixtures.NeutronFixture(self))
self.neutron = self.useFixture(nova_fixtures.NeutronFixture(self))
self.useFixture(nova_fixtures.AllServicesCurrent())
fake_notifier.stub_notifier(self)

View File

@ -5351,3 +5351,47 @@ class ServerMovingTestsFromFlatToNested(
source_rp_uuid)
self._delete_and_check_allocations(server)
class PortResourceRequestBasedSchedulingTestBase(
integrated_helpers.ProviderUsageBaseTestCase):
compute_driver = 'fake.SmallFakeDriver'
def setUp(self):
super(PortResourceRequestBasedSchedulingTestBase, self).setUp()
self.compute1 = self._start_compute('host1')
self.compute1_rp_uuid = self._get_provider_uuid_by_host('host1')
self.flavor = self.api.get_flavors()[0]
def _create_server(self, flavor, networks):
server_req = self._build_minimal_create_server_request(
self.api, 'bandwidth-aware-server',
image_uuid='76fa36fc-c930-4bf3-8c8a-ea2a2420deb6',
flavor_id=flavor['id'], networks=networks)
return self.api.post_server({'server': server_req})
class PortResourceRequestBasedSchedulingTest(
PortResourceRequestBasedSchedulingTestBase):
"""Tests for handling servers with ports having resource requests """
def test_interface_attach_with_port_resource_request(self):
# create a server
server = self._create_server(
flavor=self.flavor,
networks=[{'port': self.neutron.port_1['id']}])
self._wait_for_state_change(self.admin_api, server, 'ACTIVE')
# try to add a port with resource request
post = {
'interfaceAttachment': {
'port_id': self.neutron.port_with_resource_request['id']
}}
ex = self.assertRaises(client.OpenStackApiException,
self.api.attach_interface,
server['id'], post)
self.assertEqual(400, ex.response.status_code)
self.assertIn('Attaching interfaces with QoS policy is '
'not supported for instance',
six.text_type(ex))

View File

@ -6434,6 +6434,23 @@ class ComputeAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase):
mock_record.assert_called_once_with(
self.context, instance, instance_actions.ATTACH_INTERFACE)
@mock.patch('nova.compute.api.API._record_action_start')
def test_attach_interface_qos_aware_port(self, mock_record):
instance = self._create_instance_obj()
with mock.patch.object(
self.compute_api.network_api, 'show_port',
return_value={'port': {
'resource_request': {
'resources': {'CUSTOM_RESOURCE_CLASS': 42}
}}}) as mock_show_port:
self.assertRaises(
exception.AttachInterfaceWithQoSPolicyNotSupported,
self.compute_api.attach_interface,
self.context, instance,
'foo_net_id', 'foo_port_id', None
)
mock_show_port.assert_called_once_with(self.context, 'foo_port_id')
@mock.patch('nova.compute.api.API._record_action_start')
@mock.patch.object(compute_rpcapi.ComputeAPI, 'detach_interface')
def test_detach_interface(self, mock_detach, mock_record):

View File

@ -0,0 +1,10 @@
---
other:
- |
The ``POST /servers/{server_id}/os-interface`` request will be rejected
with HTTP 400 if the Neutron port referenced in the request body has
resource request as Nova currently cannot support such operation. For
example a Neutron port has resource request if a `QoS minimum bandwidth
rule`_ is attached to that port in Neutron.
.. _QoS minimum bandwidth rule: https://docs.openstack.org/neutron/latest/admin/config-qos.html