From aed0fa2c015e56a882fd6d4b759c82df08fc40d7 Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Sat, 25 Apr 2009 21:41:09 +0100 Subject: [PATCH] Generated code for lvremove, vgremove, pvremove. --- daemon/actions.h | 3 + daemon/stubs.c | 81 ++++ fish/cmds.c | 67 ++- fish/completion.c | 3 + guestfish-actions.pod | 34 +- guestfs-actions.pod | 43 +- java/com/redhat/et/libguestfs/GuestFS.java | 69 ++- java/com_redhat_et_libguestfs_GuestFS.c | 51 +++ ocaml/guestfs.ml | 3 + ocaml/guestfs.mli | 11 +- ocaml/guestfs_c_actions.c | 69 +++ perl/Guestfs.xs | 33 ++ perl/lib/Sys/Guestfs.pm | 28 +- python/guestfs-py.c | 78 ++++ python/guestfs.py | 31 +- ruby/ext/guestfs/_guestfs.c | 69 +++ src/guestfs-actions.c | 240 ++++++++++ src/guestfs-actions.h | 3 + src/guestfs_protocol.c | 30 ++ src/guestfs_protocol.h | 26 +- src/guestfs_protocol.x | 15 + tests.c | 697 ++++++++++++++++++++++++++++- 22 files changed, 1668 insertions(+), 16 deletions(-) diff --git a/daemon/actions.h b/daemon/actions.h index dafbca7..8e79f7b 100644 --- a/daemon/actions.h +++ b/daemon/actions.h @@ -97,3 +97,6 @@ extern int do_mount_ro (const char *device, const char *mountpoint); extern int do_mount_options (const char *options, const char *device, const char *mountpoint); extern int do_mount_vfs (const char *options, const char *vfstype, const char *device, const char *mountpoint); extern char *do_debug (const char *subcmd, char * const* const extraargs); +extern int do_lvremove (const char *device); +extern int do_vgremove (const char *vgname); +extern int do_pvremove (const char *device); diff --git a/daemon/stubs.c b/daemon/stubs.c index e51349a..02c76f1 100644 --- a/daemon/stubs.c +++ b/daemon/stubs.c @@ -1872,6 +1872,78 @@ done: xdr_free ((xdrproc_t) xdr_guestfs_debug_args, (char *) &args); } +static void lvremove_stub (XDR *xdr_in) +{ + int r; + struct guestfs_lvremove_args args; + const char *device; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_lvremove_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "lvremove"); + return; + } + device = args.device; + + r = do_lvremove (device); + if (r == -1) + /* do_lvremove has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_lvremove_args, (char *) &args); +} + +static void vgremove_stub (XDR *xdr_in) +{ + int r; + struct guestfs_vgremove_args args; + const char *vgname; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_vgremove_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "vgremove"); + return; + } + vgname = args.vgname; + + r = do_vgremove (vgname); + if (r == -1) + /* do_vgremove has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_vgremove_args, (char *) &args); +} + +static void pvremove_stub (XDR *xdr_in) +{ + int r; + struct guestfs_pvremove_args args; + const char *device; + + memset (&args, 0, sizeof args); + + if (!xdr_guestfs_pvremove_args (xdr_in, &args)) { + reply_with_error ("%s: daemon failed to decode procedure arguments", "pvremove"); + return; + } + device = args.device; + + r = do_pvremove (device); + if (r == -1) + /* do_pvremove has already called reply_with_error */ + goto done; + + reply (NULL, NULL); +done: + xdr_free ((xdrproc_t) xdr_guestfs_pvremove_args, (char *) &args); +} + void dispatch_incoming_message (XDR *xdr_in) { switch (proc_nr) { @@ -2103,6 +2175,15 @@ void dispatch_incoming_message (XDR *xdr_in) case GUESTFS_PROC_DEBUG: debug_stub (xdr_in); break; + case GUESTFS_PROC_LVREMOVE: + lvremove_stub (xdr_in); + break; + case GUESTFS_PROC_VGREMOVE: + vgremove_stub (xdr_in); + break; + case GUESTFS_PROC_PVREMOVE: + pvremove_stub (xdr_in); + break; default: reply_with_error ("dispatch_incoming_message: unknown procedure number %d", proc_nr); } diff --git a/fish/cmds.c b/fish/cmds.c index 7b1386f..411c6f7 100644 --- a/fish/cmds.c +++ b/fish/cmds.c @@ -87,6 +87,7 @@ void list_commands (void) printf ("%-20s %s\n", "lstat", "get file information for a symbolic link"); printf ("%-20s %s\n", "lvcreate", "create an LVM volume group"); printf ("%-20s %s\n", "lvm-remove-all", "remove all LVM LVs, VGs and PVs"); + printf ("%-20s %s\n", "lvremove", "remove an LVM logical volume"); printf ("%-20s %s\n", "lvs", "list the LVM logical volumes (LVs)"); printf ("%-20s %s\n", "lvs-full", "list the LVM logical volumes (LVs)"); printf ("%-20s %s\n", "mkdir", "create a directory"); @@ -98,6 +99,7 @@ void list_commands (void) printf ("%-20s %s\n", "mount-vfs", "mount a guest disk with mount options and vfstype"); printf ("%-20s %s\n", "mounts", "show mounted filesystems"); printf ("%-20s %s\n", "pvcreate", "create an LVM physical volume"); + printf ("%-20s %s\n", "pvremove", "remove an LVM physical volume"); printf ("%-20s %s\n", "pvs", "list the LVM physical volumes (PVs)"); printf ("%-20s %s\n", "pvs-full", "list the LVM physical volumes (PVs)"); printf ("%-20s %s\n", "read-lines", "read file as lines"); @@ -117,11 +119,12 @@ void list_commands (void) printf ("%-20s %s\n", "tgz-in", "unpack compressed tarball to directory"); printf ("%-20s %s\n", "tgz-out", "pack directory into compressed tarball"); printf ("%-20s %s\n", "touch", "update file timestamps or create a new file"); - printf ("%-20s %s\n", "tune2fs-l", "get ext2/ext3 superblock details"); + printf ("%-20s %s\n", "tune2fs-l", "get ext2/ext3/ext4 superblock details"); printf ("%-20s %s\n", "umount", "unmount a filesystem"); printf ("%-20s %s\n", "umount-all", "unmount all filesystems"); printf ("%-20s %s\n", "upload", "upload a file from the local machine"); printf ("%-20s %s\n", "vgcreate", "create an LVM volume group"); + printf ("%-20s %s\n", "vgremove", "remove an LVM volume group"); printf ("%-20s %s\n", "vgs", "list the LVM volume groups (VGs)"); printf ("%-20s %s\n", "vgs-full", "list the LVM volume groups (VGs)"); printf ("%-20s %s\n", "write-file", "create a file"); @@ -347,7 +350,7 @@ void display_command (const char *cmd) pod2text ("statvfs - get file system statistics", " statvfs \n\nReturns file system statistics for any mounted file system.\nC should be a file or directory in the mounted file system\n(typically it is the mount point itself, but it doesn't need to be).\n\nThis is the same as the C system call."); else if (strcasecmp (cmd, "tune2fs_l") == 0 || strcasecmp (cmd, "tune2fs-l") == 0) - pod2text ("tune2fs-l - get ext2/ext3 superblock details", " tune2fs-l \n\nThis returns the contents of the ext2 or ext3 filesystem superblock\non C.\n\nIt is the same as running C. See L\nmanpage for more details. The list of fields returned isn't\nclearly defined, and depends on both the version of C\nthat libguestfs was built against, and the filesystem itself."); + pod2text ("tune2fs-l - get ext2/ext3/ext4 superblock details", " tune2fs-l \n\nThis returns the contents of the ext2, ext3 or ext4 filesystem\nsuperblock on C.\n\nIt is the same as running C. See L\nmanpage for more details. The list of fields returned isn't\nclearly defined, and depends on both the version of C\nthat libguestfs was built against, and the filesystem itself."); else if (strcasecmp (cmd, "blockdev_setro") == 0 || strcasecmp (cmd, "blockdev-setro") == 0) pod2text ("blockdev-setro - set block device to read-only", " blockdev-setro \n\nSets the block device named C to read-only.\n\nThis uses the L command."); @@ -412,6 +415,15 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "debug") == 0) pod2text ("debug - debugging and internals", " debug \n\nThe C command exposes some internals of\nC (the guestfs daemon) that runs inside the\nqemu subprocess.\n\nThere is no comprehensive help for this command. You have\nto look at the file C in the libguestfs source\nto find out what you can do."); else + if (strcasecmp (cmd, "lvremove") == 0) + pod2text ("lvremove - remove an LVM logical volume", " lvremove \n\nRemove an LVM logical volume C, where C is\nthe path to the LV, such as C.\n\nYou can also remove all LVs in a volume group by specifying\nthe VG name, C."); + else + if (strcasecmp (cmd, "vgremove") == 0) + pod2text ("vgremove - remove an LVM volume group", " vgremove \n\nRemove an LVM volume group C, (for example C).\n\nThis also forcibly removes all logical volumes in the volume\ngroup (if any)."); + else + if (strcasecmp (cmd, "pvremove") == 0) + pod2text ("pvremove - remove an LVM physical volume", " pvremove \n\nThis wipes a physical volume C so that LVM will no longer\nrecognise it.\n\nThe implementation uses the C command which refuses to\nwipe physical volumes that contain any volume groups, so you have\nto remove those first."); + else display_builtin_command (cmd); } @@ -2006,6 +2018,48 @@ static int run_debug (const char *cmd, int argc, char *argv[]) return 0; } +static int run_lvremove (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *device; + if (argc != 1) { + fprintf (stderr, "%s should have 1 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + device = argv[0]; + r = guestfs_lvremove (g, device); + return r; +} + +static int run_vgremove (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *vgname; + if (argc != 1) { + fprintf (stderr, "%s should have 1 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + vgname = argv[0]; + r = guestfs_vgremove (g, vgname); + return r; +} + +static int run_pvremove (const char *cmd, int argc, char *argv[]) +{ + int r; + const char *device; + if (argc != 1) { + fprintf (stderr, "%s should have 1 parameter(s)\n", cmd); + fprintf (stderr, "type 'help %s' for help on %s\n", cmd, cmd); + return -1; + } + device = argv[0]; + r = guestfs_pvremove (g, device); + return r; +} + int run_action (const char *cmd, int argc, char *argv[]) { if (strcasecmp (cmd, "launch") == 0 || strcasecmp (cmd, "run") == 0) @@ -2290,6 +2344,15 @@ int run_action (const char *cmd, int argc, char *argv[]) if (strcasecmp (cmd, "debug") == 0) return run_debug (cmd, argc, argv); else + if (strcasecmp (cmd, "lvremove") == 0) + return run_lvremove (cmd, argc, argv); + else + if (strcasecmp (cmd, "vgremove") == 0) + return run_vgremove (cmd, argc, argv); + else + if (strcasecmp (cmd, "pvremove") == 0) + return run_pvremove (cmd, argc, argv); + else { fprintf (stderr, "%s: unknown command\n", cmd); return -1; diff --git a/fish/completion.c b/fish/completion.c index 8e52981..08d4473 100644 --- a/fish/completion.c +++ b/fish/completion.c @@ -93,6 +93,7 @@ static const char *commands[] = { "lstat", "lvcreate", "lvm-remove-all", + "lvremove", "lvs", "lvs-full", "mkdir", @@ -105,6 +106,7 @@ static const char *commands[] = { "mounts", "path", "pvcreate", + "pvremove", "pvs", "pvs-full", "qemu", @@ -134,6 +136,7 @@ static const char *commands[] = { "upload", "verbose", "vgcreate", + "vgremove", "vgs", "vgs-full", "write-file", diff --git a/guestfish-actions.pod b/guestfish-actions.pod index a79e336..47fb59b 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -629,6 +629,16 @@ and physical volumes. B. +=head2 lvremove + + lvremove device + +Remove an LVM logical volume C, where C is +the path to the LV, such as C. + +You can also remove all LVs in a volume group by specifying +the VG name, C. + =head2 lvs lvs @@ -730,6 +740,17 @@ This creates an LVM physical volume on the named C, where C should usually be a partition name such as C. +=head2 pvremove + + pvremove device + +This wipes a physical volume C so that LVM will no longer +recognise it. + +The implementation uses the C command which refuses to +wipe physical volumes that contain any volume groups, so you have +to remove those first. + =head2 pvs pvs @@ -942,8 +963,8 @@ to create a new zero-length file. tune2fs-l device -This returns the contents of the ext2 or ext3 filesystem superblock -on C. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C. It is the same as running C. See L manpage for more details. The list of fields returned isn't @@ -986,6 +1007,15 @@ Use C<-> instead of a filename to read/write from stdin/stdout. This creates an LVM volume group called C from the non-empty list of physical volumes C. +=head2 vgremove + + vgremove vgname + +Remove an LVM volume group C, (for example C). + +This also forcibly removes all logical volumes in the volume +group (if any). + =head2 vgs vgs diff --git a/guestfs-actions.pod b/guestfs-actions.pod index b945454..7c5223b 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -822,6 +822,19 @@ This function returns 0 on success or -1 on error. B. +=head2 guestfs_lvremove + + int guestfs_lvremove (guestfs_h *handle, + const char *device); + +Remove an LVM logical volume C, where C is +the path to the LV, such as C. + +You can also remove all LVs in a volume group by specifying +the VG name, C. + +This function returns 0 on success or -1 on error. + =head2 guestfs_lvs char **guestfs_lvs (guestfs_h *handle); @@ -968,6 +981,20 @@ as C. This function returns 0 on success or -1 on error. +=head2 guestfs_pvremove + + int guestfs_pvremove (guestfs_h *handle, + const char *device); + +This wipes a physical volume C so that LVM will no longer +recognise it. + +The implementation uses the C command which refuses to +wipe physical volumes that contain any volume groups, so you have +to remove those first. + +This function returns 0 on success or -1 on error. + =head2 guestfs_pvs char **guestfs_pvs (guestfs_h *handle); @@ -1270,8 +1297,8 @@ This function returns 0 on success or -1 on error. char **guestfs_tune2fs_l (guestfs_h *handle, const char *device); -This returns the contents of the ext2 or ext3 filesystem superblock -on C. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C. It is the same as running C. See L manpage for more details. The list of fields returned isn't @@ -1331,6 +1358,18 @@ from the non-empty list of physical volumes C. This function returns 0 on success or -1 on error. +=head2 guestfs_vgremove + + int guestfs_vgremove (guestfs_h *handle, + const char *vgname); + +Remove an LVM volume group C, (for example C). + +This also forcibly removes all logical volumes in the volume +group (if any). + +This function returns 0 on success or -1 on error. + =head2 guestfs_vgs char **guestfs_vgs (guestfs_h *handle); diff --git a/java/com/redhat/et/libguestfs/GuestFS.java b/java/com/redhat/et/libguestfs/GuestFS.java index f1cd508..04a8124 100644 --- a/java/com/redhat/et/libguestfs/GuestFS.java +++ b/java/com/redhat/et/libguestfs/GuestFS.java @@ -1723,10 +1723,10 @@ public class GuestFS { throws LibGuestFSException; /** - * get ext2/ext3 superblock details + * get ext2/ext3/ext4 superblock details * - * This returns the contents of the ext2 or ext3 filesystem - * superblock on "device". + * This returns the contents of the ext2, ext3 or ext4 + * filesystem superblock on "device". * * It is the same as running "tune2fs -l device". See * tune2fs(8) manpage for more details. The list of fields @@ -2209,4 +2209,67 @@ public class GuestFS { private native String _debug (long g, String subcmd, String[] extraargs) throws LibGuestFSException; + /** + * remove an LVM logical volume + * + * Remove an LVM logical volume "device", where "device" is + * the path to the LV, such as "/dev/VG/LV". + * + * You can also remove all LVs in a volume group by + * specifying the VG name, "/dev/VG". + * + * @throws LibGuestFSException + */ + public void lvremove (String device) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("lvremove: handle is closed"); + _lvremove (g, device); + } + private native void _lvremove (long g, String device) + throws LibGuestFSException; + + /** + * remove an LVM volume group + * + * Remove an LVM volume group "vgname", (for example "VG"). + * + * This also forcibly removes all logical volumes in the + * volume group (if any). + * + * @throws LibGuestFSException + */ + public void vgremove (String vgname) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("vgremove: handle is closed"); + _vgremove (g, vgname); + } + private native void _vgremove (long g, String vgname) + throws LibGuestFSException; + + /** + * remove an LVM physical volume + * + * This wipes a physical volume "device" so that LVM will + * no longer recognise it. + * + * The implementation uses the "pvremove" command which + * refuses to wipe physical volumes that contain any volume + * groups, so you have to remove those first. + * + * @throws LibGuestFSException + */ + public void pvremove (String device) + throws LibGuestFSException + { + if (g == 0) + throw new LibGuestFSException ("pvremove: handle is closed"); + _pvremove (g, device); + } + private native void _pvremove (long g, String device) + throws LibGuestFSException; + } diff --git a/java/com_redhat_et_libguestfs_GuestFS.c b/java/com_redhat_et_libguestfs_GuestFS.c index 4b96c26..8f5e353 100644 --- a/java/com_redhat_et_libguestfs_GuestFS.c +++ b/java/com_redhat_et_libguestfs_GuestFS.c @@ -2266,3 +2266,54 @@ Java_com_redhat_et_libguestfs_GuestFS__1debug return jr; } +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1lvremove + (JNIEnv *env, jobject obj, jlong jg, jstring jdevice) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + const char *device; + + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + r = guestfs_lvremove (g, device); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1vgremove + (JNIEnv *env, jobject obj, jlong jg, jstring jvgname) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + const char *vgname; + + vgname = (*env)->GetStringUTFChars (env, jvgname, NULL); + r = guestfs_vgremove (g, vgname); + (*env)->ReleaseStringUTFChars (env, jvgname, vgname); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + +JNIEXPORT void JNICALL +Java_com_redhat_et_libguestfs_GuestFS__1pvremove + (JNIEnv *env, jobject obj, jlong jg, jstring jdevice) +{ + guestfs_h *g = (guestfs_h *) (long) jg; + int r; + const char *device; + + device = (*env)->GetStringUTFChars (env, jdevice, NULL); + r = guestfs_pvremove (g, device); + (*env)->ReleaseStringUTFChars (env, jdevice, device); + if (r == -1) { + throw_exception (env, guestfs_last_error (g)); + return ; + } +} + diff --git a/ocaml/guestfs.ml b/ocaml/guestfs.ml index c3305e4..d020df8 100644 --- a/ocaml/guestfs.ml +++ b/ocaml/guestfs.ml @@ -212,3 +212,6 @@ external mount_ro : t -> string -> string -> unit = "ocaml_guestfs_mount_ro" external mount_options : t -> string -> string -> string -> unit = "ocaml_guestfs_mount_options" external mount_vfs : t -> string -> string -> string -> string -> unit = "ocaml_guestfs_mount_vfs" external debug : t -> string -> string array -> string = "ocaml_guestfs_debug" +external lvremove : t -> string -> unit = "ocaml_guestfs_lvremove" +external vgremove : t -> string -> unit = "ocaml_guestfs_vgremove" +external pvremove : t -> string -> unit = "ocaml_guestfs_pvremove" diff --git a/ocaml/guestfs.mli b/ocaml/guestfs.mli index 846332c..f38fa48 100644 --- a/ocaml/guestfs.mli +++ b/ocaml/guestfs.mli @@ -350,7 +350,7 @@ val statvfs : t -> string -> statvfs (** get file system statistics *) val tune2fs_l : t -> string -> (string * string) list -(** get ext2/ext3 superblock details *) +(** get ext2/ext3/ext4 superblock details *) val blockdev_setro : t -> string -> unit (** set block device to read-only *) @@ -415,3 +415,12 @@ val mount_vfs : t -> string -> string -> string -> string -> unit val debug : t -> string -> string array -> string (** debugging and internals *) +val lvremove : t -> string -> unit +(** remove an LVM logical volume *) + +val vgremove : t -> string -> unit +(** remove an LVM volume group *) + +val pvremove : t -> string -> unit +(** remove an LVM physical volume *) + diff --git a/ocaml/guestfs_c_actions.c b/ocaml/guestfs_c_actions.c index c396a8a..73515cf 100644 --- a/ocaml/guestfs_c_actions.c +++ b/ocaml/guestfs_c_actions.c @@ -2634,3 +2634,72 @@ ocaml_guestfs_debug (value gv, value subcmdv, value extraargsv) CAMLreturn (rv); } +CAMLprim value +ocaml_guestfs_lvremove (value gv, value devicev) +{ + CAMLparam2 (gv, devicev); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("lvremove: used handle after closing it"); + + const char *device = String_val (devicev); + int r; + + caml_enter_blocking_section (); + r = guestfs_lvremove (g, device); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "lvremove"); + + rv = Val_unit; + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_vgremove (value gv, value vgnamev) +{ + CAMLparam2 (gv, vgnamev); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("vgremove: used handle after closing it"); + + const char *vgname = String_val (vgnamev); + int r; + + caml_enter_blocking_section (); + r = guestfs_vgremove (g, vgname); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "vgremove"); + + rv = Val_unit; + CAMLreturn (rv); +} + +CAMLprim value +ocaml_guestfs_pvremove (value gv, value devicev) +{ + CAMLparam2 (gv, devicev); + CAMLlocal1 (rv); + + guestfs_h *g = Guestfs_val (gv); + if (g == NULL) + caml_failwith ("pvremove: used handle after closing it"); + + const char *device = String_val (devicev); + int r; + + caml_enter_blocking_section (); + r = guestfs_pvremove (g, device); + caml_leave_blocking_section (); + if (r == -1) + ocaml_guestfs_raise_error (g, "pvremove"); + + rv = Val_unit; + CAMLreturn (rv); +} + diff --git a/perl/Guestfs.xs b/perl/Guestfs.xs index be13fcd..53c589d 100644 --- a/perl/Guestfs.xs +++ b/perl/Guestfs.xs @@ -1485,3 +1485,36 @@ PREINIT: OUTPUT: RETVAL +void +lvremove (g, device) + guestfs_h *g; + char *device; +PREINIT: + int r; + PPCODE: + r = guestfs_lvremove (g, device); + if (r == -1) + croak ("lvremove: %s", guestfs_last_error (g)); + +void +vgremove (g, vgname) + guestfs_h *g; + char *vgname; +PREINIT: + int r; + PPCODE: + r = guestfs_vgremove (g, vgname); + if (r == -1) + croak ("vgremove: %s", guestfs_last_error (g)); + +void +pvremove (g, device) + guestfs_h *g; + char *device; +PREINIT: + int r; + PPCODE: + r = guestfs_pvremove (g, device); + if (r == -1) + croak ("pvremove: %s", guestfs_last_error (g)); + diff --git a/perl/lib/Sys/Guestfs.pm b/perl/lib/Sys/Guestfs.pm index 3d1493b..bd2d961 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -608,6 +608,14 @@ and physical volumes. B. +=item $h->lvremove ($device); + +Remove an LVM logical volume C, where C is +the path to the LV, such as C. + +You can also remove all LVs in a volume group by specifying +the VG name, C. + =item @logvols = $h->lvs (); List all the logical volumes detected. This is the equivalent @@ -687,6 +695,15 @@ This creates an LVM physical volume on the named C, where C should usually be a partition name such as C. +=item $h->pvremove ($device); + +This wipes a physical volume C so that LVM will no longer +recognise it. + +The implementation uses the C command which refuses to +wipe physical volumes that contain any volume groups, so you have +to remove those first. + =item @physvols = $h->pvs (); List all the physical volumes detected. This is the equivalent @@ -865,8 +882,8 @@ to create a new zero-length file. =item %superblock = $h->tune2fs_l ($device); -This returns the contents of the ext2 or ext3 filesystem superblock -on C. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C. It is the same as running C. See L manpage for more details. The list of fields returned isn't @@ -899,6 +916,13 @@ See also C<$h-Edownload>. This creates an LVM volume group called C from the non-empty list of physical volumes C. +=item $h->vgremove ($vgname); + +Remove an LVM volume group C, (for example C). + +This also forcibly removes all logical volumes in the volume +group (if any). + =item @volgroups = $h->vgs (); List all the volumes groups detected. This is the equivalent diff --git a/python/guestfs-py.c b/python/guestfs-py.c index 0022b5b..38f78c0 100644 --- a/python/guestfs-py.c +++ b/python/guestfs-py.c @@ -2825,6 +2825,81 @@ py_guestfs_debug (PyObject *self, PyObject *args) return py_r; } +static PyObject * +py_guestfs_lvremove (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_lvremove", + &py_g, &device)) + return NULL; + g = get_handle (py_g); + + r = guestfs_lvremove (g, device); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_vgremove (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *vgname; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_vgremove", + &py_g, &vgname)) + return NULL; + g = get_handle (py_g); + + r = guestfs_vgremove (g, vgname); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + +static PyObject * +py_guestfs_pvremove (PyObject *self, PyObject *args) +{ + PyObject *py_g; + guestfs_h *g; + PyObject *py_r; + int r; + const char *device; + + if (!PyArg_ParseTuple (args, (char *) "Os:guestfs_pvremove", + &py_g, &device)) + return NULL; + g = get_handle (py_g); + + r = guestfs_pvremove (g, device); + if (r == -1) { + PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g)); + return NULL; + } + + Py_INCREF (Py_None); + py_r = Py_None; + return py_r; +} + static PyMethodDef methods[] = { { (char *) "create", py_guestfs_create, METH_VARARGS, NULL }, { (char *) "close", py_guestfs_close, METH_VARARGS, NULL }, @@ -2925,6 +3000,9 @@ static PyMethodDef methods[] = { { (char *) "mount_options", py_guestfs_mount_options, METH_VARARGS, NULL }, { (char *) "mount_vfs", py_guestfs_mount_vfs, METH_VARARGS, NULL }, { (char *) "debug", py_guestfs_debug, METH_VARARGS, NULL }, + { (char *) "lvremove", py_guestfs_lvremove, METH_VARARGS, NULL }, + { (char *) "vgremove", py_guestfs_vgremove, METH_VARARGS, NULL }, + { (char *) "pvremove", py_guestfs_pvremove, METH_VARARGS, NULL }, { NULL, NULL, 0, NULL } }; diff --git a/python/guestfs.py b/python/guestfs.py index b2c3e49..1ebaa74 100644 --- a/python/guestfs.py +++ b/python/guestfs.py @@ -862,8 +862,8 @@ class GuestFS: return libguestfsmod.statvfs (self._o, path) def tune2fs_l (self, device): - u"""This returns the contents of the ext2 or ext3 filesystem - superblock on "device". + u"""This returns the contents of the ext2, ext3 or ext4 + filesystem superblock on "device". It is the same as running "tune2fs -l device". See tune2fs(8) manpage for more details. The list of fields @@ -1086,3 +1086,30 @@ class GuestFS: """ return libguestfsmod.debug (self._o, subcmd, extraargs) + def lvremove (self, device): + u"""Remove an LVM logical volume "device", where "device" is + the path to the LV, such as "/dev/VG/LV". + + You can also remove all LVs in a volume group by + specifying the VG name, "/dev/VG". + """ + return libguestfsmod.lvremove (self._o, device) + + def vgremove (self, vgname): + u"""Remove an LVM volume group "vgname", (for example "VG"). + + This also forcibly removes all logical volumes in the + volume group (if any). + """ + return libguestfsmod.vgremove (self._o, vgname) + + def pvremove (self, device): + u"""This wipes a physical volume "device" so that LVM will + no longer recognise it. + + The implementation uses the "pvremove" command which + refuses to wipe physical volumes that contain any volume + groups, so you have to remove those first. + """ + return libguestfsmod.pvremove (self._o, device) + diff --git a/ruby/ext/guestfs/_guestfs.c b/ruby/ext/guestfs/_guestfs.c index d4b62ca..0429ae6 100644 --- a/ruby/ext/guestfs/_guestfs.c +++ b/ruby/ext/guestfs/_guestfs.c @@ -2356,6 +2356,69 @@ static VALUE ruby_guestfs_debug (VALUE gv, VALUE subcmdv, VALUE extraargsv) return rv; } +static VALUE ruby_guestfs_lvremove (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "lvremove"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "lvremove"); + + int r; + + r = guestfs_lvremove (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_vgremove (VALUE gv, VALUE vgnamev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "vgremove"); + + const char *vgname = StringValueCStr (vgnamev); + if (!vgname) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "vgname", "vgremove"); + + int r; + + r = guestfs_vgremove (g, vgname); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + +static VALUE ruby_guestfs_pvremove (VALUE gv, VALUE devicev) +{ + guestfs_h *g; + Data_Get_Struct (gv, guestfs_h, g); + if (!g) + rb_raise (rb_eArgError, "%s: used handle after closing it", "pvremove"); + + const char *device = StringValueCStr (devicev); + if (!device) + rb_raise (rb_eTypeError, "expected string for parameter %s of %s", + "device", "pvremove"); + + int r; + + r = guestfs_pvremove (g, device); + if (r == -1) + rb_raise (e_Error, "%s", guestfs_last_error (g)); + + return Qnil; +} + /* Initialize the module. */ void Init__guestfs () { @@ -2560,4 +2623,10 @@ void Init__guestfs () ruby_guestfs_mount_vfs, 4); rb_define_method (c_guestfs, "debug", ruby_guestfs_debug, 2); + rb_define_method (c_guestfs, "lvremove", + ruby_guestfs_lvremove, 1); + rb_define_method (c_guestfs, "vgremove", + ruby_guestfs_vgremove, 1); + rb_define_method (c_guestfs, "pvremove", + ruby_guestfs_pvremove, 1); } diff --git a/src/guestfs-actions.c b/src/guestfs-actions.c index e143c27..68f122a 100644 --- a/src/guestfs-actions.c +++ b/src/guestfs-actions.c @@ -6477,3 +6477,243 @@ char *guestfs_debug (guestfs_h *g, return ctx.ret.result; /* caller will free */ } +struct lvremove_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void lvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct lvremove_ctx *ctx = (struct lvremove_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_lvremove"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_lvremove"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_lvremove (guestfs_h *g, + const char *device) +{ + struct guestfs_lvremove_args args; + struct lvremove_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_lvremove") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.device = (char *) device; + serial = guestfs__send_sync (g, GUESTFS_PROC_LVREMOVE, + (xdrproc_t) xdr_guestfs_lvremove_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, lvremove_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_lvremove"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_LVREMOVE, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + +struct vgremove_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void vgremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct vgremove_ctx *ctx = (struct vgremove_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_vgremove"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_vgremove"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_vgremove (guestfs_h *g, + const char *vgname) +{ + struct guestfs_vgremove_args args; + struct vgremove_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_vgremove") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.vgname = (char *) vgname; + serial = guestfs__send_sync (g, GUESTFS_PROC_VGREMOVE, + (xdrproc_t) xdr_guestfs_vgremove_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, vgremove_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_vgremove"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_VGREMOVE, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + +struct pvremove_ctx { + /* This flag is set by the callbacks, so we know we've done + * the callbacks as expected, and in the right sequence. + * 0 = not called, 1 = send called, + * 1001 = reply called. + */ + int cb_sequence; + struct guestfs_message_header hdr; + struct guestfs_message_error err; +}; + +static void pvremove_reply_cb (guestfs_h *g, void *data, XDR *xdr) +{ + guestfs_main_loop *ml = guestfs_get_main_loop (g); + struct pvremove_ctx *ctx = (struct pvremove_ctx *) data; + + ml->main_loop_quit (ml, g); + + if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) { + error (g, "%s: failed to parse reply header", "guestfs_pvremove"); + return; + } + if (ctx->hdr.status == GUESTFS_STATUS_ERROR) { + if (!xdr_guestfs_message_error (xdr, &ctx->err)) { + error (g, "%s: failed to parse reply error", "guestfs_pvremove"); + return; + } + goto done; + } + done: + ctx->cb_sequence = 1001; +} + +int guestfs_pvremove (guestfs_h *g, + const char *device) +{ + struct guestfs_pvremove_args args; + struct pvremove_ctx ctx; + guestfs_main_loop *ml = guestfs_get_main_loop (g); + int serial; + + if (check_state (g, "guestfs_pvremove") == -1) return -1; + guestfs_set_busy (g); + + memset (&ctx, 0, sizeof ctx); + + args.device = (char *) device; + serial = guestfs__send_sync (g, GUESTFS_PROC_PVREMOVE, + (xdrproc_t) xdr_guestfs_pvremove_args, (char *) &args); + if (serial == -1) { + guestfs_set_ready (g); + return -1; + } + + guestfs__switch_to_receiving (g); + ctx.cb_sequence = 0; + guestfs_set_reply_callback (g, pvremove_reply_cb, &ctx); + (void) ml->main_loop_run (ml, g); + guestfs_set_reply_callback (g, NULL, NULL); + if (ctx.cb_sequence != 1001) { + error (g, "%s reply failed, see earlier error messages", "guestfs_pvremove"); + guestfs_set_ready (g); + return -1; + } + + if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_PVREMOVE, serial) == -1) { + guestfs_set_ready (g); + return -1; + } + + if (ctx.hdr.status == GUESTFS_STATUS_ERROR) { + error (g, "%s", ctx.err.error_message); + guestfs_set_ready (g); + return -1; + } + + guestfs_set_ready (g); + return 0; +} + diff --git a/src/guestfs-actions.h b/src/guestfs-actions.h index 5190528..a11a6b2 100644 --- a/src/guestfs-actions.h +++ b/src/guestfs-actions.h @@ -116,3 +116,6 @@ extern int guestfs_mount_ro (guestfs_h *handle, const char *device, const char * extern int guestfs_mount_options (guestfs_h *handle, const char *options, const char *device, const char *mountpoint); extern int guestfs_mount_vfs (guestfs_h *handle, const char *options, const char *vfstype, const char *device, const char *mountpoint); extern char *guestfs_debug (guestfs_h *handle, const char *subcmd, char * const* const extraargs); +extern int guestfs_lvremove (guestfs_h *handle, const char *device); +extern int guestfs_vgremove (guestfs_h *handle, const char *vgname); +extern int guestfs_pvremove (guestfs_h *handle, const char *device); diff --git a/src/guestfs_protocol.c b/src/guestfs_protocol.c index 5bde2b9..2a34a92 100644 --- a/src/guestfs_protocol.c +++ b/src/guestfs_protocol.c @@ -1334,6 +1334,36 @@ xdr_guestfs_debug_ret (XDR *xdrs, guestfs_debug_ret *objp) } bool_t +xdr_guestfs_lvremove_args (XDR *xdrs, guestfs_lvremove_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_vgremove_args (XDR *xdrs, guestfs_vgremove_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->vgname, ~0)) + return FALSE; + return TRUE; +} + +bool_t +xdr_guestfs_pvremove_args (XDR *xdrs, guestfs_pvremove_args *objp) +{ + register int32_t *buf; + + if (!xdr_string (xdrs, &objp->device, ~0)) + return FALSE; + return TRUE; +} + +bool_t xdr_guestfs_procedure (XDR *xdrs, guestfs_procedure *objp) { register int32_t *buf; diff --git a/src/guestfs_protocol.h b/src/guestfs_protocol.h index 2a8d919..826dc42 100644 --- a/src/guestfs_protocol.h +++ b/src/guestfs_protocol.h @@ -692,6 +692,21 @@ struct guestfs_debug_ret { }; typedef struct guestfs_debug_ret guestfs_debug_ret; +struct guestfs_lvremove_args { + char *device; +}; +typedef struct guestfs_lvremove_args guestfs_lvremove_args; + +struct guestfs_vgremove_args { + char *vgname; +}; +typedef struct guestfs_vgremove_args guestfs_vgremove_args; + +struct guestfs_pvremove_args { + char *device; +}; +typedef struct guestfs_pvremove_args guestfs_pvremove_args; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -769,7 +784,10 @@ enum guestfs_procedure { GUESTFS_PROC_MOUNT_OPTIONS = 74, GUESTFS_PROC_MOUNT_VFS = 75, GUESTFS_PROC_DEBUG = 76, - GUESTFS_PROC_NR_PROCS = 76 + 1, + GUESTFS_PROC_LVREMOVE = 77, + GUESTFS_PROC_VGREMOVE = 78, + GUESTFS_PROC_PVREMOVE = 79, + GUESTFS_PROC_NR_PROCS = 79 + 1, }; typedef enum guestfs_procedure guestfs_procedure; #define GUESTFS_MESSAGE_MAX 4194304 @@ -925,6 +943,9 @@ extern bool_t xdr_guestfs_mount_options_args (XDR *, guestfs_mount_options_args extern bool_t xdr_guestfs_mount_vfs_args (XDR *, guestfs_mount_vfs_args*); extern bool_t xdr_guestfs_debug_args (XDR *, guestfs_debug_args*); extern bool_t xdr_guestfs_debug_ret (XDR *, guestfs_debug_ret*); +extern bool_t xdr_guestfs_lvremove_args (XDR *, guestfs_lvremove_args*); +extern bool_t xdr_guestfs_vgremove_args (XDR *, guestfs_vgremove_args*); +extern bool_t xdr_guestfs_pvremove_args (XDR *, guestfs_pvremove_args*); extern bool_t xdr_guestfs_procedure (XDR *, guestfs_procedure*); extern bool_t xdr_guestfs_message_direction (XDR *, guestfs_message_direction*); extern bool_t xdr_guestfs_message_status (XDR *, guestfs_message_status*); @@ -1039,6 +1060,9 @@ extern bool_t xdr_guestfs_mount_options_args (); extern bool_t xdr_guestfs_mount_vfs_args (); extern bool_t xdr_guestfs_debug_args (); extern bool_t xdr_guestfs_debug_ret (); +extern bool_t xdr_guestfs_lvremove_args (); +extern bool_t xdr_guestfs_vgremove_args (); +extern bool_t xdr_guestfs_pvremove_args (); extern bool_t xdr_guestfs_procedure (); extern bool_t xdr_guestfs_message_direction (); extern bool_t xdr_guestfs_message_status (); diff --git a/src/guestfs_protocol.x b/src/guestfs_protocol.x index 7f0793f..348f3f9 100644 --- a/src/guestfs_protocol.x +++ b/src/guestfs_protocol.x @@ -535,6 +535,18 @@ struct guestfs_debug_ret { string result<>; }; +struct guestfs_lvremove_args { + string device<>; +}; + +struct guestfs_vgremove_args { + string vgname<>; +}; + +struct guestfs_pvremove_args { + string device<>; +}; + enum guestfs_procedure { GUESTFS_PROC_MOUNT = 1, GUESTFS_PROC_SYNC = 2, @@ -612,6 +624,9 @@ enum guestfs_procedure { GUESTFS_PROC_MOUNT_OPTIONS = 74, GUESTFS_PROC_MOUNT_VFS = 75, GUESTFS_PROC_DEBUG = 76, + GUESTFS_PROC_LVREMOVE = 77, + GUESTFS_PROC_VGREMOVE = 78, + GUESTFS_PROC_PVREMOVE = 79, GUESTFS_PROC_NR_PROCS }; diff --git a/tests.c b/tests.c index be32e66..378f3af 100644 --- a/tests.c +++ b/tests.c @@ -110,6 +110,653 @@ static void no_test_warnings (void) fprintf (stderr, "warning: \"guestfs_debug\" has no tests\n"); } +static int test_pvremove_0 (void) +{ + /* InitEmpty for pvremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for pvremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_vgremove (g, "VG"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_pvremove (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_lvs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_pvremove_0: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_pvremove_1 (void) +{ + /* InitEmpty for pvremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for pvremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_vgremove (g, "VG"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_pvremove (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_vgs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_pvremove_1: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_pvremove_2 (void) +{ + /* InitEmpty for pvremove (2) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for pvremove (2) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_vgremove (g, "VG"); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_pvremove (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_pvs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_pvremove_2: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_vgremove_0 (void) +{ + /* InitEmpty for vgremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for vgremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_vgremove (g, "VG"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_lvs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_vgremove_0: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_vgremove_1 (void) +{ + /* InitEmpty for vgremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for vgremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_vgremove (g, "VG"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_vgs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_vgremove_1: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_lvremove_0 (void) +{ + /* InitEmpty for lvremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for lvremove (0) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvremove (g, "/dev/VG/LV1"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_lvs (g); + if (r == NULL) + return -1; + if (!r[0]) { + fprintf (stderr, "test_lvremove_0: short list returned from command\n"); + print_strings (r); + return -1; + } + if (strcmp (r[0], "/dev/VG/LV2") != 0) { + fprintf (stderr, "test_lvremove_0: expected \"/dev/VG/LV2\" but got \"%s\"\n", r[0]); + return -1; + } + if (r[1] != NULL) { + fprintf (stderr, "test_lvremove_0: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_lvremove_1 (void) +{ + /* InitEmpty for lvremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for lvremove (1) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvremove (g, "/dev/VG"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_lvs (g); + if (r == NULL) + return -1; + if (r[0] != NULL) { + fprintf (stderr, "test_lvremove_1: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + +static int test_lvremove_2 (void) +{ + /* InitEmpty for lvremove (2) */ + { + int r; + suppress_error = 0; + r = guestfs_umount_all (g); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvm_remove_all (g); + if (r == -1) + return -1; + } + /* TestOutputList for lvremove (2) */ + { + int r; + suppress_error = 0; + r = guestfs_pvcreate (g, "/dev/sda"); + if (r == -1) + return -1; + } + { + char *physvols[] = { + "/dev/sda", + NULL + }; + int r; + suppress_error = 0; + r = guestfs_vgcreate (g, "VG", physvols); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV1", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvcreate (g, "LV2", "VG", 50); + if (r == -1) + return -1; + } + { + int r; + suppress_error = 0; + r = guestfs_lvremove (g, "/dev/VG"); + if (r == -1) + return -1; + } + { + char **r; + int i; + suppress_error = 0; + r = guestfs_vgs (g); + if (r == NULL) + return -1; + if (!r[0]) { + fprintf (stderr, "test_lvremove_2: short list returned from command\n"); + print_strings (r); + return -1; + } + if (strcmp (r[0], "VG") != 0) { + fprintf (stderr, "test_lvremove_2: expected \"VG\" but got \"%s\"\n", r[0]); + return -1; + } + if (r[1] != NULL) { + fprintf (stderr, "test_lvremove_2: extra elements returned from command\n"); + print_strings (r); + return -1; + } + for (i = 0; r[i] != NULL; ++i) + free (r[i]); + free (r); + } + return 0; +} + static int test_mount_ro_0 (void) { /* InitBasicFS for mount_ro (0): create ext2 on /dev/sda1 */ @@ -5443,9 +6090,57 @@ int main (int argc, char *argv[]) exit (1); } - nr_tests = 77; + nr_tests = 85; test_num++; + printf ("%3d/%3d test_pvremove_0\n", test_num, nr_tests); + if (test_pvremove_0 () == -1) { + printf ("test_pvremove_0 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_pvremove_1\n", test_num, nr_tests); + if (test_pvremove_1 () == -1) { + printf ("test_pvremove_1 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_pvremove_2\n", test_num, nr_tests); + if (test_pvremove_2 () == -1) { + printf ("test_pvremove_2 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_vgremove_0\n", test_num, nr_tests); + if (test_vgremove_0 () == -1) { + printf ("test_vgremove_0 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_vgremove_1\n", test_num, nr_tests); + if (test_vgremove_1 () == -1) { + printf ("test_vgremove_1 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_lvremove_0\n", test_num, nr_tests); + if (test_lvremove_0 () == -1) { + printf ("test_lvremove_0 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_lvremove_1\n", test_num, nr_tests); + if (test_lvremove_1 () == -1) { + printf ("test_lvremove_1 FAILED\n"); + failed++; + } + test_num++; + printf ("%3d/%3d test_lvremove_2\n", test_num, nr_tests); + if (test_lvremove_2 () == -1) { + printf ("test_lvremove_2 FAILED\n"); + failed++; + } + test_num++; printf ("%3d/%3d test_mount_ro_0\n", test_num, nr_tests); if (test_mount_ro_0 () == -1) { printf ("test_mount_ro_0 FAILED\n"); -- 1.8.3.1