]> git.proxmox.com Git - mirror_ovs.git/blob - utilities/ovs-appctl.c
ovs-appctl: Add "version" command to print version of running daemons.
[mirror_ovs.git] / utilities / ovs-appctl.c
1 /*
2 * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <config.h>
18
19 #include <errno.h>
20 #include <getopt.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "command-line.h"
26 #include "daemon.h"
27 #include "dirs.h"
28 #include "dynamic-string.h"
29 #include "timeval.h"
30 #include "unixctl.h"
31 #include "util.h"
32
33 static void usage(void);
34 static const char *parse_command_line(int argc, char *argv[]);
35 static struct unixctl_client *connect_to_target(const char *target);
36
37 int
38 main(int argc, char *argv[])
39 {
40 struct unixctl_client *client;
41 const char *target;
42 struct ds request;
43 int code, error;
44 char *reply;
45 int i;
46
47 set_program_name(argv[0]);
48
49 /* Parse command line and connect to target. */
50 target = parse_command_line(argc, argv);
51 client = connect_to_target(target);
52
53 /* Compose request. */
54 ds_init(&request);
55 for (i = optind; i < argc; i++) {
56 if (i != optind) {
57 ds_put_char(&request, ' ');
58 }
59 ds_put_cstr(&request, argv[i]);
60 }
61
62 /* Transact request and process reply. */
63 error = unixctl_client_transact(client, ds_cstr(&request), &code, &reply);
64 if (error) {
65 ovs_fatal(error, "%s: transaction error", target);
66 }
67 if (code / 100 != 2) {
68 fputs(reply, stderr);
69 ovs_error(0, "%s: server returned reply code %03d", target, code);
70 exit(2);
71 }
72 fputs(reply, stdout);
73
74 unixctl_client_destroy(client);
75 free(reply);
76 ds_destroy(&request);
77
78 return 0;
79 }
80
81 static void
82 usage(void)
83 {
84 printf("\
85 %s, for querying and controlling Open vSwitch daemon\n\
86 usage: %s [TARGET] COMMAND [ARG...]\n\
87 Targets:\n\
88 -t, --target=TARGET pidfile or socket to contact\n\
89 Common commands:\n\
90 help List commands supported by the target\n\
91 version Print version of the target\n\
92 vlog/list List current logging levels\n\
93 vlog/set MODULE[:FACILITY[:LEVEL]]\n\
94 Set MODULE and FACILITY log level to LEVEL\n\
95 MODULE may be any valid module name or 'ANY'\n\
96 FACILITY may be 'syslog', 'console', 'file', or 'ANY' (default)\n\
97 LEVEL may be 'off', 'emer', 'err', 'warn', 'info', or 'dbg' (default)\n\
98 vlog/reopen Make the program reopen its log file\n\
99 Other options:\n\
100 -h, --help Print this helpful information\n\
101 -V, --version Display ovs-appctl version information\n",
102 program_name, program_name);
103 exit(EXIT_SUCCESS);
104 }
105
106 static const char *
107 parse_command_line(int argc, char *argv[])
108 {
109 static const struct option long_options[] = {
110 {"target", required_argument, NULL, 't'},
111 {"execute", no_argument, NULL, 'e'},
112 {"help", no_argument, NULL, 'h'},
113 {"version", no_argument, NULL, 'V'},
114 {NULL, 0, NULL, 0},
115 };
116 const char *target;
117 int e_options;
118
119 target = NULL;
120 e_options = 0;
121 for (;;) {
122 int option;
123
124 option = getopt_long(argc, argv, "+t:hVe", long_options, NULL);
125 if (option == -1) {
126 break;
127 }
128 switch (option) {
129 case 't':
130 if (target) {
131 ovs_fatal(0, "-t or --target may be specified only once");
132 }
133 target = optarg;
134 break;
135
136 case 'e':
137 /* We ignore -e for compatibility. Older versions specified the
138 * command as the argument to -e. Since the current version takes
139 * the command as non-option arguments and we say that -e has no
140 * arguments, this just works in the common case. */
141 if (e_options++) {
142 ovs_fatal(0, "-e or --execute may be speciifed only once");
143 }
144 break;
145
146 case 'h':
147 usage();
148 break;
149
150 case 'V':
151 ovs_print_version(0, 0);
152 exit(EXIT_SUCCESS);
153
154 case '?':
155 exit(EXIT_FAILURE);
156
157 default:
158 NOT_REACHED();
159 }
160 }
161
162 if (optind >= argc) {
163 ovs_fatal(0, "at least one non-option argument is required "
164 "(use --help for help)");
165 }
166
167 return target ? target : "ovs-vswitchd";
168 }
169
170 static struct unixctl_client *
171 connect_to_target(const char *target)
172 {
173 struct unixctl_client *client;
174 char *socket_name;
175 int error;
176
177 if (target[0] != '/') {
178 char *pidfile_name;
179 pid_t pid;
180
181 pidfile_name = xasprintf("%s/%s.pid", ovs_rundir(), target);
182 pid = read_pidfile(pidfile_name);
183 if (pid < 0) {
184 ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
185 }
186 free(pidfile_name);
187 socket_name = xasprintf("%s/%s.%ld.ctl",
188 ovs_rundir(), target, (long int) pid);
189 } else {
190 socket_name = xstrdup(target);
191 }
192
193 error = unixctl_client_create(socket_name, &client);
194 if (error) {
195 ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
196 }
197 free(socket_name);
198
199 return client;
200 }
201