+
+static void
+cmd_get_controller(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+
+ get_info(ctx->ovs, &info);
+
+ if (ctx->argc == 1) {
+ /* Return the controller from the "Open_vSwitch" table */
+ if (info.ctrl) {
+ ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
+ }
+ } else {
+ /* Return the controller for a particular bridge. */
+ struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
+
+ /* If no controller is explicitly defined for the requested
+ * bridge, fallback to the "Open_vSwitch" table's controller. */
+ if (br->ctrl) {
+ ds_put_format(&ctx->output, "%s\n", br->ctrl->target);
+ } else if (info.ctrl) {
+ ds_put_format(&ctx->output, "%s\n", info.ctrl->target);
+ }
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_del_controller(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+
+ get_info(ctx->ovs, &info);
+
+ if (ctx->argc == 1) {
+ if (info.ctrl) {
+ ovsrec_controller_delete(info.ctrl);
+ ovsrec_open_vswitch_set_controller(ctx->ovs, NULL);
+ }
+ } else {
+ struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+
+ if (br->ctrl) {
+ ovsrec_controller_delete(br->ctrl);
+ ovsrec_bridge_set_controller(br->br_cfg, NULL);
+ }
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_set_controller(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+ struct ovsrec_controller *ctrl;
+
+ get_info(ctx->ovs, &info);
+
+ if (ctx->argc == 2) {
+ /* Set the controller in the "Open_vSwitch" table. */
+ if (info.ctrl) {
+ ovsrec_controller_delete(info.ctrl);
+ }
+ ctrl = ovsrec_controller_insert(txn_from_openvswitch(ctx->ovs));
+ ovsrec_controller_set_target(ctrl, ctx->argv[1]);
+ ovsrec_open_vswitch_set_controller(ctx->ovs, ctrl);
+ } else {
+ /* Set the controller for a particular bridge. */
+ struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+
+ if (br->ctrl) {
+ ovsrec_controller_delete(br->ctrl);
+ }
+ ctrl = ovsrec_controller_insert(txn_from_openvswitch(ctx->ovs));
+ ovsrec_controller_set_target(ctrl, ctx->argv[2]);
+ ovsrec_bridge_set_controller(br->br_cfg, ctrl);
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_get_fail_mode(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+ const char *fail_mode = NULL;
+
+ get_info(ctx->ovs, &info);
+
+ if (ctx->argc == 1) {
+ /* Return the fail-mode from the "Open_vSwitch" table */
+ if (info.ctrl && info.ctrl->fail_mode) {
+ fail_mode = info.ctrl->fail_mode;
+ }
+ } else {
+ /* Return the fail-mode for a particular bridge. */
+ struct vsctl_bridge *br = find_bridge(&info, ctx->argv[1], true);
+
+ /* If no controller or fail-mode is explicitly defined for the
+ * requested bridge, fallback to the "Open_vSwitch" table's
+ * setting. */
+ if (br->ctrl && br->ctrl->fail_mode) {
+ fail_mode = br->ctrl->fail_mode;
+ } else if (info.ctrl && info.ctrl->fail_mode) {
+ fail_mode = info.ctrl->fail_mode;
+ }
+ }
+
+ if (fail_mode && strlen(fail_mode)) {
+ ds_put_format(&ctx->output, "%s\n", info.ctrl->fail_mode);
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_del_fail_mode(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+
+ get_info(ctx->ovs, &info);
+
+ if (ctx->argc == 1) {
+ if (info.ctrl && info.ctrl->fail_mode) {
+ ovsrec_controller_set_fail_mode(info.ctrl, NULL);
+ }
+ } else {
+ struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+
+ if (br->ctrl && br->ctrl->fail_mode) {
+ ovsrec_controller_set_fail_mode(br->ctrl, NULL);
+ }
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_set_fail_mode(struct vsctl_context *ctx)
+{
+ struct vsctl_info info;
+ const char *fail_mode;
+
+ get_info(ctx->ovs, &info);
+
+ fail_mode = (ctx->argc == 2) ? ctx->argv[1] : ctx->argv[2];
+
+ if (strcmp(fail_mode, "standalone") && strcmp(fail_mode, "secure")) {
+ vsctl_fatal("fail-mode must be \"standalone\" or \"secure\"");
+ }
+
+ if (ctx->argc == 2) {
+ /* Set the fail-mode in the "Open_vSwitch" table. */
+ if (!info.ctrl) {
+ vsctl_fatal("no controller declared");
+ }
+ ovsrec_controller_set_fail_mode(info.ctrl, fail_mode);
+ } else {
+ struct vsctl_bridge *br = find_real_bridge(&info, ctx->argv[1], true);
+
+ if (!br->ctrl) {
+ vsctl_fatal("no controller declared for %s", br->name);
+ }
+ ovsrec_controller_set_fail_mode(br->ctrl, fail_mode);
+ }
+
+ free_info(&info);
+}
+
+static void
+cmd_get_ssl(struct vsctl_context *ctx)
+{
+ struct ovsrec_ssl *ssl = ctx->ovs->ssl;
+
+ if (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
+cmd_del_ssl(struct vsctl_context *ctx)
+{
+ struct ovsrec_ssl *ssl = ctx->ovs->ssl;
+
+ if (ssl) {
+ ovsrec_ssl_delete(ssl);
+ ovsrec_open_vswitch_set_ssl(ctx->ovs, NULL);
+ }
+}
+
+static void
+cmd_set_ssl(struct vsctl_context *ctx)
+{
+ bool bootstrap = shash_find(&ctx->options, "--bootstrap");
+ struct ovsrec_ssl *ssl = ctx->ovs->ssl;
+
+ if (ssl) {
+ ovsrec_ssl_delete(ssl);
+ }
+ ssl = ovsrec_ssl_insert(txn_from_openvswitch(ctx->ovs));
+
+ ovsrec_ssl_set_private_key(ssl, ctx->argv[1]);
+ ovsrec_ssl_set_certificate(ssl, ctx->argv[2]);
+ ovsrec_ssl_set_ca_cert(ssl, ctx->argv[3]);
+
+ ovsrec_ssl_set_bootstrap_ca_cert(ssl, bootstrap);
+
+ ovsrec_open_vswitch_set_ssl(ctx->ovs, ssl);
+}