Add get_flavor_id method to nova_helper
The get_flavor_id method is extracted from resize_instance to improve code reusability. That method will be used in the pre_condition of resize action. Add comprehensive unit tests for the get_flavor_id method in nova_helper. Assisted-By: Claude (Sonnet 4.5) Change-Id: I31c60521e98ea223bd1b66d3fe66f3212e1036a9 Signed-off-by: Alfredo Moralejo <amoralej@redhat.com>
This commit is contained in:
@@ -569,6 +569,28 @@ class NovaHelper:
|
||||
flavors = self.connection.compute.flavors(is_public=None)
|
||||
return [Flavor.from_openstacksdk(f) for f in flavors]
|
||||
|
||||
def get_flavor_id(self, flavor):
|
||||
"""Get the flavor id for a given flavor name or id.
|
||||
|
||||
:param flavor: the name or id of the flavor to get
|
||||
:returns: the flavor id if found
|
||||
:raises: ComputeResourceNotFound if no flavor was found
|
||||
:raises: NovaClientError if there is any problem while calling the
|
||||
Nova api
|
||||
"""
|
||||
|
||||
try:
|
||||
flavor_obj = self._get_flavor(flavor)
|
||||
return flavor_obj.id
|
||||
except exception.ComputeResourceNotFound:
|
||||
flavor_id = next((f.id for f in self.get_flavor_list() if
|
||||
f.flavor_name == flavor), None)
|
||||
if flavor_id:
|
||||
return flavor_id
|
||||
|
||||
msg = f"{flavor} of type Flavor"
|
||||
raise exception.ComputeResourceNotFound(msg)
|
||||
|
||||
@nova_retries
|
||||
@handle_nova_error("Flavor")
|
||||
def _get_flavor(self, flavor):
|
||||
@@ -873,18 +895,13 @@ class NovaHelper:
|
||||
flavor_id = None
|
||||
|
||||
try:
|
||||
try:
|
||||
flavor_obj = self._get_flavor(flavor)
|
||||
flavor_id = flavor_obj.id
|
||||
except exception.ComputeResourceNotFound:
|
||||
flavor_id = next((f.id for f in self.get_flavor_list() if
|
||||
f.flavor_name == flavor), None)
|
||||
flavor_id = self.get_flavor_id(flavor)
|
||||
except exception.ComputeResourceNotFound:
|
||||
LOG.debug("Flavor not found: %s, could not resize", flavor)
|
||||
return False
|
||||
except exception.NovaClientError as e:
|
||||
LOG.debug("Nova client exception occurred while resizing "
|
||||
"instance %s. Exception: %s", instance_id, e)
|
||||
|
||||
if not flavor_id:
|
||||
LOG.debug("Flavor not found: %s, could not resize", flavor)
|
||||
return False
|
||||
|
||||
instance_status = instance.vm_state
|
||||
|
||||
@@ -1308,6 +1308,135 @@ class TestNovaHelper(test_utils.NovaResourcesMixin, base.TestCase):
|
||||
# Verify that the result is cached
|
||||
self.assertIsNotNone(nova_util._is_pinned_az_available)
|
||||
|
||||
def test_get_flavor_id_by_id(self, mock_cinder):
|
||||
"""Test get_flavor_id returns id when flavor is found by ID."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_id = 'flavor-123'
|
||||
flavor = self.create_openstacksdk_flavor(
|
||||
id=flavor_id, name='m1.small'
|
||||
)
|
||||
self.mock_connection.compute.get_flavor.return_value = flavor
|
||||
|
||||
result = nova_util.get_flavor_id(flavor_id)
|
||||
|
||||
self.assertEqual(flavor_id, result)
|
||||
self.mock_connection.compute.get_flavor.assert_called_once_with(
|
||||
flavor_id
|
||||
)
|
||||
|
||||
def test_get_flavor_id_by_name(self, mock_cinder):
|
||||
"""Test get_flavor_id returns id when flavor is found by name."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_name = 'm1.small'
|
||||
flavor_id = 'flavor-123'
|
||||
flavor = self.create_openstacksdk_flavor(
|
||||
id=flavor_id, name=flavor_name
|
||||
)
|
||||
|
||||
# First attempt to get by ID fails (NotFoundException)
|
||||
self.mock_connection.compute.get_flavor.side_effect = (
|
||||
sdk_exc.NotFoundException()
|
||||
)
|
||||
# get_flavor_list returns list with the flavor
|
||||
self.mock_connection.compute.flavors.return_value = [flavor]
|
||||
|
||||
result = nova_util.get_flavor_id(flavor_name)
|
||||
|
||||
self.assertEqual(flavor_id, result)
|
||||
self.mock_connection.compute.get_flavor.assert_called_once_with(
|
||||
flavor_name
|
||||
)
|
||||
self.mock_connection.compute.flavors.assert_called_once_with(
|
||||
is_public=None
|
||||
)
|
||||
|
||||
def test_get_flavor_id_not_found_by_id_or_name(self, mock_cinder):
|
||||
"""Test get_flavor_id raises exception when flavor is not found."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_name = 'nonexistent-flavor'
|
||||
|
||||
# First attempt to get by ID fails
|
||||
self.mock_connection.compute.get_flavor.side_effect = (
|
||||
sdk_exc.NotFoundException()
|
||||
)
|
||||
# get_flavor_list returns empty list
|
||||
self.mock_connection.compute.flavors.return_value = []
|
||||
|
||||
self.assertRaisesRegex(
|
||||
exception.ComputeResourceNotFound,
|
||||
f"{flavor_name} of type Flavor",
|
||||
nova_util.get_flavor_id,
|
||||
flavor_name
|
||||
)
|
||||
|
||||
def test_get_flavor_id_not_found_in_list(self, mock_cinder):
|
||||
"""Test get_flavor_id when flavor name not in returned list."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_name = 'm1.small'
|
||||
|
||||
# First attempt to get by ID fails
|
||||
self.mock_connection.compute.get_flavor.side_effect = (
|
||||
sdk_exc.NotFoundException()
|
||||
)
|
||||
# get_flavor_list returns flavors but none match the name
|
||||
other_flavor = self.create_openstacksdk_flavor(
|
||||
id='other-id', name='m1.large'
|
||||
)
|
||||
self.mock_connection.compute.flavors.return_value = [other_flavor]
|
||||
|
||||
self.assertRaisesRegex(
|
||||
exception.ComputeResourceNotFound,
|
||||
f"{flavor_name} of type Flavor",
|
||||
nova_util.get_flavor_id,
|
||||
flavor_name
|
||||
)
|
||||
|
||||
def test_get_flavor_id_sdk_exception(self, mock_cinder):
|
||||
"""Test get_flavor_id raises NovaClientError on SDK exception."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_id = 'flavor-123'
|
||||
|
||||
# SDK raises a generic exception
|
||||
self.mock_connection.compute.get_flavor.side_effect = (
|
||||
sdk_exc.SDKException("Connection error")
|
||||
)
|
||||
|
||||
self.assertRaises(
|
||||
exception.NovaClientError,
|
||||
nova_util.get_flavor_id,
|
||||
flavor_id
|
||||
)
|
||||
|
||||
def test_get_flavor_id_by_name_multiple_flavors(self, mock_cinder):
|
||||
"""Test get_flavor_id finds correct flavor by name in list."""
|
||||
nova_util = nova_helper.NovaHelper()
|
||||
flavor_name = 'm1.medium'
|
||||
target_id = 'flavor-456'
|
||||
|
||||
# Create multiple flavors
|
||||
flavor1 = self.create_openstacksdk_flavor(
|
||||
id='flavor-123', name='m1.small'
|
||||
)
|
||||
flavor2 = self.create_openstacksdk_flavor(
|
||||
id=target_id, name=flavor_name
|
||||
)
|
||||
flavor3 = self.create_openstacksdk_flavor(
|
||||
id='flavor-789', name='m1.large'
|
||||
)
|
||||
|
||||
# First attempt to get by ID fails
|
||||
self.mock_connection.compute.get_flavor.side_effect = (
|
||||
sdk_exc.NotFoundException()
|
||||
)
|
||||
# get_flavor_list returns multiple flavors
|
||||
self.mock_connection.compute.flavors.return_value = [
|
||||
flavor1, flavor2, flavor3
|
||||
]
|
||||
|
||||
result = nova_util.get_flavor_id(flavor_name)
|
||||
|
||||
self.assertEqual(target_id, result)
|
||||
|
||||
|
||||
class TestNovaRetries(base.TestCase):
|
||||
"""Test suite for the nova_retries decorator."""
|
||||
|
||||
Reference in New Issue
Block a user