diff --git a/api-guide/source/port_with_resource_request.rst b/api-guide/source/port_with_resource_request.rst index 867dd01812..2d4cc113e2 100644 --- a/api-guide/source/port_with_resource_request.rst +++ b/api-guide/source/port_with_resource_request.rst @@ -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 ` for administrative details. diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 731818ce26..9061535104 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -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): diff --git a/nova/api/openstack/compute/shelve.py b/nova/api/openstack/compute/shelve.py index 1783013a04..680d592655 100644 --- a/nova/api/openstack/compute/shelve.py +++ b/nova/api/openstack/compute/shelve.py @@ -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: diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index 021f9f0f82..e38234ba27 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -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 diff --git a/nova/tests/unit/api/openstack/compute/test_migrate_server.py b/nova/tests/unit/api/openstack/compute/test_migrate_server.py index 4785631c80..4416405f3d 100644 --- a/nova/tests/unit/api/openstack/compute/test_migrate_server.py +++ b/nova/tests/unit/api/openstack/compute/test_migrate_server.py @@ -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']) diff --git a/nova/tests/unit/api/openstack/compute/test_server_actions.py b/nova/tests/unit/api/openstack/compute/test_server_actions.py index 87b77b2221..4a25a3cd66 100644 --- a/nova/tests/unit/api/openstack/compute/test_server_actions.py +++ b/nova/tests/unit/api/openstack/compute/test_server_actions.py @@ -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 diff --git a/releasenotes/notes/support-unshelving-servers-with-neutron-ports-with-resource-request-d91a282fe56c7489.yaml b/releasenotes/notes/support-unshelving-servers-with-neutron-ports-with-resource-request-d91a282fe56c7489.yaml new file mode 100644 index 0000000000..d9a5bfd309 --- /dev/null +++ b/releasenotes/notes/support-unshelving-servers-with-neutron-ports-with-resource-request-d91a282fe56c7489.yaml @@ -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.