This adds the .bdrv_co_create driver callback to rbd, which enables
image creation over QMP.
Signed-off-by: Kevin Wolf
---
qapi/block-core.json | 20 +++-
block/rbd.c | 137 +--
2 files changed, 108 insertions(+), 49 deletions(-)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 5b4cd6bd12..370fcd9584 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -3415,6 +3415,24 @@
'*refcount-bits': 'int' } }
##
+# @BlockdevCreateOptionsRbd:
+#
+# Driver specific image creation options for rbd/Ceph.
+#
+# @location Where to store the new image file
+# @size Size of the virtual disk in bytes
+# @password-secret ID of secret providing the password
+# @cluster_size RBD object size
+#
+# Since: 2.12
+##
+{ 'struct': 'BlockdevCreateOptionsRbd',
+ 'data': { 'location': 'BlockdevOptionsRbd',
+'size': 'size',
+'*password-secret': 'str',
+'*cluster-size' : 'size' } }
+
+##
# @BlockdevCreateNotSupported:
#
# This is used for all drivers that don't support creating images.
@@ -3462,7 +3480,7 @@
'qed':'BlockdevCreateNotSupported',
'quorum': 'BlockdevCreateNotSupported',
'raw':'BlockdevCreateNotSupported',
- 'rbd':'BlockdevCreateNotSupported',
+ 'rbd':'BlockdevCreateOptionsRbd',
'replication':'BlockdevCreateNotSupported',
'sheepdog': 'BlockdevCreateNotSupported',
'ssh':'BlockdevCreateNotSupported',
diff --git a/block/rbd.c b/block/rbd.c
index a76a5e8755..c164f70167 100644
--- a/block/rbd.c
+++ b/block/rbd.c
@@ -348,69 +348,46 @@ static QemuOptsList runtime_opts = {
},
};
-static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
+/* FIXME Deprecate and remove keypairs or make it available in QMP */
+static int qemu_rbd_do_create(BlockdevCreateOptions *options,
+ const char *keypairs, Error **errp)
{
-Error *local_err = NULL;
-int64_t bytes = 0;
-int64_t objsize;
-int obj_order = 0;
-const char *pool, *image_name, *conf, *user, *keypairs;
-const char *secretid;
+BlockdevCreateOptionsRbd *opts = &options->u.rbd;
rados_t cluster;
rados_ioctx_t io_ctx;
-QDict *options = NULL;
-int ret = 0;
+int obj_order = 0;
+int ret;
-secretid = qemu_opt_get(opts, "password-secret");
+assert(options->driver == BLOCKDEV_DRIVER_RBD);
+if (opts->location->has_snapshot) {
+error_setg(errp, "Can't use snapshot name for image creation");
+return -EINVAL;
+}
-/* Read out options */
-bytes = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0),
- BDRV_SECTOR_SIZE);
-objsize = qemu_opt_get_size_del(opts, BLOCK_OPT_CLUSTER_SIZE, 0);
-if (objsize) {
+if (opts->has_cluster_size) {
+int64_t objsize = opts->cluster_size;
if ((objsize - 1) & objsize) {/* not a power of 2? */
error_setg(errp, "obj size needs to be power of 2");
-ret = -EINVAL;
-goto exit;
+return -EINVAL;
}
if (objsize < 4096) {
error_setg(errp, "obj size too small");
-ret = -EINVAL;
-goto exit;
+return -EINVAL;
}
obj_order = ctz32(objsize);
}
-options = qdict_new();
-qemu_rbd_parse_filename(filename, options, &local_err);
-if (local_err) {
-ret = -EINVAL;
-error_propagate(errp, local_err);
-goto exit;
-}
-
-/*
- * Caution: while qdict_get_try_str() is fine, getting non-string
- * types would require more care. When @options come from -blockdev
- * or blockdev_add, its members are typed according to the QAPI
- * schema, but when they come from -drive, they're all QString.
- */
-pool = qdict_get_try_str(options, "pool");
-conf = qdict_get_try_str(options, "conf");
-user = qdict_get_try_str(options, "user");
-image_name = qdict_get_try_str(options, "image");
-keypairs = qdict_get_try_str(options, "=keyvalue-pairs");
-
-ret = rados_create(&cluster, user);
+ret = rados_create(&cluster, opts->location->user);
if (ret < 0) {
error_setg_errno(errp, -ret, "error initializing");
-goto exit;
+return ret;
}
/* try default location when conf=NULL, but ignore failure */
-ret = rados_conf_read_file(cluster, conf);
-if (conf && ret < 0) {
-error_setg_errno(errp, -ret, "error reading conf file %s", conf);
+ret = rados_conf_read_file(cluster, opts->location->conf);
+if (opts->location->conf && ret < 0) {
+error_setg_errno(errp, -ret, "error reading conf file %s",
+ opts->location->conf);
ret = -EIO;
goto shutdown;
}