Merge "Emit notification on update_status() on a zone"
This commit is contained in:
commit
62f578174b
@ -2265,6 +2265,8 @@ class Service(service.RPCService, service.Service):
|
|||||||
return pool
|
return pool
|
||||||
|
|
||||||
# Pool Manager Integration
|
# Pool Manager Integration
|
||||||
|
@notification('dns.domain.update')
|
||||||
|
@notification('dns.zone.update')
|
||||||
@transaction
|
@transaction
|
||||||
def update_status(self, context, zone_id, status, serial):
|
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 zone_id: The ID of the designate zone.
|
||||||
:param status: The status, 'SUCCESS' or 'ERROR'.
|
:param status: The status, 'SUCCESS' or 'ERROR'.
|
||||||
:param serial: The consensus serial number for the zone.
|
: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,
|
# TODO(kiall): If the status is SUCCESS and the zone is already ACTIVE,
|
||||||
# we likely don't need to do anything.
|
# we likely don't need to do anything.
|
||||||
self._update_record_status(context, zone_id, status, serial)
|
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):
|
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 = self.storage.get_zone(context, zone_id)
|
||||||
|
|
||||||
zone, deleted = self._update_zone_or_record_status(
|
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.
|
# that the action, status and serial are updated correctly.
|
||||||
self.storage.delete_zone(context, zone.id)
|
self.storage.delete_zone(context, zone.id)
|
||||||
|
|
||||||
|
return zone
|
||||||
|
|
||||||
def _update_record_status(self, context, zone_id, status, serial):
|
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 = {
|
criterion = {
|
||||||
'zone_id': zone_id
|
'zone_id': zone_id
|
||||||
}
|
}
|
||||||
@ -2347,6 +2359,8 @@ class Service(service.RPCService, service.Service):
|
|||||||
if len(recordset.records) == 0:
|
if len(recordset.records) == 0:
|
||||||
self.storage.delete_recordset(context, recordset.id)
|
self.storage.delete_recordset(context, recordset.id)
|
||||||
|
|
||||||
|
return records
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _update_zone_or_record_status(zone_or_record, status, serial):
|
def _update_zone_or_record_status(zone_or_record, status, serial):
|
||||||
deleted = False
|
deleted = False
|
||||||
|
@ -66,7 +66,9 @@ class NotifyEndpoint(base.BaseEndpoint):
|
|||||||
|
|
||||||
def poll_for_serial_number(self, context, zone, nameserver, timeout,
|
def poll_for_serial_number(self, context, zone, nameserver, timeout,
|
||||||
retry_interval, max_retries, delay):
|
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 context: The user context.
|
||||||
:param zone: The designate zone object. This contains the zone
|
:param zone: The designate zone object. This contains the zone
|
||||||
name. zone.serial = expected_serial
|
name. zone.serial = expected_serial
|
||||||
@ -78,7 +80,7 @@ class NotifyEndpoint(base.BaseEndpoint):
|
|||||||
an expected serial number. After this many retries, mindns returns
|
an expected serial number. After this many retries, mindns returns
|
||||||
an ERROR.
|
an ERROR.
|
||||||
:param delay: The time to wait before sending the first request.
|
: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(
|
(status, actual_serial, retries) = self.get_serial_number(
|
||||||
context, zone, nameserver.host, nameserver.port, timeout,
|
context, zone, nameserver.host, nameserver.port, timeout,
|
||||||
|
@ -247,7 +247,11 @@ class Service(service.RPCService, coordination.CoordinationMixin,
|
|||||||
# Standard Create/Update/Delete Methods
|
# Standard Create/Update/Delete Methods
|
||||||
|
|
||||||
def create_zone(self, context, zone):
|
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 context: Security context information.
|
||||||
:param zone: Zone to be created
|
:param zone: Zone to be created
|
||||||
:return: None
|
:return: None
|
||||||
@ -291,7 +295,8 @@ class Service(service.RPCService, coordination.CoordinationMixin,
|
|||||||
self.retry_interval, self.max_retries, self.delay)
|
self.retry_interval, self.max_retries, self.delay)
|
||||||
|
|
||||||
def _create_zone_on_target(self, context, target, zone):
|
def _create_zone_on_target(self, context, target, zone):
|
||||||
"""
|
"""Called by create_zone, run create_zone on backends
|
||||||
|
|
||||||
:param context: Security context information.
|
:param context: Security context information.
|
||||||
:param target: Target to create Zone on
|
:param target: Target to create Zone on
|
||||||
:param zone: Zone to be created
|
:param zone: Zone to be created
|
||||||
@ -354,8 +359,8 @@ class Service(service.RPCService, coordination.CoordinationMixin,
|
|||||||
for nameserver in self.pool.nameservers:
|
for nameserver in self.pool.nameservers:
|
||||||
# See if there is already another update in progress
|
# See if there is already another update in progress
|
||||||
try:
|
try:
|
||||||
update_status = self.cache.retrieve(
|
self.cache.retrieve(context, nameserver.id, zone.id,
|
||||||
context, nameserver.id, zone.id, UPDATE_ACTION)
|
UPDATE_ACTION)
|
||||||
except exceptions.PoolManagerStatusNotFound:
|
except exceptions.PoolManagerStatusNotFound:
|
||||||
update_status = self._build_status_object(
|
update_status = self._build_status_object(
|
||||||
nameserver, zone, UPDATE_ACTION)
|
nameserver, zone, UPDATE_ACTION)
|
||||||
|
@ -3006,6 +3006,41 @@ class CentralServiceTest(CentralTestCase):
|
|||||||
self.admin_context, zone['id'], recordset['id'],
|
self.admin_context, zone['id'], recordset['id'],
|
||||||
record['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(
|
def test_update_status_delete_last_record_without_incrementing_serial(
|
||||||
self):
|
self):
|
||||||
zone = self.create_zone()
|
zone = self.create_zone()
|
||||||
|
Loading…
Reference in New Issue
Block a user