summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api-guide/source/port_with_resource_request.rst3
-rw-r--r--doc/source/admin/configuration/cross-cell-resize.rst3
-rw-r--r--nova/compute/api.py17
-rw-r--r--nova/tests/functional/test_servers.py39
-rw-r--r--nova/tests/unit/compute/test_api.py32
-rw-r--r--releasenotes/notes/cros-scell-resize-not-supported-with-ports-having-resource-request-a8e1029ef5983793.yaml4
6 files changed, 65 insertions, 33 deletions
diff --git a/api-guide/source/port_with_resource_request.rst b/api-guide/source/port_with_resource_request.rst
index b09698c008..b5bb5bc491 100644
--- a/api-guide/source/port_with_resource_request.rst
+++ b/api-guide/source/port_with_resource_request.rst
@@ -30,7 +30,8 @@ neutron ports having resource requests if both the source and destination
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. However cross cell resize and cross cell migrate
-operations are still not supported with such ports.
+operations are still not supported with such ports and Nova will fall back to
+same-cell resize if the server has such ports.
As of 21.0.0 (Ussuri), nova supports evacuating, live migrating and unshelving
servers with neutron ports having resource requests.
diff --git a/doc/source/admin/configuration/cross-cell-resize.rst b/doc/source/admin/configuration/cross-cell-resize.rst
index 8a82b60417..d17ee24109 100644
--- a/doc/source/admin/configuration/cross-cell-resize.rst
+++ b/doc/source/admin/configuration/cross-cell-resize.rst
@@ -237,7 +237,8 @@ These are known to not yet be supported in the code:
* Instances with ports attached that have
:doc:`bandwidth-aware </admin/ports-with-resource-requests>` resource
- provider allocations.
+ provider allocations. Nova falls back to same-cell resize if the server has
+ such ports.
* Rescheduling to alternative hosts within the same target cell in case the
primary selected host fails the ``prep_snapshot_based_resize_at_dest`` call.
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 61e20cfa1a..4ea4e9d27a 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -3852,8 +3852,7 @@ class API(base.Base):
migration,
migration.source_compute)
- @staticmethod
- def _allow_cross_cell_resize(context, instance):
+ def _allow_cross_cell_resize(self, context, instance):
"""Determine if the request can perform a cross-cell resize on this
instance.
@@ -3861,8 +3860,6 @@ class API(base.Base):
:param instance: Instance object being resized
:returns: True if cross-cell resize is allowed, False otherwise
"""
- # TODO(gibi): do not allow cross cell migration if the instance has
- # neutron ports with resource request. See bug 1907522.
# First check to see if the requesting project/user is allowed by
# policy to perform cross-cell resize.
allowed = context.can(
@@ -3885,7 +3882,17 @@ class API(base.Base):
'version in the deployment %s is less than %s so '
'cross-cell resize is not allowed at this time.',
min_compute_version, MIN_COMPUTE_CROSS_CELL_RESIZE)
- allowed = False
+ return False
+
+ if self.network_api.get_requested_resource_for_instance(
+ context, instance.uuid):
+ LOG.info(
+ 'Request is allowed by policy to perform cross-cell '
+ 'resize but the instance has ports with resource request '
+ 'and cross-cell resize is not supported with such ports.',
+ instance=instance)
+ return False
+
return allowed
@staticmethod
diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py
index a7a3eb506d..342c13c37e 100644
--- a/nova/tests/functional/test_servers.py
+++ b/nova/tests/functional/test_servers.py
@@ -8025,41 +8025,36 @@ class CrossCellResizeWithQoSPort(PortResourceRequestBasedSchedulingTestBase):
# host is in a different cell and while cross cell migration is
# enabled it is not supported for neutron ports with resource
# request.
- # FIXME(gibi): We expect this to fail with NoValidHost.
- # Unfortunately it fails due to sending an invalid port binding to
- # Neutron today. This is bug 1907522.
self.api.post_server_action(server['id'], {'migrate': None})
self._wait_for_migration_status(server, ['error'])
- # FIXME(gibi): This is also the result of the bug1907522 as the
- # cleanup after the failure is incomplete.
self._wait_for_server_parameter(
server,
- {'status': 'RESIZE', 'OS-EXT-STS:task_state': 'resize_prep'})
+ {'status': 'ACTIVE', 'OS-EXT-SRV-ATTR:host': 'host1'})
event = self._wait_for_action_fail_completion(
server, 'migrate', 'conductor_migrate_server')
- # This is just the last exception in the chain of exceptions
- # happening after the port binding fails.
self.assertIn(
- 'exception.InstanceInfoCacheNotFound', event['traceback'])
- # This is the root case
+ 'exception.NoValidHost', event['traceback'])
self.assertIn(
+ 'Request is allowed by policy to perform cross-cell resize '
+ 'but the instance has ports with resource request and '
+ 'cross-cell resize is not supported with such ports.',
+ self.stdlog.logger.output)
+ self.assertNotIn(
'nova.exception.PortBindingFailed: Binding failed for port',
self.stdlog.logger.output)
# Now start a new compute in the same cell as the instance and retry
# the migration.
- #
- # This should work after the fallback to same cell resize is
- # implemented
- #
- # self._start_compute('host3', cell_name='cell1')
- #
- # with mock.patch(
- # 'nova.network.neutron.API._create_port_binding',
- # side_effect=spy_on_create_binding, autospec=True
- # ):
- # server = self._migrate_server(server)
- # self.assertEqual('host3', server['OS-EXT-SRV-ATTR:host'])
+ self._start_compute('host3', cell_name='cell1')
+ self.compute3_rp_uuid = self._get_provider_uuid_by_host('host3')
+ self._create_networking_rp_tree('host3', self.compute3_rp_uuid)
+
+ with mock.patch(
+ 'nova.network.neutron.API._create_port_binding',
+ side_effect=spy_on_create_binding, autospec=True
+ ):
+ server = self._migrate_server(server)
+ self.assertEqual('host3', server['OS-EXT-SRV-ATTR:host'])
self._delete_server_and_check_allocations(
server, qos_normal_port, qos_sriov_port)
diff --git a/nova/tests/unit/compute/test_api.py b/nova/tests/unit/compute/test_api.py
index 8e9d651325..552bca3544 100644
--- a/nova/tests/unit/compute/test_api.py
+++ b/nova/tests/unit/compute/test_api.py
@@ -7522,28 +7522,54 @@ class ComputeAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase):
version is not new enough.
"""
instance = objects.Instance(
- project_id='fake-project', user_id='fake-user')
+ project_id='fake-project', user_id='fake-user',
+ uuid=uuids.instance)
+ with mock.patch.object(self.context, 'can', return_value=True) as can:
+ self.assertFalse(self.compute_api._allow_cross_cell_resize(
+ self.context, instance))
+ can.assert_called_once()
+ mock_get_min_ver.assert_called_once_with(
+ self.context, ['nova-compute'])
+
+ @mock.patch('nova.network.neutron.API.get_requested_resource_for_instance',
+ return_value=[objects.RequestGroup()])
+ @mock.patch('nova.objects.service.get_minimum_version_all_cells',
+ return_value=compute_api.MIN_COMPUTE_CROSS_CELL_RESIZE)
+ def test_allow_cross_cell_resize_false_port_with_resource_req(
+ self, mock_get_min_ver, mock_get_res_req):
+ """Policy allows cross-cell resize but minimum nova-compute service
+ version is not new enough.
+ """
+ instance = objects.Instance(
+ project_id='fake-project', user_id='fake-user',
+ uuid=uuids.instance)
with mock.patch.object(self.context, 'can', return_value=True) as can:
self.assertFalse(self.compute_api._allow_cross_cell_resize(
self.context, instance))
can.assert_called_once()
mock_get_min_ver.assert_called_once_with(
self.context, ['nova-compute'])
+ mock_get_res_req.assert_called_once_with(self.context, uuids.instance)
+ @mock.patch('nova.network.neutron.API.get_requested_resource_for_instance',
+ return_value=[])
@mock.patch('nova.objects.service.get_minimum_version_all_cells',
return_value=compute_api.MIN_COMPUTE_CROSS_CELL_RESIZE)
- def test_allow_cross_cell_resize_true(self, mock_get_min_ver):
+ def test_allow_cross_cell_resize_true(
+ self, mock_get_min_ver, mock_get_res_req):
"""Policy allows cross-cell resize and minimum nova-compute service
version is new enough.
"""
instance = objects.Instance(
- project_id='fake-project', user_id='fake-user')
+ project_id='fake-project', user_id='fake-user',
+ uuid=uuids.instance)
with mock.patch.object(self.context, 'can', return_value=True) as can:
self.assertTrue(self.compute_api._allow_cross_cell_resize(
self.context, instance))
can.assert_called_once()
mock_get_min_ver.assert_called_once_with(
self.context, ['nova-compute'])
+ mock_get_res_req.assert_called_once_with(self.context, uuids.instance)
def _test_block_accelerators(self, instance, args_info,
until_service=None):
diff --git a/releasenotes/notes/cros-scell-resize-not-supported-with-ports-having-resource-request-a8e1029ef5983793.yaml b/releasenotes/notes/cros-scell-resize-not-supported-with-ports-having-resource-request-a8e1029ef5983793.yaml
index 678eddcebd..31498a9d9c 100644
--- a/releasenotes/notes/cros-scell-resize-not-supported-with-ports-having-resource-request-a8e1029ef5983793.yaml
+++ b/releasenotes/notes/cros-scell-resize-not-supported-with-ports-having-resource-request-a8e1029ef5983793.yaml
@@ -4,4 +4,6 @@ issues:
When the tempest test coverage was added for resize and cold migrate
with neutron ports having QoS minimum bandwidth policy rules we
discovered that the cross cell resize code path cannot handle such ports.
- See bug https://bugs.launchpad.net/nova/+bug/1907522 for details.
+ See bug https://bugs.launchpad.net/nova/+bug/1907522 for details. A fix
+ was implemented that makes sure that Nova falls back to same-cell resize if
+ the server has such ports.