summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordekehn <dekehn@gmail.com>2022-03-29 15:09:29 +0000
committerMichael Johnson <johnsomor@gmail.com>2022-06-04 20:54:05 +0000
commiteacd478e0560c26a0bcdde04d7855f83fb8ff890 (patch)
tree405420500463199ad9d7dfb635504a5027d3c835
parentcf7a666111f5caa779cad3580eb9f5d9461a6bd1 (diff)
downloaddesignate-eacd478e0560c26a0bcdde04d7855f83fb8ff890.tar.gz
Clarifies the zone import error message
This patch defines the situation where the import_zone exception handler produces the message 'An undefined error occurred' to the exception during the zone import where an underlying exception occurred from the rpc dispatcher at the same time as a duplicate zone exception. Kiall Mac Innes explains this in https://opendev.org/openstack/designate/commit/2c9460505d07d0e46765a552b637e5a3296b667b the problem here is in the way the _import_zone was written where https://github.com/openstack/designate/commit/9b809a11b3068552274340606eb76d2217411b85 was written with threading.local, so it only works if it stays within the same thread. Since _import_zone is created on a separate thread, the necessity to add the decorator @rpc_expected_exceptions() at the top. Closes-bug: #1950118 Closes-bug: #1964323 Change-Id: If7d50cbd4fa0ce86e0ddf03068da36acd7d72cb4 (cherry picked from commit d705c5d6b861f319096afdd3ad50a2100651b064)
-rw-r--r--designate/central/service.py1
-rw-r--r--designate/tests/test_central/test_service.py111
2 files changed, 112 insertions, 0 deletions
diff --git a/designate/central/service.py b/designate/central/service.py
index 92be0afa..6c37a8a0 100644
--- a/designate/central/service.py
+++ b/designate/central/service.py
@@ -3072,6 +3072,7 @@ class Service(service.RPCService):
return created_zone_import
+ @rpc.expected_exceptions()
def _import_zone(self, context, zone_import, request_body):
zone = None
try:
diff --git a/designate/tests/test_central/test_service.py b/designate/tests/test_central/test_service.py
index de7ce767..f2f8eb11 100644
--- a/designate/tests/test_central/test_service.py
+++ b/designate/tests/test_central/test_service.py
@@ -3570,6 +3570,117 @@ class CentralServiceTest(CentralTestCase):
zone_import.message)
self.assertEqual('ERROR', zone_import.status)
+ def test_create_zone_import_duplicate_threading(self):
+ context = self.get_context(project_id=utils.generate_uuid())
+ request_body = self.get_zonefile_fixture()
+ zone_import = self.central_service.create_zone_import(context,
+ request_body)
+ self.wait_for_import(zone_import.id)
+
+ def create_zone_import():
+ context = self.get_context(project_id=utils.generate_uuid())
+ request_body = self.get_zonefile_fixture()
+ zone_import = self.central_service.create_zone_import(context,
+ request_body)
+ return self.wait_for_import(zone_import.id, error_is_ok=True)
+
+ with futurist.GreenThreadPoolExecutor() as executor:
+ results = []
+ for fixture in [0, 2, 3, 4, 5]:
+ results.append(executor.submit(create_zone_import,))
+ for future in futures.as_completed(results):
+ result = future.result()
+ self.assertEqual('Duplicate zone.', result.message)
+
+ @mock.patch('dns.zone.from_text')
+ @mock.patch('designate.central.service.Service.update_zone_import')
+ def test_create_zone_import_from_text_exceptions(
+ self, mock_update_zone_import, mock_dnszone_from_text):
+
+ # the second set of exceptions for the create_zone
+ context = self.get_context(project_id=utils.generate_uuid())
+ request_body = self.get_zonefile_fixture()
+ values = {
+ 'status': 'PENDING',
+ 'message': None,
+ 'zone_id': None,
+ 'tenant_id': context.project_id,
+ 'task_type': 'IMPORT'
+ }
+ zone_import = objects.ZoneImport(**values)
+
+ mock_dnszone_from_text.side_effect = [exceptions.BadRequest(),
+ Exception('boom')]
+
+ LOG.debug("Testing zone import exceptions: BadRequest")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertIsNotNone(zone_import.message)
+ self.assertEqual('An SOA record is required.', zone_import.message)
+
+ LOG.debug("Testing zone import exceptions: Undefined")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertIsNotNone(zone_import.message)
+ self.assertEqual('An undefined error occurred. boom',
+ zone_import.message)
+
+ @mock.patch('designate.central.service.Service.create_zone')
+ @mock.patch('designate.central.service.Service.update_zone_import')
+ def test_create_zone_import_create_import_exceptions(
+ self, mock_update_zone_import, mock_create_zone):
+
+ # setup to test the create_zone exceptions from _import_zone method
+ context = self.get_context(project_id=utils.generate_uuid())
+ request_body = self.get_zonefile_fixture()
+ values = {
+ 'status': 'PENDING',
+ 'message': None,
+ 'zone_id': None,
+ 'tenant_id': context.project_id,
+ 'task_type': 'IMPORT'
+ }
+ zone_import = objects.ZoneImport(**values)
+
+ mock_create_zone.side_effect = [mock.DEFAULT,
+ exceptions.DuplicateZone(),
+ exceptions.InvalidTTL(),
+ exceptions.OverQuota(),
+ Exception('boom')]
+
+ LOG.debug("Testing zone import exceptions: No exception case")
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('COMPLETE', zone_import.status)
+ self.assertIn('imported', zone_import.message)
+
+ LOG.debug("Testing zone import exceptions: DuplicateZone")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertEqual('Duplicate zone.', zone_import.message)
+
+ LOG.debug("Testing zone import exceptions: InvalidTTL")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertIsNotNone(zone_import.message)
+
+ LOG.debug("Testing zone import exceptions: OverQuota")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertEqual('Quota exceeded during zone import.',
+ zone_import.message)
+
+ LOG.debug("Testing zone import exceptions: Undefined")
+ zone_import = objects.ZoneImport(**values)
+ self.central_service._import_zone(context, zone_import, request_body)
+ self.assertEqual('ERROR', zone_import.status)
+ self.assertEqual('An undefined error occurred. boom',
+ zone_import.message)
+
def test_find_zone_imports(self):
context = self.get_context(project_id=utils.generate_uuid())