X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fovs-vsctl.c;h=9c019cc00d1f9a12d9e79d98c103f6724ae2df8f;hb=45a7de56bbcb2adfabf2082b1133e768777d44d6;hp=79bc4ac133530b93be042f42ea21049699e6e091;hpb=5d9cb63c9160df34d8f282db0e933e3f021f7fb6;p=openvswitch diff --git a/utilities/ovs-vsctl.c b/utilities/ovs-vsctl.c index 79bc4ac1..9c019cc0 100644 --- a/utilities/ovs-vsctl.c +++ b/utilities/ovs-vsctl.c @@ -45,6 +45,10 @@ static const char *db; /* --oneline: Write each command's output as a single line? */ static bool oneline; +/* --dry-run: Do not commit any changes. */ +static bool dry_run; + +static void vsctl_fatal(const char *, ...) PRINTF_FORMAT(1, 2) NO_RETURN; static char *default_db(void); static void usage(void) NO_RETURN; static void parse_options(int argc, char *argv[]); @@ -90,10 +94,10 @@ main(int argc, char *argv[]) } } if (!n_commands) { - ovs_fatal(0, "missing command name (use --help for help)"); + vsctl_fatal("missing command name (use --help for help)"); } - /* Now execut the commands. */ + /* Now execute the commands. */ idl = ovsdb_idl_create(db, &ovsrec_idl_class); seqno = ovsdb_idl_get_seqno(idl); trials = 0; @@ -104,7 +108,7 @@ main(int argc, char *argv[]) new_seqno = ovsdb_idl_get_seqno(idl); if (new_seqno != seqno) { if (++trials > 5) { - ovs_fatal(0, "too many database inconsistency failures"); + vsctl_fatal("too many database inconsistency failures"); } do_vsctl(argc - optind, argv + optind, idl); seqno = new_seqno; @@ -115,17 +119,36 @@ main(int argc, char *argv[]) } } +static void +vsctl_fatal(const char *format, ...) +{ + char *message; + va_list args; + + va_start(args, format); + message = xvasprintf(format, args); + va_end(args); + + vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER); + VLOG_ERR("%s", message); + ovs_fatal(0, "%s", message); +} + static void parse_options(int argc, char *argv[]) { enum { OPT_DB = UCHAR_MAX + 1, OPT_ONELINE, - OPT_NO_SYSLOG + OPT_NO_SYSLOG, + OPT_NO_WAIT, + OPT_DRY_RUN }; static struct option long_options[] = { {"db", required_argument, 0, OPT_DB}, {"no-syslog", no_argument, 0, OPT_NO_SYSLOG}, + {"no-wait", no_argument, 0, OPT_NO_WAIT}, + {"dry-run", no_argument, 0, OPT_DRY_RUN}, {"oneline", no_argument, 0, OPT_ONELINE}, {"verbose", optional_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, @@ -154,6 +177,14 @@ parse_options(int argc, char *argv[]) vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN); break; + case OPT_NO_WAIT: + /* XXX not yet implemented */ + break; + + case OPT_DRY_RUN: + dry_run = true; + break; + case 'h': usage(); @@ -482,50 +513,57 @@ check_conflicts(struct vsctl_info *info, const char *name, struct vsctl_port *port; if (shash_find(&info->bridges, name)) { - ovs_fatal(0, "%s because a bridge named %s already exists", msg, name); + vsctl_fatal("%s because a bridge named %s already exists", + msg, name); } port = shash_find_data(&info->ports, name); if (port) { - ovs_fatal(0, "%s because a port named %s already exists on bridge %s", - msg, name, port->bridge->name); + vsctl_fatal("%s because a port named %s already exists on " + "bridge %s", msg, name, port->bridge->name); } iface = shash_find_data(&info->ifaces, name); if (iface) { - ovs_fatal(0, "%s because an interface named %s already exists " - "on bridge %s", msg, name, iface->port->bridge->name); + vsctl_fatal("%s because an interface named %s already exists " + "on bridge %s", msg, name, iface->port->bridge->name); } free(msg); } static struct vsctl_bridge * -find_bridge(struct vsctl_info *info, const char *name) +find_bridge(struct vsctl_info *info, const char *name, bool must_exist) { struct vsctl_bridge *br = shash_find_data(&info->bridges, name); - if (!br) { - ovs_fatal(0, "no bridge named %s", name); + if (must_exist && !br) { + vsctl_fatal("no bridge named %s", name); } return br; } static struct vsctl_port * -find_port(struct vsctl_info *info, const char *name) +find_port(struct vsctl_info *info, const char *name, bool must_exist) { struct vsctl_port *port = shash_find_data(&info->ports, name); - if (!port || !strcmp(name, port->bridge->name)) { - ovs_fatal(0, "no port named %s", name); + if (port && !strcmp(name, port->bridge->name)) { + port = NULL; + } + if (must_exist && !port) { + vsctl_fatal("no port named %s", name); } return port; } static struct vsctl_iface * -find_iface(struct vsctl_info *info, const char *name) +find_iface(struct vsctl_info *info, const char *name, bool must_exist) { struct vsctl_iface *iface = shash_find_data(&info->ifaces, name); - if (!iface || !strcmp(name, iface->port->bridge->name)) { - ovs_fatal(0, "no interface named %s", name); + if (iface && !strcmp(name, iface->port->bridge->name)) { + iface = NULL; + } + if (must_exist && !iface) { + vsctl_fatal("no interface named %s", name); } return iface; } @@ -594,6 +632,11 @@ ovs_delete_bridge(const struct ovsrec_open_vswitch *ovs, free(bridges); } +static void +cmd_init(struct vsctl_context *ctx UNUSED) +{ +} + static void cmd_add_br(struct vsctl_context *ctx) { @@ -622,7 +665,8 @@ cmd_add_br(struct vsctl_context *ctx) ovs_insert_bridge(ctx->ovs, br); } else if (ctx->argc == 3) { - ovs_fatal(0, "'%s' comamnd takes exactly 1 or 3 arguments", ctx->argv[0]); + vsctl_fatal("'%s' command takes exactly 1 or 3 arguments", + ctx->argv[0]); } else if (ctx->argc == 4) { const char *parent_name = ctx->argv[2]; int vlan = atoi(ctx->argv[3]); @@ -633,15 +677,15 @@ cmd_add_br(struct vsctl_context *ctx) int64_t tag = vlan; if (vlan < 1 || vlan > 4095) { - ovs_fatal(0, "%s: vlan must be between 1 and 4095", ctx->argv[0]); + vsctl_fatal("%s: vlan must be between 1 and 4095", ctx->argv[0]); } - parent = shash_find_data(&info.bridges, parent_name); + parent = find_bridge(&info, parent_name, false); if (parent && parent->vlan) { - ovs_fatal(0, "cannot create brdige with fake bridge as parent"); + vsctl_fatal("cannot create brdige with fake bridge as parent"); } if (!parent) { - ovs_fatal(0, "parent bridge %s does not exist", parent_name); + vsctl_fatal("parent bridge %s does not exist", parent_name); } br = parent->br_cfg; @@ -684,22 +728,26 @@ del_port(struct vsctl_info *info, struct vsctl_port *port) static void cmd_del_br(struct vsctl_context *ctx) { - struct shash_node *node; - struct vsctl_info info; + bool must_exist = !shash_find(&ctx->options, "--if-exists"); struct vsctl_bridge *bridge; + struct vsctl_info info; get_info(ctx->ovs, &info); - bridge = find_bridge(&info, ctx->argv[1]); - SHASH_FOR_EACH (node, &info.ports) { - struct vsctl_port *port = node->data; - if (port->bridge == bridge - || !strcmp(port->port_cfg->name, bridge->name)) { - del_port(&info, port); + bridge = find_bridge(&info, ctx->argv[1], must_exist); + if (bridge) { + struct shash_node *node; + + SHASH_FOR_EACH (node, &info.ports) { + struct vsctl_port *port = node->data; + if (port->bridge == bridge + || !strcmp(port->port_cfg->name, bridge->name)) { + del_port(&info, port); + } + } + if (bridge->br_cfg) { + ovsrec_bridge_delete(bridge->br_cfg); + ovs_delete_bridge(ctx->ovs, bridge->br_cfg); } - } - if (bridge->br_cfg) { - ovsrec_bridge_delete(bridge->br_cfg); - ovs_delete_bridge(ctx->ovs, bridge->br_cfg); } free_info(&info); } @@ -742,7 +790,7 @@ cmd_br_exists(struct vsctl_context *ctx) struct vsctl_info info; get_info(ctx->ovs, &info); - if (!shash_find_data(&info.bridges, ctx->argv[1])) { + if (!find_bridge(&info, ctx->argv[1], false)) { exit(2); } free_info(&info); @@ -796,7 +844,7 @@ cmd_br_set_external_id(struct vsctl_context *ctx) size_t n; get_info(ctx->ovs, &info); - bridge = find_bridge(&info, ctx->argv[1]); + bridge = find_bridge(&info, ctx->argv[1], true); if (bridge->br_cfg) { set_external_id(bridge->br_cfg->key_external_ids, bridge->br_cfg->value_external_ids, @@ -851,7 +899,7 @@ cmd_br_get_external_id(struct vsctl_context *ctx) struct vsctl_bridge *bridge; get_info(ctx->ovs, &info); - bridge = find_bridge(&info, ctx->argv[1]); + bridge = find_bridge(&info, ctx->argv[1], true); if (bridge->br_cfg) { get_external_id(bridge->br_cfg->key_external_ids, bridge->br_cfg->value_external_ids, @@ -878,7 +926,7 @@ cmd_list_ports(struct vsctl_context *ctx) struct svec ports; get_info(ctx->ovs, &info); - br = find_bridge(&info, ctx->argv[1]); + br = find_bridge(&info, ctx->argv[1], true); svec_init(&ports); SHASH_FOR_EACH (node, &info.ports) { @@ -909,7 +957,7 @@ add_port(const struct ovsrec_open_vswitch *ovs, check_conflicts(&info, port_name, xasprintf("cannot create a port named %s", port_name)); /* XXX need to check for conflicts on interfaces too */ - bridge = find_bridge(&info, br_name); + bridge = find_bridge(&info, br_name, true); ifaces = xmalloc(n_ifaces * sizeof *ifaces); for (i = 0; i < n_ifaces; i++) { @@ -948,25 +996,30 @@ cmd_add_bond(struct vsctl_context *ctx) static void cmd_del_port(struct vsctl_context *ctx) { + bool must_exist = !shash_find(&ctx->options, "--if-exists"); struct vsctl_info info; get_info(ctx->ovs, &info); if (ctx->argc == 2) { - struct vsctl_port *port = find_port(&info, ctx->argv[1]); - del_port(&info, port); - } else if (ctx->argc == 3) { - struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1]); - struct vsctl_port *port = find_port(&info, ctx->argv[2]); - - if (port->bridge == bridge) { + struct vsctl_port *port = find_port(&info, ctx->argv[1], must_exist); + if (port) { del_port(&info, port); - } else if (port->bridge->parent == bridge) { - ovs_fatal(0, "bridge %s does not have a port %s (although its " - "parent bridge %s does)", - ctx->argv[1], ctx->argv[2], bridge->parent->name); - } else { - ovs_fatal(0, "bridge %s does not have a port %s", - ctx->argv[1], ctx->argv[2]); + } + } else if (ctx->argc == 3) { + struct vsctl_bridge *bridge = find_bridge(&info, ctx->argv[1], true); + struct vsctl_port *port = find_port(&info, ctx->argv[2], must_exist); + + if (port) { + if (port->bridge == bridge) { + del_port(&info, port); + } else if (port->bridge->parent == bridge) { + vsctl_fatal("bridge %s does not have a port %s (although its " + "parent bridge %s does)", + ctx->argv[1], ctx->argv[2], bridge->parent->name); + } else { + vsctl_fatal("bridge %s does not have a port %s", + ctx->argv[1], ctx->argv[2]); + } } } free_info(&info); @@ -979,7 +1032,7 @@ cmd_port_to_br(struct vsctl_context *ctx) struct vsctl_info info; get_info(ctx->ovs, &info); - port = find_port(&info, ctx->argv[1]); + port = find_port(&info, ctx->argv[1], true); ds_put_format(&ctx->output, "%s\n", port->bridge->name); free_info(&info); } @@ -993,7 +1046,7 @@ cmd_port_set_external_id(struct vsctl_context *ctx) size_t n; get_info(ctx->ovs, &info); - port = find_port(&info, ctx->argv[1]); + port = find_port(&info, ctx->argv[1], true); set_external_id(port->port_cfg->key_external_ids, port->port_cfg->value_external_ids, port->port_cfg->n_external_ids, @@ -1013,7 +1066,7 @@ cmd_port_get_external_id(struct vsctl_context *ctx) struct vsctl_port *port; get_info(ctx->ovs, &info); - port = find_port(&info, ctx->argv[1]); + port = find_port(&info, ctx->argv[1], true); get_external_id(port->port_cfg->key_external_ids, port->port_cfg->value_external_ids, port->port_cfg->n_external_ids, @@ -1028,7 +1081,7 @@ cmd_br_to_vlan(struct vsctl_context *ctx) struct vsctl_info info; get_info(ctx->ovs, &info); - bridge = find_bridge(&info, ctx->argv[1]); + bridge = find_bridge(&info, ctx->argv[1], true); ds_put_format(&ctx->output, "%d\n", bridge->vlan); free_info(&info); } @@ -1040,7 +1093,7 @@ cmd_br_to_parent(struct vsctl_context *ctx) struct vsctl_info info; get_info(ctx->ovs, &info); - bridge = find_bridge(&info, ctx->argv[1]); + bridge = find_bridge(&info, ctx->argv[1], true); if (bridge->parent) { bridge = bridge->parent; } @@ -1057,7 +1110,7 @@ cmd_list_ifaces(struct vsctl_context *ctx) struct svec ifaces; get_info(ctx->ovs, &info); - br = find_bridge(&info, ctx->argv[1]); + br = find_bridge(&info, ctx->argv[1], true); svec_init(&ifaces); SHASH_FOR_EACH (node, &info.ifaces) { @@ -1081,7 +1134,7 @@ cmd_iface_to_br(struct vsctl_context *ctx) struct vsctl_info info; get_info(ctx->ovs, &info); - iface = find_iface(&info, ctx->argv[1]); + iface = find_iface(&info, ctx->argv[1], true); ds_put_format(&ctx->output, "%s\n", iface->port->bridge->name); free_info(&info); } @@ -1095,7 +1148,7 @@ cmd_iface_set_external_id(struct vsctl_context *ctx) size_t n; get_info(ctx->ovs, &info); - iface = find_iface(&info, ctx->argv[1]); + iface = find_iface(&info, ctx->argv[1], true); set_external_id(iface->iface_cfg->key_external_ids, iface->iface_cfg->value_external_ids, iface->iface_cfg->n_external_ids, @@ -1115,7 +1168,7 @@ cmd_iface_get_external_id(struct vsctl_context *ctx) struct vsctl_iface *iface; get_info(ctx->ovs, &info); - iface = find_iface(&info, ctx->argv[1]); + iface = find_iface(&info, ctx->argv[1], true); get_external_id(iface->iface_cfg->key_external_ids, iface->iface_cfg->value_external_ids, iface->iface_cfg->n_external_ids, @@ -1147,15 +1200,17 @@ do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl) int n_output; int i, start; + txn = ovsdb_idl_txn_create(idl); + if (dry_run) { + ovsdb_idl_txn_set_dry_run(txn); + } + ovs = ovsrec_open_vswitch_first(idl); if (!ovs) { - /* XXX it would be more user-friendly to create a record ourselves - * (while verifying that the table is empty before doing so). */ - ovs_fatal(0, "%s: database does not contain any Open vSwitch " - "configuration", db); + /* XXX add verification that table is empty */ + ovs = ovsrec_open_vswitch_insert(txn); } - txn = ovsdb_idl_txn_create(idl); output = xmalloc(argc * sizeof *output); n_output = 0; for (start = i = 0; i <= argc; i++) { @@ -1183,7 +1238,7 @@ do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl) case TXN_ABORTED: /* Should not happen--we never call ovsdb_idl_txn_abort(). */ - ovs_fatal(0, "transaction aborted"); + vsctl_fatal("transaction aborted"); case TXN_SUCCESS: break; @@ -1195,7 +1250,7 @@ do_vsctl(int argc, char *argv[], struct ovsdb_idl *idl) return; case TXN_ERROR: - ovs_fatal(0, "transaction error"); + vsctl_fatal("transaction error"); default: NOT_REACHED(); @@ -1234,9 +1289,12 @@ static vsctl_handler_func * get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) { static const struct vsctl_command all_commands[] = { + /* Open vSwitch commands. */ + {"init", 0, 0, cmd_init, ""}, + /* Bridge commands. */ {"add-br", 1, 3, cmd_add_br, ""}, - {"del-br", 1, 1, cmd_del_br, ""}, + {"del-br", 1, 1, cmd_del_br, "--if-exists"}, {"list-br", 0, 0, cmd_list_br, ""}, {"br-exists", 1, 1, cmd_br_exists, ""}, {"br-to-vlan", 1, 1, cmd_br_to_vlan, ""}, @@ -1248,7 +1306,7 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) {"list-ports", 1, 1, cmd_list_ports, ""}, {"add-port", 2, 2, cmd_add_port, ""}, {"add-bond", 4, INT_MAX, cmd_add_bond, ""}, - {"del-port", 1, 2, cmd_del_port, ""}, + {"del-port", 1, 2, cmd_del_port, "--if-exists"}, {"port-to-br", 1, 1, cmd_port_to_br, ""}, {"port-set-external-id", 2, 3, cmd_port_set_external_id, ""}, {"port-get-external-id", 1, 2, cmd_port_get_external_id, ""}, @@ -1269,11 +1327,11 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) break; } if (!shash_add_once(&ctx->options, argv[i], NULL)) { - ovs_fatal(0, "'%s' option specified multiple times", argv[i]); + vsctl_fatal("'%s' option specified multiple times", argv[i]); } } if (i == argc) { - ovs_fatal(0, "missing command name"); + vsctl_fatal("missing command name"); } for (p = all_commands; p < &all_commands[ARRAY_SIZE(all_commands)]; p++) { @@ -1285,18 +1343,18 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) const char *s = strstr(p->options, node->name); int end = s ? s[strlen(node->name)] : EOF; if (end != ',' && end != ' ' && end != '\0') { - ovs_fatal(0, "'%s' command has no '%s' option", - argv[i], node->name); + vsctl_fatal("'%s' command has no '%s' option", + argv[i], node->name); } } n_arg = argc - i - 1; if (n_arg < p->min_args) { - ovs_fatal(0, "'%s' command requires at least %d arguments", - p->name, p->min_args); + vsctl_fatal("'%s' command requires at least %d arguments", + p->name, p->min_args); } else if (n_arg > p->max_args) { - ovs_fatal(0, "'%s' command takes at most %d arguments", - p->name, p->max_args); + vsctl_fatal("'%s' command takes at most %d arguments", + p->name, p->max_args); } else { ctx->argc = n_arg + 1; ctx->argv = &argv[i]; @@ -1305,7 +1363,7 @@ get_vsctl_handler(int argc, char *argv[], struct vsctl_context *ctx) } } - ovs_fatal(0, "unknown command '%s'; use --help for help", argv[0]); + vsctl_fatal("unknown command '%s'; use --help for help", argv[i]); } static void