Report PortLimitExceeded error to customer

When share creation fails due to missing ports quota (
'manila.exception.PortLimitExceeded: Maximum number of ports
exceeded.'), error message propogated to user is not useful.
Improve user message in this scenario.

Closes-bug: #2019846
Change-Id: I1f010c4ff9faf837bd50b6c2823cbc526f3a42df
This commit is contained in:
Kiran Pawar 2023-05-16 10:09:07 +00:00
parent b3951d06dd
commit a372e53098
4 changed files with 95 additions and 0 deletions

View File

@ -141,6 +141,13 @@ class Detail(object):
DRIVER_FAILED_TRANSFER_ACCEPT = (
'026',
_("Share transfer cannot be accepted without clearing access rules."))
SHARE_NETWORK_PORT_QUOTA_LIMIT_EXCEEDED = (
'027',
_("Failed to create a new network port on the share network subnet. "
"The limit of the number of ports has been exceeded. You may "
"increase the network port quotas or free up some ports and retry. "
"If this doesn't work, contact your administrator to troubleshoot "
"issues with your network."))
ALL = (
UNKNOWN_ERROR,
@ -169,6 +176,7 @@ class Detail(object):
NO_DEFAULT_SHARE_TYPE,
MISSING_SECURITY_SERVICE,
DRIVER_FAILED_TRANSFER_ACCEPT,
SHARE_NETWORK_PORT_QUOTA_LIMIT_EXCEEDED,
)
# Exception and detail mappings

View File

@ -2048,6 +2048,23 @@ class ShareManager(manager.SchedulerDependentManager):
share_group=share_group_ref,
)
)
except exception.PortLimitExceeded:
with excutils.save_and_reraise_exception():
error = ("Creation of share instance %s failed: "
"failed to allocate network")
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
.SHARE_NETWORK_PORT_QUOTA_LIMIT_EXCEEDED))
except exception.SecurityServiceFailedAuth:
with excutils.save_and_reraise_exception():
error = ("Provision of share server failed: "

View File

@ -2163,6 +2163,69 @@ class ShareManagerTestCase(test.TestCase):
share_id).id)
manager.LOG.info.assert_called_with(mock.ANY, share.instance['id'])
def test_create_share_instance_with_network_port_limit_exceeded(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']
)
fake_share = db_utils.create_share(
share_network_id=share_network['id'], size=1)
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.PortLimitExceeded()
self.mock_object(self.share_manager, '_setup_server',
mock.Mock(side_effect=raise_manila_exception))
self.assertRaises(
exception.PortLimitExceeded,
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.SHARE_NETWORK_PORT_QUOTA_LIMIT_EXCEEDED))
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

@ -0,0 +1,7 @@
---
fixes:
- |
When share creation fails due to missing ports quota, error message
propogated to user is not useful. So reported PortLimitExceeded error to
user instead of generic error. For more details, please refer
(`launchpad bug 2019846 <https://bugs.launchpad.net/manila/+bug/2019846>`_).