From 8b271101a1724bab926c65c77436d8128bf1c2df Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 10 May 2013 21:38:14 +0100 Subject: [PATCH] Add support for iSCSI. --- fish/guestfish.pod | 8 +++++ generator/actions.ml | 7 +++++ src/drives.c | 70 ++++++++++++++++++++++++++++++++++++++++++ src/guestfs-internal.h | 1 + src/guestfs.pod | 18 +++++++++++ src/launch-libvirt.c | 3 ++ 6 files changed, 107 insertions(+) diff --git a/fish/guestfish.pod b/fish/guestfish.pod index 8382f8958..c3b43c936 100644 --- a/fish/guestfish.pod +++ b/fish/guestfish.pod @@ -1127,6 +1127,14 @@ The equivalent API command would be: > add /disk protocol:gluster server:tcp:example.com +=head2 B<-a iscsi://example.com[:port]/target-iqn-name[/lun]> + +Add a disk located on an iSCSI server. + +The equivalent API command would be: + + > add target-iqn-name/lun protocol:iscsi server:tcp:example.com + =head2 B<-a nbd://example.com[:port]> =head2 B<-a nbd://example.com[:port]/exportname> diff --git a/generator/actions.ml b/generator/actions.ml index a22d43d26..67c4f2fbe 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -1341,6 +1341,13 @@ The C parameter must also be supplied - see below. See also: L +=item C + +Connect to the iSCSI server. +The C parameter must also be supplied - see below. + +See also: L. + =item C Connect to the Network Block Device server. diff --git a/src/drives.c b/src/drives.c index aba2db6d3..406746429 100644 --- a/src/drives.c +++ b/src/drives.c @@ -354,6 +354,53 @@ create_drive_ssh (guestfs_h *g, use_cache_none); } +static struct drive * +create_drive_iscsi (guestfs_h *g, + struct drive_server *servers, size_t nr_servers, + const char *exportname, + const char *username, const char *secret, + bool readonly, const char *format, + const char *iface, const char *name, + const char *disk_label, + bool use_cache_none) +{ + if (username != NULL) { + error (g, _("iscsi: you cannot specify a username with this protocol")); + return NULL; + } + + if (secret != NULL) { + error (g, _("iscsi: you cannot specify a secret with this protocol")); + return NULL; + } + + if (nr_servers != 1) { + error (g, _("iscsi: you must specify exactly one server")); + return NULL; + } + + if (servers[0].transport != drive_transport_none && + servers[0].transport != drive_transport_tcp) { + error (g, _("iscsi: only tcp transport is supported")); + return NULL; + } + + /* If the exportname begins with a '/', skip it. */ + if (exportname[0] == '/') + exportname++; + + if (STREQ (exportname, "")) { + error (g, _("iscsi: target name should not be an empty string")); + return NULL; + } + + return create_drive_non_file (g, drive_protocol_iscsi, + servers, nr_servers, exportname, + username, secret, + readonly, format, iface, name, disk_label, + use_cache_none); +} + /* Traditionally you have been able to use /dev/null as a filename, as * many times as you like. Ancient KVM (RHEL 5) cannot handle adding * /dev/null readonly. qemu 1.2 + virtio-scsi segfaults when you use @@ -818,6 +865,12 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, readonly, format, iface, name, disk_label, false); } + else if (STREQ (protocol, "iscsi")) { + drv = create_drive_iscsi (g, servers, nr_servers, filename, + username, secret, + readonly, format, iface, name, + disk_label, false); + } else if (STREQ (protocol, "nbd")) { drv = create_drive_nbd (g, servers, nr_servers, filename, username, secret, @@ -1100,6 +1153,23 @@ guestfs___drive_source_qemu_param (guestfs_h *g, const struct drive_source *src) src->u.exportname, src->servers[0].u.socket); } + case drive_protocol_iscsi: { + char *ret; + + /* XXX quoting */ + if (src->servers[0].port == 0) + ret = safe_asprintf (g, "iscsi://%s/%s", + src->servers[0].u.hostname, + src->u.exportname); + else + ret = safe_asprintf (g, "iscsi://%s:%d/%s", + src->servers[0].u.hostname, + src->servers[0].port, + src->u.exportname); + + return ret; + } + case drive_protocol_nbd: { CLEANUP_FREE char *p = NULL; char *ret; diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 6a58f2f41..c2681fb1a 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -116,6 +116,7 @@ struct event { enum drive_protocol { drive_protocol_file, drive_protocol_gluster, + drive_protocol_iscsi, drive_protocol_nbd, drive_protocol_rbd, drive_protocol_sheepdog, diff --git a/src/guestfs.pod b/src/guestfs.pod index 99374c21d..e749a9df0 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -680,6 +680,24 @@ single element. The single element is a string defining the Gluster server. The format of this string is documented in L. +=head3 ISCSI + +Libguestfs can access iSCSI disks remotely. + +To do this, set the optional C and C parameters like +this: + + char **server = { "iscsi.example.org:3000", NULL }; + guestfs_add_drive_opts (g, "target-iqn-name/lun", + GUESTFS_ADD_DRIVE_OPTS_FORMAT, "raw", + GUESTFS_ADD_DRIVE_OPTS_PROTOCOL, "iscsi", + GUESTFS_ADD_DRIVE_OPTS_SERVER, server, + -1); + +The C parameter is a list which must have a single element. +The single element is a string defining the iSCSI server. The format +of this string is documented in L. + =head3 NETWORK BLOCK DEVICE Libguestfs can access Network Block Device (NBD) disks remotely. diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index e33ddc6d5..d667e9889 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -1112,6 +1112,8 @@ construct_libvirt_xml_disk (guestfs_h *g, */ case drive_protocol_gluster: protocol_str = "gluster"; goto network_protocols; + case drive_protocol_iscsi: + protocol_str = "iscsi"; goto network_protocols; case drive_protocol_nbd: protocol_str = "nbd"; goto network_protocols; case drive_protocol_rbd: @@ -1598,6 +1600,7 @@ make_drive_priv (guestfs_h *g, struct drive *drv, break; case drive_protocol_gluster: + case drive_protocol_iscsi: case drive_protocol_nbd: case drive_protocol_rbd: case drive_protocol_sheepdog: