|
@@ -37,6 +37,16 @@ from isc.datasrc import sqlite3_ds
|
|
|
from optparse import OptionParser, OptionValueError
|
|
|
from isc.config.ccsession import *
|
|
|
import isc.util.process
|
|
|
+from zonemgr_messages import *
|
|
|
+
|
|
|
+# Initialize logging for called modules.
|
|
|
+isc.log.init("b10-zonemgr")
|
|
|
+logger = isc.log.Logger("zonemgr")
|
|
|
+
|
|
|
+# Constants for debug levels, to be removed when we have #1074.
|
|
|
+DBG_START_SHUT = 0
|
|
|
+DBG_ZONEMGR_COMMAND = 10
|
|
|
+DBG_ZONEMGR_BASIC = 40
|
|
|
|
|
|
isc.util.process.rename()
|
|
|
|
|
@@ -77,13 +87,6 @@ REFRESH_OFFSET = 3
|
|
|
RETRY_OFFSET = 4
|
|
|
EXPIRED_OFFSET = 5
|
|
|
|
|
|
-# verbose mode
|
|
|
-VERBOSE_MODE = False
|
|
|
-
|
|
|
-def log_msg(msg):
|
|
|
- if VERBOSE_MODE:
|
|
|
- sys.stdout.write("[b10-zonemgr] %s\n" % str(msg))
|
|
|
-
|
|
|
class ZonemgrException(Exception):
|
|
|
pass
|
|
|
|
|
@@ -93,7 +96,6 @@ class ZonemgrRefresh:
|
|
|
do zone refresh.
|
|
|
Zone timers can be started by calling run_timer(), and it
|
|
|
can be stopped by calling shutdown() in another thread.
|
|
|
-
|
|
|
"""
|
|
|
|
|
|
def __init__(self, cc, db_file, slave_socket, config_data):
|
|
@@ -157,6 +159,7 @@ class ZonemgrRefresh:
|
|
|
def zone_refresh_success(self, zone_name_class):
|
|
|
"""Update zone info after zone refresh success"""
|
|
|
if (self._zone_not_exist(zone_name_class)):
|
|
|
+ logger.error(ZONEMGR_UNKNOWN_ZONE_SUCCESS, zone_name_class[0], zone_name_class[1])
|
|
|
raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
|
|
|
"belong to zonemgr" % zone_name_class)
|
|
|
self.zonemgr_reload_zone(zone_name_class)
|
|
@@ -167,6 +170,7 @@ class ZonemgrRefresh:
|
|
|
def zone_refresh_fail(self, zone_name_class):
|
|
|
"""Update zone info after zone refresh fail"""
|
|
|
if (self._zone_not_exist(zone_name_class)):
|
|
|
+ logger.error(ZONEMGR_UNKNOWN_ZONE_FAIL, zone_name_class[0], zone_name_class[1])
|
|
|
raise ZonemgrException("[b10-zonemgr] Zone (%s, %s) doesn't "
|
|
|
"belong to zonemgr" % zone_name_class)
|
|
|
# Is zone expired?
|
|
@@ -179,6 +183,7 @@ class ZonemgrRefresh:
|
|
|
def zone_handle_notify(self, zone_name_class, master):
|
|
|
"""Handle zone notify"""
|
|
|
if (self._zone_not_exist(zone_name_class)):
|
|
|
+ logger.error(ZONEMGR_UNKNOWN_ZONE_NOTIFIED, zone_name_class[0], zone_name_class[1])
|
|
|
raise ZonemgrException("[b10-zonemgr] Notified zone (%s, %s) "
|
|
|
"doesn't belong to zonemgr" % zone_name_class)
|
|
|
self._set_zone_notifier_master(zone_name_class, master)
|
|
@@ -191,10 +196,12 @@ class ZonemgrRefresh:
|
|
|
|
|
|
def zonemgr_add_zone(self, zone_name_class):
|
|
|
""" Add a zone into zone manager."""
|
|
|
- log_msg("Loading zone (%s, %s)" % zone_name_class)
|
|
|
+
|
|
|
+ logger.debug(DBG_ZONEMGR_BASIC, ZONEMGR_LOAD_ZONE, zone_name_class[0], zone_name_class[1])
|
|
|
zone_info = {}
|
|
|
zone_soa = sqlite3_ds.get_zone_soa(str(zone_name_class[0]), self._db_file)
|
|
|
if not zone_soa:
|
|
|
+ logger.error(ZONEMGR_NO_SOA, zone_name_class[0], zone_name_class[1])
|
|
|
raise ZonemgrException("[b10-zonemgr] zone (%s, %s) doesn't have soa." % zone_name_class)
|
|
|
zone_info["zone_soa_rdata"] = zone_soa[7]
|
|
|
zone_info["zone_state"] = ZONE_OK
|
|
@@ -265,7 +272,7 @@ class ZonemgrRefresh:
|
|
|
except isc.cc.session.SessionTimeout:
|
|
|
pass # for now we just ignore the failure
|
|
|
except socket.error:
|
|
|
- sys.stderr.write("[b10-zonemgr] Failed to send to module %s, the session has been closed." % module_name)
|
|
|
+ logger.error(ZONEMGR_SEND_FAIL, module_name)
|
|
|
|
|
|
def _find_need_do_refresh_zone(self):
|
|
|
"""Find the first zone need do refresh, if no zone need
|
|
@@ -274,7 +281,8 @@ class ZonemgrRefresh:
|
|
|
zone_need_refresh = None
|
|
|
for zone_name_class in self._zonemgr_refresh_info.keys():
|
|
|
zone_state = self._get_zone_state(zone_name_class)
|
|
|
- # If hasn't received refresh response but are within refresh timeout, skip the zone
|
|
|
+ # If hasn't received refresh response but are within refresh
|
|
|
+ # timeout, skip the zone
|
|
|
if (ZONE_REFRESHING == zone_state and
|
|
|
(self._get_zone_refresh_timeout(zone_name_class) > self._get_current_time())):
|
|
|
continue
|
|
@@ -294,7 +302,7 @@ class ZonemgrRefresh:
|
|
|
|
|
|
def _do_refresh(self, zone_name_class):
|
|
|
"""Do zone refresh."""
|
|
|
- log_msg("Do refresh for zone (%s, %s)." % zone_name_class)
|
|
|
+ logger.debug(DBG_ZONEMGR_BASIC, ZONEMGR_REFRESH_ZONE, zone_name_class[0], zone_name_class[1])
|
|
|
self._set_zone_state(zone_name_class, ZONE_REFRESHING)
|
|
|
self._set_zone_refresh_timeout(zone_name_class, self._get_current_time() + self._max_transfer_timeout)
|
|
|
notify_master = self._get_zone_notifier_master(zone_name_class)
|
|
@@ -351,7 +359,7 @@ class ZonemgrRefresh:
|
|
|
if e.args[0] == errno.EINTR:
|
|
|
(rlist, wlist, xlist) = ([], [], [])
|
|
|
else:
|
|
|
- sys.stderr.write("[b10-zonemgr] Error with select(); %s\n" % e)
|
|
|
+ logger.error(ZONEMGR_SELECT_ERROR, e);
|
|
|
break
|
|
|
|
|
|
for fd in rlist:
|
|
@@ -365,12 +373,14 @@ class ZonemgrRefresh:
|
|
|
|
|
|
def run_timer(self, daemon=False):
|
|
|
"""
|
|
|
- Keep track of zone timers. Spawns and starts a thread. The thread object is returned.
|
|
|
+ Keep track of zone timers. Spawns and starts a thread. The thread object
|
|
|
+ is returned.
|
|
|
|
|
|
You can stop it by calling shutdown().
|
|
|
"""
|
|
|
# Small sanity check
|
|
|
if self._running:
|
|
|
+ logger.error(ZONEMGR_TIMER_THREAD_RUNNING)
|
|
|
raise RuntimeError("Trying to run the timers twice at the same time")
|
|
|
|
|
|
# Prepare the launch
|
|
@@ -395,6 +405,7 @@ class ZonemgrRefresh:
|
|
|
called from a different thread.
|
|
|
"""
|
|
|
if not self._running:
|
|
|
+ logger.error(ZONEMGR_NO_TIMER_THREAD)
|
|
|
raise RuntimeError("Trying to shutdown, but not running")
|
|
|
|
|
|
# Ask the thread to stop
|
|
@@ -515,8 +526,8 @@ class Zonemgr:
|
|
|
return db_file
|
|
|
|
|
|
def shutdown(self):
|
|
|
- """Shutdown the zonemgr process. the thread which is keeping track of zone
|
|
|
- timers should be terminated.
|
|
|
+ """Shutdown the zonemgr process. The thread which is keeping track of
|
|
|
+ zone timers should be terminated.
|
|
|
"""
|
|
|
self._zone_refresh.shutdown()
|
|
|
|
|
@@ -556,17 +567,17 @@ class Zonemgr:
|
|
|
# jitter should not be bigger than half of the original value
|
|
|
if config_data.get('refresh_jitter') > 0.5:
|
|
|
config_data['refresh_jitter'] = 0.5
|
|
|
- log_msg("[b10-zonemgr] refresh_jitter is too big, its value will "
|
|
|
- "be set to 0.5")
|
|
|
-
|
|
|
+ logger.warn(ZONEMGR_JITTER_TOO_BIG)
|
|
|
|
|
|
def _parse_cmd_params(self, args, command):
|
|
|
zone_name = args.get("zone_name")
|
|
|
if not zone_name:
|
|
|
+ logger.error(ZONEMGR_NO_ZONE_NAME)
|
|
|
raise ZonemgrException("zone name should be provided")
|
|
|
|
|
|
zone_class = args.get("zone_class")
|
|
|
if not zone_class:
|
|
|
+ logger.error(ZONEMGR_NO_ZONE_CLASS)
|
|
|
raise ZonemgrException("zone class should be provided")
|
|
|
|
|
|
if (command != ZONE_NOTIFY_COMMAND):
|
|
@@ -574,6 +585,7 @@ class Zonemgr:
|
|
|
|
|
|
master_str = args.get("master")
|
|
|
if not master_str:
|
|
|
+ logger.error(ZONEMGR_NO_MASTER_ADDRESS)
|
|
|
raise ZonemgrException("master address should be provided")
|
|
|
|
|
|
return ((zone_name, zone_class), master_str)
|
|
@@ -581,15 +593,16 @@ class Zonemgr:
|
|
|
|
|
|
def command_handler(self, command, args):
|
|
|
"""Handle command receivd from command channel.
|
|
|
- ZONE_NOTIFY_COMMAND is issued by Auth process; ZONE_XFRIN_SUCCESS_COMMAND
|
|
|
- and ZONE_XFRIN_FAILED_COMMAND are issued by Xfrin process; shutdown is issued
|
|
|
- by a user or Boss process. """
|
|
|
+ ZONE_NOTIFY_COMMAND is issued by Auth process;
|
|
|
+ ZONE_XFRIN_SUCCESS_COMMAND and ZONE_XFRIN_FAILED_COMMAND are issued by
|
|
|
+ Xfrin process;
|
|
|
+ shutdown is issued by a user or Boss process. """
|
|
|
answer = create_answer(0)
|
|
|
if command == ZONE_NOTIFY_COMMAND:
|
|
|
""" Handle Auth notify command"""
|
|
|
# master is the source sender of the notify message.
|
|
|
zone_name_class, master = self._parse_cmd_params(args, command)
|
|
|
- log_msg("Received notify command for zone (%s, %s)." % zone_name_class)
|
|
|
+ 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
|
|
@@ -598,6 +611,7 @@ class Zonemgr:
|
|
|
elif command == ZONE_XFRIN_SUCCESS_COMMAND:
|
|
|
""" Handle xfrin success command"""
|
|
|
zone_name_class = self._parse_cmd_params(args, command)
|
|
|
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_SUCCESS, zone_name_class[0], zone_name_class[1])
|
|
|
with self._lock:
|
|
|
self._zone_refresh.zone_refresh_success(zone_name_class)
|
|
|
self._master_socket.send(b" ")# make self._slave_socket readble
|
|
@@ -605,14 +619,17 @@ class Zonemgr:
|
|
|
elif command == ZONE_XFRIN_FAILED_COMMAND:
|
|
|
""" Handle xfrin fail command"""
|
|
|
zone_name_class = self._parse_cmd_params(args, command)
|
|
|
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_XFRIN_FAILED, zone_name_class[0], zone_name_class[1])
|
|
|
with self._lock:
|
|
|
self._zone_refresh.zone_refresh_fail(zone_name_class)
|
|
|
self._master_socket.send(b" ")# make self._slave_socket readble
|
|
|
|
|
|
elif command == "shutdown":
|
|
|
+ logger.debug(DBG_ZONEMGR_COMMAND, ZONEMGR_RECEIVE_SHUTDOWN)
|
|
|
self.shutdown()
|
|
|
|
|
|
else:
|
|
|
+ logger.warn(ZONEMGR_RECEIVE_UNKNOWN, str(command))
|
|
|
answer = create_answer(1, "Unknown command:" + str(command))
|
|
|
|
|
|
return answer
|
|
@@ -639,25 +656,29 @@ def set_cmd_options(parser):
|
|
|
|
|
|
if '__main__' == __name__:
|
|
|
try:
|
|
|
+ logger.debug(DBG_START_SHUT, ZONEMGR_STARTING)
|
|
|
parser = OptionParser()
|
|
|
set_cmd_options(parser)
|
|
|
(options, args) = parser.parse_args()
|
|
|
- VERBOSE_MODE = options.verbose
|
|
|
+ if options.verbose:
|
|
|
+ logger.set_severity("DEBUG", 99)
|
|
|
|
|
|
set_signal_handler()
|
|
|
zonemgrd = Zonemgr()
|
|
|
zonemgrd.run()
|
|
|
except KeyboardInterrupt:
|
|
|
- sys.stderr.write("[b10-zonemgr] exit zonemgr process\n")
|
|
|
+ logger.info(ZONEMGR_KEYBOARD_INTERRUPT)
|
|
|
+
|
|
|
except isc.cc.session.SessionError as e:
|
|
|
- sys.stderr.write("[b10-zonemgr] Error creating zonemgr, "
|
|
|
- "is the command channel daemon running?\n")
|
|
|
+ logger.error(ZONEMGR_SESSION_ERROR)
|
|
|
+
|
|
|
except isc.cc.session.SessionTimeout as e:
|
|
|
- sys.stderr.write("[b10-zonemgr] Error creating zonemgr, "
|
|
|
- "is the configuration manager running?\n")
|
|
|
+ logger.error(ZONEMGR_SESSION_TIMEOUT)
|
|
|
+
|
|
|
except isc.config.ModuleCCSessionError as e:
|
|
|
- sys.stderr.write("[b10-zonemgr] exit zonemgr process: %s\n" % str(e))
|
|
|
+ logger.error(ZONEMGR_CCSESSION_ERROR, str(e))
|
|
|
|
|
|
if zonemgrd and zonemgrd.running:
|
|
|
zonemgrd.shutdown()
|
|
|
|
|
|
+ logger.debug(DBG_START_SHUT, ZONEMGR_SHUTDOWN)
|