ovn-sb: Remove the "Gateway" table from the ovn-sb schema.
[cascardo/ovs.git] / ovn / ovn-nbctl.c
index 61ec1e9..0bdb3a3 100644 (file)
@@ -22,7 +22,7 @@
 #include "command-line.h"
 #include "dirs.h"
 #include "fatal-signal.h"
-#include "ovn/ovn-nb-idl.h"
+#include "ovn/lib/ovn-nb-idl.h"
 #include "poll-loop.h"
 #include "process.h"
 #include "stream.h"
@@ -48,6 +48,10 @@ usage(void)
 %s: OVN northbound DB management utility\n\
 usage: %s [OPTIONS] COMMAND [ARG...]\n\
 \n\
+General commands:\n\
+  show                      print overview of database contents\n\
+  show LSWITCH              print overview of database contents for LSWITCH\n\
+\n\
 Logical switch commands:\n\
   lswitch-add [LSWITCH]     create a logical switch named LSWITCH\n\
   lswitch-del LSWITCH       delete LSWITCH and all its ports\n\
@@ -73,7 +77,20 @@ Logical port commands:\n\
   lport-set-macs LPORT [MAC]...\n\
                             set MAC addresses for LPORT.\n\
   lport-get-macs LPORT      get a list of MAC addresses on LPORT\n\
+  lport-set-port-security LPORT [ADDRS]...\n\
+                            set port security addresses for LPORT.\n\
+  lport-get-port-security LPORT    get LPORT's port security addresses\n\
   lport-get-up LPORT        get state of LPORT ('up' or 'down')\n\
+  lport-set-enabled LPORT STATE\n\
+                            set administrative state LPORT\n\
+                            ('enabled' or 'disabled')\n\
+  lport-get-enabled LPORT   get administrative state LPORT\n\
+                            ('enabled' or 'disabled')\n\
+  lport-set-type LPORT TYPE Set the type for LPORT\n\
+  lport-get-type LPORT      Get the type for LPORT\n\
+  lport-set-options LPORT KEY=VALUE [KEY=VALUE]...\n\
+                            Set options related to the type of LPORT\n\
+  lport-get-options LPORT   Get the type specific options for LPORT\n\
 \n\
 Options:\n\
   --db=DATABASE             connect to DATABASE\n\
@@ -126,6 +143,48 @@ lswitch_by_name_or_uuid(struct nbctl_context *nb_ctx, const char *id)
     return lswitch;
 }
 
+static void
+print_lswitch(const struct nbrec_logical_switch *lswitch)
+{
+    printf("    lswitch "UUID_FMT" (%s)\n",
+           UUID_ARGS(&lswitch->header_.uuid), lswitch->name);
+
+    for (size_t i = 0; i < lswitch->n_ports; i++) {
+        const struct nbrec_logical_port *lport = lswitch->ports[i];
+
+        printf("        lport %s\n", lport->name);
+        if (lport->parent_name && lport->n_tag) {
+            printf("            parent: %s, tag:%"PRIu64"\n",
+                   lport->parent_name, lport->tag[0]);
+        }
+        if (lport->n_macs) {
+            printf("            macs:");
+            for (size_t j = 0; j < lport->n_macs; j++) {
+                printf(" %s", lport->macs[j]);
+            }
+            printf("\n");
+        }
+    }
+}
+
+static void
+do_show(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const struct nbrec_logical_switch *lswitch;
+
+    if (ctx->argc == 2) {
+        lswitch = lswitch_by_name_or_uuid(nb_ctx, ctx->argv[1]);
+        if (lswitch) {
+            print_lswitch(lswitch);
+        }
+    } else {
+        NBREC_LOGICAL_SWITCH_FOR_EACH(lswitch, nb_ctx->idl) {
+            print_lswitch(lswitch);
+        }
+    }
+}
+
 static void
 do_lswitch_add(struct ovs_cmdl_context *ctx)
 {
@@ -264,7 +323,7 @@ do_lport_add(struct ovs_cmdl_context *ctx)
     }
 
     if (ctx->argc != 3 && ctx->argc != 5) {
-        /* If a parent_name is specififed, a tag must be specified as well. */
+        /* If a parent_name is specified, a tag must be specified as well. */
         VLOG_WARN("Invalid arguments to lport-add.");
         return;
     }
@@ -277,14 +336,44 @@ do_lport_add(struct ovs_cmdl_context *ctx)
         }
     }
 
-    /* Finally, create the transaction. */
+    /* Create the logical port. */
     lport = nbrec_logical_port_insert(nb_ctx->txn);
     nbrec_logical_port_set_name(lport, ctx->argv[2]);
-    nbrec_logical_port_set_lswitch(lport, lswitch);
     if (ctx->argc == 5) {
         nbrec_logical_port_set_parent_name(lport, ctx->argv[3]);
         nbrec_logical_port_set_tag(lport, &tag, 1);
     }
+
+    /* Insert the logical port into the logical switch. */
+    nbrec_logical_switch_verify_ports(lswitch);
+    struct nbrec_logical_port **new_ports = xmalloc(sizeof *new_ports *
+                                                    (lswitch->n_ports + 1));
+    memcpy(new_ports, lswitch->ports, sizeof *new_ports * lswitch->n_ports);
+    new_ports[lswitch->n_ports] = lport;
+    nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports + 1);
+    free(new_ports);
+}
+
+/* Removes lport 'lswitch->ports[idx]'. */
+static void
+remove_lport(const struct nbrec_logical_switch *lswitch, size_t idx)
+{
+    const struct nbrec_logical_port *lport = lswitch->ports[idx];
+
+    /* First remove 'lport' from the array of ports.  This is what will
+     * actually cause the logical port to be deleted when the transaction is
+     * sent to the database server (due to garbage collection). */
+    struct nbrec_logical_port **new_ports
+        = xmemdup(lswitch->ports, sizeof *new_ports * lswitch->n_ports);
+    new_ports[idx] = new_ports[lswitch->n_ports - 1];
+    nbrec_logical_switch_verify_ports(lswitch);
+    nbrec_logical_switch_set_ports(lswitch, new_ports, lswitch->n_ports - 1);
+    free(new_ports);
+
+    /* Delete 'lport' from the IDL.  This won't have a real effect on the
+     * database server (the IDL will suppress it in fact) but it means that it
+     * won't show up when we iterate with NBREC_LOGICAL_PORT_FOR_EACH later. */
+    nbrec_logical_port_delete(lport);
 }
 
 static void
@@ -298,44 +387,35 @@ do_lport_del(struct ovs_cmdl_context *ctx)
         return;
     }
 
-    nbrec_logical_port_delete(lport);
-}
-
-static bool
-is_lswitch(const struct nbrec_logical_switch *lswitch,
-        struct uuid *lswitch_uuid, const char *name)
-{
-    if (lswitch_uuid) {
-        return uuid_equals(lswitch_uuid, &lswitch->header_.uuid);
-    } else {
-        return !strcmp(lswitch->name, name);
+    /* Find the switch that contains 'lport', then delete it. */
+    const struct nbrec_logical_switch *lswitch;
+    NBREC_LOGICAL_SWITCH_FOR_EACH (lswitch, nb_ctx->idl) {
+        for (size_t i = 0; i < lswitch->n_ports; i++) {
+            if (lswitch->ports[i] == lport) {
+                remove_lport(lswitch, i);
+                return;
+            }
+        }
     }
-}
 
+    VLOG_WARN("logical port %s is not part of any logical switch",
+              ctx->argv[1]);
+}
 
 static void
 do_lport_list(struct ovs_cmdl_context *ctx)
 {
     struct nbctl_context *nb_ctx = ctx->pvt;
     const char *id = ctx->argv[1];
-    const struct nbrec_logical_port *lport;
-    bool is_uuid = false;
-    struct uuid lswitch_uuid;
+    const struct nbrec_logical_switch *lswitch;
 
-    if (uuid_from_string(&lswitch_uuid, id)) {
-        is_uuid = true;
+    lswitch = lswitch_by_name_or_uuid(nb_ctx, id);
+    if (!lswitch) {
+        return;
     }
 
-    NBREC_LOGICAL_PORT_FOR_EACH(lport, nb_ctx->idl) {
-        bool match;
-        if (is_uuid) {
-            match = is_lswitch(lport->lswitch, &lswitch_uuid, NULL);
-        } else {
-            match = is_lswitch(lport->lswitch, NULL, id);
-        }
-        if (!match) {
-            continue;
-        }
+    for (size_t i = 0; i < lswitch->n_ports; i++) {
+        const struct nbrec_logical_port *lport = lswitch->ports[i];
         printf(UUID_FMT " (%s)\n",
                UUID_ARGS(&lport->header_.uuid), lport->name);
     }
@@ -464,6 +544,40 @@ do_lport_get_macs(struct ovs_cmdl_context *ctx)
     }
 }
 
+static void
+do_lport_set_port_security(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    nbrec_logical_port_set_port_security(lport,
+            (const char **) ctx->argv + 2, ctx->argc - 2);
+}
+
+static void
+do_lport_get_port_security(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+    size_t i;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    for (i = 0; i < lport->n_port_security; i++) {
+        printf("%s\n", lport->port_security[i]);
+    }
+}
+
 static void
 do_lport_get_up(struct ovs_cmdl_context *ctx)
 {
@@ -478,6 +592,124 @@ do_lport_get_up(struct ovs_cmdl_context *ctx)
 
     printf("%s\n", (lport->up && *lport->up) ? "up" : "down");
 }
+
+static void
+do_lport_set_enabled(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const char *state = ctx->argv[2];
+    const struct nbrec_logical_port *lport;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    if (!strcasecmp(state, "enabled")) {
+        bool enabled = true;
+        nbrec_logical_port_set_enabled(lport, &enabled, 1);
+    } else if (!strcasecmp(state, "disabled")) {
+        bool enabled = false;
+        nbrec_logical_port_set_enabled(lport, &enabled, 1);
+    } else {
+        VLOG_ERR("Invalid state '%s' provided to lport-set-enabled", state);
+    }
+}
+
+static void
+do_lport_get_enabled(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    printf("%s\n",
+           (!lport->enabled || *lport->enabled) ? "enabled" : "disabled");
+}
+
+static void
+do_lport_set_type(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const char *type = ctx->argv[2];
+    const struct nbrec_logical_port *lport;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    nbrec_logical_port_set_type(lport, type);
+}
+
+static void
+do_lport_get_type(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    printf("%s\n", lport->type);
+}
+
+static void
+do_lport_set_options(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+    size_t i;
+    struct smap options = SMAP_INITIALIZER(&options);
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    for (i = 2; i < ctx->argc; i++) {
+        char *key, *value;
+        value = xstrdup(ctx->argv[i]);
+        key = strsep(&value, "=");
+        if (value) {
+            smap_add(&options, key, value);
+        }
+        free(key);
+    }
+
+    nbrec_logical_port_set_options(lport, &options);
+
+    smap_destroy(&options);
+}
+
+static void
+do_lport_get_options(struct ovs_cmdl_context *ctx)
+{
+    struct nbctl_context *nb_ctx = ctx->pvt;
+    const char *id = ctx->argv[1];
+    const struct nbrec_logical_port *lport;
+    struct smap_node *node;
+
+    lport = lport_by_name_or_uuid(nb_ctx, id);
+    if (!lport) {
+        return;
+    }
+
+    SMAP_FOR_EACH(node, &lport->options) {
+        printf("%s=%s\n", node->key, node->value);
+    }
+}
 \f
 static void
 parse_options(int argc, char *argv[])
@@ -537,6 +769,13 @@ parse_options(int argc, char *argv[])
 }
 
 static const struct ovs_cmdl_command all_commands[] = {
+    {
+        .name = "show",
+        .usage = "[LSWITCH]",
+        .min_args = 0,
+        .max_args = 1,
+        .handler = do_show,
+    },
     {
         .name = "lswitch-add",
         .usage = "[LSWITCH]",
@@ -636,6 +875,21 @@ static const struct ovs_cmdl_command all_commands[] = {
         .max_args = 1,
         .handler = do_lport_get_macs,
     },
+    {
+        .name = "lport-set-port-security",
+        .usage = "LPORT [ADDRS]...",
+        .min_args = 0,
+        /* Accept however many arguments the system will allow. */
+        .max_args = INT_MAX,
+        .handler = do_lport_set_port_security,
+    },
+    {
+        .name = "lport-get-port-security",
+        .usage = "LPORT",
+        .min_args = 1,
+        .max_args = 1,
+        .handler = do_lport_get_port_security,
+    },
     {
         .name = "lport-get-up",
         .usage = "LPORT",
@@ -643,6 +897,48 @@ static const struct ovs_cmdl_command all_commands[] = {
         .max_args = 1,
         .handler = do_lport_get_up,
     },
+    {
+        .name = "lport-set-enabled",
+        .usage = "LPORT STATE",
+        .min_args = 2,
+        .max_args = 2,
+        .handler = do_lport_set_enabled,
+    },
+    {
+        .name = "lport-get-enabled",
+        .usage = "LPORT",
+        .min_args = 1,
+        .max_args = 1,
+        .handler = do_lport_get_enabled,
+    },
+    {
+        .name = "lport-set-type",
+        .usage = "LPORT TYPE",
+        .min_args = 2,
+        .max_args = 2,
+        .handler = do_lport_set_type,
+    },
+    {
+        .name = "lport-get-type",
+        .usage = "LPORT",
+        .min_args = 1,
+        .max_args = 1,
+        .handler = do_lport_get_type,
+    },
+    {
+        .name = "lport-set-options",
+        .usage = "LPORT KEY=VALUE [KEY=VALUE]...",
+        .min_args = 1,
+        .max_args = INT_MAX,
+        .handler = do_lport_set_options
+    },
+    {
+        .name = "lport-get-options",
+        .usage = "LPORT",
+        .min_args = 1,
+        .max_args = 1,
+        .handler = do_lport_get_options,
+    },
 
     {
         /* sentinel */
@@ -661,7 +957,10 @@ default_db(void)
 {
     static char *def;
     if (!def) {
-        def = xasprintf("unix:%s/db.sock", ovs_rundir());
+        def = getenv("OVN_NB_DB");
+        if (!def) {
+            def = xasprintf("unix:%s/db.sock", ovs_rundir());
+        }
     }
     return def;
 }