diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-10-03 10:50:51 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-10-08 20:04:47 +0100 |
commit | 7786d56db8c22413949f98ef6b15fe0ea367d195 (patch) | |
tree | 7234b2d5b450a21677a9cc19e0b1c506546fa1ee /src | |
parent | 3ad44c866042919374e2d840502e53da2ed8aef0 (diff) | |
download | libguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.tar.gz libguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.tar.xz libguestfs-7786d56db8c22413949f98ef6b15fe0ea367d195.zip |
launch: Add add_drive 'label' option.
New API: list-disk-labels
Allow the user to pass an optional disk label when adding a drive.
This is passed through to qemu / libvirt using the disk serial field,
and from there to the appliance which exposes it through udev,
creating a special alias of the device /dev/disk/guestfs/<label>.
Partitions are named /dev/disk/guestfs/<label><partnum>.
virtio-blk and virtio-scsi limit the serial field to 20 bytes. We
further limit the name to maximum 20 ASCII characters in [a-zA-Z].
list-devices and list-partitions are not changed: these calls still
return raw block device names. However a new call, list-disk-labels,
returns a hash table allowing callers to map between disk labels, and
block device and partition names.
This commit also includes a test.
Diffstat (limited to 'src')
-rw-r--r-- | src/MAX_PROC_NR | 2 | ||||
-rw-r--r-- | src/guestfs-internal.h | 1 | ||||
-rw-r--r-- | src/guestfs.pod | 20 | ||||
-rw-r--r-- | src/launch-appliance.c | 6 | ||||
-rw-r--r-- | src/launch-libvirt.c | 6 | ||||
-rw-r--r-- | src/launch.c | 42 |
6 files changed, 70 insertions, 7 deletions
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR index cb35cf9f..446dfcc5 100644 --- a/src/MAX_PROC_NR +++ b/src/MAX_PROC_NR @@ -1 +1 @@ -368 +369 diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 652cf311..ed9ada48 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -143,6 +143,7 @@ struct drive { char *format; char *iface; char *name; + char *disk_label; bool use_cache_none; void *priv; /* Data used by attach method. */ diff --git a/src/guestfs.pod b/src/guestfs.pod index 2b33bf32..48d810b0 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -1191,6 +1191,26 @@ L</guestfs_list_devices>, L</guestfs_list_partitions> and similar calls return the true names of the devices and partitions as known to the appliance, but see L</guestfs_canonical_device_name>. +=head3 DISK LABELS + +In libguestfs E<ge> 1.20, you can give a label to a disk when you add +it, using the optional C<label> parameter to L</guestfs_add_drive_opts>. +(Note that disk labels are different from and not related to +filesystem labels). + +Not all versions of libguestfs support setting a disk label, and when +it is supported, it is limited to 20 ASCII characters C<[a-zA-Z]>. + +When you add a disk with a label, it can either be addressed +using C</dev/sd*>, or using C</dev/disk/guestfs/I<label>>. +Partitions on the disk can be addressed using +C</dev/disk/guestfs/I<label>I<partnum>>. + +Listing devices (L</guestfs_list_devices>) and partitions +(L</guestfs_list_partitions>) returns the raw block device name. +However you can use L</guestfs_list_disk_labels> to map disk labels +to raw block device and partition names. + =head3 ALGORITHM FOR BLOCK DEVICE NAME TRANSLATION Usually this translation is transparent. However in some (very rare) diff --git a/src/launch-appliance.c b/src/launch-appliance.c index 531faefd..378f1211 100644 --- a/src/launch-appliance.c +++ b/src/launch-appliance.c @@ -908,6 +908,8 @@ qemu_drive_param (guestfs_h *g, const struct drive *drv, size_t index) len += strlen (drv->iface); if (drv->format) len += strlen (drv->format); + if (drv->disk_label) + len += strlen (drv->disk_label); r = safe_malloc (g, len); @@ -930,11 +932,13 @@ qemu_drive_param (guestfs_h *g, const struct drive *drv, size_t index) else iface = "virtio"; - snprintf (&r[i], len-i, "%s%s%s%s,id=hd%zu,if=%s", + snprintf (&r[i], len-i, "%s%s%s%s%s%s,id=hd%zu,if=%s", drv->readonly ? ",snapshot=on" : "", drv->use_cache_none ? ",cache=none" : "", drv->format ? ",format=" : "", drv->format ? drv->format : "", + drv->disk_label ? ",serial=" : "", + drv->disk_label ? drv->disk_label : "", index, iface); diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c index d33693e8..aa1c39f2 100644 --- a/src/launch-libvirt.c +++ b/src/launch-libvirt.c @@ -913,6 +913,12 @@ construct_libvirt_xml_disk (guestfs_h *g, xmlTextWriterPtr xo, } XMLERROR (-1, xmlTextWriterEndElement (xo)); + if (drv->disk_label) { + XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "serial")); + XMLERROR (-1, xmlTextWriterWriteString (xo, BAD_CAST drv->disk_label)); + XMLERROR (-1, xmlTextWriterEndElement (xo)); + } + XMLERROR (-1, xmlTextWriterStartElement (xo, BAD_CAST "address")); XMLERROR (-1, xmlTextWriterWriteAttribute (xo, BAD_CAST "type", diff --git a/src/launch.c b/src/launch.c index 6e111111..1b6cf4bd 100644 --- a/src/launch.c +++ b/src/launch.c @@ -71,6 +71,7 @@ static struct drive * create_drive_struct (guestfs_h *g, const char *path, int readonly, const char *format, const char *iface, const char *name, + const char *disk_label, int use_cache_none) { struct drive *drv = safe_malloc (g, sizeof (struct drive)); @@ -80,6 +81,7 @@ create_drive_struct (guestfs_h *g, const char *path, drv->format = format ? safe_strdup (g, format) : NULL; drv->iface = iface ? safe_strdup (g, iface) : NULL; drv->name = name ? safe_strdup (g, name) : NULL; + drv->disk_label = disk_label ? safe_strdup (g, disk_label) : NULL; drv->use_cache_none = use_cache_none; drv->priv = drv->free_priv = NULL; @@ -92,7 +94,7 @@ guestfs___add_dummy_appliance_drive (guestfs_h *g) { struct drive *drv; - drv = create_drive_struct (g, "", 0, NULL, NULL, NULL, 0); + drv = create_drive_struct (g, "", 0, NULL, NULL, NULL, NULL, 0); add_drive_to_handle (g, drv); } @@ -119,6 +121,7 @@ free_drive_struct (struct drive *drv) free (drv->format); free (drv->iface); free (drv->name); + free (drv->disk_label); if (drv->priv && drv->free_priv) drv->free_priv (drv->priv); free (drv); @@ -183,6 +186,27 @@ valid_format_iface (const char *str) return 1; } +/* Check the disk label is reasonable. It can't contain certain + * characters, eg. '/', ','. However be stricter here and ensure it's + * just alphabetic and <= 20 characters in length. + */ +static int +valid_disk_label (const char *str) +{ + size_t len = strlen (str); + + if (len == 0 || len > 20) + return 0; + + while (len > 0) { + char c = *str++; + len--; + if (!c_isalpha (c)) + return 0; + } + return 1; +} + /* 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 @@ -193,7 +217,7 @@ valid_format_iface (const char *str) */ static int add_null_drive (guestfs_h *g, int readonly, const char *format, - const char *iface, const char *name) + const char *iface, const char *name, const char *disk_label) { char *tmpfile = NULL; int fd = -1; @@ -227,7 +251,7 @@ add_null_drive (guestfs_h *g, int readonly, const char *format, goto err; } - drv = create_drive_struct (g, tmpfile, readonly, format, iface, name, 0); + drv = create_drive_struct (g, tmpfile, readonly, format, iface, name, disk_label, 0); add_drive_to_handle (g, drv); free (tmpfile); @@ -248,6 +272,7 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, const char *format; const char *iface; const char *name; + const char *disk_label; int use_cache_none; struct drive *drv; @@ -265,6 +290,8 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, ? optargs->iface : NULL; name = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_NAME_BITMASK ? optargs->name : NULL; + disk_label = optargs->bitmask & GUESTFS_ADD_DRIVE_OPTS_LABEL_BITMASK + ? optargs->label : NULL; if (format && !valid_format_iface (format)) { error (g, _("%s parameter is empty or contains disallowed characters"), @@ -276,9 +303,13 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, "iface"); return -1; } + if (disk_label && !valid_disk_label (disk_label)) { + error (g, _("label parameter is empty, too long, or contains disallowed characters")); + return -1; + } if (STREQ (filename, "/dev/null")) - return add_null_drive (g, readonly, format, iface, name); + return add_null_drive (g, readonly, format, iface, name, disk_label); /* For writable files, see if we can use cache=none. This also * checks for the existence of the file. For readonly we have @@ -295,7 +326,8 @@ guestfs__add_drive_opts (guestfs_h *g, const char *filename, } } - drv = create_drive_struct (g, filename, readonly, format, iface, name, use_cache_none); + drv = create_drive_struct (g, filename, readonly, format, iface, name, disk_label, + use_cache_none); add_drive_to_handle (g, drv); return 0; } |