X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=src%2Fgenerator.ml;h=7edfe6781dc896b76c3b938d0f55c743c63f2704;hp=bdd032c8279e7d43f86d355fdb03ab27a75c161f;hb=5d628a4a9cc11eb9a61a1dc683aadca9ac378736;hpb=0232e722826cfda0f6042da983f9eb871f24e946 diff --git a/src/generator.ml b/src/generator.ml index bdd032c..7edfe67 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -33,6 +33,7 @@ *) #load "unix.cma";; +#load "str.cma";; open Printf @@ -135,7 +136,15 @@ can easily destroy all your data>." * the virtual machine and block devices are reused between tests. * So don't try testing kill_subprocess :-x * - * Between each test we umount-all and lvm-remove-all (except InitNone). + * Between each test we blockdev-setrw, umount-all, lvm-remove-all + * (except InitNone). + * + * If the appliance is running an older Linux kernel (eg. RHEL 5) then + * devices are named /dev/hda etc. To cope with this, the test suite + * adds some hairly logic to detect this case, and then automagically + * replaces all strings which match "/dev/sd.*" with "/dev/hd.*". + * When writing test cases you shouldn't have to worry about this + * difference. * * Don't assume anything about the previous contents of the block * devices. Use 'Init*' to create some initial scenarios. @@ -284,6 +293,29 @@ The first character of C string must be a C<-> (dash). C can be NULL."); + ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"], + [], + "set the qemu binary", + "\ +Set the qemu binary that we will use. + +The default is chosen when the library was compiled by the +configure script. + +You can also override this by setting the C +environment variable. + +Setting C to C restores the default qemu binary."); + + ("get_qemu", (RConstString "qemu", []), -1, [], + [], + "get the qemu binary", + "\ +Return the current qemu binary. + +This is always non-NULL. If it wasn't set already, then this will +return the default qemu binary name."); + ("set_path", (RErr, [String "path"]), -1, [FishAlias "path"], [], "set the search path", @@ -293,9 +325,6 @@ Set the path that libguestfs searches for kernel and initrd.img. The default is C<$libdir/guestfs> unless overridden by setting C environment variable. -The string C is stashed in the libguestfs handle, so the caller -must make sure it remains valid for the lifetime of the handle. - Setting C to C restores the default path."); ("get_path", (RConstString "path", []), -1, [], @@ -307,13 +336,39 @@ Return the current search path. This is always non-NULL. If it wasn't set already, then this will return the default path."); + ("set_append", (RErr, [String "append"]), -1, [FishAlias "append"], + [], + "add options to kernel command line", + "\ +This function is used to add additional options to the +guest kernel command line. + +The default is C unless overridden by setting +C environment variable. + +Setting C to C means I additional options +are passed (libguestfs always adds a few of its own)."); + + ("get_append", (RConstString "append", []), -1, [], + [], + "get the additional kernel options", + "\ +Return the additional kernel options which are added to the +guest kernel command line. + +If C then no options are added."); + ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"], [], "set autosync mode", "\ If C is true, this enables autosync. Libguestfs will make a -best effort attempt to run C when the handle is closed -(also if the program exits without closing handles)."); +best effort attempt to run C followed by +C when the handle is closed +(also if the program exits without closing handles). + +This is disabled by default (except in guestfish where it is +enabled by default)."); ("get_autosync", (RBool "autosync", []), -1, [], [], @@ -399,6 +454,16 @@ actions using the low-level API. For more information on states, see L."); + ("end_busy", (RErr, []), -1, [NotInFish], + [], + "leave the busy state", + "\ +This sets the state to C, or if in C then it leaves the +state as is. This is only used when implementing +actions using the low-level API. + +For more information on states, see L."); + ] let daemon_functions = [ @@ -958,7 +1023,7 @@ on the volume group C, with C megabytes."); "make a filesystem", "\ This creates a filesystem on C (usually a partition -of LVM logical volume). The filesystem type is C, for +or LVM logical volume). The filesystem type is C, for example C."); ("sfdisk", (RErr, [String "device"; @@ -1014,7 +1079,12 @@ with length C. As a special case, if C is C<0> then the length is calculated using C (so in this case -the content cannot contain embedded ASCII NULs)."); +the content cannot contain embedded ASCII NULs). + +I Owing to a bug, writing content containing ASCII NUL +characters does I work, even if the length is specified. +We hope to resolve this bug in a future version. In the meantime +use C."); ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"], [InitEmpty, TestOutputList ( @@ -1047,6 +1117,20 @@ Some internal mounts are not shown."); ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"], [InitBasicFS, TestOutputList ( [["umount_all"]; + ["mounts"]], []); + (* check that umount_all can unmount nested mounts correctly: *) + InitEmpty, TestOutputList ( + [["sfdisk"; "/dev/sda"; "0"; "0"; "0"; ",10 ,20 ,"]; + ["mkfs"; "ext2"; "/dev/sda1"]; + ["mkfs"; "ext2"; "/dev/sda2"]; + ["mkfs"; "ext2"; "/dev/sda3"]; + ["mount"; "/dev/sda1"; "/"]; + ["mkdir"; "/mp1"]; + ["mount"; "/dev/sda2"; "/mp1"]; + ["mkdir"; "/mp1/mp2"]; + ["mount"; "/dev/sda3"; "/mp1/mp2"]; + ["mkdir"; "/mp1/mp2/mp3"]; + ["umount_all"]; ["mounts"]], [])], "unmount all filesystems", "\ @@ -1080,8 +1164,55 @@ The exact command which runs is C. Note in particular that the filename is not prepended to the output (the C<-b> option)."); - ("command", (RString "output", [StringList "arguments"]), 50, [], - [], (* XXX how to test? *) + ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning], + [InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 1"]], "Result1"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 2"]], "Result2\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 3"]], "\nResult3"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 4"]], "\nResult4\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 5"]], "\nResult5\n\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 6"]], "\n\nResult6\n\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 7"]], ""); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 8"]], "\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 9"]], "\n\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n"); + InitBasicFS, TestOutput ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command 11"]], "Result11-1\nResult11-2"); + InitBasicFS, TestLastFail ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command"; "/test-command"]])], "run a command from the guest filesystem", "\ This call runs a command from the guest filesystem. The @@ -1094,6 +1225,13 @@ The first element is the name of the program to run. Subsequent elements are parameters. The list must be non-empty (ie. must contain a program name). +The return value is anything printed to I by +the command. + +If the command returns a non-zero exit status, then +this function returns an error message. The error message +string is the content of I from the command. + The C<$PATH> environment variable will contain at least C and C. If you require a program from another location, you should provide the full path in the @@ -1105,8 +1243,51 @@ correct places. It is the caller's responsibility to ensure all filesystems that are needed are mounted at the right locations."); - ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [], - [], (* XXX how to test? *) + ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning], + [InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 1"]], ["Result1"]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 2"]], ["Result2"]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 3"]], ["";"Result3"]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 4"]], ["";"Result4"]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 5"]], ["";"Result5";""]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 7"]], []); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 8"]], [""]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 9"]], ["";""]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]); + InitBasicFS, TestOutputList ( + [["upload"; "test-command"; "/test-command"]; + ["chmod"; "493"; "/test-command"]; + ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])], "run a command, returning lines", "\ This is the same as C, but splits the @@ -1151,10 +1332,10 @@ This is the same as the C system call."); ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [], [], (* XXX test *) - "get ext2/ext3 superblock details", + "get ext2/ext3/ext4 superblock details", "\ -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 @@ -1409,6 +1590,386 @@ it to local file C. To download an uncompressed tarball, use C."); + ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [], + [InitBasicFS, TestLastFail ( + [["umount"; "/"]; + ["mount_ro"; "/dev/sda1"; "/"]; + ["touch"; "/new"]]); + InitBasicFS, TestOutput ( + [["write_file"; "/new"; "data"; "0"]; + ["umount"; "/"]; + ["mount_ro"; "/dev/sda1"; "/"]; + ["cat"; "/new"]], "data")], + "mount a guest disk, read-only", + "\ +This is the same as the C command, but it +mounts the filesystem with the read-only (I<-o ro>) flag."); + + ("mount_options", (RErr, [String "options"; String "device"; String "mountpoint"]), 74, [], + [], + "mount a guest disk with mount options", + "\ +This is the same as the C command, but it +allows you to set the mount options as for the +L I<-o> flag."); + + ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [], + [], + "mount a guest disk with mount options and vfstype", + "\ +This is the same as the C command, but it +allows you to set both the mount options and the vfstype +as for the L I<-o> and I<-t> flags."); + + ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [], + [], + "debugging and internals", + "\ +The C command exposes some internals of +C (the guestfs daemon) that runs inside the +qemu subprocess. + +There is no comprehensive help for this command. You have +to look at the file C in the libguestfs source +to find out what you can do."); + + ("lvremove", (RErr, [String "device"]), 77, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG/LV1"]; + ["lvs"]], ["/dev/VG/LV2"]); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["lvremove"; "/dev/VG"]; + ["vgs"]], ["VG"])], + "remove an LVM logical volume", + "\ +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."); + + ("vgremove", (RErr, [String "vgname"]), 78, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["vgs"]], [])], + "remove an LVM volume group", + "\ +Remove an LVM volume group C, (for example C). + +This also forcibly removes all logical volumes in the volume +group (if any)."); + + ("pvremove", (RErr, [String "device"]), 79, [], + [InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["lvs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["vgs"]], []); + InitEmpty, TestOutputList ( + [["pvcreate"; "/dev/sda"]; + ["vgcreate"; "VG"; "/dev/sda"]; + ["lvcreate"; "LV1"; "VG"; "50"]; + ["lvcreate"; "LV2"; "VG"; "50"]; + ["vgremove"; "VG"]; + ["pvremove"; "/dev/sda"]; + ["pvs"]], [])], + "remove an LVM physical volume", + "\ +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."); + + ("set_e2label", (RErr, [String "device"; String "label"]), 80, [], + [InitBasicFS, TestOutput ( + [["set_e2label"; "/dev/sda1"; "testlabel"]; + ["get_e2label"; "/dev/sda1"]], "testlabel")], + "set the ext2/3/4 filesystem label", + "\ +This sets the ext2/3/4 filesystem label of the filesystem on +C to C