2009-11-04 15:11:44 -08:00
|
|
|
|
/*
|
2013-01-24 14:23:45 -08:00
|
|
|
|
* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
|
2009-11-04 15:11:44 -08:00
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
2011-10-06 11:25:25 -07:00
|
|
|
|
#include "column.h"
|
2009-11-04 15:11:44 -08:00
|
|
|
|
#include "command-line.h"
|
|
|
|
|
#include "compiler.h"
|
2012-01-11 10:23:10 -08:00
|
|
|
|
#include "dirs.h"
|
2011-10-06 11:25:25 -07:00
|
|
|
|
#include "dynamic-string.h"
|
2014-02-26 10:44:46 -08:00
|
|
|
|
#include "fatal-signal.h"
|
2009-11-13 13:37:55 -08:00
|
|
|
|
#include "file.h"
|
2010-02-12 11:26:54 -08:00
|
|
|
|
#include "lockfile.h"
|
2009-11-13 13:23:35 -08:00
|
|
|
|
#include "log.h"
|
2009-11-04 15:11:44 -08:00
|
|
|
|
#include "json.h"
|
|
|
|
|
#include "ovsdb.h"
|
2011-10-06 11:25:25 -07:00
|
|
|
|
#include "ovsdb-data.h"
|
2009-11-04 15:11:44 -08:00
|
|
|
|
#include "ovsdb-error.h"
|
2010-02-12 11:26:54 -08:00
|
|
|
|
#include "socket-util.h"
|
2009-11-04 15:11:44 -08:00
|
|
|
|
#include "table.h"
|
|
|
|
|
#include "timeval.h"
|
|
|
|
|
#include "util.h"
|
2014-12-15 14:10:38 +01:00
|
|
|
|
#include "openvswitch/vlog.h"
|
2010-07-16 11:02:49 -07:00
|
|
|
|
|
2010-01-11 13:47:35 -08:00
|
|
|
|
/* -m, --more: Verbosity level for "show-log" command output. */
|
|
|
|
|
static int show_log_verbosity;
|
|
|
|
|
|
2015-03-16 12:01:55 -04:00
|
|
|
|
static const struct ovs_cmdl_command *get_all_commands(void);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
2014-12-15 14:10:38 +01:00
|
|
|
|
OVS_NO_RETURN static void usage(void);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
static void parse_options(int argc, char *argv[]);
|
|
|
|
|
|
2012-01-11 10:23:10 -08:00
|
|
|
|
static const char *default_db(void);
|
|
|
|
|
static const char *default_schema(void);
|
|
|
|
|
|
2009-11-04 15:11:44 -08:00
|
|
|
|
int
|
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
set_program_name(argv[0]);
|
|
|
|
|
parse_options(argc, argv);
|
2014-02-26 10:44:46 -08:00
|
|
|
|
fatal_ignore_sigpipe();
|
2015-03-16 12:01:55 -04:00
|
|
|
|
ovs_cmdl_run_command(argc - optind, argv + optind, get_all_commands());
|
2009-11-04 15:11:44 -08:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
parse_options(int argc, char *argv[])
|
|
|
|
|
{
|
2013-04-23 16:40:56 -07:00
|
|
|
|
static const struct option long_options[] = {
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"more", no_argument, NULL, 'm'},
|
|
|
|
|
{"verbose", optional_argument, NULL, 'v'},
|
|
|
|
|
{"help", no_argument, NULL, 'h'},
|
2014-09-11 17:24:35 -07:00
|
|
|
|
{"option", no_argument, NULL, 'o'},
|
2011-05-04 13:49:42 -07:00
|
|
|
|
{"version", no_argument, NULL, 'V'},
|
|
|
|
|
{NULL, 0, NULL, 0},
|
2009-11-04 15:11:44 -08:00
|
|
|
|
};
|
2015-03-16 12:01:55 -04:00
|
|
|
|
char *short_options = ovs_cmdl_long_options_to_short_options(long_options);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
c = getopt_long(argc, argv, short_options, long_options, NULL);
|
|
|
|
|
if (c == -1) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
2010-01-11 13:47:35 -08:00
|
|
|
|
case 'm':
|
|
|
|
|
show_log_verbosity++;
|
|
|
|
|
break;
|
|
|
|
|
|
2009-11-04 15:11:44 -08:00
|
|
|
|
case 'h':
|
|
|
|
|
usage();
|
|
|
|
|
|
2014-09-11 17:24:35 -07:00
|
|
|
|
case 'o':
|
2015-03-16 12:01:55 -04:00
|
|
|
|
ovs_cmdl_print_options(long_options);
|
2014-09-11 17:24:35 -07:00
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
|
2009-11-04 15:11:44 -08:00
|
|
|
|
case 'V':
|
2011-08-02 12:16:44 -07:00
|
|
|
|
ovs_print_version(0, 0);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
|
vlog_set_verbosity(optarg);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
abort();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(short_options);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage(void)
|
|
|
|
|
{
|
|
|
|
|
printf("%s: Open vSwitch database management utility\n"
|
|
|
|
|
"usage: %s [OPTIONS] COMMAND [ARG...]\n"
|
2012-01-11 10:23:10 -08:00
|
|
|
|
" create [DB [SCHEMA]] create DB with the given SCHEMA\n"
|
|
|
|
|
" compact [DB [DST]] compact DB in-place (or to DST)\n"
|
|
|
|
|
" convert [DB [SCHEMA [DST]]] convert DB to SCHEMA (to DST)\n"
|
|
|
|
|
" db-version [DB] report version of schema used by DB\n"
|
|
|
|
|
" db-cksum [DB] report checksum of schema used by DB\n"
|
|
|
|
|
" schema-version [SCHEMA] report SCHEMA's schema version\n"
|
|
|
|
|
" schema-cksum [SCHEMA] report SCHEMA's checksum\n"
|
|
|
|
|
" query [DB] TRNS execute read-only transaction on DB\n"
|
|
|
|
|
" transact [DB] TRNS execute read/write transaction on DB\n"
|
|
|
|
|
" [-m]... show-log [DB] print DB's log entries\n"
|
|
|
|
|
"The default DB is %s.\n"
|
|
|
|
|
"The default SCHEMA is %s.\n",
|
|
|
|
|
program_name, program_name, default_db(), default_schema());
|
2009-11-04 15:11:44 -08:00
|
|
|
|
vlog_usage();
|
|
|
|
|
printf("\nOther options:\n"
|
2010-01-11 13:47:35 -08:00
|
|
|
|
" -m, --more increase show-log verbosity\n"
|
2009-11-04 15:11:44 -08:00
|
|
|
|
" -h, --help display this help message\n"
|
|
|
|
|
" -V, --version display version information\n");
|
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
|
}
|
2012-01-11 10:23:10 -08:00
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
default_db(void)
|
|
|
|
|
{
|
|
|
|
|
static char *db;
|
|
|
|
|
if (!db) {
|
2012-07-27 15:52:21 -07:00
|
|
|
|
db = xasprintf("%s/conf.db", ovs_dbdir());
|
2012-01-11 10:23:10 -08:00
|
|
|
|
}
|
|
|
|
|
return db;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
default_schema(void)
|
|
|
|
|
{
|
|
|
|
|
static char *schema;
|
|
|
|
|
if (!schema) {
|
|
|
|
|
schema = xasprintf("%s/vswitch.ovsschema", ovs_pkgdatadir());
|
|
|
|
|
}
|
|
|
|
|
return schema;
|
|
|
|
|
}
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
|
|
|
|
static struct json *
|
|
|
|
|
parse_json(const char *s)
|
|
|
|
|
{
|
|
|
|
|
struct json *json = json_from_string(s);
|
|
|
|
|
if (json->type == JSON_STRING) {
|
|
|
|
|
ovs_fatal(0, "\"%s\": %s", s, json->u.string);
|
|
|
|
|
}
|
|
|
|
|
return json;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_and_free_json(struct json *json)
|
|
|
|
|
{
|
|
|
|
|
char *string = json_to_string(json, JSSF_SORT);
|
|
|
|
|
json_destroy(json);
|
|
|
|
|
puts(string);
|
|
|
|
|
free(string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
check_ovsdb_error(struct ovsdb_error *error)
|
|
|
|
|
{
|
|
|
|
|
if (error) {
|
|
|
|
|
ovs_fatal(0, "%s", ovsdb_error_to_string(error));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_create(int argc, char *argv[])
|
2009-11-04 15:11:44 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
|
|
|
|
|
const char *schema_file_name = argc >= 3 ? argv[2] : default_schema();
|
2009-11-04 15:11:44 -08:00
|
|
|
|
struct ovsdb_schema *schema;
|
2009-11-13 13:23:35 -08:00
|
|
|
|
struct ovsdb_log *log;
|
2009-11-04 15:11:44 -08:00
|
|
|
|
struct json *json;
|
|
|
|
|
|
|
|
|
|
/* Read schema from file and convert to JSON. */
|
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
|
|
|
|
|
json = ovsdb_schema_to_json(schema);
|
2010-02-01 14:33:29 -08:00
|
|
|
|
ovsdb_schema_destroy(schema);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
|
|
|
|
/* Create database file. */
|
2010-02-15 11:31:32 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_log_open(db_file_name, OVSDB_LOG_CREATE,
|
|
|
|
|
-1, &log));
|
2009-11-13 13:23:35 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_log_write(log, json));
|
|
|
|
|
check_ovsdb_error(ovsdb_log_commit(log));
|
|
|
|
|
ovsdb_log_close(log);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
|
|
|
|
json_destroy(json);
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-12 11:26:54 -08:00
|
|
|
|
static void
|
2012-07-30 14:55:10 -07:00
|
|
|
|
compact_or_convert(const char *src_name_, const char *dst_name_,
|
2010-02-12 11:26:54 -08:00
|
|
|
|
const struct ovsdb_schema *new_schema,
|
|
|
|
|
const char *comment)
|
|
|
|
|
{
|
2012-07-30 14:55:10 -07:00
|
|
|
|
char *src_name, *dst_name;
|
2010-02-12 11:26:54 -08:00
|
|
|
|
struct lockfile *src_lock;
|
|
|
|
|
struct lockfile *dst_lock;
|
2012-07-30 14:55:10 -07:00
|
|
|
|
bool in_place = dst_name_ == NULL;
|
2010-02-12 11:26:54 -08:00
|
|
|
|
struct ovsdb *db;
|
|
|
|
|
int retval;
|
|
|
|
|
|
2012-07-30 14:55:10 -07:00
|
|
|
|
/* Dereference symlinks for source and destination names. In the in-place
|
|
|
|
|
* case this ensures that, if the source name is a symlink, we replace its
|
|
|
|
|
* target instead of replacing the symlink by a regular file. In the
|
|
|
|
|
* non-in-place, this has the same effect for the destination name. */
|
|
|
|
|
src_name = follow_symlinks(src_name_);
|
|
|
|
|
dst_name = (in_place
|
|
|
|
|
? xasprintf("%s.tmp", src_name)
|
|
|
|
|
: follow_symlinks(dst_name_));
|
|
|
|
|
|
2010-03-08 14:01:16 -08:00
|
|
|
|
/* Lock the source, if we will be replacing it. */
|
2010-02-12 11:26:54 -08:00
|
|
|
|
if (in_place) {
|
2012-08-08 17:40:43 -07:00
|
|
|
|
retval = lockfile_lock(src_name, &src_lock);
|
2010-03-08 14:01:16 -08:00
|
|
|
|
if (retval) {
|
|
|
|
|
ovs_fatal(retval, "%s: failed to lock lockfile", src_name);
|
|
|
|
|
}
|
2010-02-12 11:26:54 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-08 14:01:16 -08:00
|
|
|
|
/* Get (temporary) destination and lock it. */
|
2012-08-08 17:40:43 -07:00
|
|
|
|
retval = lockfile_lock(dst_name, &dst_lock);
|
2010-02-12 11:26:54 -08:00
|
|
|
|
if (retval) {
|
|
|
|
|
ovs_fatal(retval, "%s: failed to lock lockfile", dst_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Save a copy. */
|
|
|
|
|
check_ovsdb_error(new_schema
|
|
|
|
|
? ovsdb_file_open_as_schema(src_name, new_schema, &db)
|
2010-03-18 11:24:55 -07:00
|
|
|
|
: ovsdb_file_open(src_name, true, &db, NULL));
|
2010-02-12 11:26:54 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_file_save_copy(dst_name, false, comment, db));
|
|
|
|
|
ovsdb_destroy(db);
|
|
|
|
|
|
|
|
|
|
/* Replace source. */
|
|
|
|
|
if (in_place) {
|
2014-06-16 15:49:06 -07:00
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
unlink(src_name);
|
|
|
|
|
#endif
|
2010-02-12 11:26:54 -08:00
|
|
|
|
if (rename(dst_name, src_name)) {
|
|
|
|
|
ovs_fatal(errno, "failed to rename \"%s\" to \"%s\"",
|
|
|
|
|
dst_name, src_name);
|
|
|
|
|
}
|
|
|
|
|
fsync_parent_dir(dst_name);
|
|
|
|
|
lockfile_unlock(src_lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lockfile_unlock(dst_lock);
|
2012-03-27 14:09:14 -07:00
|
|
|
|
|
2012-07-30 14:55:10 -07:00
|
|
|
|
free(src_name);
|
|
|
|
|
free(dst_name);
|
2010-02-12 11:26:54 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_compact(int argc, char *argv[])
|
2010-02-12 11:26:54 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db = argc >= 2 ? argv[1] : default_db();
|
|
|
|
|
const char *target = argc >= 3 ? argv[2] : NULL;
|
|
|
|
|
|
2012-03-19 10:07:09 -07:00
|
|
|
|
compact_or_convert(db, target, NULL, "compacted by ovsdb-tool "VERSION);
|
2010-02-12 11:26:54 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_convert(int argc, char *argv[])
|
2010-02-12 11:26:54 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db = argc >= 2 ? argv[1] : default_db();
|
|
|
|
|
const char *schema = argc >= 3 ? argv[2] : default_schema();
|
|
|
|
|
const char *target = argc >= 4 ? argv[3] : NULL;
|
2010-02-12 11:26:54 -08:00
|
|
|
|
struct ovsdb_schema *new_schema;
|
|
|
|
|
|
2012-01-11 10:23:10 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_file(schema, &new_schema));
|
|
|
|
|
compact_or_convert(db, target, new_schema,
|
2012-03-19 10:07:09 -07:00
|
|
|
|
"converted by ovsdb-tool "VERSION);
|
2010-02-12 11:26:54 -08:00
|
|
|
|
ovsdb_schema_destroy(new_schema);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 15:57:14 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_needs_conversion(int argc, char *argv[])
|
2011-02-08 15:57:14 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
|
|
|
|
|
const char *schema_file_name = argc >= 3 ? argv[2] : default_schema();
|
2011-02-08 15:57:14 -08:00
|
|
|
|
struct ovsdb_schema *schema1, *schema2;
|
|
|
|
|
|
|
|
|
|
check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema1));
|
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema2));
|
|
|
|
|
puts(ovsdb_schema_equal(schema1, schema2) ? "no" : "yes");
|
|
|
|
|
ovsdb_schema_destroy(schema1);
|
|
|
|
|
ovsdb_schema_destroy(schema2);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-27 14:26:47 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_db_version(int argc, char *argv[])
|
2010-12-27 14:26:47 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
|
2011-02-08 15:36:21 -08:00
|
|
|
|
struct ovsdb_schema *schema;
|
2010-12-27 14:26:47 -08:00
|
|
|
|
|
2011-02-08 15:36:21 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
|
|
|
|
|
puts(schema->version);
|
|
|
|
|
ovsdb_schema_destroy(schema);
|
2010-12-27 14:26:47 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 15:23:33 -08:00
|
|
|
|
static void
|
|
|
|
|
do_db_cksum(int argc OVS_UNUSED, char *argv[])
|
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
|
2011-02-08 15:23:33 -08:00
|
|
|
|
struct ovsdb_schema *schema;
|
|
|
|
|
|
|
|
|
|
check_ovsdb_error(ovsdb_file_read_schema(db_file_name, &schema));
|
|
|
|
|
puts(schema->cksum);
|
|
|
|
|
ovsdb_schema_destroy(schema);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-27 14:26:47 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_schema_version(int argc, char *argv[])
|
2010-12-27 14:26:47 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *schema_file_name = argc >= 2 ? argv[1] : default_schema();
|
2010-12-27 14:26:47 -08:00
|
|
|
|
struct ovsdb_schema *schema;
|
|
|
|
|
|
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
|
|
|
|
|
puts(schema->version);
|
|
|
|
|
ovsdb_schema_destroy(schema);
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-08 15:23:33 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_schema_cksum(int argc, char *argv[])
|
2011-02-08 15:23:33 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *schema_file_name = argc >= 2 ? argv[1] : default_schema();
|
2011-02-08 15:23:33 -08:00
|
|
|
|
struct ovsdb_schema *schema;
|
|
|
|
|
|
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_file(schema_file_name, &schema));
|
|
|
|
|
puts(schema->cksum);
|
|
|
|
|
ovsdb_schema_destroy(schema);
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-04 15:11:44 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
transact(bool read_only, int argc, char *argv[])
|
2009-11-04 15:11:44 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 3 ? argv[1] : default_db();
|
|
|
|
|
const char *transaction = argv[argc - 1];
|
2009-11-04 15:11:44 -08:00
|
|
|
|
struct json *request, *result;
|
|
|
|
|
struct ovsdb *db;
|
|
|
|
|
|
2010-03-18 11:24:55 -07:00
|
|
|
|
check_ovsdb_error(ovsdb_file_open(db_file_name, read_only, &db, NULL));
|
2009-11-04 15:11:44 -08:00
|
|
|
|
|
|
|
|
|
request = parse_json(transaction);
|
2011-07-26 10:24:17 -07:00
|
|
|
|
result = ovsdb_execute(db, NULL, request, 0, NULL);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
json_destroy(request);
|
|
|
|
|
|
|
|
|
|
print_and_free_json(result);
|
|
|
|
|
ovsdb_destroy(db);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_query(int argc, char *argv[])
|
2009-11-04 15:11:44 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
transact(true, argc, argv);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_transact(int argc, char *argv[])
|
2009-11-04 15:11:44 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
transact(false, argc, argv);
|
2009-11-04 15:11:44 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-01-11 13:47:35 -08:00
|
|
|
|
static void
|
2011-10-06 11:25:25 -07:00
|
|
|
|
print_db_changes(struct shash *tables, struct shash *names,
|
|
|
|
|
const struct ovsdb_schema *schema)
|
2010-01-11 13:47:35 -08:00
|
|
|
|
{
|
|
|
|
|
struct shash_node *n1;
|
|
|
|
|
|
|
|
|
|
SHASH_FOR_EACH (n1, tables) {
|
|
|
|
|
const char *table = n1->name;
|
2011-10-06 11:25:25 -07:00
|
|
|
|
struct ovsdb_table_schema *table_schema;
|
2010-01-11 13:47:35 -08:00
|
|
|
|
struct json *rows = n1->data;
|
|
|
|
|
struct shash_node *n2;
|
|
|
|
|
|
|
|
|
|
if (n1->name[0] == '_' || rows->type != JSON_OBJECT) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-06 11:25:25 -07:00
|
|
|
|
table_schema = shash_find_data(&schema->tables, table);
|
2010-01-11 13:47:35 -08:00
|
|
|
|
SHASH_FOR_EACH (n2, json_object(rows)) {
|
|
|
|
|
const char *row_uuid = n2->name;
|
|
|
|
|
struct json *columns = n2->data;
|
|
|
|
|
struct shash_node *n3;
|
|
|
|
|
char *old_name, *new_name;
|
|
|
|
|
bool free_new_name = false;
|
|
|
|
|
|
|
|
|
|
old_name = new_name = shash_find_data(names, row_uuid);
|
|
|
|
|
if (columns->type == JSON_OBJECT) {
|
|
|
|
|
struct json *new_name_json;
|
|
|
|
|
|
|
|
|
|
new_name_json = shash_find_data(json_object(columns), "name");
|
|
|
|
|
if (new_name_json) {
|
|
|
|
|
new_name = json_to_string(new_name_json, JSSF_SORT);
|
|
|
|
|
free_new_name = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\ttable %s", table);
|
|
|
|
|
|
|
|
|
|
if (!old_name) {
|
|
|
|
|
if (new_name) {
|
2011-10-06 11:23:54 -07:00
|
|
|
|
printf(" insert row %s (%.8s):\n", new_name, row_uuid);
|
2010-01-11 13:47:35 -08:00
|
|
|
|
} else {
|
|
|
|
|
printf(" insert row %.8s:\n", row_uuid);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2011-10-06 11:23:54 -07:00
|
|
|
|
printf(" row %s (%.8s):\n", old_name, row_uuid);
|
2010-01-11 13:47:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (columns->type == JSON_OBJECT) {
|
|
|
|
|
if (show_log_verbosity > 1) {
|
|
|
|
|
SHASH_FOR_EACH (n3, json_object(columns)) {
|
|
|
|
|
const char *column = n3->name;
|
2011-10-06 11:25:25 -07:00
|
|
|
|
const struct ovsdb_column *column_schema;
|
2010-01-11 13:47:35 -08:00
|
|
|
|
struct json *value = n3->data;
|
2011-10-06 11:25:25 -07:00
|
|
|
|
char *value_string = NULL;
|
|
|
|
|
|
|
|
|
|
column_schema =
|
|
|
|
|
(table_schema
|
|
|
|
|
? shash_find_data(&table_schema->columns, column)
|
|
|
|
|
: NULL);
|
|
|
|
|
if (column_schema) {
|
|
|
|
|
const struct ovsdb_type *type;
|
2013-01-24 14:23:45 -08:00
|
|
|
|
struct ovsdb_error *error;
|
2011-10-06 11:25:25 -07:00
|
|
|
|
struct ovsdb_datum datum;
|
|
|
|
|
|
|
|
|
|
type = &column_schema->type;
|
|
|
|
|
error = ovsdb_datum_from_json(&datum, type,
|
|
|
|
|
value, NULL);
|
|
|
|
|
if (!error) {
|
|
|
|
|
struct ds s;
|
|
|
|
|
|
|
|
|
|
ds_init(&s);
|
|
|
|
|
ovsdb_datum_to_string(&datum, type, &s);
|
|
|
|
|
value_string = ds_steal_cstr(&s);
|
2013-01-24 14:23:45 -08:00
|
|
|
|
} else {
|
|
|
|
|
ovsdb_error_destroy(error);
|
2011-10-06 11:25:25 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!value_string) {
|
|
|
|
|
value_string = json_to_string(value, JSSF_SORT);
|
|
|
|
|
}
|
2010-01-11 13:47:35 -08:00
|
|
|
|
printf("\t\t%s=%s\n", column, value_string);
|
|
|
|
|
free(value_string);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!old_name
|
|
|
|
|
|| (new_name != old_name && strcmp(old_name, new_name))) {
|
|
|
|
|
if (old_name) {
|
|
|
|
|
shash_delete(names, shash_find(names, row_uuid));
|
|
|
|
|
free(old_name);
|
|
|
|
|
}
|
|
|
|
|
shash_add(names, row_uuid, (new_name
|
|
|
|
|
? xstrdup(new_name)
|
|
|
|
|
: xmemdup0(row_uuid, 8)));
|
|
|
|
|
}
|
|
|
|
|
} else if (columns->type == JSON_NULL) {
|
2010-03-15 14:50:14 -07:00
|
|
|
|
struct shash_node *node;
|
|
|
|
|
|
2010-01-11 13:47:35 -08:00
|
|
|
|
printf("\t\tdelete row\n");
|
2010-03-15 14:50:14 -07:00
|
|
|
|
node = shash_find(names, row_uuid);
|
|
|
|
|
if (node) {
|
|
|
|
|
shash_delete(names, node);
|
|
|
|
|
}
|
2010-01-11 13:47:35 -08:00
|
|
|
|
free(old_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (free_new_name) {
|
|
|
|
|
free(new_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-16 13:58:33 -08:00
|
|
|
|
static void
|
2012-01-11 10:23:10 -08:00
|
|
|
|
do_show_log(int argc, char *argv[])
|
2009-12-16 13:58:33 -08:00
|
|
|
|
{
|
2012-01-11 10:23:10 -08:00
|
|
|
|
const char *db_file_name = argc >= 2 ? argv[1] : default_db();
|
2010-01-11 13:47:35 -08:00
|
|
|
|
struct shash names;
|
2009-12-16 13:58:33 -08:00
|
|
|
|
struct ovsdb_log *log;
|
2011-10-06 11:25:25 -07:00
|
|
|
|
struct ovsdb_schema *schema;
|
2009-12-16 13:58:33 -08:00
|
|
|
|
unsigned int i;
|
|
|
|
|
|
2010-02-15 11:31:32 -08:00
|
|
|
|
check_ovsdb_error(ovsdb_log_open(db_file_name, OVSDB_LOG_READ_ONLY,
|
|
|
|
|
-1, &log));
|
2010-01-11 13:47:35 -08:00
|
|
|
|
shash_init(&names);
|
2011-10-06 11:25:25 -07:00
|
|
|
|
schema = NULL;
|
2009-12-16 13:58:33 -08:00
|
|
|
|
for (i = 0; ; i++) {
|
|
|
|
|
struct json *json;
|
|
|
|
|
|
|
|
|
|
check_ovsdb_error(ovsdb_log_read(log, &json));
|
|
|
|
|
if (!json) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("record %u:", i);
|
2011-10-06 11:25:25 -07:00
|
|
|
|
if (i == 0) {
|
|
|
|
|
check_ovsdb_error(ovsdb_schema_from_json(json, &schema));
|
|
|
|
|
printf(" \"%s\" schema, version=\"%s\", cksum=\"%s\"\n",
|
|
|
|
|
schema->name, schema->version, schema->cksum);
|
|
|
|
|
} else if (json->type == JSON_OBJECT) {
|
2009-12-16 13:58:33 -08:00
|
|
|
|
struct json *date, *comment;
|
|
|
|
|
|
|
|
|
|
date = shash_find_data(json_object(json), "_date");
|
|
|
|
|
if (date && date->type == JSON_INTEGER) {
|
2013-09-13 18:52:54 -07:00
|
|
|
|
long long int t = json_integer(date);
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
if (t < INT32_MAX) {
|
|
|
|
|
/* Older versions of ovsdb wrote timestamps in seconds. */
|
|
|
|
|
t *= 1000;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-01 23:20:56 +02:00
|
|
|
|
s = xastrftime_msec(" %Y-%m-%d %H:%M:%S.###", t, true);
|
2013-05-02 16:16:06 -07:00
|
|
|
|
fputs(s, stdout);
|
|
|
|
|
free(s);
|
2009-12-16 13:58:33 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
comment = shash_find_data(json_object(json), "_comment");
|
|
|
|
|
if (comment && comment->type == JSON_STRING) {
|
|
|
|
|
printf(" \"%s\"", json_string(comment));
|
|
|
|
|
}
|
2010-01-11 13:47:35 -08:00
|
|
|
|
|
|
|
|
|
if (i > 0 && show_log_verbosity > 0) {
|
|
|
|
|
putchar('\n');
|
2011-10-06 11:25:25 -07:00
|
|
|
|
print_db_changes(json_object(json), &names, schema);
|
2010-01-11 13:47:35 -08:00
|
|
|
|
}
|
2009-12-16 13:58:33 -08:00
|
|
|
|
}
|
|
|
|
|
json_destroy(json);
|
|
|
|
|
putchar('\n');
|
|
|
|
|
}
|
2010-01-11 13:47:35 -08:00
|
|
|
|
|
2011-02-22 18:09:16 -08:00
|
|
|
|
ovsdb_log_close(log);
|
2011-10-06 11:25:25 -07:00
|
|
|
|
ovsdb_schema_destroy(schema);
|
2010-01-11 13:47:35 -08:00
|
|
|
|
/* XXX free 'names'. */
|
2009-12-16 13:58:33 -08:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-04 15:11:44 -08:00
|
|
|
|
static void
|
2010-02-11 11:11:23 -08:00
|
|
|
|
do_help(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
2009-11-04 15:11:44 -08:00
|
|
|
|
{
|
|
|
|
|
usage();
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-16 13:27:32 -07:00
|
|
|
|
static void
|
|
|
|
|
do_list_commands(int argc OVS_UNUSED, char *argv[] OVS_UNUSED)
|
|
|
|
|
{
|
2015-03-16 12:01:55 -04:00
|
|
|
|
ovs_cmdl_print_commands(get_all_commands());
|
2014-10-16 13:27:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-16 12:01:55 -04:00
|
|
|
|
static const struct ovs_cmdl_command all_commands[] = {
|
2014-10-16 13:27:32 -07:00
|
|
|
|
{ "create", "[db [schema]]", 0, 2, do_create },
|
|
|
|
|
{ "compact", "[db [dst]]", 0, 2, do_compact },
|
|
|
|
|
{ "convert", "[db [schema [dst]]]", 0, 3, do_convert },
|
|
|
|
|
{ "needs-conversion", NULL, 0, 2, do_needs_conversion },
|
|
|
|
|
{ "db-version", "[db]", 0, 1, do_db_version },
|
|
|
|
|
{ "db-cksum", "[db]", 0, 1, do_db_cksum },
|
|
|
|
|
{ "schema-version", "[schema]", 0, 1, do_schema_version },
|
|
|
|
|
{ "schema-cksum", "[schema]", 0, 1, do_schema_cksum },
|
|
|
|
|
{ "query", "[db] trns", 1, 2, do_query },
|
|
|
|
|
{ "transact", "[db] trns", 1, 2, do_transact },
|
|
|
|
|
{ "show-log", "[db]", 0, 1, do_show_log },
|
|
|
|
|
{ "help", NULL, 0, INT_MAX, do_help },
|
|
|
|
|
{ "list-commands", NULL, 0, INT_MAX, do_list_commands },
|
|
|
|
|
{ NULL, NULL, 0, 0, NULL },
|
2009-11-04 15:11:44 -08:00
|
|
|
|
};
|
2013-07-19 10:04:47 -07:00
|
|
|
|
|
2015-03-16 12:01:55 -04:00
|
|
|
|
static const struct ovs_cmdl_command *get_all_commands(void)
|
2013-07-19 10:04:47 -07:00
|
|
|
|
{
|
|
|
|
|
return all_commands;
|
|
|
|
|
}
|