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/config/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/http/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_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
+pyexec_DATA = stats_messages.py stats_httpd_messages.py
 
 CLEANFILES = b10-stats stats.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
 EXTRA_DIST = $(man_MANS) b10-stats.xml b10-stats-httpd.xml
 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_messages.mes stats_httpd_messages.mes
 
 if ENABLE_MAN
 
@@ -26,6 +30,12 @@ b10-stats-httpd.8: b10-stats-httpd.xml
 
 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
 b10-stats: 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.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
 import isc.util.process
 isc.util.process.rename()
@@ -143,9 +153,8 @@ class SessionSubject(Subject, metaclass=Singleton):
     """
     A concrete subject class which creates CC session object
     """
-    def __init__(self, session=None, verbose=False):
+    def __init__(self, session=None):
         Subject.__init__(self)
-        self.verbose = verbose
         self.session=session
         self.running = False
 
@@ -165,9 +174,8 @@ class CCSessionListener(Listener):
     A concrete listener class which creates SessionSubject object and
     ModuleCCSession object
     """
-    def __init__(self, subject, verbose=False):
+    def __init__(self, subject):
         Listener.__init__(self, subject)
-        self.verbose = verbose
         self.session = subject.session
         self.boot_time = get_datetime()
 
@@ -203,8 +211,7 @@ class CCSessionListener(Listener):
                 kwargs = self.initialize_data(cmd["command_args"])
                 self.add_event(Callback(name=name, callback=callback, args=(), kwargs=kwargs))
             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):
         """
@@ -217,8 +224,7 @@ class CCSessionListener(Listener):
         self.stats_data['stats.lname'] = self.session.lname
         self.cc_session.start()
         # 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)
         seq = self.session.group_sendmsg(cmd, 'Boss')
         self.session.group_recvmsg(True, seq)
@@ -239,8 +245,8 @@ class CCSessionListener(Listener):
         """
         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
         return create_answer(0)
@@ -262,8 +268,7 @@ class CCSessionListener(Listener):
         """
         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
         return create_answer(0)
 
@@ -283,13 +288,14 @@ class CCSessionListener(Listener):
         """
         handle remove command
         """
-        if self.verbose:
-            sys.stdout.write("[b10-stats] 'remove' command received, args: "+str(args)+"\n")
 
         # 'args' must be dictionary type
         if args and args['stats_item_name'] in self.stats_data:
             stats_item_name = args['stats_item_name']
 
+        logger.debug(DBG_STATS_MESSAGING, STATS_RECEIVED_REMOVE_COMMAND,
+                     stats_item_name)
+
         # just remove one item
         self.stats_data.pop(stats_item_name)
 
@@ -299,8 +305,6 @@ class CCSessionListener(Listener):
         """
         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'
         # if "show" command invoked
@@ -310,16 +314,21 @@ class CCSessionListener(Listener):
         # if with args
         if args and args['stats_item_name'] in self.stats_data:
             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]})
 
+        logger.debug(DBG_STATS_MESSAGING,
+                     STATS_RECEIVED_SHOW_ALL_COMMAND)
         return create_answer(0, self.stats_data)
 
     def command_reset(self, args):
         """
         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
         self.stats_data = self.initialize_data(self.stats_spec)
@@ -336,8 +345,7 @@ class CCSessionListener(Listener):
         """
         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."
         return create_answer(0, "I'm alive.")
 
@@ -345,9 +353,7 @@ class CCSessionListener(Listener):
         """
         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)+"'")
 
 
@@ -394,20 +400,21 @@ def main(session=None):
         parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                       help="display more about what is going on")
         (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()
         while subject.running:
             subject.check()
         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:
-        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:
-        sys.stderr.write("[b10-stats] Interrupted, exiting\n")
+        logger.info(STATS_STOPPED_BY_KEYBOARD)
 
 if __name__ == "__main__":
     main()

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

@@ -34,6 +34,17 @@ import isc.cc
 import isc.config
 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
 # from a directory relative to that, otherwise we use the ones
 # installed on the system
@@ -98,9 +109,7 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
                     return None
         except StatsHttpdError as err:
             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
         else:
             self.send_response(200)
@@ -109,15 +118,6 @@ class HttpHandler(http.server.BaseHTTPRequestHandler):
             self.end_headers()
             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):
     """Exception class for HttpServer class. It is intended to be
     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
     object."""
     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.xml_handler = xml_handler
         self.xsd_handler = xsd_handler
         self.xsl_handler = xsl_handler
         self.log_writer = log_writer
-        self.verbose = verbose
         http.server.HTTPServer.__init__(self, server_address, handler)
 
 class StatsHttpdError(Exception):
@@ -154,8 +153,7 @@ class StatsHttpd:
     statistics module. It handles HTTP requests, and command channel
     and config channel CC session. It uses select.select function
     while waiting for clients requests."""
-    def __init__(self, verbose=False):
-        self.verbose = verbose
+    def __init__(self):
         self.running = False
         self.poll_intval = 0.5
         self.write_log = sys.stderr.write
@@ -169,8 +167,7 @@ class StatsHttpd:
     def open_mccs(self):
         """Opens a ModuleCCSession object"""
         # 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(
             SPECFILE_LOCATION, self.config_handler, self.command_handler)
         self.cc_session = self.mccs._session
@@ -183,8 +180,8 @@ class StatsHttpd:
         """Closes a ModuleCCSession object"""
         if self.mccs is None:
             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 = None
 
@@ -221,7 +218,7 @@ class StatsHttpd:
             httpd = HttpServer(
                 server_address, HttpHandler,
                 self.xml_handler, self.xsd_handler, self.xsl_handler,
-                self.write_log, self.verbose)
+                self.write_log)
         except (socket.gaierror, socket.error,
                 OverflowError, TypeError) as err:
             # try IPv4 next
@@ -233,10 +230,8 @@ class StatsHttpd:
                     (server_address[0], server_address[1],
                      err.__class__.__name__, err))
         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
 
     def close_httpd(self):
@@ -244,11 +239,8 @@ class StatsHttpd:
         if len(self.httpd) == 0:
             return
         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()
         self.httpd = []
 
@@ -285,8 +277,7 @@ class StatsHttpd:
     def stop(self):
         """Stops the running StatsHttpd objects. Closes CC session and
         HTTP handling sockets"""
-        if self.verbose:
-            self.write_log("[b10-stats-httpd] Shutting down\n")
+        logger.info(STATHTTPD_SHUTDOWN)
         self.close_httpd()
         self.close_mccs()
 
@@ -303,13 +294,11 @@ class StatsHttpd:
     def config_handler(self, new_config):
         """Config handler for the ModuleCCSession object. It resets
         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():
-            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(
                     1, "Unknown known config: %s" % key)
         # backup old config
@@ -319,9 +308,7 @@ class StatsHttpd:
         try:
             self.open_httpd()
         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
             self.config_handler(old_config)
             return isc.config.ccsession.create_answer(
@@ -333,19 +320,19 @@ class StatsHttpd:
         """Command handler for the ModuleCCSesson object. It handles
         "status" and "shutdown" commands."""
         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(
                 0, "Stats Httpd is up. (PID " + str(os.getpid()) + ")")
         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
             return isc.config.ccsession.create_answer(
                 0, "Stats Httpd is shutting down.")
         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(
                 1, "Unknown command: " + str(command))
 
@@ -479,14 +466,18 @@ if __name__ == "__main__":
             "-v", "--verbose", dest="verbose", action="store_true",
             help="display more about what is going on")
         (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()
-    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:
-        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:
-        sys.exit("[b10-stats-httpd] %s" % hse)
+        logger.fatal(STATHTTPD_START_SERVER_ERROR, hse)
+        sys.exit(1)
     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"""
 
     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.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):
         for ht in self.httpd:
@@ -155,21 +151,6 @@ class TestHttpHandler(unittest.TestCase):
         handler.do_HEAD()
         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):
     """Tests for HttpServerError exception"""
 
@@ -183,12 +164,9 @@ class TestHttpServer(unittest.TestCase):
     """Tests for HttpServer class"""
 
     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:
             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.xsd_handler, self.stats_httpd.xsd_handler)
             self.assertEqual(ht.xsl_handler, self.stats_httpd.xsl_handler)
@@ -209,17 +187,14 @@ class TestStatsHttpd(unittest.TestCase):
     """Tests for StatsHttpd class"""
 
     def setUp(self):
-        self.verbose = True
         fake_socket._CLOSED = False
         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):
         self.stats_httpd.stop()
 
     def test_init(self):
-        self.assertTrue(self.stats_httpd.verbose)
         self.assertFalse(self.stats_httpd.mccs.get_socket()._closed)
         self.assertEqual(self.stats_httpd.mccs.get_socket().fileno(),
                          id(self.stats_httpd.mccs.get_socket()))
@@ -317,8 +292,7 @@ class TestStatsHttpd(unittest.TestCase):
         self.stats_httpd.cc_session.group_sendmsg(
             { 'command': [ "shutdown" ] }, "StatsHttpd")
         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(
             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 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:
-    TEST_SPECFILE_LOCATION = sys.path[0] + "/testdata/stats_test.spec"
+    TEST_SPECFILE_LOCATION = "./testdata/stats_test.spec"
 
 class TestStats(unittest.TestCase):
 
     def setUp(self):
         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.module_name = self.listener.cc_session.get_module_spec().get_module_name()
         self.stats_data = {
@@ -516,9 +516,9 @@ class TestStats(unittest.TestCase):
 class TestStats2(unittest.TestCase):
 
     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()
         # check starting
         self.assertFalse(self.subject.running)
@@ -553,9 +553,9 @@ class TestStats2(unittest.TestCase):
         stats.SPECFILE_LOCATION = TEST_SPECFILE_LOCATION
         stats.SCHEMA_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.listener = stats.CCSessionListener(self.subject, verbose=True)
+        self.listener = stats.CCSessionListener(self.subject)
 
         self.assertEqual(self.listener.stats_spec, [])
         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
 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 *