ovsdb-tool: Add "show-log" command for use in debugging.
[cascardo/ovs.git] / ovsdb / ovsdb-tool.c
1 /*
2  * Copyright (c) 2009 Nicira Networks.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <getopt.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include "command-line.h"
26 #include "compiler.h"
27 #include "file.h"
28 #include "log.h"
29 #include "json.h"
30 #include "ovsdb.h"
31 #include "ovsdb-error.h"
32 #include "table.h"
33 #include "timeval.h"
34 #include "util.h"
35
36 #include "vlog.h"
37 #define THIS_MODULE VLM_ovsdb_tool
38
39 static const struct command all_commands[];
40
41 static void usage(void) NO_RETURN;
42 static void parse_options(int argc, char *argv[]);
43
44 int
45 main(int argc, char *argv[])
46 {
47     set_program_name(argv[0]);
48     time_init();
49     vlog_init();
50     parse_options(argc, argv);
51     signal(SIGPIPE, SIG_IGN);
52     run_command(argc - optind, argv + optind, all_commands);
53     return 0;
54 }
55
56 static void
57 parse_options(int argc, char *argv[])
58 {
59     static struct option long_options[] = {
60         {"verbose", optional_argument, 0, 'v'},
61         {"help", no_argument, 0, 'h'},
62         {"version", no_argument, 0, 'V'},
63         {0, 0, 0, 0},
64     };
65     char *short_options = long_options_to_short_options(long_options);
66
67     for (;;) {
68         int c;
69
70         c = getopt_long(argc, argv, short_options, long_options, NULL);
71         if (c == -1) {
72             break;
73         }
74
75         switch (c) {
76         case 'h':
77             usage();
78
79         case 'V':
80             OVS_PRINT_VERSION(0, 0);
81             exit(EXIT_SUCCESS);
82
83         case 'v':
84             vlog_set_verbosity(optarg);
85             break;
86
87         case '?':
88             exit(EXIT_FAILURE);
89
90         default:
91             abort();
92         }
93     }
94     free(short_options);
95 }
96
97 static void
98 usage(void)
99 {
100     printf("%s: Open vSwitch database management utility\n"
101            "usage: %s [OPTIONS] COMMAND [ARG...]\n"
102            "  create DB SCHEMA   create DB with the given SCHEMA\n"
103            "  compact DB [DST]   compact DB in-place (or to DST)\n"
104            "  extract-schema DB  print DB's schema on stdout\n"
105            "  query DB TRNS      execute read-only transaction on DB\n"
106            "  transact DB TRNS   execute read/write transaction on DB\n"
107            "  show-log DB        prints information about DB's log entries\n",
108            program_name, program_name);
109     vlog_usage();
110     printf("\nOther options:\n"
111            "  -h, --help                  display this help message\n"
112            "  -V, --version               display version information\n");
113     exit(EXIT_SUCCESS);
114 }
115 \f
116 static struct json *
117 parse_json(const char *s)
118 {
119     struct json *json = json_from_string(s);
120     if (json->type == JSON_STRING) {
121         ovs_fatal(0, "\"%s\": %s", s, json->u.string);
122     }
123     return json;
124 }
125
126 static void
127 print_and_free_json(struct json *json)
128 {
129     char *string = json_to_string(json, JSSF_SORT);
130     json_destroy(json);
131     puts(string);
132     free(string);
133 }
134
135 static void
136 check_ovsdb_error(struct ovsdb_error *error)
137 {
138     if (error) {
139         ovs_fatal(0, "%s", ovsdb_error_to_string(error));
140     }
141 }
142 \f
143 static void
144 do_create(int argc UNUSED, char *argv[])
145 {
146     const char *db_file_name = argv[1];
147     const char *schema_file_name = argv[2];
148     struct ovsdb_schema *schema;
149     struct ovsdb_log *log;
150     struct json *json;
151
152     /* Read schema from file and convert to JSON. */
153     check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
154     json = ovsdb_schema_to_json(schema);
155
156     /* Create database file. */
157     check_ovsdb_error(ovsdb_log_open(db_file_name, O_RDWR | O_CREAT | O_EXCL,
158                                      &log));
159     check_ovsdb_error(ovsdb_log_write(log, json));
160     check_ovsdb_error(ovsdb_log_commit(log));
161     ovsdb_log_close(log);
162
163     json_destroy(json);
164 }
165
166 static void
167 transact(bool read_only, const char *db_file_name, const char *transaction)
168 {
169     struct json *request, *result;
170     struct ovsdb *db;
171
172     check_ovsdb_error(ovsdb_file_open(db_file_name, read_only, &db));
173
174     request = parse_json(transaction);
175     result = ovsdb_execute(db, request, 0, NULL);
176     json_destroy(request);
177
178     print_and_free_json(result);
179     ovsdb_destroy(db);
180 }
181
182 static void
183 do_query(int argc UNUSED, char *argv[])
184 {
185     transact(true, argv[1], argv[2]);
186 }
187
188 static void
189 do_transact(int argc UNUSED, char *argv[])
190 {
191     transact(false, argv[1], argv[2]);
192 }
193
194 static void
195 do_show_log(int argc UNUSED, char *argv[])
196 {
197     const char *db_file_name = argv[1];
198     struct ovsdb_log *log;
199     unsigned int i;
200
201     check_ovsdb_error(ovsdb_log_open(db_file_name, O_RDONLY, &log));
202     for (i = 0; ; i++) {
203         struct json *json;
204
205         check_ovsdb_error(ovsdb_log_read(log, &json));
206         if (!json) {
207             break;
208         }
209
210         printf("record %u:", i);
211         if (json->type == JSON_OBJECT) {
212             struct json *date, *comment;
213
214             date = shash_find_data(json_object(json), "_date");
215             if (date && date->type == JSON_INTEGER) {
216                 time_t t = json_integer(date);
217                 char s[128];
218
219                 strftime(s, sizeof s, "%Y-%m-%d %H:%M:%S", localtime(&t));
220                 printf(" %s", s);
221             }
222
223             comment = shash_find_data(json_object(json), "_comment");
224             if (comment && comment->type == JSON_STRING) {
225                 printf(" \"%s\"", json_string(comment));
226             }
227         }
228         json_destroy(json);
229         putchar('\n');
230     }
231 }
232
233 static void
234 do_help(int argc UNUSED, char *argv[] UNUSED)
235 {
236     usage();
237 }
238
239 static const struct command all_commands[] = {
240     { "create", 2, 2, do_create },
241     { "query", 2, 2, do_query },
242     { "transact", 2, 2, do_transact },
243     { "show-log", 1, 1, do_show_log },
244     { "help", 0, INT_MAX, do_help },
245     { NULL, 0, 0, NULL },
246 };