[ovs-dev] [PATCH] ovn-nb: remote connection management in nb db

Lance Richardson lrichard at redhat.com
Fri Nov 11 16:14:20 UTC 2016


Add support for managing remote connections, including
SSL configuration, to northbound db schema, and add necessary
commands to ovn-nbctl.

Signed-off-by: Lance Richardson <lrichard at redhat.com>
---
 ovn/ovn-nb.ovsschema          |  53 +++++++-
 ovn/ovn-nb.xml                | 288 ++++++++++++++++++++++++++++++++++++++++++
 ovn/utilities/ovn-nbctl.8.xml |  36 ++++++
 ovn/utilities/ovn-nbctl.c     | 208 ++++++++++++++++++++++++++++++
 tests/ovn.at                  |  52 ++++++++
 5 files changed, 632 insertions(+), 5 deletions(-)

diff --git a/ovn/ovn-nb.ovsschema b/ovn/ovn-nb.ovsschema
index 65f2d7c..39c7f99 100644
--- a/ovn/ovn-nb.ovsschema
+++ b/ovn/ovn-nb.ovsschema
@@ -1,7 +1,7 @@
 {
     "name": "OVN_Northbound",
     "version": "5.4.1",
-    "cksum": "3773248894 11490",
+    "cksum": "3485560318 13777",
     "tables": {
         "NB_Global": {
             "columns": {
@@ -10,7 +10,16 @@
                 "hv_cfg": {"type": {"key": "integer"}},
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
-                             "min": 0, "max": "unlimited"}}},
+                             "min": 0, "max": "unlimited"}},
+                "connections": {
+                    "type": {"key": {"type": "uuid",
+                                     "refTable": "Connection"},
+                                     "min": 0,
+                                     "max": "unlimited"}},
+                "ssl": {
+                    "type": {"key": {"type": "uuid",
+                                     "refTable": "SSL"},
+                                     "min": 0, "max": 1}}},
             "maxRows": 1,
             "isRoot": true},
         "Logical_Switch": {
@@ -221,6 +230,40 @@
                 "external_ids": {
                     "type": {"key": "string", "value": "string",
                              "min": 0, "max": "unlimited"}}},
-            "isRoot": true}
-    }
-}
+            "isRoot": true},
+        "Connection": {
+            "columns": {
+                "target": {"type": "string"},
+                "max_backoff": {"type": {"key": {"type": "integer",
+                                         "minInteger": 1000},
+                                         "min": 0,
+                                         "max": 1}},
+                "inactivity_probe": {"type": {"key": "integer",
+                                              "min": 0,
+                                              "max": 1}},
+                "other_config": {"type": {"key": "string",
+                                          "value": "string",
+                                          "min": 0,
+                                          "max": "unlimited"}},
+                "external_ids": {"type": {"key": "string",
+                                 "value": "string",
+                                 "min": 0,
+                                 "max": "unlimited"}},
+                "is_connected": {"type": "boolean", "ephemeral": true},
+                "status": {"type": {"key": "string",
+                                    "value": "string",
+                                    "min": 0,
+                                    "max": "unlimited"},
+                                    "ephemeral": true}},
+            "indexes": [["target"]]},
+        "SSL": {
+            "columns": {
+                "private_key": {"type": "string"},
+                "certificate": {"type": "string"},
+                "ca_cert": {"type": "string"},
+                "bootstrap_ca_cert": {"type": "boolean"},
+                "external_ids": {"type": {"key": "string",
+                                          "value": "string",
+                                          "min": 0,
+                                          "max": "unlimited"}}},
+            "maxRows": 1}}}
diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml
index 7626551..1166050 100644
--- a/ovn/ovn-nb.xml
+++ b/ovn/ovn-nb.xml
@@ -69,6 +69,17 @@
         See <em>External IDs</em> at the beginning of this document.
       </column>
     </group>
+    <group title="Connection Options">
+      <column name="connections">
+        Database clients to which the Open vSwitch database server should
+        connect or on which it should listen, along with options for how these
+        connections should be configured.  See the <ref table="Connection"/>
+        table for more information.
+      </column>
+      <column name="ssl">
+        Global SSL configuration.
+      </column>
+    </group>
   </table>
 
   <table name="Logical_Switch" title="L2 logical switch">
@@ -1477,4 +1488,281 @@
       </column>
     </group>
   </table>
+
+  <table name="Connection" title="OVSDB client connections.">
+    <p>
+      Configuration for a database connection to an Open vSwitch database
+      (OVSDB) client.
+    </p>
+
+    <p>
+      This table primarily configures the Open vSwitch database server
+      (<code>ovsdb-server</code>).
+    </p>
+
+    <p>
+      The Open vSwitch database server can initiate and maintain active
+      connections to remote clients.  It can also listen for database
+      connections.
+    </p>
+
+    <group title="Core Features">
+      <column name="target">
+        <p>Connection methods for clients.</p>
+        <p>
+          The following connection methods are currently supported:
+        </p>
+        <dl>
+          <dt><code>ssl:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            <p>
+              The specified SSL <var>port</var> on the host at the given
+              <var>ip</var>, which must be expressed as an IP address
+              (not a DNS name). A valid SSL configuration must be provided
+              when this form is used, this configuration can be specified
+              via command-line options or the <ref table="SSL"/> table.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always
+              built as part of Open vSwitch.
+            </p>
+          </dd>
+
+          <dt><code>tcp:<var>ip</var></code>[<code>:<var>port</var></code>]</dt>
+          <dd>
+            <p>
+              The specified TCP <var>port</var> on the host at the given
+              <var>ip</var>, which must be expressed as an IP address (not a
+              DNS name), where <var>ip</var> can be IPv4 or IPv6 address.  If
+              <var>ip</var> is an IPv6 address, wrap it in square brackets,
+              e.g. <code>tcp:[::1]:6640</code>.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+          </dd>
+          <dt><code>pssl:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            <p>
+              Listens for SSL connections on the specified TCP <var>port</var>.
+              Specify 0 for <var>port</var> to have the kernel automatically
+              choose an available port.  If <var>ip</var>, which must be
+              expressed as an IP address (not a DNS name), is specified, then
+              connections are restricted to the specified local IP address
+              (either IPv4 or IPv6 address).  If <var>ip</var> is an IPv6
+              address, wrap in square brackets,
+              e.g. <code>pssl:6640:[::1]</code>.  If <var>ip</var> is not
+              specified then it listens only on IPv4 (but not IPv6) addresses.
+              A valid SSL configuration must be provided when this form is used,
+             this can be specified either via command-line options or the
+             <ref table="SSL"/> table.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+            <p>
+              SSL support is an optional feature that is not always built as
+              part of Open vSwitch.
+            </p>
+          </dd>
+          <dt><code>ptcp:</code>[<var>port</var>][<code>:<var>ip</var></code>]</dt>
+          <dd>
+            <p>
+              Listens for connections on the specified TCP <var>port</var>.
+              Specify 0 for <var>port</var> to have the kernel automatically
+              choose an available port.  If <var>ip</var>, which must be
+              expressed as an IP address (not a DNS name), is specified, then
+              connections are restricted to the specified local IP address
+              (either IPv4 or IPv6 address).  If <var>ip</var> is an IPv6
+              address, wrap it in square brackets,
+              e.g. <code>ptcp:6640:[::1]</code>.  If <var>ip</var> is not
+              specified then it listens only on IPv4 addresses.
+            </p>
+            <p>
+              If <var>port</var> is not specified, it defaults to 6640.
+            </p>
+          </dd>
+        </dl>
+        <p>When multiple clients are configured, the <ref column="target"/>
+        values must be unique.  Duplicate <ref column="target"/> values yield
+        unspecified results.</p>
+      </column>
+    </group>
+
+    <group title="Client Failure Detection and Handling">
+      <column name="max_backoff">
+        Maximum number of milliseconds to wait between connection attempts.
+        Default is implementation-specific.
+      </column>
+
+      <column name="inactivity_probe">
+        Maximum number of milliseconds of idle time on connection to the client
+        before sending an inactivity probe message.  If Open vSwitch does not
+        communicate with the client for the specified number of seconds, it
+        will send a probe.  If a response is not received for the same
+        additional amount of time, Open vSwitch assumes the connection has been
+        broken and attempts to reconnect.  Default is implementation-specific.
+        A value of 0 disables inactivity probes.
+      </column>
+    </group>
+
+    <group title="Status">
+      <p>
+        Key-value pair of <ref column="is_connected"/> is always updated.
+        Other key-value pairs in the status columns may be updated depends
+        on the <ref column="target"/> type.
+      </p>
+
+      <p>
+        When <ref column="target"/> specifies a connection method that
+        listens for inbound connections (e.g. <code>ptcp:</code> or
+        <code>punix:</code>), both <ref column="n_connections"/> and
+        <ref column="is_connected"/> may also be updated while the
+        remaining key-value pairs are omitted.
+      </p>
+
+      <p>
+        On the other hand, when <ref column="target"/> specifies an
+        outbound connection, all key-value pairs may be updated, except
+        the above-mentioned two key-value pairs associated with inbound
+        connection targets. They are omitted.
+      </p>
+
+    <column name="is_connected">
+        <code>true</code> if currently connected to this client,
+        <code>false</code> otherwise.
+      </column>
+
+      <column name="status" key="last_error">
+        A human-readable description of the last error on the connection
+        to the manager; i.e. <code>strerror(errno)</code>.  This key
+        will exist only if an error has occurred.
+      </column>
+
+      <column name="status" key="state"
+              type='{"type": "string", "enum": ["set", ["VOID", "BACKOFF", "CONNECTING", "ACTIVE", "IDLE"]]}'>
+        <p>
+          The state of the connection to the manager:
+        </p>
+        <dl>
+          <dt><code>VOID</code></dt>
+          <dd>Connection is disabled.</dd>
+
+          <dt><code>BACKOFF</code></dt>
+          <dd>Attempting to reconnect at an increasing period.</dd>
+
+          <dt><code>CONNECTING</code></dt>
+          <dd>Attempting to connect.</dd>
+
+          <dt><code>ACTIVE</code></dt>
+          <dd>Connected, remote host responsive.</dd>
+
+          <dt><code>IDLE</code></dt>
+          <dd>Connection is idle.  Waiting for response to keep-alive.</dd>
+        </dl>
+        <p>
+          These values may change in the future.  They are provided only for
+          human consumption.
+        </p>
+      </column>
+
+      <column name="status" key="sec_since_connect"
+              type='{"type": "integer", "minInteger": 0}'>
+        The amount of time since this client last successfully connected
+        to the database (in seconds). Value is empty if client has never
+        successfully been connected.
+      </column>
+
+      <column name="status" key="sec_since_disconnect"
+              type='{"type": "integer", "minInteger": 0}'>
+        The amount of time since this client last disconnected from the
+        database (in seconds). Value is empty if client has never
+        disconnected.
+      </column>
+
+      <column name="status" key="locks_held">
+        Space-separated list of the names of OVSDB locks that the connection
+        holds.  Omitted if the connection does not hold any locks.
+      </column>
+
+      <column name="status" key="locks_waiting">
+        Space-separated list of the names of OVSDB locks that the connection is
+        currently waiting to acquire.  Omitted if the connection is not waiting
+        for any locks.
+      </column>
+
+      <column name="status" key="locks_lost">
+        Space-separated list of the names of OVSDB locks that the connection
+        has had stolen by another OVSDB client.  Omitted if no locks have been
+        stolen from this connection.
+      </column>
+
+      <column name="status" key="n_connections"
+              type='{"type": "integer", "minInteger": 2}'>
+        When <ref column="target"/> specifies a connection method that
+        listens for inbound connections (e.g. <code>ptcp:</code> or
+        <code>pssl:</code>) and more than one connection is actually active,
+        the value is the number of active connections.  Otherwise, this
+        key-value pair is omitted.
+      </column>
+
+      <column name="status" key="bound_port" type='{"type": "integer"}'>
+        When <ref column="target"/> is <code>ptcp:</code> or
+        <code>pssl:</code>, this is the TCP port on which the OVSDB server is
+        listening.  (This is particularly useful when <ref
+        column="target"/> specifies a port of 0, allowing the kernel to
+        choose any available port.)
+      </column>
+    </group>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+      <column name="other_config"/>
+    </group>
+  </table>
+  <table name="SSL">
+    SSL configuration for ovn-nb database access.
+
+    <column name="private_key">
+      Name of a PEM file containing the private key used as the switch's
+      identity for SSL connections to the controller.
+    </column>
+
+    <column name="certificate">
+      Name of a PEM file containing a certificate, signed by the
+      certificate authority (CA) used by the controller and manager,
+      that certifies the switch's private key, identifying a trustworthy
+      switch.
+    </column>
+
+    <column name="ca_cert">
+      Name of a PEM file containing the CA certificate used to verify
+      that the switch is connected to a trustworthy controller.
+    </column>
+
+    <column name="bootstrap_ca_cert">
+      If set to <code>true</code>, then Open vSwitch will attempt to
+      obtain the CA certificate from the controller on its first SSL
+      connection and save it to the named PEM file. If it is successful,
+      it will immediately drop the connection and reconnect, and from then
+      on all SSL connections must be authenticated by a certificate signed
+      by the CA certificate thus obtained.  <em>This option exposes the
+      SSL connection to a man-in-the-middle attack obtaining the initial
+      CA certificate.</em>  It may still be useful for bootstrapping.
+    </column>
+
+    <group title="Common Columns">
+      The overall purpose of these columns is described under <code>Common
+      Columns</code> at the beginning of this document.
+
+      <column name="external_ids"/>
+    </group>
+  </table>
+
 </database>
diff --git a/ovn/utilities/ovn-nbctl.8.xml b/ovn/utilities/ovn-nbctl.8.xml
index 5b702fc..70de2db 100644
--- a/ovn/utilities/ovn-nbctl.8.xml
+++ b/ovn/utilities/ovn-nbctl.8.xml
@@ -654,6 +654,42 @@
       </dd>
     </dl>
 
+    <h1>Remote Connectivity Commands</h1>
+    <dl>
+      <dt><code>get-connection</code></dt>
+      <dd>
+      Prints the configured connection(s).
+      </dd>
+
+      <dt><code>del-connection</code></dt>
+      <dd>
+      Deletes the configured connection(s).
+      </dd>
+
+      <dt><code>set-connection</code> <var>target</var>...</dt>
+      <dd>
+      Sets the configured manager target or targets.
+      </dd>
+    </dl>
+
+    <h1>SSL Configuration Commands</h1>
+    <dl>
+      <dt><code>get-ssl</code></dt>
+      <dd>
+      Prints the SSL configuration.
+      </dd>
+
+      <dt><code>del-ssl</code></dt>
+      <dd>
+      Deletes the current SSL configuration.
+      </dd>
+
+      <dt>[<code>--bootstrap</code>] <code>set-ssl</code> <var>private-key</var> <var>certificate</var> <var>ca-cert</var></dt>
+      <dd>
+      Sets the SSL configuration.
+      </dd>
+    </dl>
+
     <h1>Options</h1>
 
     <dl>
diff --git a/ovn/utilities/ovn-nbctl.c b/ovn/utilities/ovn-nbctl.c
index 477ff76..d63573f 100644
--- a/ovn/utilities/ovn-nbctl.c
+++ b/ovn/utilities/ovn-nbctl.c
@@ -410,6 +410,16 @@ DHCP Options commands:\n\
   dhcp-options-get-options DHCO_OPTIONS_UUID \n\
                            displays the DHCP options for DHCP_OPTIONS_UUID\n\
 \n\
+Connection commands:\n\
+  get-connection             print the connections\n\
+  del-connection             delete the connections\n\
+  set-connection TARGET...   set the list of connections to TARGET...\n\
+\n\
+SSL commands:\n\
+  get-ssl                     print the SSL configuration\n\
+  del-ssl                     delete the SSL configuration\n\
+  set-ssl PRIV-KEY CERT CA-CERT  set the SSL configuration\n\
+\n\
 %s\
 \n\
 Synchronization command (use with --wait=sb|hv):\n\
@@ -2603,6 +2613,185 @@ nbctl_lr_route_list(struct ctl_context *ctx)
     free(ipv6_routes);
 }
 
+static void
+verify_connections(struct ctl_context *ctx)
+{
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    const struct nbrec_connection *conn;
+
+    nbrec_nb_global_verify_connections(nb_global);
+
+    NBREC_CONNECTION_FOR_EACH(conn, ctx->idl) {
+        nbrec_connection_verify_target(conn);
+    }
+}
+
+static void
+pre_connection(struct ctl_context *ctx)
+{
+    ovsdb_idl_add_column(ctx->idl, &nbrec_nb_global_col_connections);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_connection_col_target);
+}
+
+static void
+cmd_get_connection(struct ctl_context *ctx)
+{
+    const struct nbrec_connection *conn;
+    struct svec targets;
+    size_t i;
+
+    verify_connections(ctx);
+
+    /* Print the targets in sorted order for reproducibility. */
+    svec_init(&targets);
+
+    NBREC_CONNECTION_FOR_EACH(conn, ctx->idl) {
+        svec_add(&targets, conn->target);
+    }
+
+    svec_sort_unique(&targets);
+    for (i = 0; i < targets.n; i++) {
+        ds_put_format(&ctx->output, "%s\n", targets.names[i]);
+    }
+    svec_destroy(&targets);
+}
+
+static void
+delete_connections(struct ctl_context *ctx)
+{
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    const struct nbrec_connection *conn, *next;
+
+    /* Delete Manager rows pointed to by 'connection_options' column. */
+    NBREC_CONNECTION_FOR_EACH_SAFE(conn, next, ctx->idl) {
+        nbrec_connection_delete(conn);
+    }
+
+    /* Delete 'Manager' row refs in 'manager_options' column. */
+    nbrec_nb_global_set_connections(nb_global, NULL, 0);
+}
+
+static void
+cmd_del_connection(struct ctl_context *ctx)
+{
+    verify_connections(ctx);
+    delete_connections(ctx);
+}
+
+static void
+insert_connections(struct ctl_context *ctx, char *targets[], size_t n)
+{
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    struct nbrec_connection **connections;
+    size_t i, conns=0;
+
+    /* Insert each connection in a new row in Connection table. */
+    connections = xmalloc(n * sizeof *connections);
+    for (i = 0; i < n; i++) {
+        if (stream_verify_name(targets[i]) &&
+                   pstream_verify_name(targets[i])) {
+            VLOG_WARN("target type \"%s\" is possibly erroneous", targets[i]);
+        }
+
+        connections[conns] = nbrec_connection_insert(ctx->txn);
+        nbrec_connection_set_target(connections[conns], targets[i]);
+        conns++;
+    }
+
+    /* Store uuids of new connection rows in 'connection' column. */
+    nbrec_nb_global_set_connections(nb_global, connections, conns);
+    free(connections);
+}
+
+static void
+cmd_set_connection(struct ctl_context *ctx)
+{
+    const size_t n = ctx->argc - 1;
+
+    verify_connections(ctx);
+    delete_connections(ctx);
+    insert_connections(ctx, &ctx->argv[1], n);
+}
+
+static void
+pre_cmd_get_ssl(struct ctl_context *ctx)
+{
+    ovsdb_idl_add_column(ctx->idl, &nbrec_nb_global_col_ssl);
+
+    ovsdb_idl_add_column(ctx->idl, &nbrec_ssl_col_private_key);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_ssl_col_certificate);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_ssl_col_ca_cert);
+    ovsdb_idl_add_column(ctx->idl, &nbrec_ssl_col_bootstrap_ca_cert);
+}
+
+static void
+cmd_get_ssl(struct ctl_context *ctx)
+{
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    const struct nbrec_ssl *ssl = nbrec_ssl_first(ctx->idl);
+
+    nbrec_nb_global_verify_ssl(nb_global);
+    if (ssl) {
+        nbrec_ssl_verify_private_key(ssl);
+        nbrec_ssl_verify_certificate(ssl);
+        nbrec_ssl_verify_ca_cert(ssl);
+        nbrec_ssl_verify_bootstrap_ca_cert(ssl);
+
+        ds_put_format(&ctx->output, "Private key: %s\n", ssl->private_key);
+        ds_put_format(&ctx->output, "Certificate: %s\n", ssl->certificate);
+        ds_put_format(&ctx->output, "CA Certificate: %s\n", ssl->ca_cert);
+        ds_put_format(&ctx->output, "Bootstrap: %s\n",
+                ssl->bootstrap_ca_cert ? "true" : "false");
+    }
+}
+
+static void
+pre_cmd_del_ssl(struct ctl_context *ctx)
+{
+    ovsdb_idl_add_column(ctx->idl, &nbrec_nb_global_col_ssl);
+}
+
+static void
+cmd_del_ssl(struct ctl_context *ctx)
+{
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    const struct nbrec_ssl *ssl = nbrec_ssl_first(ctx->idl);
+
+    if (ssl) {
+        nbrec_nb_global_verify_ssl(nb_global);
+        nbrec_ssl_delete(ssl);
+        nbrec_nb_global_set_ssl(nb_global, NULL);
+    }
+}
+
+static void
+pre_cmd_set_ssl(struct ctl_context *ctx)
+{
+    ovsdb_idl_add_column(ctx->idl, &nbrec_nb_global_col_ssl);
+}
+
+static void
+cmd_set_ssl(struct ctl_context *ctx)
+{
+    bool bootstrap = shash_find(&ctx->options, "--bootstrap");
+    const struct nbrec_nb_global *nb_global = nbrec_nb_global_first(ctx->idl);
+    const struct nbrec_ssl *ssl = nbrec_ssl_first(ctx->idl);
+
+    nbrec_nb_global_verify_ssl(nb_global);
+    if (ssl) {
+        nbrec_ssl_delete(ssl);
+    }
+    ssl = nbrec_ssl_insert(ctx->txn);
+
+    nbrec_ssl_set_private_key(ssl, ctx->argv[1]);
+    nbrec_ssl_set_certificate(ssl, ctx->argv[2]);
+    nbrec_ssl_set_ca_cert(ssl, ctx->argv[3]);
+
+    nbrec_ssl_set_bootstrap_ca_cert(ssl, bootstrap);
+
+    nbrec_nb_global_set_ssl(nb_global, ssl);
+}
+
 static const struct ctl_table_class tables[] = {
     {&nbrec_table_nb_global,
      {{&nbrec_table_nb_global, NULL, NULL},
@@ -2658,6 +2847,13 @@ static const struct ctl_table_class tables[] = {
        NULL},
       {NULL, NULL, NULL}}},
 
+    {&nbrec_table_connection,
+     {{&nbrec_table_connection, NULL, NULL},
+      {NULL, NULL, NULL}}},
+
+    {&nbrec_table_ssl,
+     {{&nbrec_table_nb_global, NULL, &nbrec_nb_global_col_ssl}}},
+
     {NULL, {{NULL, NULL, NULL}, {NULL, NULL, NULL}}}
 };
 
@@ -3005,6 +3201,18 @@ static const struct ctl_command_syntax nbctl_commands[] = {
     {"dhcp-options-get-options", 1, 1, "DHCP_OPT_UUID", NULL,
      nbctl_dhcp_options_get_options, NULL, "", RO },
 
+    /* Connection commands. */
+    {"get-connection", 0, 0, "", pre_connection, cmd_get_connection, NULL, "", RO},
+    {"del-connection", 0, 0, "", pre_connection, cmd_del_connection, NULL, "", RW},
+    {"set-connection", 1, INT_MAX, "TARGET...", pre_connection, cmd_set_connection,
+     NULL, "", RW},
+
+    /* SSL commands. */
+    {"get-ssl", 0, 0, "", pre_cmd_get_ssl, cmd_get_ssl, NULL, "", RO},
+    {"del-ssl", 0, 0, "", pre_cmd_del_ssl, cmd_del_ssl, NULL, "", RW},
+    {"set-ssl", 3, 3, "PRIVATE-KEY CERTIFICATE CA-CERT", pre_cmd_set_ssl,
+     cmd_set_ssl, NULL, "--bootstrap", RW},
+
     {NULL, 0, 0, NULL, NULL, NULL, NULL, "", RO},
 };
 
diff --git a/tests/ovn.at b/tests/ovn.at
index 39d2af8..9e3c47d 100644
--- a/tests/ovn.at
+++ b/tests/ovn.at
@@ -5607,6 +5607,58 @@ AT_CHECK([ovn-sbctl --db=ssl:127.0.0.1:$TCP_PORT \
 OVS_APP_EXIT_AND_WAIT([ovsdb-server])
 AT_CLEANUP
 
+AT_SETUP([ovn -- nb connection/ssl commands])
+AT_SKIP_IF([test $HAVE_PYTHON = no])
+AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
+PKIDIR="$(cd $abs_top_builddir/tests && pwd)"
+AT_SKIP_IF([expr "$PKIDIR" : ".*[ 	'\"
+\\]"])
+
+: > .$1.db.~lock~
+ovsdb-tool create ovn-nb.db "$abs_top_srcdir"/ovn/ovn-nb.ovsschema
+
+# Start nb db server using db connection/ssl entries (unpopulated initially)
+start_daemon ovsdb-server --remote=punix:ovnnb_db.sock \
+                          --remote=db:OVN_Northbound,NB_Global,connections \
+                          --private-key=db:OVN_Northbound,SSL,private_key \
+                          --certificate=db:OVN_Northbound,SSL,certificate \
+                          --ca-cert=db:OVN_Northbound,SSL,ca_cert \
+                          ovn-nb.db
+
+# Populate SSL configuration entries in nb db
+AT_CHECK(
+    [ovn-nbctl set-ssl $PKIDIR/testpki-privkey.pem \
+                       $PKIDIR/testpki-cert.pem \
+                       $PKIDIR/testpki-cacert.pem], [0], [stdout], [ignore])
+
+# Populate a passive SSL connection in nb db
+AT_CHECK([ovn-nbctl set-connection pssl:0:127.0.0.1], [0], [stdout], [ignore])
+
+PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT])
+
+# Verify SSL connetivity to nb db server
+AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
+                    --private-key=$PKIDIR/testpki-privkey.pem \
+                    --certificate=$PKIDIR/testpki-cert.pem \
+                    --ca-cert=$PKIDIR/testpki-cacert.pem \
+          list NB_Global],
+         [0], [stdout], [ignore])
+AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
+                    --private-key=$PKIDIR/testpki-privkey.pem \
+                    --certificate=$PKIDIR/testpki-cert.pem \
+                    --ca-cert=$PKIDIR/testpki-cacert.pem \
+          list Connection],
+         [0], [stdout], [ignore])
+AT_CHECK([ovn-nbctl --db=ssl:127.0.0.1:$TCP_PORT \
+                    --private-key=$PKIDIR/testpki-privkey.pem \
+                    --certificate=$PKIDIR/testpki-cert.pem \
+                    --ca-cert=$PKIDIR/testpki-cacert.pem \
+          get-connection],
+         [0], [stdout], [ignore])
+
+OVS_APP_EXIT_AND_WAIT([ovsdb-server])
+AT_CLEANUP
+
 AT_SETUP([ovn -- nested containers])
 ovn_start
 
-- 
2.5.5



More information about the dev mailing list