[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] iSCSI: add configuration variables for iSCSI
From: |
Orit Wasserman |
Subject: |
Re: [Qemu-devel] [PATCH] iSCSI: add configuration variables for iSCSI |
Date: |
Sun, 27 Nov 2011 10:47:31 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:8.0) Gecko/20111115 Thunderbird/8.0 |
On 11/27/2011 01:24 AM, Ronnie Sahlberg wrote:
> This patch adds configuration variables for iSCSI to set
> initiator-name to use when logging in to the target,
> which type of header-digest to negotiate with the target
> and username and password for CHAP authentication.
>
> This allows specifying a initiator-name either from the command line
> -iscsi initiator-name=iqn.2004-01.com.example:test
> or from a configuration file included with -readconfig
> [iscsi]
> initiator-name = iqn.2004-01.com.example:test
> header-digest = CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
> user = CHAP username
> password = CHAP password
>
> The patch also updates the manpage and qemu-doc
>
> Signed-off-by: Ronnie Sahlberg <address@hidden>
> ---
> block/iscsi.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
> qemu-config.c | 27 ++++++++++++++
> qemu-doc.texi | 28 ++++++++++++++-
> qemu-options.hx | 16 ++++++--
> vl.c | 8 ++++
> 5 files changed, 179 insertions(+), 7 deletions(-)
>
> diff --git a/block/iscsi.c b/block/iscsi.c
> index 938c568..851b804 100644
> --- a/block/iscsi.c
> +++ b/block/iscsi.c
> @@ -455,6 +455,97 @@ iscsi_connect_cb(struct iscsi_context *iscsi, int
> status, void *command_data,
> }
> }
>
> +static void parse_chap(struct iscsi_context *iscsi)
> +{
> + QemuOptsList *list;
> + QemuOpts *opts;
> + const char *user = NULL;
> + const char *password = NULL;
> +
> + list = qemu_find_opts("iscsi");
> + if (!list) {
> + return;
> + }
> +
> + opts = QTAILQ_FIRST(&list->head);
> + if (!opts) {
> + return;
> + }
> +
> + user = qemu_opt_get(opts, "user");
> + if (!user) {
> + return;
> + }
> +
> + password = qemu_opt_get(opts, "password");
> + if (!password) {
I think you should issue an error here.
Why should a user give a user name without it's password?
Orit
> + return;
> + }
> +
> + if (iscsi_set_initiator_username_pwd(iscsi, user, password)) {
> + error_report("Failed to set initiator username and password");
> + return;
> + }
> +}
> +
> +static void parse_header_digest(struct iscsi_context *iscsi)
> +{
> + QemuOptsList *list;
> + QemuOpts *opts;
> + const char *digest = NULL;
> +
> + list = qemu_find_opts("iscsi");
> + if (!list) {
> + return;
> + }
> +
> + opts = QTAILQ_FIRST(&list->head);
> + if (!opts) {
> + return;
> + }
> +
> + digest = qemu_opt_get(opts, "header-digest");
> + if (!digest) {
> + return;
> + }
> +
> + if (!strcmp(digest, "CRC32C")) {
> + iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C);
> + } else if (!strcmp(digest, "NONE")) {
> + iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE);
> + } else if (!strcmp(digest, "CRC32C-NONE")) {
> + iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_CRC32C_NONE);
> + } else if (!strcmp(digest, "NONE-CRC32C")) {
> + iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
> + } else {
> + error_report("Invalid header-digest setting : %s", digest);
> + }
> +}
> +
> +static char *parse_initiator_name(void)
> +{
> + QemuOptsList *list;
> + QemuOpts *opts;
> + const char *name = NULL;
> +
> + list = qemu_find_opts("iscsi");
> + if (!list) {
> + return g_strdup("iqn.2008-11.org.linux-kvm");
> + }
> +
> + opts = QTAILQ_FIRST(&list->head);
> + if (!opts) {
> + return g_strdup("iqn.2008-11.org.linux-kvm");
> + }
> +
> + name = qemu_opt_get(opts, "initiator-name");
> + if (!name) {
> + return g_strdup("iqn.2008-11.org.linux-kvm");
> + }
> +
> + return g_strdup(name);
> +}
> +
> /*
> * We support iscsi url's on the form
> * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
> @@ -465,6 +556,7 @@ static int iscsi_open(BlockDriverState *bs, const char
> *filename, int flags)
> struct iscsi_context *iscsi = NULL;
> struct iscsi_url *iscsi_url = NULL;
> struct IscsiTask task;
> + char *initiator_name = NULL;
> int ret;
>
> if ((BDRV_SECTOR_SIZE % 512) != 0) {
> @@ -476,8 +568,9 @@ static int iscsi_open(BlockDriverState *bs, const char
> *filename, int flags)
>
> memset(iscsilun, 0, sizeof(IscsiLun));
>
> - /* Should really append the KVM name after the ':' here */
> - iscsi = iscsi_create_context("iqn.2008-11.org.linux-kvm:");
> + initiator_name = parse_initiator_name();
> +
> + iscsi = iscsi_create_context(initiator_name);
> if (iscsi == NULL) {
> error_report("iSCSI: Failed to create iSCSI context.");
> ret = -ENOMEM;
> @@ -507,6 +600,10 @@ static int iscsi_open(BlockDriverState *bs, const char
> *filename, int flags)
> goto failed;
> }
> }
> +
> + /* check if we got CHAP username/password via the options */
> + parse_chap(iscsi);
> +
> if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) {
> error_report("iSCSI: Failed to set session type to normal.");
> ret = -EINVAL;
> @@ -515,6 +612,9 @@ static int iscsi_open(BlockDriverState *bs, const char
> *filename, int flags)
>
> iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C);
>
> + /* check if we got HEADER_DIGEST via the options */
> + parse_header_digest(iscsi);
> +
> task.iscsilun = iscsilun;
> task.status = 0;
> task.complete = 0;
> @@ -548,6 +648,9 @@ static int iscsi_open(BlockDriverState *bs, const char
> *filename, int flags)
> return 0;
>
> failed:
> + if (initiator_name != NULL) {
> + g_free(initiator_name);
> + }
> if (iscsi_url != NULL) {
> iscsi_destroy_url(iscsi_url);
> }
> diff --git a/qemu-config.c b/qemu-config.c
> index 597d7e1..8ad984d 100644
> --- a/qemu-config.c
> +++ b/qemu-config.c
> @@ -90,6 +90,32 @@ static QemuOptsList qemu_drive_opts = {
> },
> };
>
> +static QemuOptsList qemu_iscsi_opts = {
> + .name = "iscsi",
> + .head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
> + .desc = {
> + {
> + .name = "user",
> + .type = QEMU_OPT_STRING,
> + .help = "username for CHAP authentication to target",
> + },{
> + .name = "password",
> + .type = QEMU_OPT_STRING,
> + .help = "password for CHAP authentication to target",
> + },{
> + .name = "header-digest",
> + .type = QEMU_OPT_STRING,
> + .help = "HeaderDigest setting. "
> + "{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
> + },{
> + .name = "initiator-name",
> + .type = QEMU_OPT_STRING,
> + .help = "Initiator iqn name to use when connecting",
> + },
> + { /* end of list */ }
> + },
> +};
> +
> static QemuOptsList qemu_chardev_opts = {
> .name = "chardev",
> .implied_opt_name = "backend",
> @@ -535,6 +561,7 @@ static QemuOptsList *vm_config_groups[32] = {
> &qemu_option_rom_opts,
> &qemu_machine_opts,
> &qemu_boot_opts,
> + &qemu_iscsi_opts,
> NULL,
> };
>
> diff --git a/qemu-doc.texi b/qemu-doc.texi
> index 9c3cb62..2116085 100644
> --- a/qemu-doc.texi
> +++ b/qemu-doc.texi
> @@ -731,6 +731,31 @@ export LIBISCSI_CHAP_PASSWORD=<password>
> iscsi://<host>/<target-iqn-name>/<lun>
> @end example
>
> +Various session related parameters can be set via special options, either
> +in a configuration file provided via '-readconfig' or directly on the
> +command line.
> +
> address@hidden
> +Setting a specific initiator name to use when logging in to the target
> +-iscsi initiator-name=iqn.qemu.test:my-initiator
> address@hidden example
> +
> address@hidden
> +Controlling which type of header digest to negotiate with the target
> +-iscsi header-digest=CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
> address@hidden example
> +
> +These can also be set via a configuration file
> address@hidden
> +[iscsi]
> + user = "CHAP username"
> + password = "CHAP password"
> + initiator-name = "iqn.qemu.test:my-initiator"
> + # header digest is one of CRC32C|CRC32C-NONE|NONE-CRC32C|NONE
> + header-digest = "CRC32C"
> address@hidden example
> +
> +
> Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
> @example
> This example shows how to set up an iSCSI target with one CDROM and one DISK
> @@ -745,7 +770,8 @@ tgtadm --lld iscsi --mode logicalunit --op new --tid 1
> --lun 2 \
> -b /IMAGES/cd.iso --device-type=cd
> tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
>
> -qemu-system-i386 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
> +qemu-system-i386 -iscsi initiator-name=iqn.qemu.test:my-initiator \
> + -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
> -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
> @end example
>
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 681eaf1..669ff42 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1753,24 +1753,32 @@ Syntax for specifying iSCSI LUNs is
>
> Example (without authentication):
> @example
> -qemu -cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \
> ---drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
> +qemu -iscsi initiator-name=iqn.2001-04.com.example:my-initiator \
> +-cdrom iscsi://192.0.2.1/iqn.2001-04.com.example/2 \
> +-drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
> @end example
>
> Example (CHAP username/password via URL):
> @example
> -qemu --drive file=iscsi://user%password@@192.0.2.1/iqn.2001-04.com.example/1
> +qemu -drive file=iscsi://user%password@@192.0.2.1/iqn.2001-04.com.example/1
> @end example
>
> Example (CHAP username/password via environment variables):
> @example
> LIBISCSI_CHAP_USERNAME="user" \
> LIBISCSI_CHAP_PASSWORD="password" \
> -qemu --drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
> +qemu -drive file=iscsi://192.0.2.1/iqn.2001-04.com.example/1
> @end example
>
> iSCSI support is an optional feature of QEMU and only available when
> compiled and linked against libiscsi.
> +ETEXI
> +DEF("iscsi", HAS_ARG, QEMU_OPTION_iscsi,
> + "-iscsi [user=user][,password=password]\n"
> + " [,header-digest=CRC32C|CR32C-NONE|NONE-CRC32C|NONE\n"
> + " [,initiator-name=iqn]\n"
> + " iSCSI session parameters\n", QEMU_ARCH_ALL)
> +STEXI
>
> @item NBD
> QEMU supports NBD (Network Block Devices) both using TCP protocol as well
> diff --git a/vl.c b/vl.c
> index f5afed4..0c553fa 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -2496,6 +2496,14 @@ int main(int argc, char **argv, char **envp)
> exit(1);
> }
> break;
> +#ifdef CONFIG_LIBISCSI
> + case QEMU_OPTION_iscsi:
> + opts = qemu_opts_parse(qemu_find_opts("iscsi"), optarg, 0);
> + if (!opts) {
> + exit(1);
> + }
> + break;
> +#endif
> #ifdef CONFIG_SLIRP
> case QEMU_OPTION_tftp:
> legacy_tftp_prefix = optarg;