a91e77893db470b2d656163471819de2713600d3
[sliver-openvswitch.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
24 #include "command-line.h"
25 #include "daemon.h"
26 #include "fault.h"
27 #include "file.h"
28 #include "json.h"
29 #include "jsonrpc.h"
30 #include "jsonrpc-server.h"
31 #include "leak-checker.h"
32 #include "list.h"
33 #include "ovsdb-error.h"
34 #include "poll-loop.h"
35 #include "process.h"
36 #include "stream.h"
37 #include "svec.h"
38 #include "timeval.h"
39 #include "trigger.h"
40 #include "util.h"
41 #include "unixctl.h"
42
43 #include "vlog.h"
44 #define THIS_MODULE VLM_ovsdb_server
45
46 static const struct jsonrpc_server_cbs ovsdb_jsonrpc_cbs;
47
48 static void parse_options(int argc, char *argv[], char **file_namep,
49                           struct svec *active, struct svec *passive);
50 static void usage(void) NO_RETURN;
51
52 int
53 main(int argc, char *argv[])
54 {
55     struct unixctl_server *unixctl;
56     struct ovsdb_jsonrpc_server *jsonrpc;
57     struct svec active, passive;
58     struct ovsdb_error *error;
59     struct ovsdb *db;
60     char *file_name;
61     int retval;
62
63     set_program_name(argv[0]);
64     register_fault_handlers();
65     time_init();
66     vlog_init();
67     signal(SIGPIPE, SIG_IGN);
68     process_init();
69
70     parse_options(argc, argv, &file_name, &active, &passive);
71
72     error = ovsdb_file_open(file_name, false, &db);
73     if (error) {
74         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
75     }
76
77     retval = ovsdb_jsonrpc_server_create(db, &active, &passive, &jsonrpc);
78     if (retval) {
79         ovs_fatal(retval, "failed to initialize JSON-RPC server for OVSDB");
80     }
81     svec_destroy(&active);
82     svec_destroy(&passive);
83
84     die_if_already_running();
85     daemonize();
86
87     retval = unixctl_server_create(NULL, &unixctl);
88     if (retval) {
89         ovs_fatal(retval, "could not listen for control connections");
90     }
91
92     for (;;) {
93         ovsdb_jsonrpc_server_run(jsonrpc);
94         unixctl_server_run(unixctl);
95         ovsdb_trigger_run(db, time_msec());
96
97         ovsdb_jsonrpc_server_wait(jsonrpc);
98         unixctl_server_wait(unixctl);
99         ovsdb_trigger_wait(db, time_msec());
100         poll_block();
101     }
102
103     return 0;
104 }
105
106 static void
107 parse_options(int argc, char *argv[], char **file_namep,
108               struct svec *active, struct svec *passive)
109 {
110     enum {
111         OPT_DUMMY = UCHAR_MAX + 1,
112         OPT_CONNECT,
113         OPT_LISTEN,
114         VLOG_OPTION_ENUMS,
115         LEAK_CHECKER_OPTION_ENUMS
116     };
117     static struct option long_options[] = {
118         {"connect",     required_argument, 0, OPT_CONNECT},
119         {"listen",      required_argument, 0, OPT_LISTEN},
120         {"help",        no_argument, 0, 'h'},
121         {"version",     no_argument, 0, 'V'},
122         DAEMON_LONG_OPTIONS,
123         VLOG_LONG_OPTIONS,
124         LEAK_CHECKER_LONG_OPTIONS,
125         {0, 0, 0, 0},
126     };
127     char *short_options = long_options_to_short_options(long_options);
128
129     svec_init(active);
130     svec_init(passive);
131     for (;;) {
132         int c;
133
134         c = getopt_long(argc, argv, short_options, long_options, NULL);
135         if (c == -1) {
136             break;
137         }
138
139         switch (c) {
140         case OPT_CONNECT:
141             svec_add(active, optarg);
142             break;
143
144         case OPT_LISTEN:
145             svec_add(passive, optarg);
146             break;
147
148         case 'h':
149             usage();
150
151         case 'V':
152             OVS_PRINT_VERSION(0, 0);
153             exit(EXIT_SUCCESS);
154
155         VLOG_OPTION_HANDLERS
156         DAEMON_OPTION_HANDLERS
157         LEAK_CHECKER_OPTION_HANDLERS
158
159         case '?':
160             exit(EXIT_FAILURE);
161
162         default:
163             abort();
164         }
165     }
166     free(short_options);
167
168     argc -= optind;
169     argv += optind;
170
171     if (argc != 1) {
172         ovs_fatal(0, "database file is only non-option argument; "
173                 "use --help for usage");
174     }
175
176     *file_namep = argv[0];
177 }
178
179 static void
180 usage(void)
181 {
182     printf("%s: Open vSwitch database server\n"
183            "usage: %s [OPTIONS] DATABASE\n"
184            "where DATABASE is a database file in ovsdb format.\n",
185            program_name, program_name);
186     printf("\nJSON-RPC options (may be specified any number of times):\n"
187            "  --connect=REMOTE        make active connection to REMOTE\n"
188            "  --listen=LOCAL          passively listen on LOCAL\n");
189     stream_usage("JSON-RPC", true, true);
190     daemon_usage();
191     vlog_usage();
192     printf("\nOther options:\n"
193            "  -h, --help              display this help message\n"
194            "  -V, --version           display version information\n");
195     leak_checker_usage();
196     exit(EXIT_SUCCESS);
197 }