mirror of https://github.com/xemu-project/xemu.git
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:
parent
63fd65a0a5
commit
16e4bdb1bf
135
block/ssh.c
135
block/ssh.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue