python: Implement "vlog/set", "vlog/list" unixctl commands in Python vlog.
authorBen Pfaff <blp@nicira.com>
Mon, 14 May 2012 21:00:33 +0000 (14:00 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 22 May 2012 17:17:06 +0000 (10:17 -0700)
This doesn't implement control over log patterns, though.

The change to vlog.man in this commit doesn't have any practical effect
because OVS doesn't come with any Python daemons that have their own
manpages.

Signed-off-by: Ben Pfaff <blp@nicira.com>
lib/vlog.man
python/ovs/vlog.py
tests/unixctl-py.at
tests/vlog.at
utilities/ovs-appctl.8.in

index a8c8223..0017449 100644 (file)
@@ -45,10 +45,15 @@ a word but has no effect.
 Sets the maximum logging verbosity level, equivalent to
 \fB\-\-verbose=ANY:ANY:dbg\fR.
 .
+.\" Python vlog doesn't implement -vPATTERN so only document it if
+.\" \*(PY is empty:
+.ie dPY
+.el \{
 .IP "\fB\-vPATTERN:\fIfacility\fB:\fIpattern\fR"
 .IQ "\fB\-\-verbose=PATTERN:\fIfacility\fB:\fIpattern\fR"
 Sets the log pattern for \fIfacility\fR to \fIpattern\fR.  Refer to
 \fBovs\-appctl\fR(8) for a description of the valid syntax for \fIpattern\fR.
+\}
 .
 .TP
 \fB\-\-log\-file\fR[\fB=\fIfile\fR]
index b3a8b81..ed95012 100644 (file)
@@ -16,6 +16,7 @@
 import datetime
 import logging
 import logging.handlers
+import re
 import socket
 import sys
 
@@ -122,6 +123,10 @@ class Vlog:
 
         ovs.unixctl.command_register("vlog/reopen", "", 0, 0,
                                      Vlog._unixctl_vlog_reopen, None)
+        ovs.unixctl.command_register("vlog/set", "spec", 1, sys.maxint,
+                                     Vlog._unixctl_vlog_set, None)
+        ovs.unixctl.command_register("vlog/list", "", 0, 0,
+                                     Vlog._unixctl_vlog_list, None)
 
     @staticmethod
     def set_level(module, facility, level):
@@ -157,6 +162,43 @@ class Vlog:
             for f in facilities:
                 Vlog.__mfl[m][f] = level
 
+    @staticmethod
+    def set_levels_from_string(s):
+        module = None
+        level = None
+        facility = None
+
+        for word in [w.lower() for w in re.split('[ :]', s)]:
+            if word == "any":
+                pass
+            elif word in FACILITIES:
+                if facility:
+                    return "cannot specify multiple facilities"
+                facility = word
+            elif word in LEVELS:
+                if level:
+                    return "cannot specify multiple levels"
+                level = word
+            elif word in Vlog.__mfl:
+                if module:
+                    return "cannot specify multiple modules"
+                module = word
+            else:
+                return "no facility, level, or module \"%s\"" % word
+
+        Vlog.set_level(module or "any", facility or "any", level or "any")
+
+    @staticmethod
+    def get_levels():
+        lines = ["                 console    syslog    file\n",
+                 "                 -------    ------    ------\n"]
+        lines.extend(sorted(["%-16s  %4s       %4s       %4s\n"
+                             % (m,
+                                Vlog.__mfl[m]["console"],
+                                Vlog.__mfl[m]["syslog"],
+                                Vlog.__mfl[m]["file"]) for m in Vlog.__mfl]))
+        return ''.join(lines)
+
     @staticmethod
     def reopen_log_file():
         """Closes and then attempts to re-open the current log file.  (This is
@@ -177,6 +219,19 @@ class Vlog:
         else:
             conn.reply("Logging to file not configured")
 
+    @staticmethod
+    def _unixctl_vlog_set(conn, argv, unused_aux):
+        for arg in argv:
+            msg = Vlog.set_levels_from_string(arg)
+            if msg:
+                conn.reply(msg)
+                return
+        conn.reply(None)
+
+    @staticmethod
+    def _unixctl_vlog_list(conn, unused_argv, unused_aux):
+        conn.reply(Vlog.get_levels())
+
 def add_args(parser):
     """Adds vlog related options to 'parser', an ArgumentParser object.  The
     resulting arguments parsed by 'parser' should be passed to handle_args."""
@@ -187,7 +242,7 @@ def add_args(parser):
                        " is used if LOG_FILE is omitted.")
     group.add_argument("-v", "--verbose", nargs="*",
                        help="Sets logging levels, see ovs-vswitchd(8)."
-                       "  Defaults to ANY:ANY:dbg.")
+                       "  Defaults to dbg.")
 
 
 def handle_args(args):
@@ -205,23 +260,8 @@ def handle_args(args):
         args.verbose = ["any:any:dbg"]
 
     for verbose in args.verbose:
-        args = verbose.split(':')
-
-        if len(args) >= 3:
-            level = args[2]
-        else:
-            level = "dbg"
-
-        if len(args) >= 2:
-            facility = args[1]
-        else:
-            facility = "any"
-
-        if len(args) >= 1:
-            module = args[0]
-        else:
-            module = "any"
-
-        Vlog.set_level(module, facility, level)
+        msg = Vlog.set_levels_from_string(verbose)
+        if msg:
+            ovs.util.ovs_fatal(0, "processing \"%s\": %s" % (verbose, msg))
 
     Vlog.init(log_file)
index 37070c9..0374602 100644 (file)
@@ -106,7 +106,9 @@ The available commands are:
   help
   log                     [[arg ...]]
   version
+  vlog/list
   vlog/reopen
+  vlog/set                spec
 ])
 mv stdout expout
 AT_CHECK([PYAPPCTL -t test-unixctl.py help], [0], [expout])
index a1afb10..61cef2a 100644 (file)
@@ -180,3 +180,47 @@ AT_CHECK([sed 's/.*|//' log], [0], [dnl
 message3
 ])
 AT_CLEANUP
+
+AT_SETUP([vlog - vlog/set and vlog/list - 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_CHECK([$PYTHON $srcdir/test-unixctl.py --log-file=`pwd`/log --pidfile --detach])
+
+AT_CHECK([APPCTL -t test-unixctl.py vlog/list], [0], [dnl
+                 console    syslog    file
+                 -------    ------    ------
+daemon            info       info       info
+fatal-signal      info       info       info
+jsonrpc           info       info       info
+poller            info       info       info
+reconnect         info       info       info
+socket_util       info       info       info
+stream            info       info       info
+test-unixctl      info       info       info
+unixctl_server    info       info       info
+])
+
+AT_CHECK([APPCTL -t test-unixctl.py vlog/set daemon:syslog:err])
+AT_CHECK([APPCTL -t test-unixctl.py vlog/set file:dbg])
+AT_CHECK([APPCTL -t test-unixctl.py vlog/set nonexistent], [0],
+  [no facility, level, or module "nonexistent"
+])
+AT_CHECK([APPCTL -t test-unixctl.py vlog/list], [0], [dnl
+                 console    syslog    file
+                 -------    ------    ------
+daemon            info        err        dbg
+fatal-signal      info       info        dbg
+jsonrpc           info       info        dbg
+poller            info       info        dbg
+reconnect         info       info        dbg
+socket_util       info       info        dbg
+stream            info       info        dbg
+test-unixctl      info       info        dbg
+unixctl_server    info       info        dbg
+])
+AT_CLEANUP
index 4606f57..c2ed26b 100644 (file)
@@ -214,6 +214,10 @@ width.  (A field wider than \fIwidth\fR is not truncated to fit.)
 The default pattern for console and file output is \fB%D{%Y-%m-%dT
 %H:%M:%SZ}|%05N|%c|%p|%m\fR; for syslog output, \fB%05N|%c|%p|%m\fR.
 .
+.IP
+Daemons written in Python (e.g. \fBovs\-xapi\-sync\fR,
+\fBovs\-monitor\-ipsec) do not allow control over the log pattern.
+.
 .IP "\fBvlog/reopen\fR"
 Causes the daemon to close and reopen its log file.  (This
 is useful after rotating log files, to cause a new log file to be
@@ -228,7 +232,7 @@ This has no effect if the target application was not invoked with the
 .
 .SH "SEE ALSO"
 .
-\fBovs\-appctl\fR can control the following daemons:
+\fBovs\-appctl\fR can control all Open vSwitch daemons, including:
 .BR ovs\-vswitchd (8),
-.BR ovs\-controller (8),
-.BR ovs\-brcompatd (8).
+and
+.BR ovsdb\-server (8).