From: "Daniel P. Berrange" <berrange@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
qemu-block@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Andreas Färber" <afaerber@suse.de>
Subject: [Qemu-devel] [PATCH v3 07/10] qemu-img: allow specifying image as a set of options args
Date: Tue, 19 Jan 2016 10:37:09 +0000 [thread overview]
Message-ID: <1453199832-22523-8-git-send-email-berrange@redhat.com> (raw)
In-Reply-To: <1453199832-22523-1-git-send-email-berrange@redhat.com>
Currently qemu-img allows an image filename to be passed on the
command line, but unless using the JSON format, it does not have
a way to set any options except the format eg
qemu-img info https://127.0.0.1/images/centos7.iso
This adds a --image-opts arg that indicates that the positional
filename should be interpreted as a full option string, not
just a filename.
qemu-img info --source driver=http,url=https://127.0.0.1/images,sslverify=off
This flag is mutually exclusive with the '-f' / '-F' flags.
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
qemu-img-cmds.hx | 44 ++++----
qemu-img.c | 304 +++++++++++++++++++++++++++++++++++++++++++++++++------
qemu-img.texi | 6 ++
3 files changed, 303 insertions(+), 51 deletions(-)
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index 5bb1de7..ee5c770 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -10,68 +10,68 @@ STEXI
ETEXI
DEF("check", img_check,
- "check [-q] [--object objectdef] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
+ "check [-q] [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [-r [leaks | all]] [-T src_cache] filename")
STEXI
-@item check [--object objectdef] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
+@item check [--object objectdef] [--image-opts] [-q] [-f @var{fmt}] [--output=@var{ofmt}] [-r [leaks | all]] [-T @var{src_cache}] @var{filename}
ETEXI
DEF("create", img_create,
- "create [-q] [--object objectdef] [-f fmt] [-o options] filename [size]")
+ "create [-q] [--object objectdef] [--image-opts] [-f fmt] [-o options] filename [size]")
STEXI
-@item create [--object objectdef] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
+@item create [--object objectdef] [--image-opts] [-q] [-f @var{fmt}] [-o @var{options}] @var{filename} [@var{size}]
ETEXI
DEF("commit", img_commit,
- "commit [-q] [--object objectdef] [-f fmt] [-t cache] [-b base] [-d] [-p] filename")
+ "commit [-q] [--object objectdef] [--image-opts] [-f fmt] [-t cache] [-b base] [-d] [-p] filename")
STEXI
-@item commit [--object objectdef] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename}
+@item commit [--object objectdef] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-b @var{base}] [-d] [-p] @var{filename}
ETEXI
DEF("compare", img_compare,
- "compare [--object objectdef] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
+ "compare [--object objectdef] [--image-opts] [-f fmt] [-F fmt] [-T src_cache] [-p] [-q] [-s] filename1 filename2")
STEXI
-@item compare [--object objectdef] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
+@item compare [--object objectdef] [--image-opts] [-f @var{fmt}] [-F @var{fmt}] [-T @var{src_cache}] [-p] [-q] [-s] @var{filename1} @var{filename2}
ETEXI
DEF("convert", img_convert,
- "convert [--object objectdef] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
+ "convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f fmt] [-t cache] [-T src_cache] [-O output_fmt] [-o options] [-s snapshot_id_or_name] [-l snapshot_param] [-S sparse_size] filename [filename2 [...]] output_filename")
STEXI
-@item convert [--object objectdef] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
+@item convert [--object objectdef] [--image-opts] [-c] [-p] [-q] [-n] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-O @var{output_fmt}] [-o @var{options}] [-s @var{snapshot_id_or_name}] [-l @var{snapshot_param}] [-S @var{sparse_size}] @var{filename} [@var{filename2} [...]] @var{output_filename}
ETEXI
DEF("info", img_info,
- "info [--object objectdef] [-f fmt] [--output=ofmt] [--backing-chain] filename")
+ "info [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] [--backing-chain] filename")
STEXI
-@item info [--object objectdef] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
+@item info [--object objectdef] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] [--backing-chain] @var{filename}
ETEXI
DEF("map", img_map,
- "map [--object objectdef] [-f fmt] [--output=ofmt] filename")
+ "map [--object objectdef] [--image-opts] [-f fmt] [--output=ofmt] filename")
STEXI
-@item map [--object objectdef] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
+@item map [--object objectdef] [--image-opts] [-f @var{fmt}] [--output=@var{ofmt}] @var{filename}
ETEXI
DEF("snapshot", img_snapshot,
- "snapshot [--object objectdef] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
+ "snapshot [--object objectdef] [--image-opts] [-q] [-l | -a snapshot | -c snapshot | -d snapshot] filename")
STEXI
-@item snapshot [--object objectdef] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
+@item snapshot [--object objectdef] [--image-opts] [-q] [-l | -a @var{snapshot} | -c @var{snapshot} | -d @var{snapshot}] @var{filename}
ETEXI
DEF("rebase", img_rebase,
- "rebase [--object objectdef] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
+ "rebase [--object objectdef] [--image-opts] [-q] [-f fmt] [-t cache] [-T src_cache] [-p] [-u] -b backing_file [-F backing_fmt] filename")
STEXI
-@item rebase [--object objectdef] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
+@item rebase [--object objectdef] [--image-opts] [-q] [-f @var{fmt}] [-t @var{cache}] [-T @var{src_cache}] [-p] [-u] -b @var{backing_file} [-F @var{backing_fmt}] @var{filename}
ETEXI
DEF("resize", img_resize,
- "resize [--object objectdef] [-q] filename [+ | -]size")
+ "resize [--object objectdef] [--image-opts] [-q] filename [+ | -]size")
STEXI
-@item resize [--object objectdef] [-q] @var{filename} [+ | -]@var{size}
+@item resize [--object objectdef] [--image-opts] [-q] @var{filename} [+ | -]@var{size}
ETEXI
DEF("amend", img_amend,
- "amend [--object objectdef] [-p] [-q] [-f fmt] [-t cache] -o options filename")
+ "amend [--object objectdef] [--image-opts] [-p] [-q] [-f fmt] [-t cache] -o options filename")
STEXI
-@item amend [--object objectdef] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
+@item amend [--object objectdef] [--image-opts] [-p] [-q] [-f @var{fmt}] [-t @var{cache}] -o @var{options} @var{filename}
@end table
ETEXI
diff --git a/qemu-img.c b/qemu-img.c
index a5019e6..2c97dde 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -51,6 +51,7 @@ enum {
OPTION_OUTPUT = 256,
OPTION_BACKING_CHAIN = 257,
OPTION_OBJECT = 258,
+ OPTION_IMAGE_OPTS = 259,
};
typedef enum OutputFormat {
@@ -171,6 +172,16 @@ static QemuOptsList qemu_object_opts = {
},
};
+static QemuOptsList qemu_source_opts = {
+ .name = "source",
+ .implied_opt_name = "file",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_source_opts.head),
+ .desc = {
+ { }
+ },
+};
+
+
static int object_create(void *opaque, QemuOpts *opts, Error **errp)
{
Error *err = NULL;
@@ -232,9 +243,31 @@ static int print_block_option_help(const char *filename, const char *fmt)
return 0;
}
-static BlockBackend *img_open(const char *id, const char *filename,
- const char *fmt, int flags,
- bool require_io, bool quiet)
+static BlockBackend *img_open_opts(const char *id,
+ QemuOpts *opts, int flags)
+{
+ QDict *options;
+ Error *local_err = NULL;
+ char *file = NULL;
+ BlockBackend *blk;
+ file = g_strdup(qemu_opt_get(opts, "file"));
+ qemu_opt_unset(opts, "file");
+ options = qemu_opts_to_qdict(opts, NULL);
+ blk = blk_new_open(id, file, NULL, options, flags, &local_err);
+ if (!blk) {
+ error_report("Could not open '%s': %s", file ? file : "",
+ error_get_pretty(local_err));
+ g_free(file);
+ error_free(local_err);
+ return NULL;
+ }
+ g_free(file);
+ return blk;
+}
+
+static BlockBackend *img_open_file(const char *id, const char *filename,
+ const char *fmt, int flags,
+ bool require_io, bool quiet)
{
BlockBackend *blk;
BlockDriverState *bs;
@@ -547,6 +580,7 @@ static int img_check(int argc, char **argv)
ImageCheck *check;
bool quiet = false;
QemuOpts *opts;
+ bool image_opts = false;
fmt = NULL;
output = NULL;
@@ -559,6 +593,7 @@ static int img_check(int argc, char **argv)
{"repair", required_argument, 0, 'r'},
{"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:r:T:q",
@@ -602,6 +637,9 @@ static int img_check(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
if (optind != argc - 1) {
@@ -630,7 +668,20 @@ static int img_check(int argc, char **argv)
return 1;
}
- blk = img_open("image", filename, fmt, flags, true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and --format are mutually exclusive");
+ exit(1);
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ exit(1);
+ }
+ blk = img_open_opts("image", opts, flags);
+ } else {
+ blk = img_open_file("image", filename, fmt, flags, true, quiet);
+ }
if (!blk) {
return 1;
}
@@ -743,6 +794,7 @@ static int img_commit(int argc, char **argv)
Error *local_err = NULL;
CommonBlockJobCBInfo cbi;
QemuOpts *opts;
+ bool image_opts = false;
fmt = NULL;
cache = BDRV_DEFAULT_CACHE;
@@ -752,6 +804,7 @@ static int img_commit(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:ht:b:dpq",
@@ -791,6 +844,9 @@ static int img_commit(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -817,7 +873,20 @@ static int img_commit(int argc, char **argv)
return 1;
}
- blk = img_open("image", filename, fmt, flags, true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and --format are mutually exclusive");
+ exit(1);
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ exit(1);
+ }
+ blk = img_open_opts("image", opts, flags);
+ } else {
+ blk = img_open_file("image", filename, fmt, flags, true, quiet);
+ }
if (!blk) {
return 1;
}
@@ -1067,6 +1136,7 @@ static int img_compare(int argc, char **argv)
int c, pnum;
uint64_t progress_base;
QemuOpts *opts;
+ bool image_opts = false;
cache = BDRV_DEFAULT_CACHE;
for (;;) {
@@ -1074,6 +1144,7 @@ static int img_compare(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:F:T:pqs",
@@ -1111,6 +1182,9 @@ static int img_compare(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -1143,18 +1217,49 @@ static int img_compare(int argc, char **argv)
goto out3;
}
- blk1 = img_open("image_1", filename1, fmt1, flags, true, quiet);
- if (!blk1) {
- ret = 2;
- goto out3;
- }
- bs1 = blk_bs(blk1);
+ if (image_opts) {
+ if (fmt1 || fmt2) {
+ error_report("--image-opts and -f or -F are mutually exclusive");
+ goto out3;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename1, true);
+ if (!opts) {
+ ret = 2;
+ goto out3;
+ }
+ blk1 = img_open_opts("image_1", opts, flags);
+ if (!blk1) {
+ ret = 2;
+ goto out3;
+ }
- blk2 = img_open("image_2", filename2, fmt2, flags, true, quiet);
- if (!blk2) {
- ret = 2;
- goto out2;
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename2, true);
+ if (!opts) {
+ ret = 2;
+ goto out2;
+ }
+
+ blk2 = img_open_opts("image_2", opts, flags);
+ if (!blk2) {
+ ret = 2;
+ goto out3;
+ }
+ } else {
+ blk1 = img_open_file("image_1", filename1, fmt1, flags, true, quiet);
+ if (!blk1) {
+ ret = 2;
+ goto out3;
+ }
+
+ blk2 = img_open_file("image_2", filename2, fmt2, flags, true, quiet);
+ if (!blk2) {
+ ret = 2;
+ goto out2;
+ }
}
+ bs1 = blk_bs(blk1);
bs2 = blk_bs(blk2);
buf1 = blk_blockalign(blk1, IO_BUF_SIZE);
@@ -1642,6 +1747,7 @@ static int img_convert(int argc, char **argv)
Error *local_err = NULL;
QemuOpts *sn_opts = NULL;
ImgConvertState state;
+ bool image_opts = false;
fmt = NULL;
out_fmt = "raw";
@@ -1655,6 +1761,7 @@ static int img_convert(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:O:B:ce6o:s:l:S:pt:T:qn",
@@ -1756,6 +1863,9 @@ static int img_convert(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -1771,7 +1881,6 @@ static int img_convert(int argc, char **argv)
}
qemu_progress_init(progress, 1.0);
-
bs_n = argc - optind - 1;
out_filename = bs_n >= 1 ? argv[argc - 1] : NULL;
@@ -1809,8 +1918,23 @@ static int img_convert(int argc, char **argv)
for (bs_i = 0; bs_i < bs_n; bs_i++) {
char *id = bs_n > 1 ? g_strdup_printf("source_%d", bs_i)
: g_strdup("source");
- blk[bs_i] = img_open(id, argv[optind + bs_i], fmt, src_flags,
- true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and -f are mutually exclusive");
+ ret = -1;
+ goto out;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ argv[optind + bs_i], true);
+ if (!opts) {
+ ret = -1;
+ goto out;
+ }
+ blk[bs_i] = img_open_opts(id, opts, src_flags);
+ } else {
+ blk[bs_i] = img_open_file(id, argv[optind + bs_i], fmt, src_flags,
+ true, quiet);
+ }
g_free(id);
if (!blk[bs_i]) {
ret = -1;
@@ -1951,7 +2075,12 @@ static int img_convert(int argc, char **argv)
goto out;
}
- out_blk = img_open("target", out_filename, out_fmt, flags, true, quiet);
+ /* XXX we should allow --image-opts to trigger use of
+ * img_open_opts here, but then we have trouble with
+ * the bdrv_create() call which takes different params
+ */
+ out_blk = img_open_file("target", out_filename,
+ out_fmt, flags, true, quiet);
if (!out_blk) {
ret = -1;
goto out;
@@ -2118,7 +2247,8 @@ static gboolean str_equal_func(gconstpointer a, gconstpointer b)
* image file. If there was an error a message will have been printed to
* stderr.
*/
-static ImageInfoList *collect_image_info_list(const char *filename,
+static ImageInfoList *collect_image_info_list(bool image_opts,
+ const char *filename,
const char *fmt,
bool chain)
{
@@ -2126,6 +2256,7 @@ static ImageInfoList *collect_image_info_list(const char *filename,
ImageInfoList **last = &head;
GHashTable *filenames;
Error *err = NULL;
+ QemuOpts *opts;
filenames = g_hash_table_new_full(g_str_hash, str_equal_func, NULL, NULL);
@@ -2142,8 +2273,24 @@ static ImageInfoList *collect_image_info_list(const char *filename,
}
g_hash_table_insert(filenames, (gpointer)filename, NULL);
- blk = img_open("image", filename, fmt,
- BDRV_O_FLAGS | BDRV_O_NO_BACKING, false, false);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and -f are mutually exclusive");
+ goto err;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ goto err;
+ }
+ blk = img_open_opts("image", opts,
+ BDRV_O_FLAGS | BDRV_O_NO_BACKING);
+ opts = NULL;
+ } else {
+ blk = img_open_file("image", filename, fmt,
+ BDRV_O_FLAGS | BDRV_O_NO_BACKING,
+ false, false);
+ }
if (!blk) {
goto err;
}
@@ -2195,6 +2342,7 @@ static int img_info(int argc, char **argv)
const char *filename, *fmt, *output;
ImageInfoList *list;
QemuOpts *opts;
+ bool image_opts = false;
fmt = NULL;
output = NULL;
@@ -2206,6 +2354,7 @@ static int img_info(int argc, char **argv)
{"output", required_argument, 0, OPTION_OUTPUT},
{"backing-chain", no_argument, 0, OPTION_BACKING_CHAIN},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:h",
@@ -2234,6 +2383,9 @@ static int img_info(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
if (optind != argc - 1) {
@@ -2256,7 +2408,7 @@ static int img_info(int argc, char **argv)
exit(1);
}
- list = collect_image_info_list(filename, fmt, chain);
+ list = collect_image_info_list(image_opts, filename, fmt, chain);
if (!list) {
return 1;
}
@@ -2380,6 +2532,7 @@ static int img_map(int argc, char **argv)
MapEntry curr = { .length = 0 }, next;
int ret = 0;
QemuOpts *opts;
+ bool image_opts = false;
fmt = NULL;
output = NULL;
@@ -2390,6 +2543,7 @@ static int img_map(int argc, char **argv)
{"format", required_argument, 0, 'f'},
{"output", required_argument, 0, OPTION_OUTPUT},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:h",
@@ -2415,6 +2569,9 @@ static int img_map(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
if (optind != argc - 1) {
@@ -2437,7 +2594,20 @@ static int img_map(int argc, char **argv)
exit(1);
}
- blk = img_open("image", filename, fmt, BDRV_O_FLAGS, true, false);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and -f are mutually exclusive");
+ exit(1);
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ exit(1);
+ }
+ blk = img_open_opts("image", opts, BDRV_O_FLAGS);
+ } else {
+ blk = img_open_file("image", filename, fmt, BDRV_O_FLAGS, true, false);
+ }
if (!blk) {
return 1;
}
@@ -2503,6 +2673,7 @@ static int img_snapshot(int argc, char **argv)
bool quiet = false;
Error *err = NULL;
QemuOpts *opts;
+ bool image_opts = false;
bdrv_oflags = BDRV_O_FLAGS | BDRV_O_RDWR;
/* Parse commandline parameters */
@@ -2511,6 +2682,7 @@ static int img_snapshot(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "la:c:d:hq",
@@ -2565,6 +2737,9 @@ static int img_snapshot(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -2580,7 +2755,16 @@ static int img_snapshot(int argc, char **argv)
}
/* Open the image */
- blk = img_open("image", filename, NULL, bdrv_oflags, true, quiet);
+ if (image_opts) {
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ exit(1);
+ }
+ blk = img_open_opts("image", opts, bdrv_oflags);
+ } else {
+ blk = img_open_file("image", filename, NULL, bdrv_oflags, true, quiet);
+ }
if (!blk) {
return 1;
}
@@ -2645,6 +2829,7 @@ static int img_rebase(int argc, char **argv)
bool quiet = false;
Error *local_err = NULL;
QemuOpts *opts;
+ bool image_opts = false;
/* Parse commandline parameters */
fmt = NULL;
@@ -2657,6 +2842,7 @@ static int img_rebase(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "hf:F:b:upt:T:q",
@@ -2700,6 +2886,9 @@ static int img_rebase(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -2710,6 +2899,7 @@ static int img_rebase(int argc, char **argv)
if (optind != argc - 1) {
error_exit("Expecting one image file name");
}
+
if (!unsafe && !out_baseimg) {
error_exit("Must specify backing file (-b) or use unsafe mode (-u)");
}
@@ -2744,7 +2934,22 @@ static int img_rebase(int argc, char **argv)
* Ignore the old backing file for unsafe rebase in case we want to correct
* the reference to a renamed or moved backing file.
*/
- blk = img_open("image", filename, fmt, flags, true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and --format are mutually exclusive");
+ ret = -1;
+ goto out;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ ret = -1;
+ goto out;
+ }
+ blk = img_open_opts("image", opts, flags);
+ } else {
+ blk = img_open_file("image", filename, fmt, flags, true, quiet);
+ }
if (!blk) {
ret = -1;
goto out;
@@ -2995,6 +3200,7 @@ static int img_resize(int argc, char **argv)
}
},
};
+ bool image_opts = false;
/* Remove size from argv manually so that negative numbers are not treated
* as options by getopt. */
@@ -3012,6 +3218,7 @@ static int img_resize(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "f:hq",
@@ -3037,6 +3244,9 @@ static int img_resize(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
if (optind != argc - 1) {
@@ -3077,8 +3287,23 @@ static int img_resize(int argc, char **argv)
n = qemu_opt_get_size(param, BLOCK_OPT_SIZE, 0);
qemu_opts_del(param);
- blk = img_open("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
- true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and --format are mutually exclusive");
+ ret = -1;
+ goto out;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ ret = -1;
+ goto out;
+ }
+ blk = img_open_opts("image", opts, BDRV_O_FLAGS | BDRV_O_RDWR);
+ } else {
+ blk = img_open_file("image", filename, fmt, BDRV_O_FLAGS | BDRV_O_RDWR,
+ true, quiet);
+ }
if (!blk) {
ret = -1;
goto out;
@@ -3137,6 +3362,7 @@ static int img_amend(int argc, char **argv)
bool quiet = false, progress = false;
BlockBackend *blk = NULL;
BlockDriverState *bs = NULL;
+ bool image_opts = true;
cache = BDRV_DEFAULT_CACHE;
for (;;) {
@@ -3144,6 +3370,7 @@ static int img_amend(int argc, char **argv)
static const struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"object", required_argument, 0, OPTION_OBJECT},
+ {"image-opts", no_argument, 0, OPTION_IMAGE_OPTS},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, "ho:f:t:pq",
@@ -3190,6 +3417,9 @@ static int img_amend(int argc, char **argv)
exit(1);
}
break;
+ case OPTION_IMAGE_OPTS:
+ image_opts = true;
+ break;
}
}
@@ -3229,7 +3459,22 @@ static int img_amend(int argc, char **argv)
goto out;
}
- blk = img_open("image", filename, fmt, flags, true, quiet);
+ if (image_opts) {
+ if (fmt) {
+ error_report("--image-opts and --format are mutually exclusive");
+ ret = -1;
+ goto out;
+ }
+ opts = qemu_opts_parse_noisily(qemu_find_opts("source"),
+ filename, true);
+ if (!opts) {
+ ret = -1;
+ goto out;
+ }
+ blk = img_open_opts("image", opts, flags);
+ } else {
+ blk = img_open_file("image", filename, fmt, flags, true, quiet);
+ }
if (!blk) {
ret = -1;
goto out;
@@ -3327,6 +3572,7 @@ int main(int argc, char **argv)
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_object_opts);
+ qemu_add_opts(&qemu_source_opts);
/* find the command */
for (cmd = img_cmds; cmd->name != NULL; cmd++) {
diff --git a/qemu-img.texi b/qemu-img.texi
index da93272..f31e726 100644
--- a/qemu-img.texi
+++ b/qemu-img.texi
@@ -32,6 +32,12 @@ page for a description of the object properties. The only object type that
it makes sense to define is the @code{secret} object, which is used to
supply passwords and/or encryption keys.
+@item --image-opts
+
+Indicates that the @var{filename} parameter is to be interpreted as a
+full option string, not a plain filename. This parameter is mutually
+exclusive with the @var{-f} and @var{-F} parameters.
+
@item fmt
is the disk image format. It is guessed automatically in most cases. See below
for a description of the supported disk formats.
--
2.5.0
next prev parent reply other threads:[~2016-01-19 10:37 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-19 10:37 [Qemu-devel] [PATCH v3 00/10] Make qemu-img/qemu-nbd/qemu-io CLI more flexible Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 01/10] qom: add helpers for UserCreatable object types Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 02/10] qemu-img: add support for --object command line arg Daniel P. Berrange
2016-01-21 16:19 ` Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 03/10] qemu-nbd: " Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 04/10] qemu-io: " Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 05/10] qemu-io: allow specifying image as a set of options args Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 06/10] qemu-nbd: " Daniel P. Berrange
2016-01-19 10:37 ` Daniel P. Berrange [this message]
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 08/10] qemu-nbd: don't overlap long option values with short options Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 09/10] qemu-nbd: use no_argument/required_argument constants Daniel P. Berrange
2016-01-19 10:37 ` [Qemu-devel] [PATCH v3 10/10] qemu-io: " Daniel P. Berrange
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1453199832-22523-8-git-send-email-berrange@redhat.com \
--to=berrange@redhat.com \
--cc=afaerber@suse.de \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.