ssh: Use QAPI BlockdevOptionsSsh object

Create a BlockdevOptionsSsh object in connect_to_ssh() and take the
options from there. 'host_key_check' is still processed separately
because it's not in the schema yet.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
Reviewed-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
Kevin Wolf 2018-02-02 16:12:18 +01:00
parent 63fd65a0a5
commit 16e4bdb1bf
1 changed files with 61 additions and 74 deletions

View File

@ -35,6 +35,7 @@
#include "qemu/sockets.h" #include "qemu/sockets.h"
#include "qemu/uri.h" #include "qemu/uri.h"
#include "qapi/qapi-visit-sockets.h" #include "qapi/qapi-visit-sockets.h"
#include "qapi/qapi-visit-block-core.h"
#include "qapi/qmp/qdict.h" #include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h" #include "qapi/qmp/qstring.h"
#include "qapi/qobject-input-visitor.h" #include "qapi/qobject-input-visitor.h"
@ -543,21 +544,6 @@ static QemuOptsList ssh_runtime_opts = {
.type = QEMU_OPT_NUMBER, .type = QEMU_OPT_NUMBER,
.help = "Port to connect to", .help = "Port to connect to",
}, },
{
.name = "path",
.type = QEMU_OPT_STRING,
.help = "Path of the image on the host",
},
{
.name = "user",
.type = QEMU_OPT_STRING,
.help = "User as which to connect",
},
{
.name = "host_key_check",
.type = QEMU_OPT_STRING,
.help = "Defines how and what to check the host key against",
},
{ /* end of list */ } { /* end of list */ }
}, },
}; };
@ -582,23 +568,31 @@ static bool ssh_process_legacy_socket_options(QDict *output_opts,
return true; return true;
} }
static InetSocketAddress *ssh_config(QDict *options, Error **errp) static BlockdevOptionsSsh *ssh_parse_options(QDict *options, Error **errp)
{ {
InetSocketAddress *inet = NULL; BlockdevOptionsSsh *result = NULL;
QDict *addr = NULL; QemuOpts *opts = NULL;
QObject *crumpled_addr = NULL; Error *local_err = NULL;
Visitor *iv = NULL; QObject *crumpled;
Error *local_error = NULL; const QDictEntry *e;
Visitor *v;
qdict_extract_subqdict(options, &addr, "server."); /* Translate legacy options */
if (!qdict_size(addr)) { opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort);
error_setg(errp, "SSH server address missing"); qemu_opts_absorb_qdict(opts, options, &local_err);
goto out; if (local_err) {
error_propagate(errp, local_err);
goto fail;
} }
crumpled_addr = qdict_crumple(addr, errp); if (!ssh_process_legacy_socket_options(options, opts, errp)) {
if (!crumpled_addr) { goto fail;
goto out; }
/* Create the QAPI object */
crumpled = qdict_crumple(options, errp);
if (crumpled == NULL) {
goto fail;
} }
/* /*
@ -609,51 +603,50 @@ static InetSocketAddress *ssh_config(QDict *options, Error **errp)
* but when they come from -drive, they're all QString. The * but when they come from -drive, they're all QString. The
* visitor expects the former. * visitor expects the former.
*/ */
iv = qobject_input_visitor_new(crumpled_addr); v = qobject_input_visitor_new(crumpled);
visit_type_InetSocketAddress(iv, NULL, &inet, &local_error); visit_type_BlockdevOptionsSsh(v, NULL, &result, &local_err);
if (local_error) { visit_free(v);
error_propagate(errp, local_error); qobject_decref(crumpled);
goto out;
if (local_err) {
error_propagate(errp, local_err);
goto fail;
} }
out: /* Remove the processed options from the QDict (the visitor processes
QDECREF(addr); * _all_ options in the QDict) */
qobject_decref(crumpled_addr); while ((e = qdict_first(options))) {
visit_free(iv); qdict_del(options, e->key);
return inet; }
fail:
qemu_opts_del(opts);
return result;
} }
static int connect_to_ssh(BDRVSSHState *s, QDict *options, static int connect_to_ssh(BDRVSSHState *s, QDict *options,
int ssh_flags, int creat_mode, Error **errp) int ssh_flags, int creat_mode, Error **errp)
{ {
BlockdevOptionsSsh *opts;
int r, ret; int r, ret;
QemuOpts *opts = NULL; const char *user, *host_key_check;
Error *local_err = NULL;
const char *user, *path, *host_key_check;
long port = 0; long port = 0;
opts = qemu_opts_create(&ssh_runtime_opts, NULL, 0, &error_abort); host_key_check = qdict_get_try_str(options, "host_key_check");
qemu_opts_absorb_qdict(opts, options, &local_err); if (!host_key_check) {
if (local_err) { host_key_check = "yes";
ret = -EINVAL; } else {
error_propagate(errp, local_err); qdict_del(options, "host_key_check");
goto err;
} }
if (!ssh_process_legacy_socket_options(options, opts, errp)) { opts = ssh_parse_options(options, errp);
ret = -EINVAL; if (opts == NULL) {
goto err; return -EINVAL;
} }
path = qemu_opt_get(opts, "path"); if (opts->has_user) {
if (!path) { user = opts->user;
ret = -EINVAL; } else {
error_setg(errp, "No path was specified");
goto err;
}
user = qemu_opt_get(opts, "user");
if (!user) {
user = g_get_user_name(); user = g_get_user_name();
if (!user) { if (!user) {
error_setg_errno(errp, errno, "Can't get user name"); error_setg_errno(errp, errno, "Can't get user name");
@ -662,17 +655,9 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
} }
} }
host_key_check = qemu_opt_get(opts, "host_key_check");
if (!host_key_check) {
host_key_check = "yes";
}
/* Pop the config into our state object, Exit if invalid */ /* Pop the config into our state object, Exit if invalid */
s->inet = ssh_config(options, errp); s->inet = opts->server;
if (!s->inet) { opts->server = NULL;
ret = -EINVAL;
goto err;
}
if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) { if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) {
error_setg(errp, "Use only numeric port value"); error_setg(errp, "Use only numeric port value");
@ -729,15 +714,17 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
/* Open the remote file. */ /* Open the remote file. */
DPRINTF("opening file %s flags=0x%x creat_mode=0%o", DPRINTF("opening file %s flags=0x%x creat_mode=0%o",
path, ssh_flags, creat_mode); opts->path, ssh_flags, creat_mode);
s->sftp_handle = libssh2_sftp_open(s->sftp, path, ssh_flags, creat_mode); s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags,
creat_mode);
if (!s->sftp_handle) { if (!s->sftp_handle) {
session_error_setg(errp, s, "failed to open remote file '%s'", path); session_error_setg(errp, s, "failed to open remote file '%s'",
opts->path);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
qemu_opts_del(opts); qapi_free_BlockdevOptionsSsh(opts);
r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs);
if (r < 0) { if (r < 0) {
@ -764,7 +751,7 @@ static int connect_to_ssh(BDRVSSHState *s, QDict *options,
} }
s->session = NULL; s->session = NULL;
qemu_opts_del(opts); qapi_free_BlockdevOptionsSsh(opts);
return ret; return ret;
} }