Enable unshelve with qos ports

Previous patches in the blueprint implemented the support for unshelve
with qos ports and added functional test coverage for the
various scenarios. So this patch changes the API check
that rejected such operation to check for the service version and therefore
conditionally enable the feature.

Change-Id: Iaf70ee41f1bfb1a4964da3f59cd3a0b4b5e20d36
blueprint: support-move-ops-with-qos-ports-ussuri
This commit is contained in:
Balazs Gibizer 2020-03-18 10:56:32 +01:00
parent 94c7e7ad43
commit a4c3260f56
7 changed files with 43 additions and 56 deletions

View File

@ -31,8 +31,8 @@ compute services are upgraded to 20.0.0 (Train) and the
``[upgrade_levels]/compute`` configuration does not prevent the computes from
using the latest RPC version.
As of 21.0.0 (Ussuri), nova supports evacuating and live migrating servers
with neutron ports having resource requests.
As of 21.0.0 (Ussuri), nova supports evacuating, live migrating and unshelving
servers with neutron ports having resource requests.
See :nova-doc:`the admin guide <admin/port_with_resource_request.html>` for
administrative details.

View File

@ -33,6 +33,7 @@ from nova import exception
from nova.i18n import _
from nova.network import constants
from nova import objects
from nova.objects import service
from nova import quota
from nova import utils
@ -558,20 +559,15 @@ def supports_port_resource_request(req):
return api_version_request.is_supported(req, '2.72')
def supports_port_resource_request_during_move(req):
"""Check to see if the requested API version is high enough for support
port resource request during move operation.
def supports_port_resource_request_during_move():
"""Check to see if the global compute service version is high enough to
support port resource request during move operation.
NOTE: At the moment there is no such microversion that supports port
resource request during move. This function is added as a preparation for
that microversion (assuming there will be a new microversion, which is
yet to be decided).
:param req: The incoming API request
:returns: True if the requested API microversion is high enough for
:returns: True if the compute service version is high enough for
port resource request move support, False otherwise.
"""
return False
return service.get_minimum_version_all_cells(
nova_context.get_admin_context(), ['nova-compute']) >= 49
def instance_has_port_with_resource_request(instance_uuid, network_api):

View File

@ -14,6 +14,7 @@
"""The shelved mode extension."""
from oslo_log import log as logging
from webob import exc
from nova.api.openstack import api_version_request
@ -28,6 +29,8 @@ from nova.i18n import _
from nova.network import neutron
from nova.policies import shelve as shelve_policies
LOG = logging.getLogger(__name__)
class ShelveController(wsgi.Controller):
def __init__(self):
@ -98,12 +101,15 @@ class ShelveController(wsgi.Controller):
if (instance.vm_state == vm_states.SHELVED_OFFLOADED and
common.instance_has_port_with_resource_request(
instance.uuid, self.network_api) and
not common.supports_port_resource_request_during_move(
req)):
not common.supports_port_resource_request_during_move()):
LOG.warning("The unshelve action on a server with ports having "
"resource requests, like a port with a QoS minimum "
"bandwidth policy, is not supported until every "
"nova-compute is upgraded to Ussuri")
msg = _("The unshelve action on a server with ports having "
"resource requests, like a port with a QoS minimum "
"bandwidth policy, is not supported with this "
"microversion")
"bandwidth policy, is not supported by this cluster right "
"now")
raise exc.HTTPBadRequest(explanation=msg)
try:

View File

@ -6025,14 +6025,25 @@ class UnsupportedPortResourceRequestBasedSchedulingTest(
# can exist with such a port.
self._add_resource_request_to_a_bound_port(self.neutron.port_1['id'])
ex = self.assertRaises(
client.OpenStackApiException,
self.api.post_server_action, server['id'], {'unshelve': None})
with mock.patch(
"nova.objects.service.get_minimum_version_all_cells",
return_value=48,
):
ex = self.assertRaises(
client.OpenStackApiException,
self.api.post_server_action, server['id'], {'unshelve': None})
self.assertEqual(400, ex.response.status_code)
self.assertIn(
'The unshelve action on a server with ports having resource '
'requests', six.text_type(ex))
"The unshelve action on a server with ports having resource "
"requests, like a port with a QoS minimum bandwidth policy, is "
"not supported by this cluster right now",
six.text_type(ex))
self.assertIn(
"The unshelve action on a server with ports having resource "
"requests, like a port with a QoS minimum bandwidth policy, is "
"not supported until every nova-compute is upgraded to Ussuri",
self.stdlog.logger.output)
def test_unshelve_not_offloaded_server_with_port_resource_request(
self):
@ -6076,7 +6087,6 @@ class NonAdminUnsupportedPortResourceRequestBasedSchedulingTest(
# allow non-admin to call the operations
self.policy.set_rules({
'os_compute_api:os-evacuate': '@',
'os_compute_api:servers:create': '@',
'os_compute_api:servers:create:attach_network': '@',
'os_compute_api:servers:show': '@',
@ -6084,7 +6094,6 @@ class NonAdminUnsupportedPortResourceRequestBasedSchedulingTest(
'os_compute_api:os-attach-interfaces:create': '@',
'os_compute_api:os-shelve:shelve': '@',
'os_compute_api:os-shelve:unshelve': '@',
'os_compute_api:os-migrate-server:migrate_live': '@',
})
@ -7409,23 +7418,7 @@ class ServerMoveWithPortResourceRequestTest(
self._delete_server_and_check_allocations(
server, qos_normal_port, qos_sriov_port)
def _turn_off_api_check(self):
# The API actively rejecting the move operations with resource
# request so we have to turn off that check.
# TODO(gibi): Remove this when the move operations are supported and
# the API check is removed.
patcher = mock.patch(
'nova.api.openstack.common.'
'supports_port_resource_request_during_move',
return_value=True)
self.addCleanup(patcher.stop)
patcher.start()
def test_unshelve_offloaded_server_with_qos_port(self):
# TODO(gibi): remove this when live migration is fully supported and
# therefore the check is removed from the api
self._turn_off_api_check()
non_qos_normal_port = self.neutron.port_1
qos_normal_port = self.neutron.port_with_resource_request
qos_sriov_port = self.neutron.port_with_sriov_resource_request
@ -7486,10 +7479,6 @@ class ServerMoveWithPortResourceRequestTest(
server, qos_normal_port, qos_sriov_port)
def test_unshelve_offloaded_server_with_qos_port_pci_update_fails(self):
# TODO(gibi): remove this when live migration is fully supported and
# therefore the check is removed from the api
self._turn_off_api_check()
# Update the name of the network device RP of PF2 on host2 to something
# unexpected. This will cause
# update_pci_request_spec_with_allocated_interface_name() to raise
@ -7548,10 +7537,6 @@ class ServerMoveWithPortResourceRequestTest(
def test_unshelve_offloaded_server_with_qos_port_fails_due_to_neutron(
self):
# TODO(gibi): remove this when live migration is fully supported and
# therefore the check is removed from the api
self._turn_off_api_check()
non_qos_normal_port = self.neutron.port_1
qos_normal_port = self.neutron.port_with_resource_request
qos_sriov_port = self.neutron.port_with_sriov_resource_request

View File

@ -295,14 +295,11 @@ class MigrateServerTestsV21(admin_only_action_common.CommonTests):
expected_exc=webob.exc.HTTPInternalServerError,
check_response=False)
@mock.patch('nova.api.openstack.common.'
'supports_port_resource_request_during_move',
return_value=True)
@mock.patch('nova.objects.Service.get_by_host_and_binary')
@mock.patch('nova.api.openstack.common.'
'instance_has_port_with_resource_request', return_value=True)
def test_migrate_with_bandwidth_from_old_compute_not_supported(
self, mock_has_res_req, mock_get_service, mock_support):
self, mock_has_res_req, mock_get_service):
instance = self._stub_instance_get()
mock_get_service.return_value = objects.Service(host=instance['host'])

View File

@ -1247,14 +1247,11 @@ class ServerActionsControllerTestV21(test.TestCase):
self.controller._action_create_image,
self.req, FAKE_UUID, body=body)
@mock.patch('nova.api.openstack.common.'
'supports_port_resource_request_during_move',
return_value=True)
@mock.patch('nova.objects.Service.get_by_host_and_binary')
@mock.patch('nova.api.openstack.common.'
'instance_has_port_with_resource_request', return_value=True)
def test_resize_with_bandwidth_from_old_compute_not_supported(
self, mock_has_res_req, mock_get_service, mock_support):
self, mock_has_res_req, mock_get_service):
body = dict(resize=dict(flavorRef="http://localhost/3"))
mock_get_service.return_value = objects.Service()
mock_get_service.return_value.version = 38

View File

@ -0,0 +1,6 @@
---
features:
- |
The server ``unshelve`` action API now supports servers with neutron
ports having resource requests, e.g. ports that have QoS minimum bandwidth
rules attached.