Fix AXFR loop when updating secondary zone
When a secondary zone is created or updated we trigger an AXFR, this AXFR then goes ahead and updates the zone. This then causes the AXFR code to get triggered again as it thinks the masters has changed. We fix this by ensuring that when we update the zone from the AXFR code that we always reset the masters field. Partial-Bug: #1856442 Change-Id: Ifc2efb5a6d1091ff16373f3cbe3846f5e4371272
This commit is contained in:
@@ -819,9 +819,7 @@ class Service(service.RPCService):
|
||||
self.worker_api.create_zone(context, zone)
|
||||
|
||||
if zone.type == constants.ZONE_SECONDARY:
|
||||
xfr_zone = copy.deepcopy(zone)
|
||||
xfr_zone.obj_reset_changes(recursive=True)
|
||||
self.worker_api.perform_zone_xfr(context, xfr_zone)
|
||||
self.worker_api.perform_zone_xfr(context, zone)
|
||||
|
||||
# If zone is a superzone, update subzones
|
||||
# with new parent IDs
|
||||
|
||||
@@ -1622,42 +1622,6 @@ class CentralZoneTestCase(CentralBasic):
|
||||
refresh_time = central_service._generate_soa_refresh_interval()
|
||||
self.assertEqual(3563, refresh_time)
|
||||
|
||||
@patch.object(objects.Zone, 'obj_reset_changes')
|
||||
def test_create_secondary_zone(self, mock_obj_reset_changes):
|
||||
self.service._enforce_zone_quota = mock.Mock()
|
||||
self.service._create_zone_in_storage = mock.Mock(
|
||||
return_value=objects.Zone(name='example.com.', type='SECONDARY'))
|
||||
self.service._is_valid_zone_name = mock.Mock()
|
||||
self.service._is_valid_ttl = mock.Mock()
|
||||
self.service._is_subzone = mock.Mock(return_value=False)
|
||||
self.service._is_superzone = mock.Mock(return_value=[])
|
||||
self.service.storage.get_pool.return_value = RoObject(
|
||||
ns_records=[RoObject()])
|
||||
self.useFixture(
|
||||
fixtures.MockPatchObject(
|
||||
self.service.storage,
|
||||
'find_pools',
|
||||
return_value=objects.PoolList.from_list(
|
||||
[
|
||||
{'id': '94ccc2c1-d751-44fe-b57f-8894c9f5c842'}
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
output = self.service.create_zone(
|
||||
self.context,
|
||||
objects.Zone(
|
||||
tenant_id='1',
|
||||
name='example.com.',
|
||||
ttl=60,
|
||||
pool_id=CentralZoneTestCase.pool__id,
|
||||
refresh=0,
|
||||
type='SECONDARY'
|
||||
)
|
||||
)
|
||||
self.assertEqual('example.com.', output.name)
|
||||
mock_obj_reset_changes.assert_called_once_with(recursive=True)
|
||||
|
||||
|
||||
class IsSubzoneTestCase(CentralBasic):
|
||||
def setUp(self):
|
||||
|
||||
@@ -60,6 +60,38 @@ class TestXfr(oslotest.base.BaseTestCase):
|
||||
self.assertIn('transferred_at', zone.obj_what_changed())
|
||||
self.assertNotIn('name', zone.obj_what_changed())
|
||||
|
||||
@mock.patch.object(dnsutils, 'do_axfr', mock.Mock())
|
||||
def test_zone_sync_not_change_masters(self):
|
||||
recordset = objects.RecordSet(
|
||||
name='www.example.test.', type='TXT',
|
||||
records=objects.RecordList(objects=[
|
||||
objects.Record(data='foo bar'),
|
||||
])
|
||||
)
|
||||
zone = objects.Zone(
|
||||
id='7592878e-4ade-40de-8b8d-699b871ee6fa',
|
||||
name='example.com.',
|
||||
serial=1,
|
||||
masters=objects.ZoneMasterList.from_list(
|
||||
[{'host': '127.0.0.1', 'port': 53}, ]
|
||||
),
|
||||
type=constants.ZONE_SECONDARY,
|
||||
recordsets=objects.RecordSetList(objects=[]),
|
||||
)
|
||||
|
||||
self.xfr = worker_zone.ZoneXfr(mock.Mock(), self.context, zone)
|
||||
self.xfr._central_api = mock.Mock()
|
||||
|
||||
with mock.patch.object(dnsutils, 'from_dnspython_zone') as mock_dns:
|
||||
zone.recordsets = objects.RecordSetList(objects=[recordset])
|
||||
zone.masters = objects.ZoneMasterList()
|
||||
mock_dns.return_value = zone
|
||||
|
||||
self.xfr()
|
||||
|
||||
self.assertIn('transferred_at', zone.obj_what_changed())
|
||||
self.assertNotIn('masters', zone.obj_what_changed())
|
||||
|
||||
@mock.patch.object(dnsutils, 'do_axfr', mock.Mock())
|
||||
def test_zone_sync_using_list_of_servers(self):
|
||||
zone = objects.Zone(
|
||||
|
||||
@@ -183,7 +183,7 @@ class ZoneXfr(base.Task):
|
||||
|
||||
self.zone.update(dnsutils.from_dnspython_zone(dnspython_zone))
|
||||
self.zone.transferred_at = timeutils.utcnow()
|
||||
self.zone.obj_reset_changes(['name'])
|
||||
self.zone.obj_reset_changes(['name', 'masters'], recursive=True)
|
||||
self.central_api.update_zone(
|
||||
self.context, self.zone, increment_serial=False
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user