diff options
-rw-r--r-- | daemon/actions.h | 3 | ||||
-rw-r--r-- | daemon/stubs.c | 81 | ||||
-rw-r--r-- | fish/cmds.c | 67 | ||||
-rw-r--r-- | fish/completion.c | 3 | ||||
-rw-r--r-- | guestfish-actions.pod | 34 | ||||
-rw-r--r-- | guestfs-actions.pod | 43 | ||||
-rw-r--r-- | java/com/redhat/et/libguestfs/GuestFS.java | 69 | ||||
-rw-r--r-- | java/com_redhat_et_libguestfs_GuestFS.c | 51 | ||||
-rw-r--r-- | ocaml/guestfs.ml | 3 | ||||
-rw-r--r-- | ocaml/guestfs.mli | 11 | ||||
-rw-r--r-- | ocaml/guestfs_c_actions.c | 69 | ||||
-rw-r--r-- | perl/Guestfs.xs | 33 | ||||
-rw-r--r-- | perl/lib/Sys/Guestfs.pm | 28 | ||||
-rw-r--r-- | python/guestfs-py.c | 78 | ||||
-rw-r--r-- | python/guestfs.py | 31 | ||||
-rw-r--r-- | ruby/ext/guestfs/_guestfs.c | 69 | ||||
-rw-r--r-- | src/guestfs-actions.c | 240 | ||||
-rw-r--r-- | src/guestfs-actions.h | 3 | ||||
-rw-r--r-- | src/guestfs_protocol.c | 30 | ||||
-rw-r--r-- | src/guestfs_protocol.h | 26 | ||||
-rw-r--r-- | src/guestfs_protocol.x | 15 | ||||
-rw-r--r-- | tests.c | 697 |
22 files changed, 1668 insertions, 16 deletions
diff --git a/daemon/actions.h b/daemon/actions.h index dafbca76..8e79f7b8 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 e51349ae..02c76f1e 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 7b1386fa..411c6f71 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 <path>\n\nReturns file system statistics for any mounted file system.\nC<path> 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<statvfs(2)> system call."); else if (strcasecmp (cmd, "tune2fs_l") == 0 || strcasecmp (cmd, "tune2fs-l") == 0) - pod2text ("tune2fs-l - get ext2/ext3 superblock details", " tune2fs-l <device>\n\nThis returns the contents of the ext2 or ext3 filesystem superblock\non C<device>.\n\nIt is the same as running C<tune2fs -l device>. See L<tune2fs(8)>\nmanpage for more details. The list of fields returned isn't\nclearly defined, and depends on both the version of C<tune2fs>\nthat libguestfs was built against, and the filesystem itself."); + pod2text ("tune2fs-l - get ext2/ext3/ext4 superblock details", " tune2fs-l <device>\n\nThis returns the contents of the ext2, ext3 or ext4 filesystem\nsuperblock on C<device>.\n\nIt is the same as running C<tune2fs -l device>. See L<tune2fs(8)>\nmanpage for more details. The list of fields returned isn't\nclearly defined, and depends on both the version of C<tune2fs>\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 <device>\n\nSets the block device named C<device> to read-only.\n\nThis uses the L<blockdev(8)> command."); @@ -412,6 +415,15 @@ void display_command (const char *cmd) if (strcasecmp (cmd, "debug") == 0) pod2text ("debug - debugging and internals", " debug <subcmd> <extraargs>\n\nThe C<debug> command exposes some internals of\nC<guestfsd> (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<daemon/debug.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 <device>\n\nRemove an LVM logical volume C<device>, where C<device> is\nthe path to the LV, such as C</dev/VG/LV>.\n\nYou can also remove all LVs in a volume group by specifying\nthe VG name, C</dev/VG>."); + else + if (strcasecmp (cmd, "vgremove") == 0) + pod2text ("vgremove - remove an LVM volume group", " vgremove <vgname>\n\nRemove an LVM volume group C<vgname>, (for example C<VG>).\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 <device>\n\nThis wipes a physical volume C<device> so that LVM will no longer\nrecognise it.\n\nThe implementation uses the C<pvremove> 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 8e529810..08d44735 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 a79e3363..47fb59b7 100644 --- a/guestfish-actions.pod +++ b/guestfish-actions.pod @@ -629,6 +629,16 @@ and physical volumes. B<This command is dangerous. Without careful use you can easily destroy all your data>. +=head2 lvremove + + lvremove device + +Remove an LVM logical volume C<device>, where C<device> is +the path to the LV, such as C</dev/VG/LV>. + +You can also remove all LVs in a volume group by specifying +the VG name, C</dev/VG>. + =head2 lvs lvs @@ -730,6 +740,17 @@ This creates an LVM physical volume on the named C<device>, where C<device> should usually be a partition name such as C</dev/sda1>. +=head2 pvremove + + pvremove device + +This wipes a physical volume C<device> so that LVM will no longer +recognise it. + +The implementation uses the C<pvremove> 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<device>. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C<device>. It is the same as running C<tune2fs -l device>. See L<tune2fs(8)> 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<volgroup> from the non-empty list of physical volumes C<physvols>. +=head2 vgremove + + vgremove vgname + +Remove an LVM volume group C<vgname>, (for example C<VG>). + +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 b945454a..7c5223bb 100644 --- a/guestfs-actions.pod +++ b/guestfs-actions.pod @@ -822,6 +822,19 @@ This function returns 0 on success or -1 on error. B<This command is dangerous. Without careful use you can easily destroy all your data>. +=head2 guestfs_lvremove + + int guestfs_lvremove (guestfs_h *handle, + const char *device); + +Remove an LVM logical volume C<device>, where C<device> is +the path to the LV, such as C</dev/VG/LV>. + +You can also remove all LVs in a volume group by specifying +the VG name, C</dev/VG>. + +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</dev/sda1>. 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<device> so that LVM will no longer +recognise it. + +The implementation uses the C<pvremove> 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<device>. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C<device>. It is the same as running C<tune2fs -l device>. See L<tune2fs(8)> manpage for more details. The list of fields returned isn't @@ -1331,6 +1358,18 @@ from the non-empty list of physical volumes C<physvols>. 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<vgname>, (for example C<VG>). + +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 f1cd508b..04a8124c 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 4b96c262..8f5e3537 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 c3305e45..d020df8c 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 846332ca..f38fa48a 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 c396a8a8..73515cfc 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 be13fcde..53c589d9 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 3d1493b5..bd2d9616 100644 --- a/perl/lib/Sys/Guestfs.pm +++ b/perl/lib/Sys/Guestfs.pm @@ -608,6 +608,14 @@ and physical volumes. B<This command is dangerous. Without careful use you can easily destroy all your data>. +=item $h->lvremove ($device); + +Remove an LVM logical volume C<device>, where C<device> is +the path to the LV, such as C</dev/VG/LV>. + +You can also remove all LVs in a volume group by specifying +the VG name, C</dev/VG>. + =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<device>, where C<device> should usually be a partition name such as C</dev/sda1>. +=item $h->pvremove ($device); + +This wipes a physical volume C<device> so that LVM will no longer +recognise it. + +The implementation uses the C<pvremove> 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<device>. +This returns the contents of the ext2, ext3 or ext4 filesystem +superblock on C<device>. It is the same as running C<tune2fs -l device>. See L<tune2fs(8)> manpage for more details. The list of fields returned isn't @@ -899,6 +916,13 @@ See also C<$h-E<gt>download>. This creates an LVM volume group called C<volgroup> from the non-empty list of physical volumes C<physvols>. +=item $h->vgremove ($vgname); + +Remove an LVM volume group C<vgname>, (for example C<VG>). + +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 0022b5b5..38f78c03 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 b2c3e49a..1ebaa74a 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 d4b62cad..0429ae60 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 e143c27b..68f122aa 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 51905285..a11a6b27 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 5bde2b97..2a34a925 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 2a8d9194..826dc42e 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 7f0793f4..348f3f9c 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 }; @@ -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"); |