Merge "Handle Neuton Subnet Full Exception" into stable/2025.1

This commit is contained in:
Zuul
2025-10-21 02:48:48 +00:00
committed by Gerrit Code Review
7 changed files with 110 additions and 1 deletions

View File

@@ -538,6 +538,10 @@ class PortLimitExceeded(QuotaError):
message = _("Maximum number of ports exceeded.")
class IpAddressGenerationFailureClient(ManilaException):
message = _("No free IP addresses available in neutron subnet.")
class ShareAccessExists(ManilaException):
message = _("Share access %(access_type)s:%(access)s exists.")

View File

@@ -169,6 +169,14 @@ class Detail(object):
'031',
_("Metadata delete operation includes driver updatable metadata, and "
"it is not passed to share driver to perform required operation."))
NEUTRON_SUBNET_FULL = (
'033',
_("Share Driver failed to create share server on share network "
"due no more free IP addresses in the neutron subnet."
"You may free some IP addresses in the subnet "
"or create a new subnet/share network. If this doesn't work, "
"contact your administrator to troubleshoot "
"issues with your network."))
ALL = (
UNKNOWN_ERROR,
@@ -201,7 +209,8 @@ class Detail(object):
SHARE_BACKEND_NOT_READY_YET,
UPDATE_METADATA_SUCCESS,
UPDATE_METADATA_FAILURE,
UPDATE_METADATA_NOT_DELETED
UPDATE_METADATA_NOT_DELETED,
NEUTRON_SUBNET_FULL
)
# Exception and detail mappings

View File

@@ -197,6 +197,9 @@ class API(object):
raise exception.PortLimitExceeded()
raise exception.NetworkException(code=e.status_code,
message=e.message)
except neutron_client_exc.IpAddressGenerationFailureClient:
LOG.warning('No free IP addresses in neutron subnet %s', subnet_id)
raise exception.IpAddressGenerationFailureClient()
except ks_exec.ConnectFailure:
LOG.warning('Create Port: Neutron connection failure')
# check if port is created in neutron else re-raise connectFailure

View File

@@ -2156,6 +2156,22 @@ class ShareManager(manager.SchedulerDependentManager):
resource_id=share_id,
detail=(message_field.Detail
.SECURITY_SERVICE_FAILED_AUTH))
except exception.IpAddressGenerationFailureClient:
with excutils.save_and_reraise_exception():
error = ("Creation of share instance %s failed: "
"No Free IP's in neutron subnet.")
LOG.error(error, share_instance_id)
self.db.share_instance_update(
context, share_instance_id,
{'status': constants.STATUS_ERROR}
)
self.message_api.create(
context,
message_field.Action.CREATE,
share['project_id'],
resource_type=message_field.Resource.SHARE,
resource_id=share_id,
detail=message_field.Detail.NEUTRON_SUBNET_FULL)
except Exception:
with excutils.save_and_reraise_exception():
error = ("Creation of share instance %s failed: "

View File

@@ -2671,6 +2671,71 @@ class ShareManagerTestCase(test.TestCase):
detail=(
message_field.Detail.SHARE_NETWORK_PORT_QUOTA_LIMIT_EXCEEDED))
def test_create_share_instance_with_ip_address_generation_failure(self):
share_network = db_utils.create_share_network(id='fake_sn_id')
share_net_subnet = db_utils.create_share_network_subnet(
id='fake_sns_id', share_network_id=share_network['id']
)
share_type = db_utils.create_share_type()
fake_share = db_utils.create_share(
share_network_id=share_network['id'], size=1,
share_type_id=share_type['id'])
fake_metadata = {
'request_host': 'fake_host',
'share_type_id': 'fake_share_type_id',
}
fake_server = db_utils.create_share_server(
id='fake_srv_id', status=constants.STATUS_CREATING,
share_network_subnets=[share_net_subnet])
self.mock_object(self.share_manager, '_build_server_metadata',
mock.Mock(return_value=fake_metadata))
self.mock_object(db, 'share_server_create',
mock.Mock(return_value=fake_server))
self.mock_object(db, 'share_instance_update',
mock.Mock(return_value=fake_share.instance))
self.mock_object(db, 'share_instance_get',
mock.Mock(return_value=fake_share.instance))
self.mock_object(
db, 'share_network_subnets_get_all_by_availability_zone_id',
mock.Mock(return_value=[share_net_subnet]))
self.mock_object(manager.LOG, 'error')
def raise_manila_exception(*args, **kwargs):
raise exception.IpAddressGenerationFailureClient()
self.mock_object(self.share_manager, '_setup_server',
mock.Mock(side_effect=raise_manila_exception))
self.assertRaises(
exception.IpAddressGenerationFailureClient,
self.share_manager.create_share_instance,
self.context,
fake_share.instance['id'],
)
db.share_server_create.assert_called_once_with(
utils.IsAMatcher(context.RequestContext), mock.ANY)
db.share_instance_update.assert_has_calls([
mock.call(
utils.IsAMatcher(context.RequestContext),
fake_share.instance['id'],
{'status': constants.STATUS_ERROR},
)
])
self.share_manager._setup_server.assert_called_once_with(
utils.IsAMatcher(context.RequestContext), fake_server,
fake_metadata)
manager.LOG.error.assert_called_with(mock.ANY,
fake_share.instance['id'])
self.share_manager.message_api.create.assert_called_once_with(
utils.IsAMatcher(context.RequestContext),
message_field.Action.CREATE,
str(fake_share.project_id),
resource_type=message_field.Resource.SHARE,
resource_id=fake_share['id'],
detail=(
message_field.Detail.NEUTRON_SUBNET_FULL))
def test_create_share_instance_with_share_network_server_fail(self):
share_network = db_utils.create_share_network(id='fake_sn_id')
share_net_subnet = db_utils.create_share_network_subnet(

View File

@@ -144,6 +144,11 @@ class ManilaExceptionTestCase(test.TestCase):
self.assertEqual(500, e.code)
self.assertIn(reason, e.msg)
def test_ip_address_generation_failure(self):
# verify response code for exception.IpAddressGenerationFailureClient
e = exception.IpAddressGenerationFailureClient()
self.assertEqual(500, e.code)
class ManilaExceptionResponseCode400(test.TestCase):

View File

@@ -0,0 +1,7 @@
---
fixes:
- |
Manila will report IpAddressGenerationFailureClient exception if neutron
subnet is full i.e. no more ports can be created on neutron subnet. For
more details, please refer to
`launchpad bug #2120176 <https://bugs.launchpad.net/manila/+bug/2120176>`_