Merge "Emit notification on update_status() on a zone"

This commit is contained in:
Jenkins 2015-12-17 18:51:30 +00:00 committed by Gerrit Code Review
commit 62f578174b
4 changed files with 64 additions and 8 deletions

View File

@ -2265,6 +2265,8 @@ class Service(service.RPCService, service.Service):
return pool
# Pool Manager Integration
@notification('dns.domain.update')
@notification('dns.zone.update')
@transaction
def update_status(self, context, zone_id, status, serial):
"""
@ -2272,14 +2274,19 @@ class Service(service.RPCService, service.Service):
:param zone_id: The ID of the designate zone.
:param status: The status, 'SUCCESS' or 'ERROR'.
:param serial: The consensus serial number for the zone.
:return: None
:return: updated zone
"""
# TODO(kiall): If the status is SUCCESS and the zone is already ACTIVE,
# we likely don't need to do anything.
self._update_record_status(context, zone_id, status, serial)
self._update_zone_status(context, zone_id, status, serial)
zone = self._update_zone_status(context, zone_id, status, serial)
return zone
def _update_zone_status(self, context, zone_id, status, serial):
"""Update zone status in storage
:return: updated zone
"""
zone = self.storage.get_zone(context, zone_id)
zone, deleted = self._update_zone_or_record_status(
@ -2298,7 +2305,12 @@ class Service(service.RPCService, service.Service):
# that the action, status and serial are updated correctly.
self.storage.delete_zone(context, zone.id)
return zone
def _update_record_status(self, context, zone_id, status, serial):
"""Update status on every record in a zone based on `serial`
:returns: updated records
"""
criterion = {
'zone_id': zone_id
}
@ -2347,6 +2359,8 @@ class Service(service.RPCService, service.Service):
if len(recordset.records) == 0:
self.storage.delete_recordset(context, recordset.id)
return records
@staticmethod
def _update_zone_or_record_status(zone_or_record, status, serial):
deleted = False

View File

@ -66,7 +66,9 @@ class NotifyEndpoint(base.BaseEndpoint):
def poll_for_serial_number(self, context, zone, nameserver, timeout,
retry_interval, max_retries, delay):
"""
"""Get the serial number of a zone on a resolver, then call update_status
on Pool Manager to update the zone status.
:param context: The user context.
:param zone: The designate zone object. This contains the zone
name. zone.serial = expected_serial
@ -78,7 +80,7 @@ class NotifyEndpoint(base.BaseEndpoint):
an expected serial number. After this many retries, mindns returns
an ERROR.
:param delay: The time to wait before sending the first request.
:return: The pool manager is informed of the status with update_status.
:return: None
"""
(status, actual_serial, retries) = self.get_serial_number(
context, zone, nameserver.host, nameserver.port, timeout,

View File

@ -247,7 +247,11 @@ class Service(service.RPCService, coordination.CoordinationMixin,
# Standard Create/Update/Delete Methods
def create_zone(self, context, zone):
"""
"""Called by Central or by periodic_recovery, instruct the backends to
create a zone, then poll for consensus.
On success, send NOTIFY to also_notifies and nameservers
Finally, poll for zone serial number on nameservers.
:param context: Security context information.
:param zone: Zone to be created
:return: None
@ -291,7 +295,8 @@ class Service(service.RPCService, coordination.CoordinationMixin,
self.retry_interval, self.max_retries, self.delay)
def _create_zone_on_target(self, context, target, zone):
"""
"""Called by create_zone, run create_zone on backends
:param context: Security context information.
:param target: Target to create Zone on
:param zone: Zone to be created
@ -354,8 +359,8 @@ class Service(service.RPCService, coordination.CoordinationMixin,
for nameserver in self.pool.nameservers:
# See if there is already another update in progress
try:
update_status = self.cache.retrieve(
context, nameserver.id, zone.id, UPDATE_ACTION)
self.cache.retrieve(context, nameserver.id, zone.id,
UPDATE_ACTION)
except exceptions.PoolManagerStatusNotFound:
update_status = self._build_status_object(
nameserver, zone, UPDATE_ACTION)

View File

@ -3006,6 +3006,41 @@ class CentralServiceTest(CentralTestCase):
self.admin_context, zone['id'], recordset['id'],
record['id'])
@mock.patch.object(notifier.Notifier, "info")
def test_update_status_send_notification(self, mock_notifier):
# Create zone and ensure that two zone/domain create notifications
# have been sent - status is PENDING
zone = self.create_zone(email='info@example.org')
self.assertEqual(2, mock_notifier.call_count)
notify_string, notified_zone = mock_notifier.call_args_list[0][0][1:]
self.assertEqual('dns.domain.create', notify_string)
self.assertEqual('example.com.', notified_zone.name)
self.assertEqual('PENDING', notified_zone.status)
notify_string, notified_zone = mock_notifier.call_args_list[1][0][1:]
self.assertEqual('dns.zone.create', notify_string)
self.assertEqual('example.com.', notified_zone.name)
self.assertEqual('PENDING', notified_zone.status)
# Perform an update; ensure that zone/domain update notifications
# have been sent and the zone is now in ACTIVE status
mock_notifier.reset_mock()
self.central_service.update_status(
self.admin_context, zone['id'], "SUCCESS", zone.serial)
self.assertEqual(2, mock_notifier.call_count)
notify_string, notified_zone = mock_notifier.call_args_list[0][0][1:]
self.assertEqual('dns.domain.update', notify_string)
self.assertEqual('example.com.', notified_zone.name)
self.assertEqual('ACTIVE', notified_zone.status)
notify_string, notified_zone = mock_notifier.call_args_list[1][0][1:]
self.assertEqual('dns.zone.update', notify_string)
self.assertEqual('example.com.', notified_zone.name)
self.assertEqual('ACTIVE', notified_zone.status)
def test_update_status_delete_last_record_without_incrementing_serial(
self):
zone = self.create_zone()