1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
|
/*
* Copyright (c) 2015, 2017 Nicira, Inc.
*
* 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.
*/
#ifndef DB_CTL_BASE_H
#define DB_CTL_BASE_H 1
#include "compiler.h"
#include "openvswitch/dynamic-string.h"
#include "openvswitch/shash.h"
struct ctl_context;
struct option;
struct ovsdb_idl;
struct ovsdb_idl_row;
struct ovsdb_idl_txn;
struct ovsdb_symbol_table;
struct table;
/* This library module contains the common parts for ovsdb manipulation
* (structs, commands and functions). To utilize this module, user must
* define the following:
*
* - the command syntaxes for each command. (See 'struct ctl_command_syntax'
* for more info) and regiters them using ctl_register_commands().
*
* - the *ctl command context by inheriting the 'struct ctl_context' for
* additional commands implemented by user. (See 'struct ctl_context' for
* more info)
*/
/* ctl_fatal() also logs the error, so it is preferred in this file. */
#define ovs_fatal please_use_ctl_fatal_instead_of_ovs_fatal
struct ctl_table_class;
struct ovsdb_idl_class;
struct ovsdb_idl_table_class;
struct cmd_show_table;
/* ctl_init() figures out the number of tables on its own and flags an error if
* 'ctl_classes' was defined with the wrong number of elements. */
#define ctl_init(idl_class, table_classes, ctl_classes, cmd_show_table, \
ctl_exit_func) \
(BUILD_ASSERT(ARRAY_SIZE(table_classes) == ARRAY_SIZE(ctl_classes)), \
ctl_init__(idl_class, ctl_classes, cmd_show_table, ctl_exit_func))
void ctl_init__(const struct ovsdb_idl_class *, const struct ctl_table_class *,
const struct cmd_show_table *cmd_show_tables,
void (*ctl_exit_func)(int status));
char *ctl_default_db(void);
void ctl_error(struct ctl_context *, const char *, ...)
OVS_PRINTF_FORMAT(2, 3);
OVS_NO_RETURN void ctl_fatal(const char *, ...) OVS_PRINTF_FORMAT(1, 2);
/* *ctl command syntax structure, to be defined by each command implementation.
*
* Execution Path
* ==============
*
* Three stylized functions accompany each of these data structures:
*
* "pre-run" "run" "post-run"
* --------------- ------------ -----------------
* *ctl ->prerequisites ->run ->postprocess
*
* Any *ctl command implementation should go through the following execution
* path:
*
* 1. parses user command-line input and finds the corresponding syntax
* structures.
*
* 2. calls prerequisites() for getting the columns or tables used by each
* command.
*
* 3. calls run() to execute each command and to generate output.
*
* 4. calls postprocess() after output has been committed. (Only needed
* by 'create' command sofar)
*
* Execution Context
* =================
*
* Each of the stylized functions requires the 'struct ctl_context' as input
* to provide context e.g. command-line arguments, table to be modified. User
* may define more specific context (by inheriting 'struct ctl_context') and
* write stylized functions that use it. In that case, CONTAINER_OF() can
* be used to cast the generic context to the specific one.
*
* */
struct ctl_command_syntax {
const char *name; /* e.g. "add-br" */
int min_args; /* Min number of arguments following name. */
int max_args; /* Max number of arguments following name. */
/* Names that roughly describe the arguments that the command
* uses. These should be similar to the names displayed in the
* man page or in the help output. */
const char *arguments;
/* If nonnull, calls ovsdb_idl_add_column() or ovsdb_idl_add_table() for
* each column or table in ctx->idl that it uses. */
void (*prerequisites)(struct ctl_context *ctx);
/* Does the actual work of the command and puts the command's output, if
* any, in ctx->output or ctx->table.
*
* Alternatively, if some prerequisite of the command is not met and the
* caller should wait for something to change and then retry, it may set
* ctx->try_again to true. (Only the "wait-until" command currently does
* this.) */
void (*run)(struct ctl_context *ctx);
/* If nonnull, called after the transaction has been successfully
* committed. ctx->output is the output from the "run" function, which
* this function may modify and otherwise postprocess as needed. (Only the
* "create" command currently does any postprocessing.) */
void (*postprocess)(struct ctl_context *ctx);
/* A comma-separated list of supported options, e.g. "--a,--b", or the
* empty string if the command does not support any options.
*
* Arguments are determined by appending special characters to option
* names:
*
* - Append "=" (e.g. "--id=") for a required argument.
*
* - Append "?" (e.g. "--ovs?") for an optional argument.
*
* - Otherwise an option does not accept an argument. */
const char *options;
enum { RO, RW } mode; /* Does this command modify the database? */
};
/* A command extracted from command-line input plus the structs for
* output generation. */
struct ctl_command {
/* Data that remains constant after initialization. */
const struct ctl_command_syntax *syntax;
int argc;
char **argv;
struct shash options;
/* Data modified by commands. */
struct ds output;
struct table *table;
};
bool ctl_might_write_to_db(const struct ctl_command *, size_t n);
const char *ctl_get_db_cmd_usage(void);
const char *ctl_list_db_tables_usage(void);
void ctl_print_commands(void);
void ctl_print_options(const struct option *);
void ctl_add_cmd_options(struct option **, size_t *n_options_p,
size_t *allocated_options_p, int opt_val);
void ctl_register_commands(const struct ctl_command_syntax *);
char * OVS_WARN_UNUSED_RESULT ctl_parse_commands(
int argc, char *argv[], struct shash *local_options,
struct ctl_command **commandsp, size_t *n_commandsp);
/* Sometimes, it is desirable to print the table with weak reference to
* rows in a 'cmd_show_table' table. In that case, the 'weak_ref_table'
* should be used and user must define all variables. */
struct weak_ref_table {
const struct ovsdb_idl_table_class *table;
const struct ovsdb_idl_column *name_column;
/* This colum must be a weak reference to the owning
* 'struct cmd_show_table''s table row. */
const struct ovsdb_idl_column *wref_column;
};
/* This struct is for organizing the 'show' command output where:
*
* - 'table' is the table to show.
*
* - if 'name_column' is not null, it is used as the name for each row
* in 'table'.
*
* - 'columns[]' allows user to specify the print of additional columns
* in 'table'.
*
* - if 'wref_table' is populated, print 'wref_table.name_column' for
* each row in table 'wref_table.table' that has a reference to 'table'
* in 'wref_table.wref_column'. Every field must be populated.
*
* */
struct cmd_show_table {
const struct ovsdb_idl_table_class *table;
const struct ovsdb_idl_column *name_column;
const struct ovsdb_idl_column *columns[4]; /* Seems like a good number. */
const struct weak_ref_table wref_table;
};
/* The base context struct for conducting the common database
* operations (commands listed in 'db_ctl_commands'). User should
* define the per-schema context by inheriting this struct as base.
*
* Database Caches
* ===============
*
* User may implement caches for contents of the database to facilitate
* specific commands. In that case, the common commands defined in
* 'db_ctl_commands' that may invalidate the cache must call the
* invalidate_cache().
*
**/
struct ctl_context {
/* Read-only. */
int argc;
char **argv;
struct shash options;
/* Modifiable state. */
char *error;
struct ds output;
struct table *table;
struct ovsdb_idl *idl;
struct ovsdb_idl_txn *txn;
struct ovsdb_symbol_table *symtab;
/* For implementation with a cache of the contents of the database,
* this function will be called when the database is changed and the
* change makes the cache no longer valid. */
void (*invalidate_cache_cb)(struct ctl_context *);
/* A command may set this member to true if some prerequisite is not met
* and the caller should wait for something to change and then retry. */
bool try_again;
/* If set during the context initialization, command implementation
* may use optimizations that will leave database changes invisible
* to IDL, e.g. use partial set updates. */
bool last_command;
};
void ctl_context_init_command(struct ctl_context *, struct ctl_command *,
bool last);
void ctl_context_init(struct ctl_context *, struct ctl_command *,
struct ovsdb_idl *, struct ovsdb_idl_txn *,
struct ovsdb_symbol_table *,
void (*invalidate_cache)(struct ctl_context *));
void ctl_context_done_command(struct ctl_context *, struct ctl_command *);
void ctl_context_done(struct ctl_context *, struct ctl_command *);
/* A way to identify a particular row in the database based on a user-provided
* string. If all fields are NULL, the struct is ignored. Otherwise,
* 'name_column' designates a column whose table is searched for rows that
* match with the user string. If 'key' is NULL, then 'name_column' should be
* a string or integer-valued column; otherwise it should be a map from a
* string to one of those types and the value corresponding to 'key' is what is
* matched. If a matching row is found, then:
*
* - If 'uuid_column' is NULL, the matching row is the final row.
*
* - Otherwise 'uuid_column' must designate a UUID-typed column whose value
* refers to exactly one row, which is the final row.
*/
struct ctl_row_id {
const struct ovsdb_idl_column *name_column;
const char *key;
const struct ovsdb_idl_column *uuid_column;
};
struct ctl_table_class {
struct ctl_row_id row_ids[4];
};
char *ctl_get_row(struct ctl_context *, const struct ovsdb_idl_table_class *,
const char *record_id, bool must_exist,
const struct ovsdb_idl_row **);
char *ctl_set_column(const char *table_name, const struct ovsdb_idl_row *,
const char *arg, struct ovsdb_symbol_table *);
#endif /* db-ctl-base.h */
|