1 /* Copyright (c) 2015 Nicira, Inc.
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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include "command-line.h"
28 #include "openvswitch/vconn.h"
29 #include "openvswitch/vlog.h"
30 #include "ovn/ovn-sb-idl.h"
31 #include "poll-loop.h"
32 #include "fatal-signal.h"
33 #include "lib/vswitch-idl.h"
36 #include "stream-ssl.h"
40 #include "ovn-controller.h"
44 VLOG_DEFINE_THIS_MODULE(main
);
46 static unixctl_cb_func ovn_controller_exit
;
48 static void parse_options(int argc
, char *argv
[]);
49 OVS_NO_RETURN
static void usage(void);
51 static char *ovs_remote
;
52 static char *ovnsb_remote
;
56 get_initial_snapshot(struct ovsdb_idl
*idl
)
60 if (ovsdb_idl_has_ever_connected(idl
)) {
68 /* Retrieve the OVN remote location from the "external-ids:ovn-remote"
69 * key and the chassis name from the "external-ids:system-id" key in the
70 * Open_vSwitch table of the OVS database instance. */
72 get_core_config(struct controller_ctx
*ctx
)
74 const struct ovsrec_open_vswitch
*cfg
;
76 cfg
= ovsrec_open_vswitch_first(ctx
->ovs_idl
);
78 VLOG_ERR("No Open_vSwitch row defined.");
79 ovsdb_idl_destroy(ctx
->ovs_idl
);
84 const char *remote
, *system_id
;
86 ovsdb_idl_run(ctx
->ovs_idl
);
88 /* xxx This does not support changing OVN Southbound OVSDB mid-run. */
89 remote
= smap_get(&cfg
->external_ids
, "ovn-remote");
91 VLOG_INFO("OVN OVSDB remote not specified. Waiting...");
95 system_id
= smap_get(&cfg
->external_ids
, "system-id");
97 VLOG_INFO("system-id not specified. Waiting...");
101 ovnsb_remote
= xstrdup(remote
);
102 ctx
->chassis_name
= xstrdup(system_id
);
106 ovsdb_idl_wait(ctx
->ovs_idl
);
113 main(int argc
, char *argv
[])
115 struct unixctl_server
*unixctl
;
116 struct controller_ctx ctx
= { .chassis_name
= NULL
};
120 ovs_cmdl_proctitle_init(argc
, argv
);
121 set_program_name(argv
[0]);
122 parse_options(argc
, argv
);
123 fatal_ignore_sigpipe();
127 retval
= unixctl_server_create(NULL
, &unixctl
);
131 unixctl_command_register("exit", "", 0, 0, ovn_controller_exit
, &exiting
);
133 daemonize_complete();
138 /* Connect to OVS OVSDB instance. We do not monitor all tables by
139 * default, so modules must register their interest explicitly. */
140 ctx
.ovs_idl
= ovsdb_idl_create(ovs_remote
, &ovsrec_idl_class
, false, true);
142 /* Register interest in "external_ids" column in "Open_vSwitch" table,
143 * since we'll need to get the OVN OVSDB remote. */
144 ovsdb_idl_add_table(ctx
.ovs_idl
, &ovsrec_table_open_vswitch
);
145 ovsdb_idl_add_column(ctx
.ovs_idl
, &ovsrec_open_vswitch_col_external_ids
);
150 get_initial_snapshot(ctx
.ovs_idl
);
152 get_core_config(&ctx
);
154 ctx
.ovnsb_idl
= ovsdb_idl_create(ovnsb_remote
, &sbrec_idl_class
,
157 get_initial_snapshot(ctx
.ovnsb_idl
);
161 ovsdb_idl_run(ctx
.ovs_idl
);
162 ovsdb_idl_run(ctx
.ovnsb_idl
);
164 if (!ovsdb_idl_is_alive(ctx
.ovnsb_idl
)) {
165 int retval
= ovsdb_idl_get_last_error(ctx
.ovnsb_idl
);
166 VLOG_ERR("%s: database connection failed (%s)",
167 ovnsb_remote
, ovs_retval_to_string(retval
));
168 retval
= EXIT_FAILURE
;
172 if (!ovsdb_idl_is_alive(ctx
.ovs_idl
)) {
173 int retval
= ovsdb_idl_get_last_error(ctx
.ovs_idl
);
174 VLOG_ERR("%s: database connection failed (%s)",
175 ovs_remote
, ovs_retval_to_string(retval
));
176 retval
= EXIT_FAILURE
;
182 unixctl_server_run(unixctl
);
184 unixctl_server_wait(unixctl
);
186 poll_immediate_wake();
189 ovsdb_idl_wait(ctx
.ovs_idl
);
190 ovsdb_idl_wait(ctx
.ovnsb_idl
);
194 unixctl_server_destroy(unixctl
);
195 bindings_destroy(&ctx
);
196 chassis_destroy(&ctx
);
198 ovsdb_idl_destroy(ctx
.ovs_idl
);
199 ovsdb_idl_destroy(ctx
.ovnsb_idl
);
205 parse_options(int argc
, char *argv
[])
208 OPT_PEER_CA_CERT
= UCHAR_MAX
+ 1,
213 static struct option long_options
[] = {
214 {"help", no_argument
, NULL
, 'h'},
215 {"version", no_argument
, NULL
, 'V'},
218 STREAM_SSL_LONG_OPTIONS
,
219 {"peer-ca-cert", required_argument
, NULL
, OPT_PEER_CA_CERT
},
222 char *short_options
= ovs_cmdl_long_options_to_short_options(long_options
);
227 c
= getopt_long(argc
, argv
, short_options
, long_options
, NULL
);
237 ovs_print_version(OFP13_VERSION
, OFP13_VERSION
);
241 DAEMON_OPTION_HANDLERS
242 STREAM_SSL_OPTION_HANDLERS
244 case OPT_PEER_CA_CERT
:
245 stream_ssl_set_peer_ca_cert_file(optarg
);
261 ovs_remote
= xasprintf("unix:%s/db.sock", ovs_rundir());
262 } else if (argc
== 1) {
263 ovs_remote
= argv
[0];
265 VLOG_FATAL("exactly zero or one non-option argument required; "
266 "use --help for usage");
273 printf("%s: OVN controller\n"
274 "usage %s [OPTIONS] [OVS-DATABASE]\n"
275 "where OVS-DATABASE is a socket on which the OVS OVSDB server is listening.\n",
276 program_name
, program_name
);
277 stream_usage("OVS-DATABASE", true, false, false);
280 printf("\nOther options:\n"
281 " -h, --help display this help message\n"
282 " -V, --version display version information\n");
287 ovn_controller_exit(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
288 const char *argv
[] OVS_UNUSED
, void *exiting_
)
290 bool *exiting
= exiting_
;
293 unixctl_command_reply(conn
, NULL
);