Merge "Validate flavor image min ram when resize volume-backed instance"

This commit is contained in:
Zuul 2024-04-19 23:35:17 +00:00 committed by Gerrit Code Review
commit 3abea334d5
3 changed files with 48 additions and 2 deletions

View File

@ -4269,6 +4269,12 @@ class API:
if volume_backed:
self._validate_flavor_image_numa_pci(
image, new_flavor, validate_pci=True)
# The server that image-backed already has the verification of
# image min_ram when calling _validate_flavor_image_nostatus.
# Here, the verification is added for the server that
# volume-backed.
if new_flavor['memory_mb'] < int(image.get('min_ram', 0)):
raise exception.FlavorMemoryTooSmall()
else:
self._validate_flavor_image_nostatus(
context, image, new_flavor, root_bdm=None,

View File

@ -13,6 +13,7 @@
import fixtures
from nova.tests.fixtures import libvirt as fakelibvirt
from nova.tests.functional.api import client
from nova.tests.functional.libvirt import base
@ -56,5 +57,11 @@ class Bug2007968RegressionTest(base.ServersTestBase):
# This can cause the instance for boot from volume to be allowed to
# get to the resize verify status, but the instance's application runs
# abnormally due to insufficient memory, and it may be killed by OOM.
server = self._resize_server(server, new_flavor)
self.assertEqual(server['status'], 'VERIFY_RESIZE')
# After the fix, compute api will directly raise FlavorMemoryTooSmall
# and will not continue the resize.
ex = self.assertRaises(client.OpenStackApiException,
self._resize_server, server, new_flavor)
self.assertEqual(400, ex.response.status_code)
self.assertIn('Flavor\'s memory is too small for requested image.',
ex.response.text)

View File

@ -2376,6 +2376,39 @@ class _ComputeAPIUnitTestMixIn(object):
mock_resize.assert_not_called()
mock_save.assert_not_called()
@mock.patch('nova.compute.utils.is_volume_backed_instance',
return_value=True)
@mock.patch('nova.servicegroup.api.API.service_is_up',
new=mock.Mock(return_value=True))
@mock.patch.object(objects.Instance, 'save')
@mock.patch.object(compute_api.API, '_record_action_start')
@mock.patch.object(quotas_obj.Quotas, 'limit_check_project_and_user')
@mock.patch.object(quotas_obj.Quotas, 'count_as_dict')
@mock.patch.object(flavors, 'get_flavor_by_flavor_id')
def test_resize_vol_backed_smaller_min_ram(self, mock_get_flavor,
mock_count, mock_limit,
mock_record, mock_save,
mock_is_vol_backed):
mock_resize = self.useFixture(fixtures.MockPatchObject(
self.compute_api.compute_task_api, 'resize_instance')).mock
# Resize down from 512 MB to 64 MB.
params = dict(image_ref='', system_metadata={'min_ram': 512})
fake_inst = self._create_instance_obj(params=params)
new_flavor = self._create_flavor(id=200, flavorid=200,
name='new_flavor', disabled=False,
memory_mb=64)
mock_get_flavor.return_value = new_flavor
self.assertRaises(exception.FlavorMemoryTooSmall,
self.compute_api.resize, self.context,
fake_inst, flavor_id=new_flavor.id)
mock_get_flavor.assert_called_once_with(200, read_deleted='no')
# Should never reach these.
mock_count.assert_not_called()
mock_limit.assert_not_called()
mock_record.assert_not_called()
mock_resize.assert_not_called()
mock_save.assert_not_called()
@mock.patch('nova.servicegroup.api.API.service_is_up',
new=mock.Mock(return_value=True))
@mock.patch.object(objects.Instance, 'save')