]> git.proxmox.com Git - ovs.git/blob - utilities/ovs-cfg-mod.c
ovs-vsctl: Add tests that adding duplicate bridges or ports fails.
[ovs.git] / utilities / ovs-cfg-mod.c
1 /* Copyright (c) 2008, 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 #include <config.h>
16
17 #include <dirent.h>
18 #include <errno.h>
19 #include <getopt.h>
20 #include <stdarg.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "cfg.h"
26 #include "command-line.h"
27 #include "svec.h"
28 #include "timeval.h"
29 #include "util.h"
30
31 #define THIS_MODULE VLM_cfg_mod
32 #include "vlog.h"
33
34 /* Configuration when we first read the configuration file. */
35 static struct svec orig_cfg = SVEC_EMPTY_INITIALIZER;
36
37 static void
38 usage(char *prog_name, int exit_code)
39 {
40 printf("Usage: %s --config-file=FILE ACTIONS\n"
41 "\nConfig:\n"
42 " -T, --timeout=MS wait at most MS milliseconds for lock\n"
43 " -F, --config-file=FILE use configuration FILE\n"
44 "\nActions:\n"
45 " -a, --add=ENTRY add ENTRY\n"
46 " -d, --del-entry=ENTRY delete ENTRY\n"
47 " -D, --del-section=KEY delete section matching KEY\n"
48 " --del-match=PATTERN delete entries matching shell PATTERN\n"
49 " -q, --query=KEY return all entries matching KEY\n"
50 " -c, --log-changes log changes up to this point\n"
51 "\nOther options:\n"
52 " -h, --help display this help message\n"
53 " -V, --version display version information\n",
54 prog_name);
55 exit(exit_code);
56 }
57
58 static void
59 open_config(char *config_file, int timeout)
60 {
61 int error;
62
63 cfg_init();
64 error = cfg_set_file(config_file);
65 if (error) {
66 ovs_fatal(error, "failed to add configuration file \"%s\"",
67 config_file);
68 }
69
70 error = cfg_lock(NULL, timeout);
71 if (error) {
72 ovs_fatal(error, "could not lock configuration file\n");
73 }
74
75 cfg_get_all(&orig_cfg);
76 }
77
78 static void
79 print_vals(char *key)
80 {
81 struct svec vals;
82 int i;
83
84 svec_init(&vals);
85 cfg_get_all_strings(&vals, "%s", key);
86
87 for (i=0; i<vals.n; i++) {
88 printf("%s\n", vals.names[i]);
89 }
90 }
91
92 static void
93 log_diffs(void)
94 {
95 struct svec new_cfg, removed, added;
96 size_t i;
97
98 svec_init(&new_cfg);
99 cfg_get_all(&new_cfg);
100 svec_diff(&orig_cfg, &new_cfg, &removed, NULL, &added);
101 if (removed.n || added.n) {
102 VLOG_INFO("configuration changes:");
103 for (i = 0; i < removed.n; i++) {
104 VLOG_INFO("-%s", removed.names[i]);
105 }
106 for (i = 0; i < added.n; i++) {
107 VLOG_INFO("+%s", added.names[i]);
108 }
109 } else {
110 VLOG_INFO("configuration unchanged");
111 }
112 svec_destroy(&added);
113 svec_destroy(&removed);
114 svec_swap(&new_cfg, &orig_cfg);
115 svec_destroy(&new_cfg);
116 }
117
118 int main(int argc, char *argv[])
119 {
120 enum {
121 OPT_DEL_MATCH = UCHAR_MAX + 1,
122 };
123 static const struct option long_options[] = {
124 {"config-file", required_argument, 0, 'F'},
125 {"timeout", required_argument, 0, 'T'},
126 {"add", required_argument, 0, 'a'},
127 {"del-entry", required_argument, 0, 'd'},
128 {"del-section", required_argument, 0, 'D'},
129 {"del-match", required_argument, 0, OPT_DEL_MATCH},
130 {"query", required_argument, 0, 'q'},
131 {"changes", no_argument, 0, 'c'},
132 {"verbose", optional_argument, 0, 'v'},
133 {"help", no_argument, 0, 'h'},
134 {"version", no_argument, 0, 'V'},
135 {0, 0, 0, 0},
136 };
137 char *short_options;
138 bool config_set = false;
139 int timeout = INT_MAX;
140
141 set_program_name(argv[0]);
142 time_init();
143 vlog_init();
144
145 short_options = long_options_to_short_options(long_options);
146 for (;;) {
147 int option;
148
149 option = getopt_long(argc, argv, short_options, long_options, NULL);
150 if (option == -1) {
151 break;
152 }
153
154 if ((option > UCHAR_MAX || !strchr("FhVv?", option))
155 && config_set == false) {
156 ovs_fatal(0, "no config file specified (use --help for help)");
157 }
158
159 switch (option) {
160 case 'T':
161 if (config_set) {
162 ovs_fatal(0, "--timeout or -T must be specified "
163 "before --file or -F");
164 }
165 timeout = atoi(optarg);
166 break;
167
168 case 'F':
169 open_config(optarg, timeout);
170 config_set = true;
171 break;
172
173 case 'a':
174 cfg_add_entry("%s", optarg);
175 break;
176
177 case 'd':
178 cfg_del_entry("%s", optarg);
179 break;
180
181 case 'D':
182 cfg_del_section("%s", optarg);
183 break;
184
185 case OPT_DEL_MATCH:
186 cfg_del_match("%s", optarg);
187 break;
188
189 case 'q':
190 print_vals(optarg);
191 break;
192
193 case 'c':
194 log_diffs();
195 break;
196
197 case 'h':
198 usage(argv[0], EXIT_SUCCESS);
199 break;
200
201 case 'V':
202 OVS_PRINT_VERSION(0, 0);
203 exit(EXIT_SUCCESS);
204
205 case 'v':
206 vlog_set_verbosity(optarg);
207 break;
208
209 case '?':
210 exit(EXIT_FAILURE);
211
212 default:
213 NOT_REACHED();
214 }
215 }
216 free(short_options);
217
218 if (optind != argc) {
219 ovs_fatal(0, "non-option arguments not accepted "
220 "(use --help for help)");
221 }
222
223 if (cfg_is_dirty()) {
224 cfg_write();
225 }
226 cfg_unlock();
227
228 exit(0);
229 }