Add cfg-mod, a vswitchd.conf-style manipulation utility.
authorJustin Pettit <jpettit@nicira.com>
Thu, 2 Apr 2009 07:49:01 +0000 (00:49 -0700)
committerJustin Pettit <jpettit@nicira.com>
Thu, 2 Apr 2009 07:49:01 +0000 (00:49 -0700)
This is a first cut of a simple utility for manipulating a
vswitchd.conf-style configuration file.  It uses the same locking mechanism
as vswitchd and its related utilities, so it can be used safely on "live"
configurations.

The man page needs a bit more love with deeper explanations and
examples.

utilities/.gitignore
utilities/automake.mk
utilities/cfg-mod.8.in [new file with mode: 0644]
utilities/cfg-mod.c [new file with mode: 0644]

index c93169bf64d65837d02354d31f687f1f20e8efe5..534ef34d1952ea4b90af2464e228a34bab04d73b 100644 (file)
@@ -1,11 +1,15 @@
 /Makefile
 /Makefile.in
+/cfg-mod
+/cfg-mod.8
 /dpctl
 /dpctl.8
+/nlmon
 /ofp-discover
 /ofp-discover.8
 /ofp-kill
 /ofp-kill.8
+/ofp-parse-leaks
 /ofp-pki
 /ofp-pki-cgi
 /ofp-pki.8
index 8373433c1137290d0d8ce618de2bde132c2e7465..5077fb0f57ada934813db2fce7b9b8b04bd1301c 100644 (file)
@@ -1,5 +1,6 @@
 bin_PROGRAMS += \
        utilities/vlogconf \
+       utilities/cfg-mod \
        utilities/dpctl \
        utilities/ofp-discover \
        utilities/ofp-kill
@@ -27,12 +28,16 @@ DISTCLEANFILES += \
        utilities/vlogconf.8
 
 man_MANS += \
+       utilities/cfg-mod.8 \
        utilities/dpctl.8 \
        utilities/ofp-discover.8 \
        utilities/ofp-kill.8 \
        utilities/ofp-pki.8 \
        utilities/vlogconf.8
 
+utilities_cfg_mod_SOURCES = utilities/cfg-mod.c
+utilities_cfg_mod_LDADD = lib/libopenflow.a
+
 utilities_dpctl_SOURCES = utilities/dpctl.c
 utilities_dpctl_LDADD = lib/libopenflow.a $(FAULT_LIBS) $(SSL_LIBS)
 
diff --git a/utilities/cfg-mod.8.in b/utilities/cfg-mod.8.in
new file mode 100644 (file)
index 0000000..224fcc4
--- /dev/null
@@ -0,0 +1,63 @@
+.TH cfg-mod 8 "April 2009" "OpenFlow" "OpenFlow Manual"
+.ds PN cfg-mod
+.
+.SH NAME
+cfg-mod \- Safely manage a vswitchd.conf-style configuration file
+.
+.SH SYNOPSIS
+.B cfg-mod
+--config-file=\fIfile\fR [ \fIaction\fR ][ \fIaction\fR \fI...\fR ]
+.
+.SH DESCRIPTION
+A program for managing a \fBvswitchd.conf\fR(5)-style configuration file.
+\fBcfg-mod\fR uses the same locking mechanisms as \fBvswitchd\fR and its
+related utilities.  This allows it to be run safely on "live" 
+configurations.
+
+The \fB--config-file\fR argument must be the first argument provided:
+.TP
+\fB-F\fR \fIfile\fR, \fB--config-file=\fIfile\fR
+.
+Use \fIfile\fR as the configuration file to modify.
+
+.SS "Specifying Actions"
+After a configuration file is specified, a series of one or more
+actions follows.  These are executed in the order provided and under a
+single lock instance, so they appear atomic to external viewers of
+\fIfile\fR.
+
+As discussed in \fBvswitchd.conf\fR(5), each line in the configuration
+file consists of a key-value pair.  Actions generally take either a 
+\fIkey\fR or \fIentry\fR argument.  A \fIkey\fR is a dot-separated
+description of a configuration option.  A \fIentry\fR is a key-value 
+pair, separated by the '=' sign.  
+
+The following actions are supported:
+
+.TP
+\fB-a\fR \fIentry\fR, \fB--add=\fIentry\fR
+.
+Add \fIentry\fR to \fIfile\fR.  Please note that duplicates are
+allowed, so if a unique key is required, a delete must be done first.
+
+.TP
+\fB-d\fR \fIentry\fR, \fB--del-entry=\fIentry\fR
+.
+Delete \fIentry\fR from \fIfile\fR.  Deletes only the first entry 
+that matches \fIentry\fR.  
+
+.TP
+\fB-D\fR \fIkey\fR, \fB--del-section=\fIkey\fR
+.
+Delete section \fIkey\fR from \fIfile\fR.  
+
+.TP
+\fB-q\fR \fIkey\fR, \fB--query=\fIkey\fR
+.
+Queries \fIfile\fR for entries that match \fIkey\fR.  Each matching
+value is printed on a separate line.  Duplicates will be printed
+multiple times.  
+.
+.SH "SEE ALSO"
+.BR vswitchd (8),
+.BR vswitchd.conf (5)
diff --git a/utilities/cfg-mod.c b/utilities/cfg-mod.c
new file mode 100644 (file)
index 0000000..4ae976a
--- /dev/null
@@ -0,0 +1,162 @@
+/* Copyright (c) 2008, 2009  Nicira Networks
+ * 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * In addition, as a special exception, Nicira Networks gives permission
+ * to link the code of its release of vswitchd with the OpenSSL project's
+ * "OpenSSL" library (or with modified versions of it that use the same
+ * license as the "OpenSSL" library), and distribute the linked
+ * executables.  You must obey the GNU General Public License in all
+ * respects for all of the code used other than "OpenSSL".  If you modify
+ * this file, you may extend this exception to your version of the file,
+ * but you are not obligated to do so.  If you do not wish to do so,
+ * delete this exception statement from your version.
+ */
+#include <config.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "cfg.h"
+#include "command-line.h"
+#include "svec.h"
+#include "timeval.h"
+#include "util.h"
+
+static void
+usage(char *prog_name, int exit_code)
+{
+    printf("Usage: %s --config-file=FILE ACTIONS\n"
+           "\nConfig:\n"
+           "  -F, --config-file=FILE  use configuration FILE\n"
+           "\nActions:\n"
+           "  -a, --add=ENTRY         add ENTRY\n"
+           "  -d, --del-entry=ENTRY   delete ENTRY\n"
+           "  -D, --del-section=KEY   delete section matching KEY\n"
+           "  -q, --query=KEY         return all entries matching KEY \n",
+           prog_name);
+    exit(exit_code);
+}
+
+static void 
+open_config(char *config_file) 
+{
+    int error;
+
+    error = cfg_set_file(config_file);
+    if (error) {
+        ofp_fatal(error, "failed to add configuration file \"%s\"",
+                config_file);
+    }
+
+    error = cfg_lock(NULL, 0);
+    if (error) {
+        ofp_fatal(error, "could not lock configuration file\n");
+    }
+}
+
+static void
+print_vals(char *key)
+{
+    struct svec vals;
+    int i;
+
+    svec_init(&vals);
+    cfg_get_all_keys(&vals, "%s", key);
+
+    for (i=0; i<vals.n; i++) {
+        printf("%s\n", vals.names[i]);
+    }
+}
+    
+int main(int argc, char *argv[])
+{
+    static const struct option long_options[] = {
+        {"config-file",  required_argument, 0, 'F'},
+        {"add",          required_argument, 0, 'a'},
+        {"del-entry",    required_argument, 0, 'd'},
+        {"del-entry",    required_argument, 0, 'D'},
+        {"query",        required_argument, 0, 'q'},
+        {0, 0, 0, 0},
+    };
+    char *short_options;
+    bool config_set = false;
+    bool modified = false;
+
+    set_program_name(argv[0]);
+    time_init();
+
+    short_options = long_options_to_short_options(long_options);
+    for (;;) {
+        int option;
+
+        option = getopt_long(argc, argv, short_options, long_options, NULL);
+        if (option == -1) {
+            break;
+        }
+
+        if (!strchr("F", option) && config_set == false) {
+            ofp_fatal(0, "no config file specified (use --help for help)");
+        }
+
+        switch (option) {
+        case 'F': 
+            open_config(optarg);
+            config_set = true;
+            break;
+
+       case 'a':
+            cfg_add_entry("%s", optarg);
+            modified = true;
+            break;
+
+        case 'd':
+            cfg_del_entry("%s", optarg);
+            modified = true;
+            break;
+
+        case 'D':
+            cfg_del_section("%s", optarg);
+            modified = true;
+            break;
+
+        case 'q':
+            print_vals(optarg);
+            break;
+
+        case 'h':
+            usage(argv[0], EXIT_SUCCESS);
+            break;
+
+        case '?':
+            exit(EXIT_FAILURE);
+
+        default:
+            NOT_REACHED();
+        }
+    }
+    free(short_options);
+
+    if (modified) {
+        cfg_write();
+    }
+    cfg_unlock();
+
+    exit(0);
+}