[ovs-dev] [python vlog 3/6] python: Implement "vlog/reopen" unixctl command in Python vlog.

Ben Pfaff blp at nicira.com
Tue May 1 21:28:38 UTC 2012


Signed-off-by: Ben Pfaff <blp at nicira.com>
---
 python/ovs/vlog.py    |   33 +++++++++++++++++++--
 tests/test-unixctl.py |    6 ++++
 tests/unixctl-py.at   |    2 +
 tests/vlog.at         |   77 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/python/ovs/vlog.py b/python/ovs/vlog.py
index ad53781..6d2e84d 100644
--- a/python/ovs/vlog.py
+++ b/python/ovs/vlog.py
@@ -1,5 +1,5 @@
 
-# Copyright (c) 2011 Nicira Networks
+# Copyright (c) 2011, 2012 Nicira Networks
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ import socket
 import sys
 
 import ovs.dirs
+import ovs.unixctl
 import ovs.util
 
 FACILITIES = {"console": "info", "file": "info", "syslog": "info"}
@@ -41,6 +42,8 @@ class Vlog:
     __inited = False
     __msg_num = 0
     __mfl = {}  # Module -> facility -> level
+    __log_file = None
+    __file_handler = None
 
     def __init__(self, name):
         """Creates a new Vlog object representing a module called 'name'.  The
@@ -99,6 +102,7 @@ class Vlog:
 
         Vlog.__inited = True
         logging.raiseExceptions = False
+        Vlog.__log_file = log_file
         for f in FACILITIES:
             logger = logging.getLogger(f)
             logger.setLevel(logging.DEBUG)
@@ -110,11 +114,15 @@ class Vlog:
                     logger.addHandler(logging.handlers.SysLogHandler(
                         address="/dev/log",
                         facility=logging.handlers.SysLogHandler.LOG_DAEMON))
-                elif f == "file" and log_file:
-                    logger.addHandler(logging.FileHandler(log_file))
+                elif f == "file" and Vlog.__log_file:
+                    Vlog.__file_handler = logging.FileHandler(Vlog.__log_file)
+                    logger.addHandler(Vlog.__file_handler)
             except (IOError, socket.error):
                 logger.setLevel(logging.CRITICAL)
 
+        ovs.unixctl.command_register("vlog/reopen", "", 0, 0,
+                                     Vlog._unixctl_vlog_reopen, None)
+
     @staticmethod
     def set_level(module, facility, level):
         """ Sets the log level of the 'module'-'facility' tuple to 'level'.
@@ -149,6 +157,25 @@ class Vlog:
             for f in facilities:
                 Vlog.__mfl[m][f] = level
 
+    @staticmethod
+    def reopen_log_file():
+        """Closes and then attempts to re-open the current log file.  (This is
+        useful just after log rotation, to ensure that the new log file starts
+        being used.)"""
+
+        if Vlog.__log_file:
+            logger = logging.getLogger("file")
+            logger.removeHandler(Vlog.__file_handler)
+            Vlog.__file_handler = logging.FileHandler(Vlog.__log_file)
+            logger.addHandler(Vlog.__file_handler)
+
+    @staticmethod
+    def _unixctl_vlog_reopen(conn, unused_argv, unused_aux):
+        if Vlog.__log_file:
+            Vlog.reopen_log_file()
+            conn.reply(None)
+        else:
+            conn.reply("Logging to file not configured")
 
 def add_args(parser):
     """Adds vlog related options to 'parser', an ArgumentParser object.  The
diff --git a/tests/test-unixctl.py b/tests/test-unixctl.py
index 392999e..6ad599a 100644
--- a/tests/test-unixctl.py
+++ b/tests/test-unixctl.py
@@ -40,6 +40,11 @@ def unixctl_echo_error(conn, argv, aux):
     conn.reply_error(str(argv))
 
 
+def unixctl_log(conn, argv, unused_aux):
+    vlog.info(str(argv[0]))
+    conn.reply(None)
+
+
 def unixctl_block(conn, unused_argv, unused_aux):
     pass
 
@@ -64,6 +69,7 @@ def main():
     ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, "aux_exit")
     ovs.unixctl.command_register("echo", "[arg ...]", 1, 2, unixctl_echo,
                                  "aux_echo")
+    ovs.unixctl.command_register("log", "[arg ...]", 1, 2, unixctl_log, None)
     ovs.unixctl.command_register("echo_error", "[arg ...]", 1, 2,
                                  unixctl_echo_error, "aux_echo_error")
     ovs.unixctl.command_register("block", "", 0, 0, unixctl_block, None)
diff --git a/tests/unixctl-py.at b/tests/unixctl-py.at
index f9caa60..37070c9 100644
--- a/tests/unixctl-py.at
+++ b/tests/unixctl-py.at
@@ -104,7 +104,9 @@ The available commands are:
   echo_error              [[arg ...]]
   exit
   help
+  log                     [[arg ...]]
   version
+  vlog/reopen
 ])
 mv stdout expout
 AT_CHECK([PYAPPCTL -t test-unixctl.py help], [0], [expout])
diff --git a/tests/vlog.at b/tests/vlog.at
index 597c27a..a1afb10 100644
--- a/tests/vlog.at
+++ b/tests/vlog.at
@@ -103,3 +103,80 @@ AssertionError
 ])
 
 AT_CLEANUP
+
+AT_SETUP([vlog - vlog/reopen - Python])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
+trap 'kill `cat test-unixctl.py.pid`' 0
+
+AT_CAPTURE_FILE([log])
+AT_CAPTURE_FILE([log.old])
+AT_CHECK([$PYTHON $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach])
+
+AT_CHECK([APPCTL -t test-unixctl.py log message])
+mv log log.old
+AT_CHECK([APPCTL -t test-unixctl.py log message2])
+AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl.py log message3])
+AT_CHECK([APPCTL -t test-unixctl.py exit])
+trap '' 0
+
+AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
+Entering run loop.
+message
+message2
+])
+AT_CHECK([sed 's/.*|//' log], [0], [dnl
+message3
+])
+AT_CLEANUP
+
+AT_SETUP([vlog - vlog/reopen without log file - Python])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
+trap 'kill `cat test-unixctl.py.pid`' 0
+
+AT_CHECK([$PYTHON $srcdir/test-unixctl.py --pidfile --detach])
+
+AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen], [0],
+  [Logging to file not configured
+])
+AT_CLEANUP
+
+dnl This checks that if vlog/reopen can't reopen the log file,
+dnl nothing particularly bad (e.g. Python throws an exception and
+dnl aborts the program) happens.
+AT_SETUP([vlog - vlog/reopen can't reopen log file - Python])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+
+# Verify that /dev/full is a character device that fails writes.
+AT_SKIP_IF([test ! -c /dev/full])
+AT_SKIP_IF([echo > /dev/full])
+
+OVS_RUNDIR=`pwd`; export OVS_RUNDIR
+OVS_LOGDIR=`pwd`; export OVS_LOGDIR
+OVS_SYSCONFDIR=`pwd`; export OVS_SYSCONFDIR
+trap 'kill `cat test-unixctl.py.pid`' 0
+
+AT_CHECK([$PYTHON $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach])
+AT_CHECK([APPCTL -t test-unixctl.py log message])
+mv log log.old
+ln -s /dev/full log
+AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl.py log message2])
+rm log
+AT_CHECK([APPCTL -t test-unixctl.py vlog/reopen])
+AT_CHECK([APPCTL -t test-unixctl.py log message3])
+AT_CHECK([APPCTL -t test-unixctl.py exit])
+AT_CHECK([sed 's/.*|//' log.old], [0], [dnl
+Entering run loop.
+message
+])
+AT_CHECK([sed 's/.*|//' log], [0], [dnl
+message3
+])
+AT_CLEANUP
-- 
1.7.2.5




More information about the dev mailing list