-----BEGIN PGP SIGNATURE-----
iQIcBAABAgAGBQJY3wERAAoJEL2+eyfA3jBXw0cP+wUG0ygMCepHtAb1R2JOzFal PG9k3bxEO0bPiHxKu8N1Iph5Mi3+d3KX7nXv0cipgboUn2wMk064Giz39XjvN9ZH CF54wXua76bCTbAD7ZGOrZMx2WzexAwNoskknxaWKI65fGXHzZTlSdn0/S/mUgvx 5PmxQeD/1qJ2IvBqymk/zIf8uR6t8iJKawchY0seXBYNZZqhC/6OzGL0sCOx2BiD b0KIrRCb8nwqNQcxTylldxMDvKS2C2vy8upuiuY4Onp76TXglaMNOLt/dGLGIMVd Ux7tiIQM+Sq6WZDrUqOZwULAY7sujJXCTGxDc8jCfb7LooK8PP5MszSotvabkH9T drPLfi4WBCiohdkpmVAAp325nIUvnLBDRkdsSxkyDMVQ3RXUchIUK6Ta6n1U15fr L8Ls/jUQankf/1NBJ5yIkTCT0L73jb2vjtdQJlZHV9hHCspTDNosrHU6O5I03BGE 4BMtDp3emrITxSOjpNz6XRxNiIq2x69R0wiAJbh8ZtEFCTI5K6Sr3JOPaWv7swYe mblYePVKcohQlHmKouiV0I8Cyuz+lLIYBO2Lp3wu1AOL1WwmpfmHkCOB/OzGkzhW UUnpWo6SXt8pbVSrzWqfg2RC1p/KASSAqo1ZQMFi9jaqksiu+UdOE32uWjQgBOr0 BMKD5LzQdm0WU0/Bjh6X =4Xoj -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging # gpg: Signature made Sat 01 Apr 2017 02:23:29 BST # gpg: using RSA key 0xBDBE7B27C0DE3057 # gpg: Good signature from "Jeffrey Cody <jcody@redhat.com>" # gpg: aka "Jeffrey Cody <jeff@codyprime.org>" # gpg: aka "Jeffrey Cody <codyprime@gmail.com>" # Primary key fingerprint: 9957 4B4D 3474 90E7 9D98 D624 BDBE 7B27 C0DE 3057 * remotes/cody/tags/block-pull-request: block/curl: Check protocol prefix qapi/curl: Extend and fix blockdev-add schema rbd: Fix regression in legacy key/values containing escaped : Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
6954cdc070
10
block/curl.c
10
block/curl.c
@ -659,6 +659,7 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
const char *cookie;
|
||||
double d;
|
||||
const char *secretid;
|
||||
const char *protocol_delimiter;
|
||||
|
||||
static int inited = 0;
|
||||
|
||||
@ -700,6 +701,15 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
goto out_noclean;
|
||||
}
|
||||
|
||||
if (!strstart(file, bs->drv->protocol_name, &protocol_delimiter) ||
|
||||
!strstart(protocol_delimiter, "://", NULL))
|
||||
{
|
||||
error_setg(errp, "%s curl driver cannot handle the URL '%s' (does not "
|
||||
"start with '%s://')", bs->drv->protocol_name, file,
|
||||
bs->drv->protocol_name);
|
||||
goto out_noclean;
|
||||
}
|
||||
|
||||
s->username = g_strdup(qemu_opt_get(opts, CURL_BLOCK_OPT_USERNAME));
|
||||
secretid = qemu_opt_get(opts, CURL_BLOCK_OPT_PASSWORD_SECRET);
|
||||
|
||||
|
83
block/rbd.c
83
block/rbd.c
@ -20,6 +20,7 @@
|
||||
#include "crypto/secret.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
|
||||
/*
|
||||
* When specifying the image filename use:
|
||||
@ -135,18 +136,16 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
|
||||
Error **errp)
|
||||
{
|
||||
const char *start;
|
||||
char *p, *buf, *keypairs;
|
||||
char *p, *buf;
|
||||
QList *keypairs = NULL;
|
||||
char *found_str;
|
||||
size_t max_keypair_size;
|
||||
|
||||
if (!strstart(filename, "rbd:", &start)) {
|
||||
error_setg(errp, "File name must start with 'rbd:'");
|
||||
return;
|
||||
}
|
||||
|
||||
max_keypair_size = strlen(start) + 1;
|
||||
buf = g_strdup(start);
|
||||
keypairs = g_malloc0(max_keypair_size);
|
||||
p = buf;
|
||||
|
||||
found_str = qemu_rbd_next_tok(p, '/', &p);
|
||||
@ -194,33 +193,30 @@ static void qemu_rbd_parse_filename(const char *filename, QDict *options,
|
||||
} else if (!strcmp(name, "id")) {
|
||||
qdict_put(options, "user" , qstring_from_str(value));
|
||||
} else {
|
||||
/* FIXME: This is pretty ugly, and not the right way to do this.
|
||||
* These should be contained in a structure, and then
|
||||
* passed explicitly as individual key/value pairs to
|
||||
* rados. Consider this legacy code that needs to be
|
||||
* updated. */
|
||||
char *tmp = g_malloc0(max_keypair_size);
|
||||
/* only use a delimiter if it is not the first keypair found */
|
||||
/* These are sets of unknown key/value pairs we'll pass along
|
||||
* to ceph */
|
||||
if (keypairs[0]) {
|
||||
snprintf(tmp, max_keypair_size, ":%s=%s", name, value);
|
||||
pstrcat(keypairs, max_keypair_size, tmp);
|
||||
} else {
|
||||
snprintf(keypairs, max_keypair_size, "%s=%s", name, value);
|
||||
/*
|
||||
* We pass these internally to qemu_rbd_set_keypairs(), so
|
||||
* we can get away with the simpler list of [ "key1",
|
||||
* "value1", "key2", "value2" ] rather than a raw dict
|
||||
* { "key1": "value1", "key2": "value2" } where we can't
|
||||
* guarantee order, or even a more correct but complex
|
||||
* [ { "key1": "value1" }, { "key2": "value2" } ]
|
||||
*/
|
||||
if (!keypairs) {
|
||||
keypairs = qlist_new();
|
||||
}
|
||||
g_free(tmp);
|
||||
qlist_append(keypairs, qstring_from_str(name));
|
||||
qlist_append(keypairs, qstring_from_str(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (keypairs[0]) {
|
||||
qdict_put(options, "=keyvalue-pairs", qstring_from_str(keypairs));
|
||||
if (keypairs) {
|
||||
qdict_put(options, "=keyvalue-pairs",
|
||||
qobject_to_json(QOBJECT(keypairs)));
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
g_free(buf);
|
||||
g_free(keypairs);
|
||||
QDECREF(keypairs);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -244,36 +240,41 @@ static int qemu_rbd_set_auth(rados_t cluster, const char *secretid,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs,
|
||||
static int qemu_rbd_set_keypairs(rados_t cluster, const char *keypairs_json,
|
||||
Error **errp)
|
||||
{
|
||||
char *p, *buf;
|
||||
char *name;
|
||||
char *value;
|
||||
QList *keypairs;
|
||||
QString *name;
|
||||
QString *value;
|
||||
const char *key;
|
||||
size_t remaining;
|
||||
int ret = 0;
|
||||
|
||||
buf = g_strdup(keypairs);
|
||||
p = buf;
|
||||
if (!keypairs_json) {
|
||||
return ret;
|
||||
}
|
||||
keypairs = qobject_to_qlist(qobject_from_json(keypairs_json,
|
||||
&error_abort));
|
||||
remaining = qlist_size(keypairs) / 2;
|
||||
assert(remaining);
|
||||
|
||||
while (p) {
|
||||
name = qemu_rbd_next_tok(p, '=', &p);
|
||||
if (!p) {
|
||||
error_setg(errp, "conf option %s has no value", name);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
while (remaining--) {
|
||||
name = qobject_to_qstring(qlist_pop(keypairs));
|
||||
value = qobject_to_qstring(qlist_pop(keypairs));
|
||||
assert(name && value);
|
||||
key = qstring_get_str(name);
|
||||
|
||||
value = qemu_rbd_next_tok(p, ':', &p);
|
||||
|
||||
ret = rados_conf_set(cluster, name, value);
|
||||
ret = rados_conf_set(cluster, key, qstring_get_str(value));
|
||||
QDECREF(name);
|
||||
QDECREF(value);
|
||||
if (ret < 0) {
|
||||
error_setg_errno(errp, -ret, "invalid conf option %s", name);
|
||||
error_setg_errno(errp, -ret, "invalid conf option %s", key);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(buf);
|
||||
QDECREF(keypairs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2737,16 +2737,101 @@
|
||||
'*debug': 'int' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsCurl:
|
||||
# @BlockdevOptionsCurlBase:
|
||||
#
|
||||
# Driver specific block device options for the curl backend.
|
||||
# Driver specific block device options shared by all protocols supported by the
|
||||
# curl backend.
|
||||
#
|
||||
# @filename: path to the image file
|
||||
# @url: URL of the image file
|
||||
#
|
||||
# @readahead: Size of the read-ahead cache; must be a multiple of
|
||||
# 512 (defaults to 256 kB)
|
||||
#
|
||||
# @timeout: Timeout for connections, in seconds (defaults to 5)
|
||||
#
|
||||
# @username: Username for authentication (defaults to none)
|
||||
#
|
||||
# @password-secret: ID of a QCryptoSecret object providing a password
|
||||
# for authentication (defaults to no password)
|
||||
#
|
||||
# @proxy-username: Username for proxy authentication (defaults to none)
|
||||
#
|
||||
# @proxy-password-secret: ID of a QCryptoSecret object providing a password
|
||||
# for proxy authentication (defaults to no password)
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsCurl',
|
||||
'data': { 'filename': 'str' } }
|
||||
{ 'struct': 'BlockdevOptionsCurlBase',
|
||||
'data': { 'url': 'str',
|
||||
'*readahead': 'int',
|
||||
'*timeout': 'int',
|
||||
'*username': 'str',
|
||||
'*password-secret': 'str',
|
||||
'*proxy-username': 'str',
|
||||
'*proxy-password-secret': 'str' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsCurlHttp:
|
||||
#
|
||||
# Driver specific block device options for HTTP connections over the curl
|
||||
# backend. URLs must start with "http://".
|
||||
#
|
||||
# @cookie: List of cookies to set; format is
|
||||
# "name1=content1; name2=content2;" as explained by
|
||||
# CURLOPT_COOKIE(3). Defaults to no cookies.
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsCurlHttp',
|
||||
'base': 'BlockdevOptionsCurlBase',
|
||||
'data': { '*cookie': 'str' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsCurlHttps:
|
||||
#
|
||||
# Driver specific block device options for HTTPS connections over the curl
|
||||
# backend. URLs must start with "https://".
|
||||
#
|
||||
# @cookie: List of cookies to set; format is
|
||||
# "name1=content1; name2=content2;" as explained by
|
||||
# CURLOPT_COOKIE(3). Defaults to no cookies.
|
||||
#
|
||||
# @sslverify: Whether to verify the SSL certificate's validity (defaults to
|
||||
# true)
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsCurlHttps',
|
||||
'base': 'BlockdevOptionsCurlBase',
|
||||
'data': { '*cookie': 'str',
|
||||
'*sslverify': 'bool' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsCurlFtp:
|
||||
#
|
||||
# Driver specific block device options for FTP connections over the curl
|
||||
# backend. URLs must start with "ftp://".
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsCurlFtp',
|
||||
'base': 'BlockdevOptionsCurlBase',
|
||||
'data': { } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsCurlFtps:
|
||||
#
|
||||
# Driver specific block device options for FTPS connections over the curl
|
||||
# backend. URLs must start with "ftps://".
|
||||
#
|
||||
# @sslverify: Whether to verify the SSL certificate's validity (defaults to
|
||||
# true)
|
||||
#
|
||||
# Since: 2.9
|
||||
##
|
||||
{ 'struct': 'BlockdevOptionsCurlFtps',
|
||||
'base': 'BlockdevOptionsCurlBase',
|
||||
'data': { '*sslverify': 'bool' } }
|
||||
|
||||
##
|
||||
# @BlockdevOptionsNbd:
|
||||
@ -2815,13 +2900,13 @@
|
||||
'cloop': 'BlockdevOptionsGenericFormat',
|
||||
'dmg': 'BlockdevOptionsGenericFormat',
|
||||
'file': 'BlockdevOptionsFile',
|
||||
'ftp': 'BlockdevOptionsCurl',
|
||||
'ftps': 'BlockdevOptionsCurl',
|
||||
'ftp': 'BlockdevOptionsCurlFtp',
|
||||
'ftps': 'BlockdevOptionsCurlFtps',
|
||||
'gluster': 'BlockdevOptionsGluster',
|
||||
'host_cdrom': 'BlockdevOptionsFile',
|
||||
'host_device':'BlockdevOptionsFile',
|
||||
'http': 'BlockdevOptionsCurl',
|
||||
'https': 'BlockdevOptionsCurl',
|
||||
'http': 'BlockdevOptionsCurlHttp',
|
||||
'https': 'BlockdevOptionsCurlHttps',
|
||||
'iscsi': 'BlockdevOptionsIscsi',
|
||||
'luks': 'BlockdevOptionsLUKS',
|
||||
'nbd': 'BlockdevOptionsNbd',
|
||||
|
Loading…
Reference in New Issue
Block a user