diff options
Diffstat (limited to 'utilities/ovs-appctl.c')
-rw-r--r-- | utilities/ovs-appctl.c | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/utilities/ovs-appctl.c b/utilities/ovs-appctl.c new file mode 100644 index 000000000..eb544452c --- /dev/null +++ b/utilities/ovs-appctl.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2008, 2009 Nicira Networks. + * + * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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. + */ +#include <config.h> +#include "vlog.h" + +#include <dirent.h> +#include <errno.h> +#include <getopt.h> +#include <stdarg.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "command-line.h" +#include "compiler.h" +#include "timeval.h" +#include "unixctl.h" +#include "util.h" + +static void +usage(char *prog_name, int exit_code) +{ + printf("Usage: %s [TARGET] [ACTION...]\n" + "Targets:\n" + " -t, --target=TARGET Path to Unix domain socket\n" + "Actions:\n" + " -l, --list List current settings\n" + " -s, --set=MODULE[:FACILITY[:LEVEL]]\n" + " Set MODULE and FACILITY log level to LEVEL\n" + " MODULE may be any valid module name or 'ANY'\n" + " FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n" + " LEVEL may be 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n" + " -r, --reopen Make the program reopen its log file\n" + " -e, --execute=COMMAND Execute control COMMAND and print its output\n" + "Other options:\n" + " -h, --help Print this helpful information\n" + " -V, --version Display version information\n", + prog_name); + exit(exit_code); +} + +static char * +transact(struct unixctl_client *client, const char *request, bool *ok) +{ + int code; + char *reply; + int error = unixctl_client_transact(client, request, &code, &reply); + if (error) { + fprintf(stderr, "%s: transaction error: %s\n", + unixctl_client_target(client), strerror(error)); + *ok = false; + return xstrdup(""); + } else { + if (code / 100 != 2) { + fprintf(stderr, "%s: server returned reply code %03d\n", + unixctl_client_target(client), code); + } + return reply; + } +} + +static void +transact_ack(struct unixctl_client *client, const char *request, bool *ok) +{ + free(transact(client, request, ok)); +} + +static void +execute_command(struct unixctl_client *client, const char *request, bool *ok) +{ + int code; + char *reply; + int error = unixctl_client_transact(client, request, &code, &reply); + if (error) { + fprintf(stderr, "%s: transaction error: %s\n", + unixctl_client_target(client), strerror(error)); + *ok = false; + } else { + if (code / 100 != 2) { + fprintf(stderr, "%s: server returned reply code %03d\n", + unixctl_client_target(client), code); + fputs(reply, stderr); + *ok = false; + } else { + fputs(reply, stdout); + } + } +} + +static void +add_target(struct unixctl_client ***clients, size_t *n_clients, + const char *path, bool *ok) +{ + struct unixctl_client *client; + int error = unixctl_client_create(path, &client); + if (error) { + fprintf(stderr, "Error connecting to \"%s\": %s\n", + path, strerror(error)); + *ok = false; + } else { + *clients = xrealloc(*clients, sizeof *clients * (*n_clients + 1)); + (*clients)[*n_clients] = client; + ++*n_clients; + } +} + +int main(int argc, char *argv[]) +{ + static const struct option long_options[] = { + /* Target options must come first. */ + {"target", required_argument, NULL, 't'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + + /* Action options come afterward. */ + {"list", no_argument, NULL, 'l'}, + {"set", required_argument, NULL, 's'}, + {"reopen", no_argument, NULL, 'r'}, + {"execute", required_argument, NULL, 'e'}, + {0, 0, 0, 0}, + }; + char *short_options; + + /* Determine targets. */ + bool ok = true; + int n_actions = 0; + struct unixctl_client **clients = NULL; + size_t n_clients = 0; + + set_program_name(argv[0]); + time_init(); + + short_options = long_options_to_short_options(long_options); + for (;;) { + int option; + size_t i; + + option = getopt_long(argc, argv, short_options, long_options, NULL); + if (option == -1) { + break; + } + if (!strchr("thV", option) && n_clients == 0) { + ovs_fatal(0, "no targets specified (use --help for help)"); + } else { + ++n_actions; + } + switch (option) { + case 't': + add_target(&clients, &n_clients, optarg, &ok); + break; + + case 'l': + for (i = 0; i < n_clients; i++) { + struct unixctl_client *client = clients[i]; + char *reply; + + printf("%s:\n", unixctl_client_target(client)); + reply = transact(client, "vlog/list", &ok); + fputs(reply, stdout); + free(reply); + } + break; + + case 's': + for (i = 0; i < n_clients; i++) { + struct unixctl_client *client = clients[i]; + char *request = xasprintf("vlog/set %s", optarg); + transact_ack(client, request, &ok); + free(request); + } + break; + + case 'r': + for (i = 0; i < n_clients; i++) { + struct unixctl_client *client = clients[i]; + char *request = xstrdup("vlog/reopen"); + transact_ack(client, request, &ok); + free(request); + } + break; + + case 'e': + for (i = 0; i < n_clients; i++) { + execute_command(clients[i], optarg, &ok); + } + break; + + case 'h': + usage(argv[0], EXIT_SUCCESS); + break; + + case 'V': + OVS_PRINT_VERSION(0, 0); + exit(EXIT_SUCCESS); + + case '?': + exit(EXIT_FAILURE); + + default: + NOT_REACHED(); + } + } + if (!n_actions) { + fprintf(stderr, + "warning: no actions specified (use --help for help)\n"); + } + exit(ok ? 0 : 1); +} |