rbd.c (464444fcc161284ac0e743b99251debc297d5236) rbd.c (2836284db603775af557e969d5a800efb0190324)
1/*
2 * QEMU Block driver for RADOS (Ceph)
3 *
4 * Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>,
5 * Josh Durgin <josh.durgin@dreamhost.com>
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2. See
8 * the COPYING file in the top-level directory.
9 *
10 * Contributions after 2012-01-13 are licensed under the terms of the
11 * GNU GPL, version 2 or (at your option) any later version.
12 */
13
14#include "qemu/osdep.h"
15
1/*
2 * QEMU Block driver for RADOS (Ceph)
3 *
4 * Copyright (C) 2010-2011 Christian Brunner <chb@muc.de>,
5 * Josh Durgin <josh.durgin@dreamhost.com>
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2. See
8 * the COPYING file in the top-level directory.
9 *
10 * Contributions after 2012-01-13 are licensed under the terms of the
11 * GNU GPL, version 2 or (at your option) any later version.
12 */
13
14#include "qemu/osdep.h"
15
16#include <rbd/librbd.h>
16#include "qapi/error.h"
17#include "qemu/error-report.h"
18#include "block/block_int.h"
19#include "crypto/secret.h"
20#include "qemu/cutils.h"
21#include "qapi/qmp/qstring.h"
22
17#include "qapi/error.h"
18#include "qemu/error-report.h"
19#include "block/block_int.h"
20#include "crypto/secret.h"
21#include "qemu/cutils.h"
22#include "qapi/qmp/qstring.h"
23
23#include <rbd/librbd.h>
24
25/*
26 * When specifying the image filename use:
27 *
28 * rbd:poolname/devicename[@snapshotname][:option1=value1[:option2=value2...]]
29 *
30 * poolname must be the name of an existing rados pool.
31 *
32 * devicename is the name of the rbd image.

--- 282 unchanged lines hidden (view full) ---

315 },
316 {
317 /* maps to 'id' in rados_create() */
318 .name = "user",
319 .type = QEMU_OPT_STRING,
320 .help = "Rados id name",
321 },
322 /*
24/*
25 * When specifying the image filename use:
26 *
27 * rbd:poolname/devicename[@snapshotname][:option1=value1[:option2=value2...]]
28 *
29 * poolname must be the name of an existing rados pool.
30 *
31 * devicename is the name of the rbd image.

--- 282 unchanged lines hidden (view full) ---

314 },
315 {
316 /* maps to 'id' in rados_create() */
317 .name = "user",
318 .type = QEMU_OPT_STRING,
319 .help = "Rados id name",
320 },
321 /*
323 * server.* extracted manually, see qemu_rbd_array_opts()
322 * server.* extracted manually, see qemu_rbd_mon_host()
324 */
325 {
326 .name = "password-secret",
327 .type = QEMU_OPT_STRING,
328 .help = "ID of secret providing the password",
329 },
330
331 /*
332 * Keys for qemu_rbd_parse_filename(), not in the QAPI schema
333 */
334 {
335 /*
336 * HACK: name starts with '=' so that qemu_opts_parse()
337 * can't set it
338 */
339 .name = "=keyvalue-pairs",
340 .type = QEMU_OPT_STRING,
341 .help = "Legacy rados key/value option parameters",
342 },
323 */
324 {
325 .name = "password-secret",
326 .type = QEMU_OPT_STRING,
327 .help = "ID of secret providing the password",
328 },
329
330 /*
331 * Keys for qemu_rbd_parse_filename(), not in the QAPI schema
332 */
333 {
334 /*
335 * HACK: name starts with '=' so that qemu_opts_parse()
336 * can't set it
337 */
338 .name = "=keyvalue-pairs",
339 .type = QEMU_OPT_STRING,
340 .help = "Legacy rados key/value option parameters",
341 },
343
344 /*
345 * The remainder aren't option keys, but option sub-sub-keys,
346 * so that qemu_rbd_array_opts() can abuse runtime_opts for
347 * its own purposes
348 * TODO clean this up
349 */
350 {
351 .name = "host",
352 .type = QEMU_OPT_STRING,
353 },
354 {
355 .name = "port",
356 .type = QEMU_OPT_STRING,
357 },
358 { /* end of list */ }
359 },
360};
361
362static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
363{
364 Error *local_err = NULL;
365 int64_t bytes = 0;

--- 134 unchanged lines hidden (view full) ---

500 qemu_vfree(acb->bounce);
501 }
502
503 acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
504
505 qemu_aio_unref(acb);
506}
507
342 { /* end of list */ }
343 },
344};
345
346static int qemu_rbd_create(const char *filename, QemuOpts *opts, Error **errp)
347{
348 Error *local_err = NULL;
349 int64_t bytes = 0;

--- 134 unchanged lines hidden (view full) ---

484 qemu_vfree(acb->bounce);
485 }
486
487 acb->common.cb(acb->common.opaque, (acb->ret > 0 ? 0 : acb->ret));
488
489 qemu_aio_unref(acb);
490}
491
508#define RBD_MON_HOST 0
509
510static char *qemu_rbd_array_opts(QDict *options, const char *prefix, int type,
511 Error **errp)
492static char *qemu_rbd_mon_host(QDict *options, Error **errp)
512{
493{
513 int num_entries;
514 QemuOpts *opts = NULL;
515 QDict *sub_options;
516 const char *host;
517 const char *port;
518 char *str;
519 char *rados_str = NULL;
520 Error *local_err = NULL;
494 const char **vals = g_new(const char *, qdict_size(options) + 1);
495 char keybuf[32];
496 const char *host, *port;
497 char *rados_str;
521 int i;
522
498 int i;
499
523 assert(type == RBD_MON_HOST);
524
525 num_entries = qdict_array_entries(options, prefix);
526
527 if (num_entries < 0) {
528 error_setg(errp, "Parse error on RBD QDict array");
529 return NULL;
530 }
531
532 for (i = 0; i < num_entries; i++) {
533 char *strbuf = NULL;
534 const char *value;
535 char *rados_str_tmp;
536
537 str = g_strdup_printf("%s%d.", prefix, i);
538 qdict_extract_subqdict(options, &sub_options, str);
539 g_free(str);
540
541 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
542 qemu_opts_absorb_qdict(opts, sub_options, &local_err);
543 QDECREF(sub_options);
544 if (local_err) {
545 error_propagate(errp, local_err);
546 g_free(rados_str);
500 for (i = 0;; i++) {
501 sprintf(keybuf, "server.%d.host", i);
502 host = qdict_get_try_str(options, keybuf);
503 qdict_del(options, keybuf);
504 sprintf(keybuf, "server.%d.port", i);
505 port = qdict_get_try_str(options, keybuf);
506 qdict_del(options, keybuf);
507 if (!host && !port) {
508 break;
509 }
510 if (!host) {
511 error_setg(errp, "Parameter server.%d.host is missing", i);
547 rados_str = NULL;
512 rados_str = NULL;
548 goto exit;
513 goto out;
549 }
550
514 }
515
551 if (type == RBD_MON_HOST) {
552 host = qemu_opt_get(opts, "host");
553 port = qemu_opt_get(opts, "port");
554
555 value = host;
556 if (port) {
557 /* check for ipv6 */
558 if (strchr(host, ':')) {
559 strbuf = g_strdup_printf("[%s]:%s", host, port);
560 } else {
561 strbuf = g_strdup_printf("%s:%s", host, port);
562 }
563 value = strbuf;
564 } else if (strchr(host, ':')) {
565 strbuf = g_strdup_printf("[%s]", host);
566 value = strbuf;
567 }
516 if (strchr(host, ':')) {
517 vals[i] = port ? g_strdup_printf("[%s]:%s", host, port)
518 : g_strdup_printf("[%s]", host);
568 } else {
519 } else {
569 abort();
520 vals[i] = port ? g_strdup_printf("%s:%s", host, port)
521 : g_strdup(host);
570 }
522 }
571
572 /* each iteration in the for loop will build upon the string, and if
573 * rados_str is NULL then it is our first pass */
574 if (rados_str) {
575 /* separate options with ';', as that is what rados_conf_set()
576 * requires */
577 rados_str_tmp = rados_str;
578 rados_str = g_strdup_printf("%s;%s", rados_str_tmp, value);
579 g_free(rados_str_tmp);
580 } else {
581 rados_str = g_strdup(value);
582 }
583
584 g_free(strbuf);
585 qemu_opts_del(opts);
586 opts = NULL;
587 }
523 }
524 vals[i] = NULL;
588
525
589exit:
590 qemu_opts_del(opts);
526 rados_str = i ? g_strjoinv(";", (char **)vals) : NULL;
527out:
528 g_strfreev((char **)vals);
591 return rados_str;
592}
593
594static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
595 Error **errp)
596{
597 BDRVRBDState *s = bs->opaque;
598 const char *pool, *snap, *conf, *clientname, *name, *keypairs;
599 const char *secretid;
600 QemuOpts *opts;
601 Error *local_err = NULL;
602 char *mon_host = NULL;
603 int r;
604
605 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
606 qemu_opts_absorb_qdict(opts, options, &local_err);
607 if (local_err) {
608 error_propagate(errp, local_err);
529 return rados_str;
530}
531
532static int qemu_rbd_open(BlockDriverState *bs, QDict *options, int flags,
533 Error **errp)
534{
535 BDRVRBDState *s = bs->opaque;
536 const char *pool, *snap, *conf, *clientname, *name, *keypairs;
537 const char *secretid;
538 QemuOpts *opts;
539 Error *local_err = NULL;
540 char *mon_host = NULL;
541 int r;
542
543 opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort);
544 qemu_opts_absorb_qdict(opts, options, &local_err);
545 if (local_err) {
546 error_propagate(errp, local_err);
609 qemu_opts_del(opts);
610 return -EINVAL;
547 r = -EINVAL;
548 goto failed_opts;
611 }
612
549 }
550
613 mon_host = qemu_rbd_array_opts(options, "server.",
614 RBD_MON_HOST, &local_err);
551 mon_host = qemu_rbd_mon_host(options, &local_err);
615 if (local_err) {
616 error_propagate(errp, local_err);
617 r = -EINVAL;
618 goto failed_opts;
619 }
620
621 secretid = qemu_opt_get(opts, "password-secret");
622

--- 536 unchanged lines hidden ---
552 if (local_err) {
553 error_propagate(errp, local_err);
554 r = -EINVAL;
555 goto failed_opts;
556 }
557
558 secretid = qemu_opt_get(opts, "password-secret");
559

--- 536 unchanged lines hidden ---