Browse Source

Merge branch 'trac763'

Jelte Jansen 14 years ago
parent
commit
046f1b9556

+ 1 - 0
configure.ac

@@ -793,6 +793,7 @@ AC_CONFIG_FILES([Makefile
                  src/bin/stats/tests/isc/cc/Makefile
                  src/bin/stats/tests/isc/cc/Makefile
                  src/bin/stats/tests/isc/config/Makefile
                  src/bin/stats/tests/isc/config/Makefile
                  src/bin/stats/tests/isc/util/Makefile
                  src/bin/stats/tests/isc/util/Makefile
+                 src/bin/stats/tests/isc/log/Makefile
                  src/bin/stats/tests/testdata/Makefile
                  src/bin/stats/tests/testdata/Makefile
                  src/bin/stats/tests/http/Makefile
                  src/bin/stats/tests/http/Makefile
                  src/bin/usermgr/Makefile
                  src/bin/usermgr/Makefile

+ 10 - 0
src/bin/stats/Makefile.am

@@ -7,14 +7,18 @@ pkglibexec_SCRIPTS = b10-stats b10-stats-httpd
 b10_statsdir = $(pkgdatadir)
 b10_statsdir = $(pkgdatadir)
 b10_stats_DATA = stats.spec stats-httpd.spec stats-schema.spec
 b10_stats_DATA = stats.spec stats-httpd.spec stats-schema.spec
 b10_stats_DATA += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
 b10_stats_DATA += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
+pyexec_DATA = stats_messages.py stats_httpd_messages.py
 
 
 CLEANFILES = b10-stats stats.pyc
 CLEANFILES = b10-stats stats.pyc
 CLEANFILES += b10-stats-httpd stats_httpd.pyc
 CLEANFILES += b10-stats-httpd stats_httpd.pyc
+CLEANFILES += stats_messages.py stats_messages.pyc
+CLEANFILES += stats_httpd_messages.py stats_httpd_messages.pyc
 
 
 man_MANS = b10-stats.8 b10-stats-httpd.8
 man_MANS = b10-stats.8 b10-stats-httpd.8
 EXTRA_DIST = $(man_MANS) b10-stats.xml b10-stats-httpd.xml
 EXTRA_DIST = $(man_MANS) b10-stats.xml b10-stats-httpd.xml
 EXTRA_DIST += stats.spec stats-httpd.spec stats-schema.spec
 EXTRA_DIST += stats.spec stats-httpd.spec stats-schema.spec
 EXTRA_DIST += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
 EXTRA_DIST += stats-httpd-xml.tpl stats-httpd-xsd.tpl stats-httpd-xsl.tpl
+EXTRA_DIST += stats_messages.mes stats_httpd_messages.mes
 
 
 if ENABLE_MAN
 if ENABLE_MAN
 
 
@@ -26,6 +30,12 @@ b10-stats-httpd.8: b10-stats-httpd.xml
 
 
 endif
 endif
 
 
+stats_messages.py: stats_messages.mes
+	$(top_builddir)/src/lib/log/compiler/message -p $(top_srcdir)/src/bin/stats/stats_messages.mes
+
+stats_httpd_messages.py: stats_httpd_messages.mes
+	$(top_builddir)/src/lib/log/compiler/message -p $(top_srcdir)/src/bin/stats/stats_httpd_messages.mes
+
 # this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
 # this is done here since configure.ac AC_OUTPUT doesn't expand exec_prefix
 b10-stats: stats.py
 b10-stats: stats.py
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|"  stats.py >$@
 	$(SED) -e "s|@@PYTHONPATH@@|@pyexecdir@|"  stats.py >$@

+ 37 - 30
src/bin/stats/stats.py.in

@@ -25,6 +25,16 @@ from collections import defaultdict
 from isc.config.ccsession import ModuleCCSession, create_answer
 from isc.config.ccsession import ModuleCCSession, create_answer
 from isc.cc import Session, SessionError
 from isc.cc import Session, SessionError
 
 
+import isc.log
+from stats_messages import *
+
+isc.log.init("b10-stats")
+logger = isc.log.Logger("stats")
+
+# Some constants for debug levels, these should be removed when we
+# have #1074
+DBG_STATS_MESSAGING = 30
+
 # for setproctitle
 # for setproctitle
 import isc.util.process
 import isc.util.process
 isc.util.process.rename()
 isc.util.process.rename()
@@ -143,9 +153,8 @@ class SessionSubject(Subject, metaclass=Singleton):
     """
     """
     A concrete subject class which creates CC session object
     A concrete subject class which creates CC session object
     """
     """
-    def __init__(self, session=None, verbose=False):
+    def __init__(self, session=None):
         Subject.__init__(self)
         Subject.__init__(self)
-        self.verbose = verbose
         self.session=session
         self.session=session
         self.running = False
         self.running = False
 
 
@@ -165,9 +174,8 @@ class CCSessionListener(Listener):
     A concrete listener class which creates SessionSubject object and
     A concrete listener class which creates SessionSubject object and
     ModuleCCSession object
     ModuleCCSession object
     """
     """
-    def __init__(self, subject, verbose=False):
+    def __init__(self, subject):
         Listener.__init__(self, subject)
         Listener.__init__(self, subject)
-        self.verbose = verbose
         self.session = subject.session
         self.session = subject.session
         self.boot_time = get_datetime()
         self.boot_time = get_datetime()
 
 
@@ -203,8 +211,7 @@ class CCSessionListener(Listener):
                 kwargs = self.initialize_data(cmd["command_args"])
                 kwargs = self.initialize_data(cmd["command_args"])
                 self.add_event(Callback(name=name, callback=callback, args=(), kwargs=kwargs))
                 self.add_event(Callback(name=name, callback=callback, args=(), kwargs=kwargs))
             except AttributeError as ae:
             except AttributeError as ae:
-                sys.stderr.write("[b10-stats] Caught undefined command while parsing spec file: "
-                                 +str(cmd["command_name"])+"\n")
+                logger.error(STATS_UNKNOWN_COMMAND_IN_SPEC, cmd["command_name"])
 
 
     def start(self):
     def start(self):
         """
         """
@@ -217,8 +224,7 @@ class CCSessionListener(Listener):
         self.stats_data['stats.lname'] = self.session.lname
         self.stats_data['stats.lname'] = self.session.lname
         self.cc_session.start()
         self.cc_session.start()
         # request Bob to send statistics data
         # request Bob to send statistics data
-        if self.verbose:
-            sys.stdout.write("[b10-stats] request Bob to send statistics data\n")
+        logger.debug(DBG_STATS_MESSAGING, STATS_SEND_REQUEST_BOSS)
         cmd = isc.config.ccsession.create_command("sendstats", None)
         cmd = isc.config.ccsession.create_command("sendstats", None)
         seq = self.session.group_sendmsg(cmd, 'Boss')
         seq = self.session.group_sendmsg(cmd, 'Boss')
         self.session.group_recvmsg(True, seq)
         self.session.group_recvmsg(True, seq)
@@ -239,8 +245,8 @@ class CCSessionListener(Listener):
         """
         """
         handle a configure from the cc channel
         handle a configure from the cc channel
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] newconfig received: "+str(new_config)+"\n")
+        logger.debug(DBG_STATS_MESSAGING, STATS_RECEIVED_NEW_CONFIG,
+                     new_config)
 
 
         # do nothing currently
         # do nothing currently
         return create_answer(0)
         return create_answer(0)
@@ -262,8 +268,7 @@ class CCSessionListener(Listener):
         """
         """
         handle shutdown command
         handle shutdown command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'shutdown' command received\n")
+        logger.info(STATS_RECEIVED_SHUTDOWN_COMMAND)
         self.subject.running = False
         self.subject.running = False
         return create_answer(0)
         return create_answer(0)
 
 
@@ -283,13 +288,14 @@ class CCSessionListener(Listener):
         """
         """
         handle remove command
         handle remove command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'remove' command received, args: "+str(args)+"\n")
 
 
         # 'args' must be dictionary type
         # 'args' must be dictionary type
         if args and args['stats_item_name'] in self.stats_data:
         if args and args['stats_item_name'] in self.stats_data:
             stats_item_name = args['stats_item_name']
             stats_item_name = args['stats_item_name']
 
 
+        logger.debug(DBG_STATS_MESSAGING, STATS_RECEIVED_REMOVE_COMMAND,
+                     stats_item_name)
+
         # just remove one item
         # just remove one item
         self.stats_data.pop(stats_item_name)
         self.stats_data.pop(stats_item_name)
 
 
@@ -299,8 +305,6 @@ class CCSessionListener(Listener):
         """
         """
         handle show command
         handle show command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'show' command received, args: "+str(args)+"\n")
 
 
         # always overwrite 'report_time' and 'stats.timestamp'
         # always overwrite 'report_time' and 'stats.timestamp'
         # if "show" command invoked
         # if "show" command invoked
@@ -310,16 +314,21 @@ class CCSessionListener(Listener):
         # if with args
         # if with args
         if args and args['stats_item_name'] in self.stats_data:
         if args and args['stats_item_name'] in self.stats_data:
             stats_item_name = args['stats_item_name']
             stats_item_name = args['stats_item_name']
+            logger.debug(DBG_STATS_MESSAGING,
+                         STATS_RECEIVED_SHOW_NAME_COMMAND,
+                         stats_item_name)
             return create_answer(0, {stats_item_name: self.stats_data[stats_item_name]})
             return create_answer(0, {stats_item_name: self.stats_data[stats_item_name]})
 
 
+        logger.debug(DBG_STATS_MESSAGING,
+                     STATS_RECEIVED_SHOW_ALL_COMMAND)
         return create_answer(0, self.stats_data)
         return create_answer(0, self.stats_data)
 
 
     def command_reset(self, args):
     def command_reset(self, args):
         """
         """
         handle reset command
         handle reset command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'reset' command received\n")
+        logger.debug(DBG_STATS_MESSAGING,
+                     STATS_RECEIVED_RESET_COMMAND)
 
 
         # re-initialize internal variables
         # re-initialize internal variables
         self.stats_data = self.initialize_data(self.stats_spec)
         self.stats_data = self.initialize_data(self.stats_spec)
@@ -336,8 +345,7 @@ class CCSessionListener(Listener):
         """
         """
         handle status command
         handle status command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'status' command received\n")
+        logger.debug(DBG_STATS_MESSAGING, STATS_RECEIVED_STATUS_COMMAND)
         # just return "I'm alive."
         # just return "I'm alive."
         return create_answer(0, "I'm alive.")
         return create_answer(0, "I'm alive.")
 
 
@@ -345,9 +353,7 @@ class CCSessionListener(Listener):
         """
         """
         handle an unknown command
         handle an unknown command
         """
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] Unknown command received: '"
-                             + str(command) + "'\n")
+        logger.error(STATS_RECEIVED_UNKNOWN_COMMAND, command)
         return create_answer(1, "Unknown command: '"+str(command)+"'")
         return create_answer(1, "Unknown command: '"+str(command)+"'")
 
 
 
 
@@ -394,20 +400,21 @@ def main(session=None):
         parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
         parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                       help="display more about what is going on")
                       help="display more about what is going on")
         (options, args) = parser.parse_args()
         (options, args) = parser.parse_args()
-        subject = SessionSubject(session=session, verbose=options.verbose)
-        listener = CCSessionListener(subject, verbose=options.verbose)
+        if options.verbose:
+            isc.log.init("b10-stats", "DEBUG", 99)
+        subject = SessionSubject(session=session)
+        listener = CCSessionListener(subject)
         subject.start()
         subject.start()
         while subject.running:
         while subject.running:
             subject.check()
             subject.check()
         subject.stop()
         subject.stop()
 
 
-    except OptionValueError:
-        sys.stderr.write("[b10-stats] Error parsing options\n")
+    except OptionValueError as ove:
+        logger.fatal(STATS_BAD_OPTION_VALUE, ove)
     except SessionError as se:
     except SessionError as se:
-        sys.stderr.write("[b10-stats] Error creating Stats module, "
-              + "is the command channel daemon running?\n")
+        logger.fatal(STATS_CC_SESSION_ERROR, se)
     except KeyboardInterrupt as kie:
     except KeyboardInterrupt as kie:
-        sys.stderr.write("[b10-stats] Interrupted, exiting\n")
+        logger.info(STATS_STOPPED_BY_KEYBOARD)
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     main()
     main()

+ 45 - 54
src/bin/stats/stats_httpd.py.in

@@ -34,6 +34,17 @@ import isc.cc
 import isc.config
 import isc.config
 import isc.util.process
 import isc.util.process
 
 
+import isc.log
+from stats_httpd_messages import *
+
+isc.log.init("b10-stats-httpd")
+logger = isc.log.Logger("stats-httpd")
+
+# Some constants for debug levels, these should be removed when we
+# have #1074
+DBG_STATHTTPD_INIT = 10
+DBG_STATHTTPD_MESSAGING = 30
+
 # If B10_FROM_SOURCE is set in the environment, we use data files
 # If B10_FROM_SOURCE is set in the environment, we use data files
 # from a directory relative to that, otherwise we use the ones
 # from a directory relative to that, otherwise we use the ones
 # installed on the system
 # installed on the system
@@ -98,9 +109,7 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
                     return None
                     return None
         except StatsHttpdError as err:
         except StatsHttpdError as err:
             self.send_error(500)
             self.send_error(500)
-            if self.server.verbose:
-                self.server.log_writer(
-                    "[b10-stats-httpd] %s\n" % err)
+            logger.error(STATHTTPD_SERVER_ERROR, err)
             return None
             return None
         else:
         else:
             self.send_response(200)
             self.send_response(200)
@@ -109,15 +118,6 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
             self.end_headers()
             self.end_headers()
             return body
             return body
 
 
-    def log_message(self, format, *args):
-        """Change the default log format"""
-        if self.server.verbose:
-            self.server.log_writer(
-                "[b10-stats-httpd] %s - - [%s] %s\n" %
-                (self.address_string(),
-                 self.log_date_time_string(),
-                 format%args))
-
 class HttpServerError(Exception):
 class HttpServerError(Exception):
     """Exception class for HttpServer class. It is intended to be
     """Exception class for HttpServer class. It is intended to be
     passed from the HttpServer object to the StatsHttpd object."""
     passed from the HttpServer object to the StatsHttpd object."""
@@ -134,13 +134,12 @@ class HttpServer(http.server.HTTPServer):
     sys.stderr.write. They are intended to be referred by HttpHandler
     sys.stderr.write. They are intended to be referred by HttpHandler
     object."""
     object."""
     def __init__(self, server_address, handler,
     def __init__(self, server_address, handler,
-                 xml_handler, xsd_handler, xsl_handler, log_writer, verbose=False):
+                 xml_handler, xsd_handler, xsl_handler, log_writer):
         self.server_address = server_address
         self.server_address = server_address
         self.xml_handler = xml_handler
         self.xml_handler = xml_handler
         self.xsd_handler = xsd_handler
         self.xsd_handler = xsd_handler
         self.xsl_handler = xsl_handler
         self.xsl_handler = xsl_handler
         self.log_writer = log_writer
         self.log_writer = log_writer
-        self.verbose = verbose
         http.server.HTTPServer.__init__(self, server_address, handler)
         http.server.HTTPServer.__init__(self, server_address, handler)
 
 
 class StatsHttpdError(Exception):
 class StatsHttpdError(Exception):
@@ -154,8 +153,7 @@ class StatsHttpd:
     statistics module. It handles HTTP requests, and command channel
     statistics module. It handles HTTP requests, and command channel
     and config channel CC session. It uses select.select function
     and config channel CC session. It uses select.select function
     while waiting for clients requests."""
     while waiting for clients requests."""
-    def __init__(self, verbose=False):
-        self.verbose = verbose
+    def __init__(self):
         self.running = False
         self.running = False
         self.poll_intval = 0.5
         self.poll_intval = 0.5
         self.write_log = sys.stderr.write
         self.write_log = sys.stderr.write
@@ -169,8 +167,7 @@ class StatsHttpd:
     def open_mccs(self):
     def open_mccs(self):
         """Opens a ModuleCCSession object"""
         """Opens a ModuleCCSession object"""
         # create ModuleCCSession
         # create ModuleCCSession
-        if self.verbose:
-            self.write_log("[b10-stats-httpd] Starting CC Session\n")
+        logger.debug(DBG_STATHTTPD_INIT, STATHTTPD_STARTING_CC_SESSION)
         self.mccs = isc.config.ModuleCCSession(
         self.mccs = isc.config.ModuleCCSession(
             SPECFILE_LOCATION, self.config_handler, self.command_handler)
             SPECFILE_LOCATION, self.config_handler, self.command_handler)
         self.cc_session = self.mccs._session
         self.cc_session = self.mccs._session
@@ -183,8 +180,8 @@ class StatsHttpd:
         """Closes a ModuleCCSession object"""
         """Closes a ModuleCCSession object"""
         if self.mccs is None:
         if self.mccs is None:
             return
             return
-        if self.verbose:
-            self.write_log("[b10-stats-httpd] Closing CC Session\n")
+
+        logger.debug(DBG_STATHTTPD_INIT, STATHTTPD_CLOSING_CC_SESSION)
         self.mccs.close()
         self.mccs.close()
         self.mccs = None
         self.mccs = None
 
 
@@ -221,7 +218,7 @@ class StatsHttpd:
             httpd = HttpServer(
             httpd = HttpServer(
                 server_address, HttpHandler,
                 server_address, HttpHandler,
                 self.xml_handler, self.xsd_handler, self.xsl_handler,
                 self.xml_handler, self.xsd_handler, self.xsl_handler,
-                self.write_log, self.verbose)
+                self.write_log)
         except (socket.gaierror, socket.error,
         except (socket.gaierror, socket.error,
                 OverflowError, TypeError) as err:
                 OverflowError, TypeError) as err:
             # try IPv4 next
             # try IPv4 next
@@ -233,10 +230,8 @@ class StatsHttpd:
                     (server_address[0], server_address[1],
                     (server_address[0], server_address[1],
                      err.__class__.__name__, err))
                      err.__class__.__name__, err))
         else:
         else:
-            if self.verbose:
-                self.write_log(
-                    "[b10-stats-httpd] Started on address %s, port %s\n" %
-                    server_address)
+            logger.info(STATHTTPD_STARTED, server_address[0],
+                        server_address[1])
         return httpd
         return httpd
 
 
     def close_httpd(self):
     def close_httpd(self):
@@ -244,11 +239,8 @@ class StatsHttpd:
         if len(self.httpd) == 0:
         if len(self.httpd) == 0:
             return
             return
         for ht in self.httpd:
         for ht in self.httpd:
-            if self.verbose:
-                self.write_log(
-                    "[b10-stats-httpd] Closing address %s, port %s\n" %
-                    (ht.server_address[0], ht.server_address[1])
-                    )
+            logger.info(STATHTTPD_CLOSING, ht.server_address[0],
+                        ht.server_address[1])
             ht.server_close()
             ht.server_close()
         self.httpd = []
         self.httpd = []
 
 
@@ -285,8 +277,7 @@ class StatsHttpd:
     def stop(self):
     def stop(self):
         """Stops the running StatsHttpd objects. Closes CC session and
         """Stops the running StatsHttpd objects. Closes CC session and
         HTTP handling sockets"""
         HTTP handling sockets"""
-        if self.verbose:
-            self.write_log("[b10-stats-httpd] Shutting down\n")
+        logger.info(STATHTTPD_SHUTDOWN)
         self.close_httpd()
         self.close_httpd()
         self.close_mccs()
         self.close_mccs()
 
 
@@ -303,13 +294,11 @@ class StatsHttpd:
     def config_handler(self, new_config):
     def config_handler(self, new_config):
         """Config handler for the ModuleCCSession object. It resets
         """Config handler for the ModuleCCSession object. It resets
         addresses and ports to listen HTTP requests on."""
         addresses and ports to listen HTTP requests on."""
-        if self.verbose:
-            self.write_log("[b10-stats-httpd] Loading config : %s\n" % str(new_config))
+        logger.debug(DBG_STATHTTPD_MESSAGING, STATHTTPD_HANDLE_CONFIG,
+                   new_config)
         for key in new_config.keys():
         for key in new_config.keys():
-            if key not in DEFAULT_CONFIG:
-                if self.verbose:
-                    self.write_log(
-                        "[b10-stats-httpd] Unknown known config: %s" % key)
+            if key not in DEFAULT_CONFIG and key != "version":
+                logger.error(STATHTTPD_UNKNOWN_CONFIG_ITEM, key)
                 return isc.config.ccsession.create_answer(
                 return isc.config.ccsession.create_answer(
                     1, "Unknown known config: %s" % key)
                     1, "Unknown known config: %s" % key)
         # backup old config
         # backup old config
@@ -319,9 +308,7 @@ class StatsHttpd:
         try:
         try:
             self.open_httpd()
             self.open_httpd()
         except HttpServerError as err:
         except HttpServerError as err:
-            if self.verbose:
-                self.write_log("[b10-stats-httpd] %s\n" % err)
-                self.write_log("[b10-stats-httpd] Restoring old config\n")
+            logger.error(STATHTTPD_SERVER_ERROR, err)
             # restore old config
             # restore old config
             self.config_handler(old_config)
             self.config_handler(old_config)
             return isc.config.ccsession.create_answer(
             return isc.config.ccsession.create_answer(
@@ -333,19 +320,19 @@ class StatsHttpd:
         """Command handler for the ModuleCCSesson object. It handles
         """Command handler for the ModuleCCSesson object. It handles
         "status" and "shutdown" commands."""
         "status" and "shutdown" commands."""
         if command == "status":
         if command == "status":
-            if self.verbose:
-                self.write_log("[b10-stats-httpd] Received 'status' command\n")
+            logger.debug(DBG_STATHTTPD_MESSAGING,
+                         STATHTTPD_RECEIVED_STATUS_COMMAND)
             return isc.config.ccsession.create_answer(
             return isc.config.ccsession.create_answer(
                 0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")")
                 0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")")
         elif command == "shutdown":
         elif command == "shutdown":
-            if self.verbose:
-                self.write_log("[b10-stats-httpd] Received 'shutdown' command\n")
+            logger.debug(DBG_STATHTTPD_MESSAGING,
+                         STATHTTPD_RECEIVED_SHUTDOWN_COMMAND)
             self.running = False
             self.running = False
             return isc.config.ccsession.create_answer(
             return isc.config.ccsession.create_answer(
                 0, "Stats Httpd is shutting down.")
                 0, "Stats Httpd is shutting down.")
         else:
         else:
-            if self.verbose:
-                self.write_log("[b10-stats-httpd] Received unknown command\n")
+            logger.debug(DBG_STATHTTPD_MESSAGING,
+                         STATHTTPD_RECEIVED_UNKNOWN_COMMAND, command)
             return isc.config.ccsession.create_answer(
             return isc.config.ccsession.create_answer(
                 1, "Unknown command: " + str(command))
                 1, "Unknown command: " + str(command))
 
 
@@ -479,14 +466,18 @@ if __name__ == "__main__":
             "-v", "--verbose", dest="verbose", action="store_true",
             "-v", "--verbose", dest="verbose", action="store_true",
             help="display more about what is going on")
             help="display more about what is going on")
         (options, args) = parser.parse_args()
         (options, args) = parser.parse_args()
-        stats_httpd = StatsHttpd(verbose=options.verbose)
+        if options.verbose:
+            isc.log.init("b10-stats-httpd", "DEBUG", 99)
+        stats_httpd = StatsHttpd()
         stats_httpd.start()
         stats_httpd.start()
-    except OptionValueError:
-        sys.exit("[b10-stats-httpd] Error parsing options")
+    except OptionValueError as ove:
+        logger.fatal(STATHTTPD_BAD_OPTION_VALUE, ove)
+        sys.exit(1)
     except isc.cc.session.SessionError as se:
     except isc.cc.session.SessionError as se:
-        sys.exit("[b10-stats-httpd] Error creating module, "
-                 + "is the command channel daemon running?")
+        logger.fatal(STATHTTPD_CC_SESSION_ERROR, se)
+        sys.exit(1)
     except HttpServerError as hse:
     except HttpServerError as hse:
-        sys.exit("[b10-stats-httpd] %s" % hse)
+        logger.fatal(STATHTTPD_START_SERVER_ERROR, hse)
+        sys.exit(1)
     except KeyboardInterrupt as kie:
     except KeyboardInterrupt as kie:
-        sys.exit("[b10-stats-httpd] Interrupted, exiting")
+        logger.info(STATHTTPD_STOPPED_BY_KEYBOARD)

+ 92 - 0
src/bin/stats/stats_httpd_messages.mes

@@ -0,0 +1,92 @@
+# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# No namespace declaration - these constants go in the global namespace
+# of the stats_httpd_messages python module.
+
+% STATHTTPD_BAD_OPTION_VALUE bad command line argument: %1
+The stats-httpd module was called with a bad command-line argument
+and will not start.
+
+% STATHTTPD_CC_SESSION_ERROR error connecting to message bus: %1
+The stats-httpd module was unable to connect to the BIND 10 command
+and control bus. A likely problem is that the message bus daemon
+(b10-msgq) is not running. The stats-httpd module will now shut down.
+
+% STATHTTPD_CLOSING_CC_SESSION stopping cc session
+Debug message indicating that the stats-httpd module is disconnecting
+from the command and control bus.
+
+% STATHTTPD_CLOSING closing %1#%2
+The stats-httpd daemon will stop listening for requests on the given
+address and port number.
+
+% STATHTTPD_HANDLE_CONFIG reading configuration: %1
+The stats-httpd daemon has received new configuration data and will now
+process it. The (changed) data is printed.
+
+% STATHTTPD_RECEIVED_SHUTDOWN_COMMAND shutdown command received
+A shutdown command was sent to the stats-httpd module, and it will
+now shut down.
+
+% STATHTTPD_RECEIVED_STATUS_COMMAND received command to return status
+A status command was sent to the stats-httpd module, and it will
+respond with 'Stats Httpd is up.' and its PID.
+
+% STATHTTPD_RECEIVED_UNKNOWN_COMMAND received unknown command: %1
+An unknown command has been sent to the stats-httpd module. The
+stats-httpd module will respond with an error, and the command will
+be ignored.
+
+% STATHTTPD_SERVER_ERROR http server error: %1
+An internal error occurred while handling an http request. A HTTP 500
+response will be sent back, and the specific error is printed. This
+is an error condition that likely points to a module that is not
+responding correctly to statistic requests.
+
+% STATHTTPD_SERVER_INIT_ERROR http server initialization error: %1
+There was a problem initializing the http server in the stats-httpd
+module upon receiving its configuration data. The most likely cause
+is a port binding problem or a bad configuration value. The specific
+error is printed in the message. The new configuration is ignored,
+and an error is sent back.
+
+% STATHTTPD_SHUTDOWN shutting down
+The stats-httpd daemon is shutting down.
+
+% STATHTTPD_START_SERVER_INIT_ERROR http server initialization error: %1
+There was a problem initializing the http server in the stats-httpd
+module upon startup. The most likely cause is that it was not able
+to bind to the listening port. The specific error is printed, and the
+module will shut down.
+
+% STATHTTPD_STARTED listening on %1#%2
+The stats-httpd daemon will now start listening for requests on the
+given address and port number.
+
+% STATHTTPD_STARTING_CC_SESSION starting cc session
+Debug message indicating that the stats-httpd module is connecting to
+the command and control bus.
+
+% STATHTTPD_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
+There was a keyboard interrupt signal to stop the stats-httpd
+daemon. The daemon will now shut down.
+
+% STATHTTPD_UNKNOWN_CONFIG_ITEM unknown configuration item: %1
+The stats-httpd daemon received a configuration update from the
+configuration manager. However, one of the items in the
+configuration is unknown. The new configuration is ignored, and an
+error is sent back. As possible cause is that there was an upgrade
+problem, and the stats-httpd version is out of sync with the rest of
+the system.

+ 75 - 0
src/bin/stats/stats_messages.mes

@@ -0,0 +1,75 @@
+# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# No namespace declaration - these constants go in the global namespace
+# of the stats_messages python module.
+
+% STATS_BAD_OPTION_VALUE bad command line argument: %1
+The stats module was called with a bad command-line argument and will
+not start.
+
+% STATS_CC_SESSION_ERROR error connecting to message bus: %1
+The stats module was unable to connect to the BIND 10 command and
+control bus. A likely problem is that the message bus daemon
+(b10-msgq) is not running. The stats module will now shut down.
+
+% STATS_RECEIVED_NEW_CONFIG received new configuration: %1
+This debug message is printed when the stats module has received a
+configuration update from the configuration manager.
+
+% STATS_RECEIVED_REMOVE_COMMAND received command to remove %1
+A remove command for the given name was sent to the stats module, and
+the given statistics value will now be removed. It will not appear in
+statistics reports until it appears in a statistics update from a
+module again.
+
+% STATS_RECEIVED_RESET_COMMAND received command to reset all statistics
+The stats module received a command to clear all collected statistics.
+The data is cleared until it receives an update from the modules again.
+
+% STATS_RECEIVED_SHOW_ALL_COMMAND received command to show all statistics
+The stats module received a command to show all statistics that it has
+collected.
+
+% STATS_RECEIVED_SHOW_NAME_COMMAND received command to show statistics for %1
+The stats module received a command to show the statistics that it has
+collected for the given item.
+
+% STATS_RECEIVED_SHUTDOWN_COMMAND shutdown command received
+A shutdown command was sent to the stats module and it will now shut down.
+
+% STATS_RECEIVED_STATUS_COMMAND received command to return status
+A status command was sent to the stats module. It will return a
+response indicating that it is running normally.
+
+% STATS_RECEIVED_UNKNOWN_COMMAND received unknown command: %1
+An unknown command has been sent to the stats module. The stats module
+will respond with an error and the command will be ignored.
+
+% STATS_SEND_REQUEST_BOSS requesting boss to send statistics
+This debug message is printed when a request is sent to the boss module
+to send its data to the stats module.
+
+% STATS_STOPPED_BY_KEYBOARD keyboard interrupt, shutting down
+There was a keyboard interrupt signal to stop the stats module. The
+daemon will now shut down.
+
+% STATS_UNKNOWN_COMMAND_IN_SPEC unknown command in specification file: %1
+The specification file for the stats module contains a command that
+is unknown in the implementation. The most likely cause is an
+installation problem, where the specification file stats.spec is
+from a different version of BIND 10 than the stats module itself.
+Please check your installation.
+
+

+ 4 - 30
src/bin/stats/tests/b10-stats-httpd_test.py

@@ -57,13 +57,9 @@ class TestHttpHandler(unittest.TestCase):
     """Tests for HttpHandler class"""
     """Tests for HttpHandler class"""
 
 
     def setUp(self):
     def setUp(self):
-        self.verbose = True
-        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
+        self.stats_httpd = stats_httpd.StatsHttpd()
         self.assertTrue(type(self.stats_httpd.httpd) is list)
         self.assertTrue(type(self.stats_httpd.httpd) is list)
         self.httpd = self.stats_httpd.httpd
         self.httpd = self.stats_httpd.httpd
-        for ht in self.httpd:
-            self.assertTrue(ht.verbose)
-        self.stats_httpd.cc_session.verbose = False
 
 
     def test_do_GET(self):
     def test_do_GET(self):
         for ht in self.httpd:
         for ht in self.httpd:
@@ -155,21 +151,6 @@ class TestHttpHandler(unittest.TestCase):
         handler.do_HEAD()
         handler.do_HEAD()
         self.assertEqual(handler.response.code, 404)
         self.assertEqual(handler.response.code, 404)
 
 
-    def test_log_message(self):
-        for ht in self.httpd:
-            self._test_log_message(ht._handler)
-
-    def _test_log_message(self, handler):
-        # switch write_log function
-        handler.server.log_writer = handler.response._write_log
-        log_message = 'ABCDEFG'
-        handler.log_message("%s", log_message)
-        self.assertEqual(handler.response.log, 
-                         "[b10-stats-httpd] %s - - [%s] %s\n" %
-                         (handler.address_string(),
-                          handler.log_date_time_string(),
-                          log_message))
-
 class TestHttpServerError(unittest.TestCase):
 class TestHttpServerError(unittest.TestCase):
     """Tests for HttpServerError exception"""
     """Tests for HttpServerError exception"""
 
 
@@ -183,12 +164,9 @@ class TestHttpServer(unittest.TestCase):
     """Tests for HttpServer class"""
     """Tests for HttpServer class"""
 
 
     def test_httpserver(self):
     def test_httpserver(self):
-        self.verbose = True
-        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
-        self.stats_httpd.cc_session.verbose = False
+        self.stats_httpd = stats_httpd.StatsHttpd()
         for ht in self.stats_httpd.httpd:
         for ht in self.stats_httpd.httpd:
             self.assertTrue(ht.server_address in self.stats_httpd.http_addrs)
             self.assertTrue(ht.server_address in self.stats_httpd.http_addrs)
-            self.assertEqual(ht.verbose, self.verbose)
             self.assertEqual(ht.xml_handler, self.stats_httpd.xml_handler)
             self.assertEqual(ht.xml_handler, self.stats_httpd.xml_handler)
             self.assertEqual(ht.xsd_handler, self.stats_httpd.xsd_handler)
             self.assertEqual(ht.xsd_handler, self.stats_httpd.xsd_handler)
             self.assertEqual(ht.xsl_handler, self.stats_httpd.xsl_handler)
             self.assertEqual(ht.xsl_handler, self.stats_httpd.xsl_handler)
@@ -209,17 +187,14 @@ class TestStatsHttpd(unittest.TestCase):
     """Tests for StatsHttpd class"""
     """Tests for StatsHttpd class"""
 
 
     def setUp(self):
     def setUp(self):
-        self.verbose = True
         fake_socket._CLOSED = False
         fake_socket._CLOSED = False
         fake_socket.has_ipv6 = True
         fake_socket.has_ipv6 = True
-        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
-        self.stats_httpd.cc_session.verbose = False
+        self.stats_httpd = stats_httpd.StatsHttpd()
 
 
     def tearDown(self):
     def tearDown(self):
         self.stats_httpd.stop()
         self.stats_httpd.stop()
 
 
     def test_init(self):
     def test_init(self):
-        self.assertTrue(self.stats_httpd.verbose)
         self.assertFalse(self.stats_httpd.mccs.get_socket()._closed)
         self.assertFalse(self.stats_httpd.mccs.get_socket()._closed)
         self.assertEqual(self.stats_httpd.mccs.get_socket().fileno(),
         self.assertEqual(self.stats_httpd.mccs.get_socket().fileno(),
                          id(self.stats_httpd.mccs.get_socket()))
                          id(self.stats_httpd.mccs.get_socket()))
@@ -317,8 +292,7 @@ class TestStatsHttpd(unittest.TestCase):
         self.stats_httpd.cc_session.group_sendmsg(
         self.stats_httpd.cc_session.group_sendmsg(
             { 'command': [ "shutdown" ] }, "StatsHttpd")
             { 'command': [ "shutdown" ] }, "StatsHttpd")
         self.stats_httpd.start()
         self.stats_httpd.start()
-        self.stats_httpd = stats_httpd.StatsHttpd(self.verbose)
-        self.stats_httpd.cc_session.verbose = False
+        self.stats_httpd = stats_httpd.StatsHttpd()
         self.assertRaises(
         self.assertRaises(
             fake_select.error, self.stats_httpd.start)
             fake_select.error, self.stats_httpd.start)
 
 

+ 11 - 11
src/bin/stats/tests/b10-stats_test.py

@@ -31,18 +31,18 @@ stats.gmtime = gmtime
 from stats import SessionSubject, CCSessionListener, get_timestamp, get_datetime
 from stats import SessionSubject, CCSessionListener, get_timestamp, get_datetime
 from fake_time import _TEST_TIME_SECS, _TEST_TIME_STRF
 from fake_time import _TEST_TIME_SECS, _TEST_TIME_STRF
 
 
-# setting Constant
-if sys.path[0] == '':
-    TEST_SPECFILE_LOCATION = "./testdata/stats_test.spec"
+if "B10_FROM_SOURCE" in os.environ:
+    TEST_SPECFILE_LOCATION = os.environ["B10_FROM_SOURCE"] +\
+    "/src/bin/stats/tests/testdata/stats_test.spec"
 else:
 else:
-    TEST_SPECFILE_LOCATION = sys.path[0] + "/testdata/stats_test.spec"
+    TEST_SPECFILE_LOCATION = "./testdata/stats_test.spec"
 
 
 class TestStats(unittest.TestCase):
 class TestStats(unittest.TestCase):
 
 
     def setUp(self):
     def setUp(self):
         self.session = Session()
         self.session = Session()
-        self.subject = SessionSubject(session=self.session, verbose=True)
-        self.listener = CCSessionListener(self.subject, verbose=True)
+        self.subject = SessionSubject(session=self.session)
+        self.listener = CCSessionListener(self.subject)
         self.stats_spec = self.listener.cc_session.get_module_spec().get_config_spec()
         self.stats_spec = self.listener.cc_session.get_module_spec().get_config_spec()
         self.module_name = self.listener.cc_session.get_module_spec().get_module_name()
         self.module_name = self.listener.cc_session.get_module_spec().get_module_name()
         self.stats_data = {
         self.stats_data = {
@@ -516,9 +516,9 @@ class TestStats(unittest.TestCase):
 class TestStats2(unittest.TestCase):
 class TestStats2(unittest.TestCase):
 
 
     def setUp(self):
     def setUp(self):
-        self.session = Session(verbose=True)
-        self.subject = SessionSubject(session=self.session, verbose=True)
-        self.listener = CCSessionListener(self.subject, verbose=True)
+        self.session = Session()
+        self.subject = SessionSubject(session=self.session)
+        self.listener = CCSessionListener(self.subject)
         self.module_name = self.listener.cc_session.get_module_spec().get_module_name()
         self.module_name = self.listener.cc_session.get_module_spec().get_module_name()
         # check starting
         # check starting
         self.assertFalse(self.subject.running)
         self.assertFalse(self.subject.running)
@@ -553,9 +553,9 @@ class TestStats2(unittest.TestCase):
         stats.SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
         stats.SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
         stats.SCHEMA_SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
         stats.SCHEMA_SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
         self.assertEqual(stats.SPECFILE_LOCATION, TEST_SPECFILE_LOCATION)
         self.assertEqual(stats.SPECFILE_LOCATION, TEST_SPECFILE_LOCATION)
-        self.subject = stats.SessionSubject(session=self.session, verbose=True)
+        self.subject = stats.SessionSubject(session=self.session)
         self.session = self.subject.session
         self.session = self.subject.session
-        self.listener = stats.CCSessionListener(self.subject, verbose=True)
+        self.listener = stats.CCSessionListener(self.subject)
 
 
         self.assertEqual(self.listener.stats_spec, [])
         self.assertEqual(self.listener.stats_spec, [])
         self.assertEqual(self.listener.stats_data, {})
         self.assertEqual(self.listener.stats_data, {})

+ 1 - 1
src/bin/stats/tests/isc/Makefile.am

@@ -1,4 +1,4 @@
-SUBDIRS = cc config util
+SUBDIRS = cc config util log
 EXTRA_DIST = __init__.py
 EXTRA_DIST = __init__.py
 CLEANFILES = __init__.pyc
 CLEANFILES = __init__.pyc
 
 

+ 7 - 0
src/bin/stats/tests/isc/log/Makefile.am

@@ -0,0 +1,7 @@
+EXTRA_DIST = __init__.py
+CLEANFILES = __init__.pyc
+
+CLEANDIRS = __pycache__
+
+clean-local:
+	rm -rf $(CLEANDIRS)

+ 33 - 0
src/bin/stats/tests/isc/log/__init__.py

@@ -0,0 +1,33 @@
+# Copyright (C) 2011  Internet Systems Consortium.
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+# This file is not installed. The log.so is installed into the right place.
+# It is only to find it in the .libs directory when we run as a test or
+# from the build directory.
+# But as nobody gives us the builddir explicitly (and we can't use generation
+# from .in file, as it would put us into the builddir and we wouldn't be found)
+# we guess from current directory. Any idea for something better? This should
+# be enough for the tests, but would it work for B10_FROM_SOURCE as well?
+# Should we look there? Or define something in bind10_config?
+
+import os
+import sys
+
+for base in sys.path[:]:
+    loglibdir = os.path.join(base, 'isc/log/.libs')
+    if os.path.exists(loglibdir):
+        sys.path.insert(0, loglibdir)
+
+from log import *