cfg-mod: Add --changes option for logging configuration changes.
authorBen Pfaff <blp@nicira.com>
Tue, 12 May 2009 20:48:26 +0000 (13:48 -0700)
committerBen Pfaff <blp@nicira.com>
Tue, 12 May 2009 23:21:56 +0000 (16:21 -0700)
This makes it a lot easier to see what actually changed.

lib/cfg.c
lib/cfg.h
lib/vlog-modules.def
utilities/cfg-mod.8.in
utilities/cfg-mod.c

index 53a71cda828606ddcf35e1fc9262372b923df8a6..67545f37a1c69e234c149d48f0ff379a6d81dec9 100644 (file)
--- a/lib/cfg.c
+++ b/lib/cfg.c
@@ -257,6 +257,14 @@ cfg_read(void)
     return 0;
 }
 
+/* Fills 'svec' with the entire configuration file. */
+void
+cfg_get_all(struct svec *svec)
+{
+    svec_clear(svec);
+    svec_append(svec, &cfg);
+}
+
 int
 cfg_get_cookie(uint8_t *cookie)
 {
index 2b79f439a189b733533adb20c189665fd1846678..1216e062d56e5c39e76b163a1f99dfc0f847f4f0 100644 (file)
--- a/lib/cfg.h
+++ b/lib/cfg.h
@@ -44,6 +44,8 @@ void cfg_unlock(void);
 int cfg_write(void);
 int cfg_write_data(uint8_t *data, size_t len);
 
+void cfg_get_all(struct svec *);
+
 #define CFG_COOKIE_LEN SHA1HashSize
 int cfg_get_cookie(uint8_t *cookie);
 
index 33a7d106869f576eb47ecc65f83d6e7c38aa10c5..b5ac41349618817d59ddbe76ed1e9de4ba9db64c 100644 (file)
@@ -4,6 +4,7 @@ VLOG_MODULE(brcompatd)
 VLOG_MODULE(bridge)
 VLOG_MODULE(chain)
 VLOG_MODULE(cfg)
+VLOG_MODULE(cfg_mod)
 VLOG_MODULE(controller)
 VLOG_MODULE(coverage)
 VLOG_MODULE(ctlpath)
index f97727d739f2f22c87a059edcd9e66331978fa79..b2f212fd08eac8f8ab65bfa0a35891ede9f95118 100644 (file)
@@ -64,6 +64,22 @@ Queries \fIfile\fR for entries that match \fIkey\fR.  Each matching
 value is printed on a separate line.  Duplicates will be printed
 multiple times.  
 .
+.IP "\fB-c\fR, \fB--changes\fR"
+.
+Logs all of the changes made to the configuration file in a ``unified
+diff''-like format.  Only actual changes are logged, so that if, for
+example, a \fB--del-match\fR action did not match any key-value pairs,
+then nothing will be logged due to that action.  Furthermore, only the
+net effects of changes are logged: if a key-value pair was deleted and
+then an identical key-value pair was added back, then nothing would be
+logged due to those changes.
+.
+This action logs changes that have taken effect at the point where it
+is inserted.  Thus, if it is given before any other action, it will
+not log any changes.  If \fB--changes\fR is given more than once,
+instances after the first log only the changes since the previous
+instance.
+.
 .SH "SEE ALSO"
 .BR vswitchd (8),
 .BR vswitchd.conf (5)
index f62ffef8bb9682db8f1b99264e5d8d8e65a861ef..b09a7ced0bad8a4febfeac0961acdb929d6b5619 100644 (file)
 #include "timeval.h"
 #include "util.h"
 
+#define THIS_MODULE VLM_cfg_mod
+#include "vlog.h"
+
+/* Configuration when we first read the configuration file. */
+static struct svec orig_cfg = SVEC_EMPTY_INITIALIZER;
+
 static void
 usage(char *prog_name, int exit_code)
 {
@@ -50,7 +56,8 @@ usage(char *prog_name, int exit_code)
            "  -d, --del-entry=ENTRY   delete ENTRY\n"
            "  -D, --del-section=KEY   delete section matching KEY\n"
            "  --del-match=PATTERN     delete entries matching shell PATTERN\n"
-           "  -q, --query=KEY         return all entries matching KEY \n",
+           "  -q, --query=KEY         return all entries matching KEY\n"
+           "  -c, --log-changes       log changes up to this point\n",
            prog_name);
     exit(exit_code);
 }
@@ -70,6 +77,8 @@ open_config(char *config_file)
     if (error) {
         ovs_fatal(error, "could not lock configuration file\n");
     }
+
+    cfg_get_all(&orig_cfg);
 }
 
 static void
@@ -85,7 +94,33 @@ print_vals(char *key)
         printf("%s\n", vals.names[i]);
     }
 }
-    
+
+static void
+log_diffs(void)
+{
+    struct svec new_cfg, removed, added;
+    size_t i;
+
+    svec_init(&new_cfg);
+    cfg_get_all(&new_cfg);
+    svec_diff(&orig_cfg, &new_cfg, &removed, NULL, &added);
+    if (removed.n || added.n) {
+        VLOG_INFO("configuration changes:");
+        for (i = 0; i < removed.n; i++) {
+            VLOG_INFO("-%s", removed.names[i]);
+        }
+        for (i = 0; i < added.n; i++) {
+            VLOG_INFO("+%s", added.names[i]);
+        }
+    } else {
+        VLOG_INFO("configuration unchanged");
+    }
+    svec_destroy(&added);
+    svec_destroy(&removed);
+    svec_swap(&new_cfg, &orig_cfg);
+    svec_destroy(&new_cfg);
+}
+
 int main(int argc, char *argv[])
 {
     enum {
@@ -98,6 +133,8 @@ int main(int argc, char *argv[])
         {"del-section",  required_argument, 0, 'D'},
         {"del-match",    required_argument, 0, OPT_DEL_MATCH},
         {"query",        required_argument, 0, 'q'},
+        {"changes",      no_argument, 0, 'c'},
+        {"verbose",      optional_argument, 0, 'v'},
         {"help",         no_argument, 0, 'h'},
         {0, 0, 0, 0},
     };
@@ -107,6 +144,7 @@ int main(int argc, char *argv[])
 
     set_program_name(argv[0]);
     time_init();
+    vlog_init();
 
     short_options = long_options_to_short_options(long_options);
     for (;;) {
@@ -152,10 +190,18 @@ int main(int argc, char *argv[])
             print_vals(optarg);
             break;
 
+        case 'c':
+            log_diffs();
+            break;
+
         case 'h':
             usage(argv[0], EXIT_SUCCESS);
             break;
 
+        case 'v':
+            vlog_set_verbosity(optarg);
+            break;
+
         case '?':
             exit(EXIT_FAILURE);