Commit 48054d5a authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[1938] make sure zonemgr doesn't treat unmatched notify as an error.

it can happen if the server is a primary of the zone; notauth case is
now handled in auth.
parent b058641f
......@@ -314,7 +314,8 @@ class TestZonemgrRefresh(unittest.TestCase):
sqlite3_ds.get_zone_soa = old_get_zone_soa
def test_zone_handle_notify(self):
self.zone_refresh.zone_handle_notify(ZONE_NAME_CLASS1_IN,"127.0.0.1")
self.assertTrue(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS1_IN, "127.0.0.1"))
notify_master = self.zone_refresh.\
_zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["notify_master"]
self.assertEqual("127.0.0.1", notify_master)
......@@ -322,12 +323,13 @@ class TestZonemgrRefresh(unittest.TestCase):
_zonemgr_refresh_info[ZONE_NAME_CLASS1_IN]["next_refresh_time"]
current_time = time.time()
self.assertTrue(zone_timeout <= current_time)
self.assertRaises(ZonemgrException,
self.zone_refresh.zone_handle_notify,
ZONE_NAME_CLASS3_CH, "127.0.0.1")
self.assertRaises(ZonemgrException,
self.zone_refresh.zone_handle_notify,
ZONE_NAME_CLASS3_IN, "127.0.0.1")
# If the specified zone does not in the configured secondary list,
# it should return False.
self.assertFalse(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS3_CH, "127.0.0.1"))
self.assertFalse(self.zone_refresh.zone_handle_notify(
ZONE_NAME_CLASS3_IN, "127.0.0.1"))
def test_zone_refresh_success(self):
soa_rdata = 'a.example.net. root.example.net. 2009073106 1800 900 2419200 21600'
......@@ -611,6 +613,19 @@ class TestZonemgrRefresh(unittest.TestCase):
config, self.cc_session)
class MyZonemgr(Zonemgr):
class DummySocket:
"""This dummy class simply steal send() to record any transmitted data.
"""
def __init__(self):
self.sent_data = []
def send(self, data):
self.sent_data.append(data)
class DummyLock:
def __enter__(self): pass
def __exit__(self, type, value, traceback): pass
def __init__(self):
self._db_file = TEST_SQLITE3_DBFILE
......@@ -625,6 +640,8 @@ class MyZonemgr(Zonemgr):
"reload_jitter" : 0.75,
"secondary_zones": []
}
self._lock = self.DummyLock()
self._master_socket = self.DummySocket()
def _start_zone_refresh_timer(self):
pass
......@@ -707,6 +724,26 @@ class TestZonemgr(unittest.TestCase):
self.zonemgr.run()
self.assertTrue(self.zonemgr._module_cc.stopped)
def test_command_handler_notify(self):
"""Check the result of NOTIFY command."""
self.zonemgr._zone_refresh = MyZonemgrRefresh()
# On successful case, the other thread will be notified via
# _master_socket.
self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: True
self.zonemgr.command_handler("notify", {"zone_name": "example.",
"zone_class": "IN",
"master": "192.0.2.1"})
self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
# If the specified is not found in the secondary list, it doesn't
# bother to wake the thread (sent_data shouldn't change)
self.zonemgr._zone_refresh.zone_handle_notify = lambda x, y: False
self.zonemgr.command_handler("notify", {"zone_name": "example.",
"zone_class": "IN",
"master": "192.0.2.1"})
self.assertEqual([b" "], self.zonemgr._master_socket.sent_data)
if __name__== "__main__":
isc.log.resetUnitTestRootLogger()
unittest.main()
......@@ -191,14 +191,31 @@ class ZonemgrRefresh:
self._set_zone_retry_timer(zone_name_class)
def zone_handle_notify(self, zone_name_class, master):
"""Handle zone notify"""
if (self._zone_not_exist(zone_name_class)):
"""Handle an incomding NOTIFY message via the Auth module.
It returns True if the specified zone matches one of the locally
configured list of secondary zones; otherwise returns False.
In the latter case it assumes the server is a primary (master) of the
zone; the Auth module should have rejected the case where it's not
even authoritative for the zone.
Note: to be more robust and less independent from other module's
behavior, it's probably safer to check the authority condition here,
too. But right now it uses SQLite3 specific API (to be deprecated),
so we rather rely on Auth.
Parameters:
zone_name_class (Name, RRClass): the notified zone name and class.
master (str): textual address of the NOTIFY sender.
"""
if self._zone_not_exist(zone_name_class):
logger.error(ZONEMGR_UNKNOWN_ZONE_NOTIFIED, zone_name_class[0],
zone_name_class[1], master)
raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
"doesn't belong to zonemgr" % zone_name_class)
return False
self._set_zone_notifier_master(zone_name_class, master)
self._set_zone_notify_timer(zone_name_class)
return True
def zonemgr_reload_zone(self, zone_name_class):
""" Reload a zone."""
......@@ -633,9 +650,12 @@ class Zonemgr:
logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_NOTIFY,
zone_name_class[0], zone_name_class[1])
with self._lock:
self._zone_refresh.zone_handle_notify(zone_name_class, master)
# Send notification to zonemgr timer thread
self._master_socket.send(b" ")# make self._slave_socket readble
need_refresh = self._zone_refresh.zone_handle_notify(
zone_name_class, master)
if need_refresh:
# Send notification to zonemgr timer thread by making
# self._slave_socket readble.
self._master_socket.send(b" ")
elif command == notify_out.ZONE_NEW_DATA_READY_CMD:
""" Handle xfrin success command"""
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment