qemu-devel
[Top][All Lists]
Advanced

[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;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]