]> git.proxmox.com Git - ovs.git/blob - ovsdb/ovsdb-server.c
ovsdb-server: Add "exit" unixctl command and --unixctl option.
[ovs.git] / ovsdb / ovsdb-server.c
1 /* Copyright (c) 2009 Nicira Networks
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <config.h>
17
18 #include "ovsdb.h"
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <signal.h>
23 #include <unistd.h>
24
25 #include "command-line.h"
26 #include "daemon.h"
27 #include "fault.h"
28 #include "file.h"
29 #include "json.h"
30 #include "jsonrpc.h"
31 #include "jsonrpc-server.h"
32 #include "leak-checker.h"
33 #include "list.h"
34 #include "ovsdb-error.h"
35 #include "poll-loop.h"
36 #include "process.h"
37 #include "stream.h"
38 #include "svec.h"
39 #include "timeval.h"
40 #include "trigger.h"
41 #include "util.h"
42 #include "unixctl.h"
43
44 #include "vlog.h"
45 #define THIS_MODULE VLM_ovsdb_server
46
47 static const struct jsonrpc_server_cbs ovsdb_jsonrpc_cbs;
48
49 static unixctl_cb_func ovsdb_server_exit;
50
51 static void parse_options(int argc, char *argv[], char **file_namep,
52 struct svec *active, struct svec *passive,
53 char **unixctl_pathp);
54 static void usage(void) NO_RETURN;
55
56 int
57 main(int argc, char *argv[])
58 {
59 char *unixctl_path = NULL;
60 struct unixctl_server *unixctl;
61 struct ovsdb_jsonrpc_server *jsonrpc;
62 struct svec active, passive;
63 struct ovsdb_error *error;
64 struct ovsdb *db;
65 const char *name;
66 char *file_name;
67 bool do_chdir;
68 bool exiting;
69 int retval;
70 size_t i;
71
72 set_program_name(argv[0]);
73 register_fault_handlers();
74 time_init();
75 vlog_init();
76 signal(SIGPIPE, SIG_IGN);
77 process_init();
78
79 parse_options(argc, argv, &file_name, &active, &passive, &unixctl_path);
80
81 if (get_detach() && is_chdir_enabled()) {
82 /* We need to skip chdir("/") in daemonize() and do it later, because
83 * we need to open the database and possible set up up Unix domain
84 * sockets in the current working directory after we daemonize. We
85 * can't open the database before we daemonize because file locks
86 * aren't inherited by child processes. */
87 do_chdir = true;
88 set_no_chdir();
89 } else {
90 do_chdir = false;
91 }
92 die_if_already_running();
93 daemonize();
94
95 error = ovsdb_file_open(file_name, false, &db);
96 if (error) {
97 ovs_fatal(0, "%s", ovsdb_error_to_string(error));
98 }
99
100 jsonrpc = ovsdb_jsonrpc_server_create(db);
101 SVEC_FOR_EACH (i, name, &active) {
102 ovsdb_jsonrpc_server_connect(jsonrpc, name);
103 }
104 SVEC_FOR_EACH (i, name, &passive) {
105 retval = ovsdb_jsonrpc_server_listen(jsonrpc, name);
106 if (retval) {
107 ovs_fatal(retval, "failed to listen on %s", name);
108 }
109 }
110 svec_destroy(&active);
111 svec_destroy(&passive);
112
113 retval = unixctl_server_create(unixctl_path, &unixctl);
114 if (retval) {
115 ovs_fatal(retval, "could not listen for control connections");
116 }
117
118 unixctl_command_register("exit", ovsdb_server_exit, &exiting);
119
120 if (do_chdir) {
121 chdir("/");
122 }
123
124 exiting = false;
125 while (!exiting) {
126 ovsdb_jsonrpc_server_run(jsonrpc);
127 unixctl_server_run(unixctl);
128 ovsdb_trigger_run(db, time_msec());
129
130 ovsdb_jsonrpc_server_wait(jsonrpc);
131 unixctl_server_wait(unixctl);
132 ovsdb_trigger_wait(db, time_msec());
133 poll_block();
134 }
135
136 return 0;
137 }
138
139 static void
140 ovsdb_server_exit(struct unixctl_conn *conn, const char *args UNUSED,
141 void *exiting_)
142 {
143 bool *exiting = exiting_;
144 *exiting = true;
145 unixctl_command_reply(conn, 200, NULL);
146 }
147
148 static void
149 parse_options(int argc, char *argv[], char **file_namep,
150 struct svec *active, struct svec *passive,
151 char **unixctl_pathp)
152 {
153 enum {
154 OPT_DUMMY = UCHAR_MAX + 1,
155 OPT_CONNECT,
156 OPT_LISTEN,
157 OPT_UNIXCTL,
158 VLOG_OPTION_ENUMS,
159 LEAK_CHECKER_OPTION_ENUMS
160 };
161 static struct option long_options[] = {
162 {"connect", required_argument, 0, OPT_CONNECT},
163 {"listen", required_argument, 0, OPT_LISTEN},
164 {"unixctl", required_argument, 0, OPT_UNIXCTL},
165 {"help", no_argument, 0, 'h'},
166 {"version", no_argument, 0, 'V'},
167 DAEMON_LONG_OPTIONS,
168 VLOG_LONG_OPTIONS,
169 LEAK_CHECKER_LONG_OPTIONS,
170 {0, 0, 0, 0},
171 };
172 char *short_options = long_options_to_short_options(long_options);
173
174 svec_init(active);
175 svec_init(passive);
176 for (;;) {
177 int c;
178
179 c = getopt_long(argc, argv, short_options, long_options, NULL);
180 if (c == -1) {
181 break;
182 }
183
184 switch (c) {
185 case OPT_CONNECT:
186 svec_add(active, optarg);
187 break;
188
189 case OPT_LISTEN:
190 svec_add(passive, optarg);
191 break;
192
193 case OPT_UNIXCTL:
194 *unixctl_pathp = optarg;
195 break;
196
197 case 'h':
198 usage();
199
200 case 'V':
201 OVS_PRINT_VERSION(0, 0);
202 exit(EXIT_SUCCESS);
203
204 VLOG_OPTION_HANDLERS
205 DAEMON_OPTION_HANDLERS
206 LEAK_CHECKER_OPTION_HANDLERS
207
208 case '?':
209 exit(EXIT_FAILURE);
210
211 default:
212 abort();
213 }
214 }
215 free(short_options);
216
217 argc -= optind;
218 argv += optind;
219
220 if (argc != 1) {
221 ovs_fatal(0, "database file is only non-option argument; "
222 "use --help for usage");
223 }
224
225 *file_namep = argv[0];
226 }
227
228 static void
229 usage(void)
230 {
231 printf("%s: Open vSwitch database server\n"
232 "usage: %s [OPTIONS] DATABASE\n"
233 "where DATABASE is a database file in ovsdb format.\n",
234 program_name, program_name);
235 printf("\nJSON-RPC options (may be specified any number of times):\n"
236 " --connect=REMOTE make active connection to REMOTE\n"
237 " --listen=LOCAL passively listen on LOCAL\n");
238 stream_usage("JSON-RPC", true, true);
239 daemon_usage();
240 vlog_usage();
241 printf("\nOther options:\n"
242 " -h, --help display this help message\n"
243 " -V, --version display version information\n");
244 leak_checker_usage();
245 exit(EXIT_SUCCESS);
246 }