]>
Commit | Line | Data |
---|---|---|
ac0630a2 RB |
1 | /* |
2 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | * you may not use this file except in compliance with the License. | |
4 | * You may obtain a copy of the License at: | |
5 | * | |
6 | * http://www.apache.org/licenses/LICENSE-2.0 | |
7 | * | |
8 | * Unless required by applicable law or agreed to in writing, software | |
9 | * distributed under the License is distributed on an "AS IS" BASIS, | |
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | * See the License for the specific language governing permissions and | |
12 | * limitations under the License. | |
13 | */ | |
14 | ||
15 | #include <config.h> | |
16 | ||
17 | #include <getopt.h> | |
18 | #include <stdlib.h> | |
19 | #include <stdio.h> | |
20 | ||
21 | #include "command-line.h" | |
22 | #include "dirs.h" | |
23 | #include "fatal-signal.h" | |
24 | #include "ovn/ovn-idl.h" | |
25 | #include "ovn/ovn-nb-idl.h" | |
26 | #include "poll-loop.h" | |
27 | #include "stream.h" | |
28 | #include "stream-ssl.h" | |
29 | #include "util.h" | |
30 | #include "openvswitch/vlog.h" | |
31 | ||
32 | VLOG_DEFINE_THIS_MODULE(ovn_nbd); | |
33 | ||
34 | static const char *ovnnb_db; | |
35 | static const char *ovn_db; | |
36 | ||
37 | static const char *default_db(void); | |
38 | ||
39 | static void | |
40 | usage(void) | |
41 | { | |
42 | printf("\ | |
43 | %s: OVN northbound management daemon\n\ | |
44 | usage: %s [OPTIONS]\n\ | |
45 | \n\ | |
46 | Options:\n\ | |
47 | --ovnnb-db=DATABASE connect to ovn-nb database at DATABASE\n\ | |
48 | (default: %s)\n\ | |
49 | --ovn-db=DATABASE connect to ovn database at DATABASE\n\ | |
50 | (default: %s)\n\ | |
51 | -h, --help display this help message\n\ | |
52 | -o, --options list available options\n\ | |
53 | -V, --version display version information\n\ | |
54 | ", program_name, program_name, default_db(), default_db()); | |
55 | vlog_usage(); | |
56 | stream_usage("database", true, true, false); | |
57 | } | |
58 | \f | |
59 | static void | |
60 | ovnnb_db_changed(struct ovsdb_idl *idl OVS_UNUSED) | |
61 | { | |
62 | /* XXX */ | |
63 | printf("ovn-nbd: ovn-nb db contents have changed.\n"); | |
64 | } | |
65 | ||
66 | static void | |
67 | ovn_db_changed(struct ovsdb_idl *idl OVS_UNUSED) | |
68 | { | |
69 | /* XXX */ | |
70 | printf("ovn-nbd: ovn db contents have changed.\n"); | |
71 | } | |
72 | \f | |
73 | static const char * | |
74 | default_db(void) | |
75 | { | |
76 | static char *def; | |
77 | if (!def) { | |
78 | def = xasprintf("unix:%s/db.sock", ovs_rundir()); | |
79 | } | |
80 | return def; | |
81 | } | |
82 | ||
83 | static void | |
84 | parse_options(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) | |
85 | { | |
86 | enum { | |
87 | VLOG_OPTION_ENUMS, | |
88 | }; | |
89 | static const struct option long_options[] = { | |
90 | {"ovn-db", required_argument, NULL, 'd'}, | |
91 | {"ovnnb-db", required_argument, NULL, 'D'}, | |
92 | {"help", no_argument, NULL, 'h'}, | |
93 | {"options", no_argument, NULL, 'o'}, | |
94 | {"version", no_argument, NULL, 'V'}, | |
95 | VLOG_LONG_OPTIONS, | |
96 | STREAM_SSL_LONG_OPTIONS, | |
97 | {NULL, 0, NULL, 0}, | |
98 | }; | |
99 | char *short_options = ovs_cmdl_long_options_to_short_options(long_options); | |
100 | ||
101 | for (;;) { | |
102 | int c; | |
103 | ||
104 | c = getopt_long(argc, argv, short_options, long_options, NULL); | |
105 | if (c == -1) { | |
106 | break; | |
107 | } | |
108 | ||
109 | switch (c) { | |
110 | VLOG_OPTION_HANDLERS; | |
111 | STREAM_SSL_OPTION_HANDLERS; | |
112 | ||
113 | case 'd': | |
114 | ovn_db = optarg; | |
115 | break; | |
116 | ||
117 | case 'D': | |
118 | ovnnb_db = optarg; | |
119 | break; | |
120 | ||
121 | case 'h': | |
122 | usage(); | |
123 | exit(EXIT_SUCCESS); | |
124 | ||
125 | case 'o': | |
126 | ovs_cmdl_print_options(long_options); | |
127 | exit(EXIT_SUCCESS); | |
128 | ||
129 | case 'V': | |
130 | ovs_print_version(0, 0); | |
131 | exit(EXIT_SUCCESS); | |
132 | ||
133 | default: | |
134 | break; | |
135 | } | |
136 | } | |
137 | ||
138 | if (!ovn_db) { | |
139 | ovn_db = default_db(); | |
140 | } | |
141 | ||
142 | if (!ovnnb_db) { | |
143 | ovnnb_db = default_db(); | |
144 | } | |
145 | ||
146 | free(short_options); | |
147 | } | |
148 | ||
149 | int | |
150 | main(int argc, char *argv[]) | |
151 | { | |
152 | extern struct vlog_module VLM_reconnect; | |
153 | struct ovsdb_idl *ovnnb_idl, *ovn_idl; | |
154 | unsigned int ovnnb_seqno, ovn_seqno; | |
155 | int res = EXIT_SUCCESS; | |
156 | ||
157 | fatal_ignore_sigpipe(); | |
158 | set_program_name(argv[0]); | |
159 | vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN); | |
160 | vlog_set_levels(&VLM_reconnect, VLF_ANY_DESTINATION, VLL_WARN); | |
161 | parse_options(argc, argv); | |
162 | nbrec_init(); | |
163 | ovnrec_init(); | |
164 | ||
165 | /* We want to detect all changes to the ovn-nb db. */ | |
166 | ovnnb_idl = ovsdb_idl_create(ovnnb_db, &nbrec_idl_class, true, true); | |
167 | ||
168 | /* There is only a small subset of changes to the ovn db that ovn-nbd has to | |
169 | * care about, so we'll enable monitoring those directly. */ | |
170 | ovn_idl = ovsdb_idl_create(ovn_db, &ovnrec_idl_class, false, true); | |
171 | ovsdb_idl_add_column(ovn_idl, &ovnrec_bindings_col_chassis); | |
172 | ||
173 | /* | |
174 | * The loop here just runs the IDL in a loop waiting for the seqno to | |
175 | * change, which indicates that the contents of the db have changed. | |
176 | * | |
177 | * If the contents of the ovn-nb db change, the mappings to the ovn db must | |
178 | * be recalculated. | |
179 | * | |
180 | * If the contents of the ovn db change, it means the 'up' state of a port | |
181 | * may have changed, as that's the only type of change ovn-nbd is watching | |
182 | * for. | |
183 | */ | |
184 | ||
185 | ovnnb_seqno = ovsdb_idl_get_seqno(ovnnb_idl); | |
186 | ovn_seqno = ovsdb_idl_get_seqno(ovn_idl); | |
187 | for (;;) { | |
188 | ovsdb_idl_run(ovnnb_idl); | |
189 | ovsdb_idl_run(ovn_idl); | |
190 | ||
191 | if (!ovsdb_idl_is_alive(ovnnb_idl)) { | |
192 | int retval = ovsdb_idl_get_last_error(ovnnb_idl); | |
193 | VLOG_ERR("%s: database connection failed (%s)", | |
194 | ovnnb_db, ovs_retval_to_string(retval)); | |
195 | res = EXIT_FAILURE; | |
196 | break; | |
197 | } | |
198 | ||
199 | if (!ovsdb_idl_is_alive(ovn_idl)) { | |
200 | int retval = ovsdb_idl_get_last_error(ovn_idl); | |
201 | VLOG_ERR("%s: database connection failed (%s)", | |
202 | ovn_db, ovs_retval_to_string(retval)); | |
203 | res = EXIT_FAILURE; | |
204 | break; | |
205 | } | |
206 | ||
207 | if (ovnnb_seqno != ovsdb_idl_get_seqno(ovnnb_idl)) { | |
208 | ovnnb_seqno = ovsdb_idl_get_seqno(ovnnb_idl); | |
209 | ovnnb_db_changed(ovnnb_idl); | |
210 | } | |
211 | ||
212 | if (ovn_seqno != ovsdb_idl_get_seqno(ovn_idl)) { | |
213 | ovn_seqno = ovsdb_idl_get_seqno(ovn_idl); | |
214 | ovn_db_changed(ovn_idl); | |
215 | } | |
216 | ||
217 | if (ovnnb_seqno == ovsdb_idl_get_seqno(ovnnb_idl) && | |
218 | ovn_seqno == ovsdb_idl_get_seqno(ovn_idl)) { | |
219 | ovsdb_idl_wait(ovnnb_idl); | |
220 | ovsdb_idl_wait(ovn_idl); | |
221 | poll_block(); | |
222 | } | |
223 | } | |
224 | ||
225 | ovsdb_idl_destroy(ovnnb_idl); | |
226 | ||
227 | exit(res); | |
228 | } |