From bf9044cd7add9d275ad95b641e4158a8a714380e Mon Sep 17 00:00:00 2001 From: Richard W.M. Jones Date: Feb 12 2014 21:58:44 +0000 Subject: New stable branch version 1.24.6. --- diff --git a/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch b/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch index a78434c..168c1cb 100644 --- a/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch +++ b/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch @@ -1,4 +1,4 @@ -From 33b3a097b4b7720d4d43ebe15e9881e976f70e4b Mon Sep 17 00:00:00 2001 +From b42b4f0cba8649a21b925f18b6819026a3cf6df0 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 22 Oct 2013 13:52:25 +0100 Subject: [PATCH] builder: Don't run virt-resize when not necessary. @@ -16,10 +16,10 @@ the template directly to the output file. 1 file changed, 48 insertions(+), 22 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 25ab8c4..16005e1 100644 +index 18c07fc..5f6ff3b 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -232,7 +232,12 @@ let main () = +@@ -234,7 +234,12 @@ let main () = Sigchecker.verify_detached sigchecker template sigfile in @@ -30,10 +30,10 @@ index 25ab8c4..16005e1 100644 + * - did the user specify --size? + *) + let output, size, format, delete_output_file, do_resize, resize_sparse = - let is_block_device file = - try (stat file).st_kind = S_BLK - with Unix_error _ -> false -@@ -259,22 +264,22 @@ let main () = + let headroom = 256L *^ 1024L *^ 1024L in + + match output with +@@ -256,22 +261,22 @@ let main () = (* Dummy: The output file is never deleted in this case. *) let delete_output_file = ref false in @@ -60,7 +60,7 @@ index 25ab8c4..16005e1 100644 (* Create the output file. *) let output, format = -@@ -285,6 +290,14 @@ let main () = +@@ -282,6 +287,14 @@ let main () = | Some output, None -> output, "raw" | Some output, Some format -> output, format in @@ -75,7 +75,7 @@ index 25ab8c4..16005e1 100644 msg (f_"Creating disk image: %s") output; let cmd = sprintf "qemu-img create -f %s%s %s %Ld%s" -@@ -308,30 +321,42 @@ let main () = +@@ -305,30 +318,42 @@ let main () = in at_exit delete_file; @@ -133,7 +133,7 @@ index 25ab8c4..16005e1 100644 (match size with | None -> msg (f_"Running virt-resize to expand the disk") -@@ -356,13 +381,14 @@ let main () = +@@ -353,13 +378,14 @@ let main () = (match lvexpand with | None -> "" | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand)) diff --git a/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch b/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch index 9344168..fb9d643 100644 --- a/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch +++ b/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch @@ -1,4 +1,4 @@ -From 65b953629686797239b33a8dff573390308fa0d4 Mon Sep 17 00:00:00 2001 +From 0adad887c70e26a578dd0809efd339c4b791a615 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 22 Oct 2013 14:09:20 +0100 Subject: [PATCH] builder: Make xzcat binary configurable and use AC_PATH_PROG. @@ -11,10 +11,10 @@ Subject: [PATCH] builder: Make xzcat binary configurable and use AC_PATH_PROG. 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 16005e1..f6d0ad9 100644 +index 5f6ff3b..b1cc1f0 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -323,13 +323,18 @@ let main () = +@@ -320,13 +320,18 @@ let main () = output, Some size, format, delete_output_file, do_resize, true in @@ -34,7 +34,7 @@ index 16005e1..f6d0ad9 100644 if debug then eprintf "%s\n%!" cmd; msg (f_"Uncompressing: %s") file_uri; let r = Sys.command cmd in -@@ -345,7 +350,7 @@ let main () = +@@ -342,7 +347,7 @@ let main () = (* Uncompress it to a temporary file. *) let { Index_parser.file_uri = file_uri } = entry in let tmpfile = Filename.temp_file "vbsrc" ".img" in @@ -44,7 +44,7 @@ index 16005e1..f6d0ad9 100644 msg (f_"Uncompressing: %s") file_uri; let r = Sys.command cmd in diff --git a/configure.ac b/configure.ac -index 0b3980f..35f254d 100644 +index d7430db..a14d5d6 100644 --- a/configure.ac +++ b/configure.ac @@ -698,6 +698,10 @@ if test "x$WRESTOOL" != "xno"; then diff --git a/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch b/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch index 83b8583..48671e7 100644 --- a/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch +++ b/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch @@ -1,4 +1,4 @@ -From 71004a0d015b4d019324ec31b88a842bcad96fef Mon Sep 17 00:00:00 2001 +From 3deff9a2bceba2f1b14fbff316505a9ef9657698 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 22 Oct 2013 14:22:46 +0100 Subject: [PATCH] builder: Use pxzcat (optionally) to speed up xzcat step. @@ -26,10 +26,10 @@ index d9c0219..0e442e1 100644 +--------------+-------------+---+-----------------------------------------+ | ocaml-gettext| | O | For localizing OCaml virt-* tools. | diff --git a/builder/builder.ml b/builder/builder.ml -index f6d0ad9..9951e71 100644 +index b1cc1f0..4fc8a71 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -323,9 +323,11 @@ let main () = +@@ -320,9 +320,11 @@ let main () = output, Some size, format, delete_output_file, do_resize, true in @@ -44,7 +44,7 @@ index f6d0ad9..9951e71 100644 if not do_resize then ( diff --git a/configure.ac b/configure.ac -index 35f254d..2e35252 100644 +index a14d5d6..a378be7 100644 --- a/configure.ac +++ b/configure.ac @@ -702,6 +702,9 @@ dnl Check for xzcat (required). diff --git a/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch b/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch index fe31a17..76fe825 100644 --- a/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch +++ b/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch @@ -1,4 +1,4 @@ -From 7114f530f3c0ae0fda9f7888b426a813c292b071 Mon Sep 17 00:00:00 2001 +From 0c23a38468103dabd260f70397a4de21eda8a591 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 22 Oct 2013 22:28:27 +0100 Subject: [PATCH] builder: Add --no-sync option to avoid sync on exit. @@ -11,10 +11,10 @@ Subject: [PATCH] builder: Add --no-sync option to avoid sync on exit. 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 9951e71..2394c76 100644 +index 4fc8a71..9e41d39 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -38,7 +38,7 @@ let main () = +@@ -40,7 +40,7 @@ let main () = attach, cache, check_signature, curl, debug, delete, edit, fingerprint, firstboot, run, format, gpg, hostname, install, list_long, network, output, password_crypto, quiet, root_password, scrub, scrub_logfile, size, source, @@ -23,7 +23,7 @@ index 9951e71..2394c76 100644 parse_cmdline () in (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -735,7 +735,8 @@ exec >>%s 2>&1 +@@ -732,7 +732,8 @@ exec >>%s 2>&1 * and therefore bypasses the host cache). In general you should not * use cache=none. *) @@ -69,7 +69,7 @@ index 7bbde70..c8e9c46 100644 - upload + sync, upload diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 051b045..9dd86de 100644 +index d31640e..ee53a8a 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -410,6 +410,23 @@ You don't have a host network (eg. in secure/restricted environments). diff --git a/0005-builder-Add-mkdir-option-to-create-directories.patch b/0005-builder-Add-mkdir-option-to-create-directories.patch index 594f560..01a5df1 100644 --- a/0005-builder-Add-mkdir-option-to-create-directories.patch +++ b/0005-builder-Add-mkdir-option-to-create-directories.patch @@ -1,4 +1,4 @@ -From b66bbde1b08b768a5d47b9f515923caab3c9bc72 Mon Sep 17 00:00:00 2001 +From a2113988fab6479f4b912a0b7644fc7a9cb6e22d Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 25 Oct 2013 13:35:51 +0100 Subject: [PATCH] builder: Add --mkdir option to create directories. @@ -12,10 +12,10 @@ Subject: [PATCH] builder: Add --mkdir option to create directories. 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 2394c76..760c8a1 100644 +index 9e41d39..acd016d 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -36,9 +36,9 @@ let main () = +@@ -38,9 +38,9 @@ let main () = (* Command line argument parsing - see cmdline.ml. *) let mode, arg, attach, cache, check_signature, curl, debug, delete, edit, fingerprint, @@ -28,7 +28,7 @@ index 2394c76..760c8a1 100644 parse_cmdline () in (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -575,6 +575,13 @@ exec >>%s 2>&1 +@@ -572,6 +572,13 @@ exec >>%s 2>&1 do_run ~display:cmd cmd ); @@ -96,7 +96,7 @@ index c8d2e58..6f76972 100755 --upload Makefile:/etc \ --delete /Makefile \ diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 9dd86de..d8d3435 100644 +index ee53a8a..dc08a6d 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -19,6 +19,7 @@ virt-builder - Build virtual machine images quickly diff --git a/0006-builder-Allow-upload-to-a-directory.patch b/0006-builder-Allow-upload-to-a-directory.patch index 0420800..c4c0a49 100644 --- a/0006-builder-Allow-upload-to-a-directory.patch +++ b/0006-builder-Allow-upload-to-a-directory.patch @@ -1,4 +1,4 @@ -From 8053edc7bc64dc41655d55f8e4f4ef3242bb0b33 Mon Sep 17 00:00:00 2001 +From 3d26612fcac6ec51fe34822b07577fb415c00f85 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 26 Oct 2013 11:27:06 +0100 Subject: [PATCH] builder: Allow --upload to a directory. diff --git a/0007-builder-Add-write-option-to-write-a-literal-file.patch b/0007-builder-Add-write-option-to-write-a-literal-file.patch index ba1cea8..29477f6 100644 --- a/0007-builder-Add-write-option-to-write-a-literal-file.patch +++ b/0007-builder-Add-write-option-to-write-a-literal-file.patch @@ -1,4 +1,4 @@ -From 17c806003bb1d41f1a70c407991c8de1d48ed492 Mon Sep 17 00:00:00 2001 +From 5937b734dd6ac056766080a096a8a1060894a688 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 26 Oct 2013 11:40:48 +0100 Subject: [PATCH] builder: Add --write option to write a literal file. @@ -12,10 +12,10 @@ Subject: [PATCH] builder: Add --write option to write a literal file. 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 760c8a1..a89b03f 100644 +index acd016d..f247cd2 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -38,7 +38,7 @@ let main () = +@@ -40,7 +40,7 @@ let main () = attach, cache, check_signature, curl, debug, delete, edit, fingerprint, firstboot, run, format, gpg, hostname, install, list_long, mkdirs, network, output, password_crypto, quiet, root_password, scrub, @@ -24,7 +24,7 @@ index 760c8a1..a89b03f 100644 parse_cmdline () in (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -582,6 +582,13 @@ exec >>%s 2>&1 +@@ -579,6 +579,13 @@ exec >>%s 2>&1 g#mkdir_p dir ) mkdirs; @@ -97,7 +97,7 @@ index 30c3cf8..438f2e9 100755 --upload Makefile:/etc/foo/bar/baz \ --delete /Makefile \ diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index d8d3435..766815d 100644 +index dc08a6d..e40dfd4 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -20,6 +20,7 @@ virt-builder - Build virtual machine images quickly diff --git a/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch b/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch index dae9b7c..7f592c5 100644 --- a/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch +++ b/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch @@ -1,4 +1,4 @@ -From f27194ce17e0806c3e3d917626c48b5f63e49928 Mon Sep 17 00:00:00 2001 +From 34d4789bf939b44e76af2f6ae2186e1638986aa2 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 26 Oct 2013 14:45:30 +0100 Subject: [PATCH] builder: Document how to boot VMs directly in qemu or KVM. @@ -9,7 +9,7 @@ Subject: [PATCH] builder: Document how to boot VMs directly in qemu or KVM. 1 file changed, 15 insertions(+) diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 766815d..c8e1ad7 100644 +index e40dfd4..a5f766d 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -865,6 +865,21 @@ To boot up an instance of your image on a Nova compute node, do: diff --git a/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch b/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch index 9e3d734..6f818f4 100644 --- a/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch +++ b/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch @@ -1,4 +1,4 @@ -From e0a88763ad882bcbad2b66adeafee33be2179a2d Mon Sep 17 00:00:00 2001 +From 2bd65a4b80934dff8efaee2bfce6ccccc02e58e0 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sat, 26 Oct 2013 17:09:06 +0100 Subject: [PATCH] firstboot: Send the output to the console as well as to the diff --git a/0010-builder-Add-a-section-on-performance-to-the-manual.patch b/0010-builder-Add-a-section-on-performance-to-the-manual.patch index 9c7bee3..b98401f 100644 --- a/0010-builder-Add-a-section-on-performance-to-the-manual.patch +++ b/0010-builder-Add-a-section-on-performance-to-the-manual.patch @@ -1,22 +1,21 @@ -From 269da752908ac9a8ba0ab6d12e5e020cd3179657 Mon Sep 17 00:00:00 2001 +From f3f0dc3c93a4ab0e5eb4b93e1e5515a69fc20f37 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Sun, 27 Oct 2013 14:59:39 +0000 Subject: [PATCH] builder: Add a section on performance to the manual. (cherry picked from commit 2937c035958f84986e84c47df49f79d19c4b5b59) --- - builder/virt-builder.pod | 45 ++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 44 insertions(+), 1 deletion(-) + builder/virt-builder.pod | 43 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index c8e1ad7..bcd3615 100644 +index a5f766d..cd20043 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod -@@ -1312,7 +1312,50 @@ etc are truly random when the guest boots. +@@ -1330,6 +1330,49 @@ want clones to have duplicate identities. - You should check digital signatures and not ignore any signing errors. + See also: L. --=head2 USER MODE LINUX +=head2 PERFORMANCE + +The most important aspect of getting good performance is caching. @@ -60,10 +59,9 @@ index c8e1ad7..bcd3615 100644 +which is single-threaded. Currently this has to be compiled in, +ie. virt-builder will probably need to be recompiled to use pxzcat. + -+=head3 User-Mode Linux + =head2 USER MODE LINUX You can use virt-builder with the User-Mode Linux (UML) backend. This - may be faster when running virt-builder inside a virtual machine -- 1.8.4.2 diff --git a/0011-builder-Add-m-memsize-and-smp-command-line-options.patch b/0011-builder-Add-m-memsize-and-smp-command-line-options.patch index ed63419..e75a1e8 100644 --- a/0011-builder-Add-m-memsize-and-smp-command-line-options.patch +++ b/0011-builder-Add-m-memsize-and-smp-command-line-options.patch @@ -1,4 +1,4 @@ -From 6a3be2dbe7dcba8e0b0880168bfb880e74fbd9c3 Mon Sep 17 00:00:00 2001 +From f9fe74926f476cf12f81988f2dffb34bb77607cb Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 29 Oct 2013 19:23:33 +0000 Subject: [PATCH] builder: Add -m/--memsize and --smp command line options. @@ -11,10 +11,10 @@ Subject: [PATCH] builder: Add -m/--memsize and --smp command line options. 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index a89b03f..85234e0 100644 +index f247cd2..2437d56 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -36,9 +36,9 @@ let main () = +@@ -38,9 +38,9 @@ let main () = (* Command line argument parsing - see cmdline.ml. *) let mode, arg, attach, cache, check_signature, curl, debug, delete, edit, fingerprint, @@ -26,7 +26,7 @@ index a89b03f..85234e0 100644 parse_cmdline () in (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -403,6 +403,8 @@ let main () = +@@ -400,6 +400,8 @@ let main () = let g = new G.guestfs () in if debug then g#set_trace true; @@ -102,7 +102,7 @@ index 28a1643..97ccd89 100644 - scrub_logfile, size, source, sync, upload, writes + scrub_logfile, size, smp, source, sync, upload, writes diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index bcd3615..7d486f7 100644 +index cd20043..66ed030 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -366,6 +366,18 @@ the image was built, use this option. @@ -135,7 +135,7 @@ index bcd3615..7d486f7 100644 =item B<--source> URL Set the source URL to look for templates. If not specified it -@@ -1402,12 +1418,6 @@ are actually interpreted by L, not virt-builder. +@@ -1438,12 +1454,6 @@ are actually interpreted by L, not virt-builder. Used to determine the location of the template cache. See L. diff --git a/0012-builder-Allow-multiple-source-paths-to-be-specified.patch b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch index 1e49d7d..38e1b22 100644 --- a/0012-builder-Allow-multiple-source-paths-to-be-specified.patch +++ b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch @@ -1,4 +1,4 @@ -From ebf8c4404850977946904aae3f905479916fce21 Mon Sep 17 00:00:00 2001 +From 502027f0517a5ef6784dc09681ef1bca6cc35ad5 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Fri, 1 Nov 2013 14:16:34 +0000 Subject: [PATCH] builder: Allow multiple source paths to be specified. @@ -27,10 +27,10 @@ There is still only one built-in path, but we can add more later. 10 files changed, 143 insertions(+), 46 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 85234e0..a3a31e5 100644 +index 2437d56..b375de4 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -35,22 +35,27 @@ let prog = Filename.basename Sys.executable_name +@@ -37,22 +37,27 @@ let () = Random.self_init () let main () = (* Command line argument parsing - see cmdline.ml. *) let mode, arg, @@ -62,7 +62,7 @@ index 85234e0..a3a31e5 100644 (* Handle some modes here, some later on. *) let mode = match mode with -@@ -125,19 +130,23 @@ let main () = +@@ -127,19 +132,23 @@ let main () = ) in @@ -93,7 +93,7 @@ index 85234e0..a3a31e5 100644 exit 0 | `Print_cache -> (* --print-cache *) -@@ -184,6 +193,7 @@ let main () = +@@ -186,6 +195,7 @@ let main () = eprintf (f_"%s: cannot find os-version '%s'.\nUse --list to list available guest types.\n") prog arg; exit 1 in @@ -354,7 +354,7 @@ index 3a159bb..3077b23 100755 os-version: phony-debian Full name: Phony Debian diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 7d486f7..bbcdb3a 100644 +index 66ed030..39729d6 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -264,10 +264,14 @@ Check that the index and templates are signed by the key with the @@ -427,7 +427,7 @@ index 7d486f7..bbcdb3a 100644 =head3 Licensing of templates You should be aware of the licensing of images that you distribute. -@@ -1420,13 +1457,13 @@ Used to determine the location of the template cache. See L. +@@ -1456,13 +1493,13 @@ Used to determine the location of the template cache. See L. =item C diff --git a/0013-builder-Add-a-real-scanner-parser-for-index-files.patch b/0013-builder-Add-a-real-scanner-parser-for-index-files.patch index 4fa5ad9..456f00b 100644 --- a/0013-builder-Add-a-real-scanner-parser-for-index-files.patch +++ b/0013-builder-Add-a-real-scanner-parser-for-index-files.patch @@ -1,4 +1,4 @@ -From 142ae72758d659df4a6a945c827b8dcffb2388f5 Mon Sep 17 00:00:00 2001 +From 3ff459f0e50cdf8aa26053b59b0a183636813241 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 4 Nov 2013 14:53:41 +0000 Subject: [PATCH] builder: Add a real scanner/parser for index files. @@ -36,7 +36,7 @@ This adds a tool called virt-index-validate to validate index files. create mode 100644 builder/virt-index-validate.pod diff --git a/.gitignore b/.gitignore -index ea42d28..4a77963 100644 +index 7bcd500..8f0cda3 100644 --- a/.gitignore +++ b/.gitignore @@ -58,10 +58,16 @@ Makefile.in @@ -80,7 +80,7 @@ index 0e442e1..dee3bd4 100644 +--------------+-------------+---+-----------------------------------------+ | genisoimage | | R | mkisofs may work. | diff --git a/builder/Makefile.am b/builder/Makefile.am -index e3878dc..2a1e448 100644 +index b8bf6ac..ff27318 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -17,6 +17,12 @@ @@ -96,7 +96,7 @@ index e3878dc..2a1e448 100644 EXTRA_DIST = \ $(SOURCES) \ virt-builder.pod \ -@@ -42,6 +48,9 @@ SOURCES = \ +@@ -40,6 +46,9 @@ SOURCES = \ sigchecker.mli \ sigchecker.ml @@ -106,7 +106,7 @@ index e3878dc..2a1e448 100644 if HAVE_OCAML # Note this list must be in dependency order. -@@ -59,6 +68,10 @@ OBJECTS = \ +@@ -58,6 +67,10 @@ OBJECTS = \ $(top_builddir)/mllib/fsync.cmx \ $(top_builddir)/mllib/password.cmx \ $(top_builddir)/mllib/config.cmx \ @@ -117,7 +117,7 @@ index e3878dc..2a1e448 100644 get_kernel.cmx \ downloader.cmx \ sigchecker.cmx \ -@@ -99,24 +112,10 @@ virt-builder: $(OBJECTS) +@@ -97,24 +110,10 @@ virt-builder: $(OBJECTS) .ml.cmx: $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@ @@ -144,7 +144,7 @@ index e3878dc..2a1e448 100644 virt-builder.1 $(top_builddir)/html/virt-builder.1.html: stamp-virt-builder.pod -@@ -172,3 +171,28 @@ endif +@@ -170,3 +169,28 @@ endif DISTCLEANFILES = .depend .PHONY: depend docs @@ -1037,7 +1037,7 @@ index 3077b23..ff16abe 100755 echo "$long_list" exit 1 diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index bbcdb3a..71569ec 100644 +index 39729d6..ce22920 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -1269,6 +1269,23 @@ For open source guests, provide a link to the source code in the @@ -1163,7 +1163,7 @@ index 0000000..6b03703 + +Copyright (C) 2013 Red Hat Inc. diff --git a/configure.ac b/configure.ac -index 2e35252..35d0879 100644 +index a378be7..732946f 100644 --- a/configure.ac +++ b/configure.ac @@ -705,6 +705,10 @@ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed]) diff --git a/0014-builder-Fix-missing-files-in-EXTRA_DIST.patch b/0014-builder-Fix-missing-files-in-EXTRA_DIST.patch index 2886812..fb20f4c 100644 --- a/0014-builder-Fix-missing-files-in-EXTRA_DIST.patch +++ b/0014-builder-Fix-missing-files-in-EXTRA_DIST.patch @@ -1,4 +1,4 @@ -From 48ee01ebe27fe3d5123f9ee70b478cd367df363a Mon Sep 17 00:00:00 2001 +From 9d625cbc7121ca518ddfe01d6a6705a2b86b9bfe Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 07:15:19 +0000 Subject: [PATCH] builder: Fix missing files in EXTRA_DIST. @@ -11,7 +11,7 @@ This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633. 1 file changed, 2 insertions(+) diff --git a/builder/Makefile.am b/builder/Makefile.am -index 2a1e448..0af3f95 100644 +index ff27318..b892477 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -26,6 +26,7 @@ AM_CFLAGS = \ @@ -29,7 +29,7 @@ index 2a1e448..0af3f95 100644 + index-parser-c.c \ list_entries.mli \ list_entries.ml \ - perl_edit.ml \ + sigchecker.mli \ -- 1.8.4.2 diff --git a/0015-builder-website-Add-index-validation-test-script.patch b/0015-builder-website-Add-index-validation-test-script.patch index b892fe0..f905ebf 100644 --- a/0015-builder-website-Add-index-validation-test-script.patch +++ b/0015-builder-website-Add-index-validation-test-script.patch @@ -1,4 +1,4 @@ -From 2627de60b603630ba8be79707766d5631d56f714 Mon Sep 17 00:00:00 2001 +From 521414b8f2fcd33994c79e68f5324222d3c9530f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 07:25:46 +0000 Subject: [PATCH] builder/website: Add index validation test script. diff --git a/0016-builder-Internal-implementation-of-parallel-xzcat-px.patch b/0016-builder-Internal-implementation-of-parallel-xzcat-px.patch index 337a410..6b71282 100644 --- a/0016-builder-Internal-implementation-of-parallel-xzcat-px.patch +++ b/0016-builder-Internal-implementation-of-parallel-xzcat-px.patch @@ -1,4 +1,4 @@ -From 2eabacbc0d217ece0091dc754969f0c0df3c7eac Mon Sep 17 00:00:00 2001 +From 1fecdfb2a3f56bfc602d0cbcc489c04059cb672b Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 10:21:32 +0000 Subject: [PATCH] builder: Internal implementation of parallel xzcat (pxzcat). @@ -42,7 +42,7 @@ index dee3bd4..8192086 100644 +--------------+-------------+---+-----------------------------------------+ | findlib | | O | For the OCaml bindings. | diff --git a/builder/Makefile.am b/builder/Makefile.am -index 0af3f95..9430d62 100644 +index b892477..1c469ac 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am @@ -21,7 +21,9 @@ AM_YFLAGS = -d @@ -56,17 +56,17 @@ index 0af3f95..9430d62 100644 EXTRA_DIST = \ $(SOURCES) \ -@@ -47,6 +49,9 @@ SOURCES = \ +@@ -45,6 +47,9 @@ SOURCES = \ + index-parser-c.c \ + list_entries.mli \ list_entries.ml \ - perl_edit.ml \ - perl_edit.mli \ + pxzcat.ml \ + pxzcat.mli \ + pxzcat-c.c \ sigchecker.mli \ sigchecker.ml -@@ -74,6 +79,8 @@ OBJECTS = \ +@@ -73,6 +78,8 @@ OBJECTS = \ index-struct.o \ index-parse.o \ index-parser-c.o \ @@ -75,7 +75,7 @@ index 0af3f95..9430d62 100644 get_kernel.cmx \ downloader.cmx \ sigchecker.cmx \ -@@ -103,7 +110,7 @@ OCAMLOPTFLAGS = $(OCAMLCFLAGS) +@@ -101,7 +108,7 @@ OCAMLOPTFLAGS = $(OCAMLCFLAGS) virt-builder: $(OBJECTS) $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \ mlguestfs.cmxa -linkpkg $^ \ @@ -85,7 +85,7 @@ index 0af3f95..9430d62 100644 -o $@ diff --git a/builder/builder.ml b/builder/builder.ml -index a3a31e5..7dba186 100644 +index b375de4..7cbc539 100644 --- a/builder/builder.ml +++ b/builder/builder.ml @@ -24,6 +24,7 @@ open Common_utils @@ -96,7 +96,7 @@ index a3a31e5..7dba186 100644 open Unix open Printf -@@ -333,27 +334,14 @@ let main () = +@@ -330,27 +331,14 @@ let main () = output, Some size, format, delete_output_file, do_resize, true in @@ -125,7 +125,7 @@ index a3a31e5..7dba186 100644 ) else ( (* If none of the above apply, uncompress to a temporary file and * run virt-resize on the result. -@@ -362,14 +350,8 @@ let main () = +@@ -359,14 +347,8 @@ let main () = (* Uncompress it to a temporary file. *) let { Index_parser.file_uri = file_uri } = entry in let tmpfile = Filename.temp_file "vbsrc" ".img" in @@ -860,10 +860,10 @@ index 0000000..a2830f0 + implementation of parallel xzcat. Otherwise regular xzcat is + used. *) diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 71569ec..a1b2a1f 100644 +index ce22920..e84d87f 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod -@@ -1420,10 +1420,9 @@ the output format is the same as the template format (usually raw). +@@ -1438,10 +1438,9 @@ the output format is the same as the template format (usually raw). =head3 pxzcat @@ -875,10 +875,10 @@ index 71569ec..a1b2a1f 100644 +xzcat) if liblzma was found at build time. If liblzma was not found +at build time, regular C is used which is single-threaded. - =head3 User-Mode Linux + =head2 USER MODE LINUX diff --git a/configure.ac b/configure.ac -index 35d0879..7648977 100644 +index 732946f..56a7eb5 100644 --- a/configure.ac +++ b/configure.ac @@ -701,9 +701,15 @@ fi @@ -926,13 +926,13 @@ index 5418a6b..1e831ff 100644 cat/filesystems.c cat/ls.c diff --git a/po/POTFILES-ml b/po/POTFILES-ml -index 2ca1042..efeb75d 100644 +index eff4de4..a63b69a 100644 --- a/po/POTFILES-ml +++ b/po/POTFILES-ml -@@ -5,6 +5,7 @@ builder/get_kernel.ml +@@ -4,6 +4,7 @@ builder/downloader.ml + builder/get_kernel.ml builder/index_parser.ml builder/list_entries.ml - builder/perl_edit.ml +builder/pxzcat.ml builder/sigchecker.ml mllib/common_gettext.ml diff --git a/0017-builder-website-Add-validate.sh-test-script-to-EXTRA.patch b/0017-builder-website-Add-validate.sh-test-script-to-EXTRA.patch index 7f1e8e7..d64a42f 100644 --- a/0017-builder-website-Add-validate.sh-test-script-to-EXTRA.patch +++ b/0017-builder-website-Add-validate.sh-test-script-to-EXTRA.patch @@ -1,4 +1,4 @@ -From e91cfd9900ec8efeff8692731608a1fc95917a64 Mon Sep 17 00:00:00 2001 +From 04bbe36875dd73533d8841b9435831480b922a70 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 15:15:17 +0000 Subject: [PATCH] builder/website: Add validate.sh test script to EXTRA_DIST. diff --git a/0018-builder-Add-missing-dependency.patch b/0018-builder-Add-missing-dependency.patch index 3cfa851..4062afc 100644 --- a/0018-builder-Add-missing-dependency.patch +++ b/0018-builder-Add-missing-dependency.patch @@ -1,4 +1,4 @@ -From b5889645e7c558b3d65206920235ac1ac990f509 Mon Sep 17 00:00:00 2001 +From 8c3b96d95efc6a91e99a7da6f1689adc2dcaa807 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 15:42:05 +0000 Subject: [PATCH] builder: Add missing dependency. @@ -16,10 +16,10 @@ This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633. 1 file changed, 2 insertions(+) diff --git a/builder/Makefile.am b/builder/Makefile.am -index 9430d62..606ecc4 100644 +index 1c469ac..30741a0 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am -@@ -121,6 +121,8 @@ virt-builder: $(OBJECTS) +@@ -119,6 +119,8 @@ virt-builder: $(OBJECTS) .ml.cmx: $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@ diff --git a/0019-builder-Add-some-generated-files-to-CLEANFILES.patch b/0019-builder-Add-some-generated-files-to-CLEANFILES.patch index 2cc8668..1827dc7 100644 --- a/0019-builder-Add-some-generated-files-to-CLEANFILES.patch +++ b/0019-builder-Add-some-generated-files-to-CLEANFILES.patch @@ -1,4 +1,4 @@ -From 9a97ac527afdacc07007aa1f0ec84c2a6f95b608 Mon Sep 17 00:00:00 2001 +From 2129b9267c2a26a15a2128cd1f9086f7e659ccb9 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 15:43:24 +0000 Subject: [PATCH] builder: Add some generated files to CLEANFILES. @@ -11,10 +11,10 @@ This updates commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633. 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/builder/Makefile.am b/builder/Makefile.am -index 606ecc4..97550a8 100644 +index 30741a0..244214b 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am -@@ -206,4 +206,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod +@@ -204,4 +204,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod $< touch $@ diff --git a/0020-builder-Add-dependency-from-index-parse.h-to-index-v.patch b/0020-builder-Add-dependency-from-index-parse.h-to-index-v.patch index f28b038..9a1a5a3 100644 --- a/0020-builder-Add-dependency-from-index-parse.h-to-index-v.patch +++ b/0020-builder-Add-dependency-from-index-parse.h-to-index-v.patch @@ -1,4 +1,4 @@ -From 065d9527e1f694f99e31950b298eb5990c7c024d Mon Sep 17 00:00:00 2001 +From f334675344aec741d10d076835e202874f3adb33 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 15:56:34 +0000 Subject: [PATCH] builder: Add dependency from index-parse.h to index-validate. @@ -13,10 +13,10 @@ rest of the build. 1 file changed, 2 insertions(+) diff --git a/builder/Makefile.am b/builder/Makefile.am -index 97550a8..3ad18cc 100644 +index 244214b..09401af 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am -@@ -193,6 +193,8 @@ virt_index_validate_SOURCES = \ +@@ -191,6 +191,8 @@ virt_index_validate_SOURCES = \ index-struct.c \ index-validate.c diff --git a/0021-builder-Add-dependencies-which-automake-doesn-t-gene.patch b/0021-builder-Add-dependencies-which-automake-doesn-t-gene.patch index 243ed56..a9b02b0 100644 --- a/0021-builder-Add-dependencies-which-automake-doesn-t-gene.patch +++ b/0021-builder-Add-dependencies-which-automake-doesn-t-gene.patch @@ -1,4 +1,4 @@ -From 0d06b917f7c8fa15e397f64d964326ce22631847 Mon Sep 17 00:00:00 2001 +From eee820fe7675ab79c33efe43684cef5c415b4ec7 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 17:40:20 +0000 Subject: [PATCH] builder: Add dependencies which automake doesn't generate @@ -14,10 +14,10 @@ commit dfe97b352d6b398c3cb3ddb1c9984767722e514b 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/builder/Makefile.am b/builder/Makefile.am -index 3ad18cc..30ada87 100644 +index 09401af..8e7f104 100644 --- a/builder/Makefile.am +++ b/builder/Makefile.am -@@ -121,8 +121,6 @@ virt-builder: $(OBJECTS) +@@ -119,8 +119,6 @@ virt-builder: $(OBJECTS) .ml.cmx: $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@ @@ -26,7 +26,7 @@ index 3ad18cc..30ada87 100644 # Manual pages and HTML files for the website. man_MANS += virt-builder.1 -@@ -193,8 +191,6 @@ virt_index_validate_SOURCES = \ +@@ -191,8 +189,6 @@ virt_index_validate_SOURCES = \ index-struct.c \ index-validate.c @@ -35,7 +35,7 @@ index 3ad18cc..30ada87 100644 man_MANS += virt-index-validate.1 noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html -@@ -213,3 +209,10 @@ CLEANFILES += \ +@@ -211,3 +207,10 @@ CLEANFILES += \ index-parse.h \ index-scan.c \ stamp-virt-index-validate.pod diff --git a/0022-builder-Fail-if-bison-is-not-installed.patch b/0022-builder-Fail-if-bison-is-not-installed.patch index 5470ba1..bdf53be 100644 --- a/0022-builder-Fail-if-bison-is-not-installed.patch +++ b/0022-builder-Fail-if-bison-is-not-installed.patch @@ -1,4 +1,4 @@ -From 51e511ec86c0f35363721a8912b40fc0b9c200c3 Mon Sep 17 00:00:00 2001 +From 21eb78f2f655b34a6b55f0d3d76f2523732f2666 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Tue, 5 Nov 2013 22:25:59 +0000 Subject: [PATCH] builder: Fail if bison is not installed. @@ -11,7 +11,7 @@ This partially fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633. 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac -index 7648977..59960c8 100644 +index 56a7eb5..f6a08c9 100644 --- a/configure.ac +++ b/configure.ac @@ -711,9 +711,14 @@ PKG_CHECK_MODULES([LIBLZMA], [liblzma],[ diff --git a/0023-builder-Fail-if-lex-is-not-installed.patch b/0023-builder-Fail-if-lex-is-not-installed.patch index 6c33834..227dd3b 100644 --- a/0023-builder-Fail-if-lex-is-not-installed.patch +++ b/0023-builder-Fail-if-lex-is-not-installed.patch @@ -1,4 +1,4 @@ -From 50ba3ce108ccdeca327c904213094fcbdfcc51e7 Mon Sep 17 00:00:00 2001 +From 8f266bb2dbb769eecb30f5c1563b9e2c2fce533f Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 6 Nov 2013 15:08:08 +0000 Subject: [PATCH] builder: Fail if lex is not installed. @@ -11,7 +11,7 @@ This completes the fix for commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633. 1 file changed, 3 insertions(+) diff --git a/configure.ac b/configure.ac -index 59960c8..634f75d 100644 +index f6a08c9..872b9a6 100644 --- a/configure.ac +++ b/configure.ac @@ -716,6 +716,9 @@ dnl XXX Could be optional with some work. diff --git a/0024-builder-sysprep-Allow-random-as-a-password-selector.patch b/0024-builder-sysprep-Allow-random-as-a-password-selector.patch index 456c6cb..6908110 100644 --- a/0024-builder-sysprep-Allow-random-as-a-password-selector.patch +++ b/0024-builder-sysprep-Allow-random-as-a-password-selector.patch @@ -1,4 +1,4 @@ -From 6c102fd01dc1cfccc0805c76ed2c333f0f3e63ee Mon Sep 17 00:00:00 2001 +From 210795169c0ba03d9287f78a639e6d403a4b0c10 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 21 Nov 2013 17:34:44 +0000 Subject: [PATCH] builder/sysprep: Allow 'random' as a password selector. @@ -15,10 +15,10 @@ This chooses a random password. 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 7dba186..473460c 100644 +index 7cbc539..57e903c 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -448,31 +448,19 @@ let main () = +@@ -445,31 +445,19 @@ let main () = * Note 'None' means that we randomize the root password. *) let () = @@ -62,7 +62,7 @@ index 7dba186..473460c 100644 eprintf (f_"%s: warning: root password could not be set for this type of guest\n%!") prog in diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index a1b2a1f..f70802b 100644 +index e84d87f..2803142 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -712,6 +712,13 @@ Set the root password to the literal string C. diff --git a/0025-builder-sysprep-Allow-accounts-to-be-locked-RHBZ-102.patch b/0025-builder-sysprep-Allow-accounts-to-be-locked-RHBZ-102.patch index bd9773d..22cd122 100644 --- a/0025-builder-sysprep-Allow-accounts-to-be-locked-RHBZ-102.patch +++ b/0025-builder-sysprep-Allow-accounts-to-be-locked-RHBZ-102.patch @@ -1,4 +1,4 @@ -From 08ffde60906f113fa2c8d6c56efb7d7bd0b15015 Mon Sep 17 00:00:00 2001 +From fddbb679b27e45fa4ef83446670de48ce12466d4 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Thu, 21 Nov 2013 17:13:22 +0000 Subject: [PATCH] builder/sysprep: Allow accounts to be locked (RHBZ#1028660). @@ -27,10 +27,10 @@ probably not useful. The shadow password field will contain "!!*". 5 files changed, 100 insertions(+), 16 deletions(-) diff --git a/builder/builder.ml b/builder/builder.ml -index 473460c..2050d10 100644 +index 57e903c..690f3e2 100644 --- a/builder/builder.ml +++ b/builder/builder.ml -@@ -458,7 +458,7 @@ let main () = +@@ -455,7 +455,7 @@ let main () = pw | None -> msg (f_"Setting random root password [did you mean to use --root-password?]"); @@ -40,7 +40,7 @@ index 473460c..2050d10 100644 set_linux_passwords ~prog ?password_crypto g root password_map | _ -> diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index f70802b..02b07e4 100644 +index 2803142..817ddd4 100644 --- a/builder/virt-builder.pod +++ b/builder/virt-builder.pod @@ -719,6 +719,27 @@ has approximately 120 bits of randomness. diff --git a/0026-builder-Move-is_block_device-function-into-common-ut.patch b/0026-builder-Move-is_block_device-function-into-common-ut.patch deleted file mode 100644 index 6461b4c..0000000 --- a/0026-builder-Move-is_block_device-function-into-common-ut.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 330f37c4c0937ca258595254a647c57a7e6554c2 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 13:18:48 +0000 -Subject: [PATCH] builder: Move is_block_device function into common utilities. - -This is just code motion. - -(cherry picked from commit 81b4e5d5cd68f65aa950251e22332b3fa477fecb) ---- - builder/builder.ml | 3 --- - mllib/common_utils.ml | 4 ++++ - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 2050d10..86e38f3 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -249,9 +249,6 @@ let main () = - * - did the user specify --size? - *) - let output, size, format, delete_output_file, do_resize, resize_sparse = -- let is_block_device file = -- try (stat file).st_kind = S_BLK -- with Unix_error _ -> false - in - - let headroom = 256L *^ 1024L *^ 1024L in -diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml -index 1f8208b..357ffba 100644 ---- a/mllib/common_utils.ml -+++ b/mllib/common_utils.ml -@@ -401,6 +401,10 @@ let rm_rf_only_files (g : Guestfs.guestfs) dir = - List.iter g#rm files - ) - -+let is_block_device file = -+ try (Unix.stat file).Unix.st_kind = Unix.S_BLK -+ with Unix.Unix_error _ -> false -+ - let is_char_device file = - try (Unix.stat file).Unix.st_kind = Unix.S_CHR - with Unix.Unix_error _ -> false --- -1.8.4.2 - diff --git a/0026-builder-Use-a-planner-to-work-out-how-to-convert-the.patch b/0026-builder-Use-a-planner-to-work-out-how-to-convert-the.patch new file mode 100644 index 0000000..1a0a07c --- /dev/null +++ b/0026-builder-Use-a-planner-to-work-out-how-to-convert-the.patch @@ -0,0 +1,730 @@ +From 0eacd5a33820223d747f0a0f7f2a13c1e6d9f02b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 13 Dec 2013 13:18:47 +0000 +Subject: [PATCH] builder: Use a planner to work out how to convert the + template to the final image. + +The original template might be, say, xz-compressed raw of a certain +size. We need to work out how to convert it to, say, qcow2 with a +larger size, in as few operations as possible. + +Instead of using a nasty aggregation of special cases to do this, use +a breadth-first search over all possible trees to try to find an +optimal plan. + +(Actually the current implementation isn't optimal, but it's fine for +virt-builder.) + +(cherry picked from commit 62cc7d3361127b4e007f8e23028213852be09124) +--- + builder/Makefile.am | 1 + + builder/builder.ml | 407 +++++++++++++++++++++++++++++++++----------------- + mllib/Makefile.am | 5 +- + mllib/common_utils.ml | 12 ++ + mllib/planner.ml | 80 ++++++++++ + mllib/planner.mli | 78 ++++++++++ + po/POTFILES-ml | 1 + + 7 files changed, 448 insertions(+), 136 deletions(-) + create mode 100644 mllib/planner.ml + create mode 100644 mllib/planner.mli + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 8e7f104..0d9ea75 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -73,6 +73,7 @@ OBJECTS = \ + $(top_builddir)/mllib/fsync-c.o \ + $(top_builddir)/mllib/fsync.cmx \ + $(top_builddir)/mllib/password.cmx \ ++ $(top_builddir)/mllib/planner.cmx \ + $(top_builddir)/mllib/config.cmx \ + index-scan.o \ + index-struct.o \ +diff --git a/builder/builder.ml b/builder/builder.ml +index 690f3e2..71dfe13 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -22,9 +22,9 @@ module G = Guestfs + + open Common_utils + open Password ++open Planner + + open Cmdline +-open Pxzcat + + open Unix + open Printf +@@ -245,146 +245,281 @@ let main () = + + Sigchecker.verify_detached sigchecker template sigfile in + +- (* Plan how to create the output. This depends on: +- * - did the user specify --output? +- * - is the output a block device? +- * - did the user specify --size? +- *) +- let output, size, format, delete_output_file, do_resize, resize_sparse = +- let headroom = 256L *^ 1024L *^ 1024L in +- +- match output with +- (* If the output file was specified and it exists and it's a block +- * device, then we should skip the creation step. ++ (* Planner: Input tags. *) ++ let itags = ++ let { Index_parser.size = size; format = format } = entry in ++ let format = match format with None -> "auto" | Some format -> format in ++ let compression_tags = ++ match detect_compression template with ++ | `XZ -> [ `XZ, "" ] ++ | `Unknown -> [] ++ in ++ [ `Template, ""; `Filename, template; `Size, Int64.to_string size; ++ `Format, format ] @ compression_tags in ++ ++ (* Planner: Goal. *) ++ let output_size = ++ let { Index_parser.size = default_size } = entry in ++ match size with None -> default_size | Some size -> size in ++ let output_filename, output_format = ++ match output, format with ++ | None, None -> sprintf "%s.img" arg, "raw" ++ | None, Some "raw" -> sprintf "%s.img" arg, "raw" ++ | None, Some format -> sprintf "%s.%s" arg format, format ++ | Some output, None -> output, "raw" ++ | Some output, Some format -> output, format in ++ let output_is_block_dev = is_block_device output_filename in ++ ++ if output_is_block_dev && size <> None then ( ++ eprintf (f_"%s: you cannot use --size option with block devices\n") prog; ++ exit 1 ++ ); ++ ++ let goal = ++ (* MUST *) ++ let goal_must = [ ++ `Filename, output_filename; ++ `Size, Int64.to_string output_size; ++ `Format, output_format ++ ] in ++ ++ (* MUST NOT *) ++ let goal_must_not = [ `Template, ""; `XZ, ""; `Format, "auto" ] in ++ ++ goal_must, goal_must_not in ++ ++ (* Planner: Transitions. *) ++ let transitions itags = ++ let is t = List.mem_assoc t itags in ++ let is_not t = not (is t) in ++ let remove = List.remove_assoc in ++ let ret = ref [] in ++ let tr task weight otags = ret := (task, weight, otags) :: !ret in ++ ++ (* XXX Weights are not very smartly chosen. At the moment I'm ++ * using a range [0..100] where 0 = free and 100 = expensive. We ++ * could estimate weights better by looking at file sizes. + *) +- | Some output when is_block_device output -> +- if size <> None then ( +- eprintf (f_"%s: you cannot use --size option with block devices\n") +- prog; +- exit 1 ++ ++ (* Since the final plan won't run in parallel, we don't only need ++ * to choose unique tempfiles per transition, so this is OK: ++ *) ++ let tempfile = Filename.temp_file "vb" ".img" in ++ unlink_on_exit tempfile; ++ ++ (* Always possible to copy from one place to another. The only ++ * thing a copy does is to remove the template tag (since it's always ++ * copied out of the cache directory). ++ *) ++ tr `Copy 50 ((`Filename, output_filename) :: remove `Template itags); ++ tr `Copy 50 ((`Filename, tempfile) :: remove `Template itags); ++ ++ (* We can rename a file instead of copying, but don't rename the ++ * cache copy! (XXX Also this is not free if copying across ++ * filesystems) ++ *) ++ if is_not `Template then ( ++ if not output_is_block_dev then ++ tr `Rename 0 ((`Filename, output_filename) :: itags); ++ tr `Rename 0 ((`Filename, tempfile) :: itags); ++ ); ++ ++ if is `XZ then ( ++ (* If the input is XZ-compressed, then we can run xzcat, either ++ * to the output file or to a temp file. ++ *) ++ if not output_is_block_dev then ++ tr `Pxzcat 80 ++ ((`Filename, output_filename) :: remove `XZ (remove `Template itags)); ++ tr `Pxzcat 80 ++ ((`Filename, tempfile) :: remove `XZ (remove `Template itags)); ++ ) ++ else ( ++ (* If the input is NOT compressed then we could run virt-resize ++ * if it makes sense to resize the image. Note that virt-resize ++ * can do both size and format conversions. ++ *) ++ let old_size = Int64.of_string (List.assoc `Size itags) in ++ let headroom = 256L *^ 1024L *^ 1024L in ++ if output_size >= old_size +^ headroom then ( ++ tr `Virt_resize 100 ++ ((`Size, Int64.to_string output_size) :: ++ (`Filename, output_filename) :: ++ (`Format, output_format) :: (remove `Template itags)); ++ tr `Virt_resize 100 ++ ((`Size, Int64.to_string output_size) :: ++ (`Filename, tempfile) :: ++ (`Format, output_format) :: (remove `Template itags)) ++ ) ++ ++ (* If the size increase is smaller than the amount of headroom ++ * inside the disk image, then virt-resize won't work. However ++ * we can do a disk resize (using 'qemu-img resize') instead, ++ * although it won't resize the filesystems for the user. ++ * ++ * 'qemu-img resize' works on the file in-place and won't change ++ * the format. It must not be run on a template directly. ++ *) ++ else if output_size > old_size && is_not `Template then ( ++ tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); ++ tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); + ); +- (* XXX Should check the output size is big enough. However this +- * requires running 'blockdev --getsize64 '. ++ ++ (* qemu-img convert is always possible, and quicker. It doesn't ++ * resize, but it does change the format. + *) ++ tr `Convert 60 ++ ((`Filename, output_filename) :: (`Format, output_format) :: ++ (remove `Template itags)); ++ tr `Convert 60 ++ ((`Filename, tempfile) :: (`Format, output_format) :: ++ (remove `Template itags)); ++ ); + +- let format = match format with None -> "raw" | Some f -> f in +- +- (* Dummy: The output file is never deleted in this case. *) +- let delete_output_file = ref false in +- +- output, None, format, delete_output_file, true, false +- +- (* Regular file output. Note the file gets deleted. *) +- | _ -> +- (* Check the --size option. *) +- let size, do_resize = +- let { Index_parser.size = default_size } = entry in +- match size with +- | None -> default_size, false +- | Some size -> +- if size < default_size +^ headroom then ( +- eprintf (f_"%s: --size is too small for this disk image, minimum size is %s\n") +- prog (human_size default_size); +- exit 1 +- ); +- size, true in +- +- (* Create the output file. *) +- let output, format = +- match output, format with +- | None, None -> sprintf "%s.img" arg, "raw" +- | None, Some "raw" -> sprintf "%s.img" arg, "raw" +- | None, Some format -> sprintf "%s.%s" arg format, format +- | Some output, None -> output, "raw" +- | Some output, Some format -> output, format in +- +- (* If the input format != output format then we must run virt-resize. *) +- let do_resize = +- let input_format = +- match entry with +- | { Index_parser.format = Some format } -> format +- | { Index_parser.format = None } -> "raw" in +- if input_format <> format then true else do_resize in +- +- msg (f_"Creating disk image: %s") output; ++ (* Return the list of possible transitions. *) ++ !ret ++ in ++ ++ (* Plan how to create the disk image. *) ++ msg (f_"Planning how to build this image"); ++ let plan = ++ try plan ~max_depth:5 transitions itags goal ++ with ++ Failure "plan" -> ++ eprintf (f_"%s: no plan could be found for making a disk image with\nthe required size, format etc. This is a bug in libguestfs!\nPlease file a bug, giving the command line arguments you used.\n") prog; ++ exit 1 ++ in ++ ++ (* Print out the plan. *) ++ if debug then ( ++ let print_tags tags = ++ (try ++ let v = List.assoc `Filename tags in eprintf " +filename=%s" v ++ with Not_found -> ()); ++ (try ++ let v = List.assoc `Size tags in eprintf " +size=%s" v ++ with Not_found -> ()); ++ (try ++ let v = List.assoc `Format tags in eprintf " +format=%s" v ++ with Not_found -> ()); ++ if List.mem_assoc `Template tags then eprintf " +template"; ++ if List.mem_assoc `XZ tags then eprintf " +xz" ++ in ++ let print_task = function ++ | `Copy -> eprintf "cp" ++ | `Rename -> eprintf "mv" ++ | `Pxzcat -> eprintf "pxzcat" ++ | `Virt_resize -> eprintf "virt-resize" ++ | `Disk_resize -> eprintf "qemu-img resize" ++ | `Convert -> eprintf "qemu-img convert" ++ in ++ ++ List.iteri ( ++ fun i (itags, task, otags) -> ++ eprintf "%d: itags:" i; ++ print_tags itags; ++ eprintf "\n"; ++ eprintf "%d: task : " i; ++ print_task task; ++ eprintf "\n"; ++ eprintf "%d: otags:" i; ++ print_tags otags; ++ eprintf "\n\n" ++ ) plan ++ ); ++ ++ (* Delete the output file before we finish. However don't delete it ++ * if it's block device. ++ *) ++ let delete_output_file = ref (not output_is_block_dev) in ++ let delete_file () = ++ if !delete_output_file then ++ try unlink output_filename with _ -> () ++ in ++ at_exit delete_file; ++ ++ (* Carry out the plan. *) ++ List.iter ( ++ function ++ | itags, `Copy, otags -> ++ let ifile = List.assoc `Filename itags in ++ let ofile = List.assoc `Filename otags in ++ msg (f_"Copying"); ++ let cmd = sprintf "cp %s %s" (quote ifile) (quote ofile) in ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1 ++ ++ | itags, `Rename, otags -> ++ let ifile = List.assoc `Filename itags in ++ let ofile = List.assoc `Filename otags in ++ let cmd = sprintf "mv %s %s" (quote ifile) (quote ofile) in ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1 ++ ++ | itags, `Pxzcat, otags -> ++ let ifile = List.assoc `Filename itags in ++ let ofile = List.assoc `Filename otags in ++ msg (f_"Uncompressing"); ++ Pxzcat.pxzcat ifile ofile ++ ++ | itags, `Virt_resize, otags -> ++ let ifile = List.assoc `Filename itags in ++ let iformat = List.assoc `Format itags in ++ let ofile = List.assoc `Filename otags in ++ let osize = Int64.of_string (List.assoc `Size otags) in ++ let osize = roundup64 osize 512L in ++ let oformat = List.assoc `Format otags in ++ let { Index_parser.expand = expand; lvexpand = lvexpand } = entry in ++ msg (f_"Resizing (using virt-resize) to expand the disk to %s") ++ (human_size osize); + let cmd = + sprintf "qemu-img create -f %s%s %s %Ld%s" +- (quote format) +- (if format = "qcow2" then " -o preallocation=metadata" else "") +- (quote output) size ++ (quote oformat) ++ (if oformat = "qcow2" then " -o preallocation=metadata" else "") ++ (quote ofile) osize + (if debug then "" else " >/dev/null 2>&1") in +- let r = Sys.command cmd in +- if r <> 0 then ( +- eprintf (f_"%s: error: could not create output file '%s'\n") +- prog output; +- exit 1 +- ); +- (* This ensures the output file will be deleted on failure, +- * until we set !delete_output_file = false at the end of the build. +- *) +- let delete_output_file = ref true in +- let delete_file () = +- if !delete_output_file then +- try unlink output with _ -> () +- in +- at_exit delete_file; ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1; ++ let cmd = ++ sprintf "virt-resize%s%s --format %s --output-format %s%s%s %s %s" ++ (if debug then " --verbose" else " --quiet") ++ (if output_is_block_dev then " --no-sparse" else "") ++ (quote iformat) ++ (quote oformat) ++ (match expand with ++ | None -> "" ++ | Some expand -> sprintf " --expand %s" (quote expand)) ++ (match lvexpand with ++ | None -> "" ++ | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand)) ++ (quote ifile) (quote ofile) in ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1 + +- output, Some size, format, delete_output_file, do_resize, true in ++ | itags, `Disk_resize, otags -> ++ let ofile = List.assoc `Filename otags in ++ let osize = Int64.of_string (List.assoc `Size otags) in ++ let osize = roundup64 osize 512L in ++ msg (f_"Resizing container (but not filesystems) to expand the disk to %s") ++ (human_size osize); ++ let cmd = sprintf "qemu-img resize %s %Ld%s" ++ (quote ofile) osize (if debug then "" else " >/dev/null") in ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1 + +- if not do_resize then ( +- (* If the user did not specify --size and the output is a regular +- * file and the format is raw, then we just uncompress the template +- * directly to the output file. This is fast but less flexible. +- *) +- let { Index_parser.file_uri = file_uri } = entry in +- msg (f_"Uncompressing: %s") file_uri; +- pxzcat template output +- ) else ( +- (* If none of the above apply, uncompress to a temporary file and +- * run virt-resize on the result. +- *) +- let tmpfile = +- (* Uncompress it to a temporary file. *) +- let { Index_parser.file_uri = file_uri } = entry in +- let tmpfile = Filename.temp_file "vbsrc" ".img" in +- msg (f_"Uncompressing: %s") file_uri; +- pxzcat template tmpfile; +- unlink_on_exit tmpfile; +- tmpfile in +- +- (* Resize the source to the output file. *) +- (match size with +- | None -> +- msg (f_"Running virt-resize to expand the disk") +- | Some size -> +- msg (f_"Running virt-resize to expand the disk to %s") (human_size size) +- ); +- +- let { Index_parser.expand = expand; lvexpand = lvexpand; +- format = input_format } = +- entry in +- let cmd = +- sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" +- (if debug then " --verbose" else " --quiet") +- (if not resize_sparse then " --no-sparse" else "") +- (match input_format with +- | None -> "" +- | Some input_format -> sprintf " --format %s" (quote input_format)) +- (quote format) +- (match expand with +- | None -> "" +- | Some expand -> sprintf " --expand %s" (quote expand)) +- (match lvexpand with +- | None -> "" +- | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand)) +- (quote tmpfile) (quote output) in +- if debug then eprintf "%s\n%!" cmd; +- let r = Sys.command cmd in +- if r <> 0 then ( +- eprintf (f_"%s: error: virt-resize failed\n") prog; +- exit 1 +- ) +- ); ++ | itags, `Convert, otags -> ++ let ifile = List.assoc `Filename itags in ++ let iformat = List.assoc `Format itags in ++ let ofile = List.assoc `Filename otags in ++ let oformat = List.assoc `Format otags in ++ msg (f_"Converting %s to %s") iformat oformat; ++ let cmd = sprintf "qemu-img convert -f %s %s -O %s %s%s" ++ (quote iformat) (quote ifile) ++ (quote oformat) (quote ofile) ++ (if debug then "" else " >/dev/null 2>&1") in ++ if debug then eprintf "%s\n%!" cmd; ++ if Sys.command cmd <> 0 then exit 1 ++ ) plan; + + (* Now mount the output disk so we can make changes. *) + msg (f_"Opening the new disk"); +@@ -397,7 +532,7 @@ let main () = + g#set_network network; + + (* The output disk is being created, so use cache=unsafe here. *) +- g#add_drive_opts ~format ~cachemode:"unsafe" output; ++ g#add_drive_opts ~format:output_format ~cachemode:"unsafe" output_filename; + + (* Attach ISOs, if we have any. *) + List.iter ( +@@ -690,7 +825,9 @@ exec >>%s 2>&1 + + Some ( + String.concat "\n" [ +- sprintf (f_"Output: %s") output; ++ sprintf (f_"Output: %s") output_filename; ++ sprintf (f_"Output size: %s") (human_size output_size); ++ sprintf (f_"Output format: %s") output_format; + sprintf (f_"Total usable space: %s") + (human_size total_bytes); + sprintf (f_"Free space: %s (%Ld%%)") +@@ -729,7 +866,7 @@ exec >>%s 2>&1 + * use cache=none. + *) + if sync then +- Fsync.file output; ++ Fsync.file output_filename; + + (* Now that we've finished the build, don't delete the output file on + * exit. +diff --git a/mllib/Makefile.am b/mllib/Makefile.am +index 8c8d508..9719273 100644 +--- a/mllib/Makefile.am ++++ b/mllib/Makefile.am +@@ -42,6 +42,8 @@ SOURCES = \ + password.ml \ + perl_edit.mli \ + perl_edit.ml \ ++ planner.mli \ ++ planner.ml \ + progress-c.c \ + progress.mli \ + progress.ml \ +@@ -84,7 +86,8 @@ OBJECTS = \ + progress.cmx \ + uRI.cmx \ + crypt.cmx \ +- password.cmx ++ password.cmx \ ++ planner.cmx + + noinst_SCRIPTS = dummy + +diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml +index 357ffba..3943417 100644 +--- a/mllib/common_utils.ml ++++ b/mllib/common_utils.ml +@@ -401,6 +401,18 @@ let rm_rf_only_files (g : Guestfs.guestfs) dir = + List.iter g#rm files + ) + ++(* Detect compression of a file. ++ * ++ * Only detects the formats we need in virt-builder so far. ++ *) ++let detect_compression filename = ++ let chan = open_in filename in ++ let buf = String.create 6 in ++ really_input chan buf 0 6; ++ close_in chan; ++ if buf = "\2537zXZ\000" then `XZ ++ else `Unknown ++ + let is_block_device file = + try (Unix.stat file).Unix.st_kind = Unix.S_BLK + with Unix.Unix_error _ -> false +diff --git a/mllib/planner.ml b/mllib/planner.ml +new file mode 100644 +index 0000000..0121b84 +--- /dev/null ++++ b/mllib/planner.ml +@@ -0,0 +1,80 @@ ++(* virt-builder ++ * Copyright (C) 2012-2013 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++type ('name, 'value) tag = 'name * 'value ++ ++type ('name, 'value) tags = ('name, 'value) tag list ++ ++type ('name, 'value, 'task) plan = ++ (('name, 'value) tags * 'task * ('name, 'value) tags) list ++ ++type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list ++ ++let plan ?(max_depth = 10) transitions itags (goal_must, goal_must_not) = ++ (* Do the given output tags match the finish condition? *) ++ let finished (otags, _, _) = ++ let must = ++ (* All tags from the MUST list must be present with the given values. *) ++ List.for_all ( ++ fun (name, value) -> ++ try List.assoc name otags = value with Not_found -> false ++ ) goal_must in ++ ++ let must_not = ++ (* No tag from the MUST NOT list can appear. *) ++ List.for_all ( ++ fun (name, value) -> ++ try List.assoc name otags <> value with Not_found -> true ++ ) goal_must_not in ++ ++ must && must_not ++ in ++ ++ (* Breadth-first search. *) ++ let rec search depth paths = ++ if depth >= max_depth then failwith "plan" ++ else ( ++ let paths = ++ List.map ( ++ fun (itags, weight, preds) -> ++ let ts = transitions itags in ++ List.map (fun (task, w, otags) -> ++ otags, weight + w, (itags, task, otags) :: preds ++ ) ts ++ ) paths in ++ let paths = List.flatten paths in ++ ++ (* Did any path reach the finish? If so, pick the path with the ++ * smallest weight and we're done. ++ *) ++ let finished_paths = List.filter finished paths in ++ let finished_paths = ++ List.sort (fun (_,w1,_) (_,w2,_) -> compare w1 w2) finished_paths in ++ match finished_paths with ++ | [] -> ++ (* No path reached the finish, so go deeper. *) ++ search (depth+1) paths ++ | (_, _, ret) :: _ -> ++ (* Return the shortest path, but we have to reverse it because ++ * we built it backwards. ++ *) ++ List.rev ret ++ ) ++ in ++ ++ search 0 [itags, 0, []] +diff --git a/mllib/planner.mli b/mllib/planner.mli +new file mode 100644 +index 0000000..770a00f +--- /dev/null ++++ b/mllib/planner.mli +@@ -0,0 +1,78 @@ ++(* virt-builder ++ * Copyright (C) 2012-2013 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++(** The Planner can plan how to reach a goal by carrying out a series ++ of operations. You tag the input state and the output state, and ++ give it a list of permitted transitions, and it will return a ++ multi-step plan (list of transitions) from the input state to the ++ output state. ++ ++ For example: ++ ++ Input tags: xz cached size=4G format=raw ++ ++ Output tags: -xz -cached +size=8G +format=raw ++ ++ (In this case the "-" before an output tag means the tag MUST NOT ++ appear, and the "+" before an output tag means the tag MUST ++ appear). ++ ++ The plan produced might be: ++ ++ (1) Run xzcat (removes xz and cached tags). ++ ++ (2) Run virt-resize (changes size=4G to size=8G) ++ ++ Tags are described as OCaml association lists. See the OCaml ++ {!List} module. ++ ++ Transitions are defined by a function (that the caller supplies) ++ which returns the possible transitions for a given set of tags, ++ and for each possible transition, the weight (higher number = ++ higher cost), and the tag state after that transition. ++ ++ The returned plan is a list of transitions. ++ ++ The implementation is a simple breadth-first search of the tree of ++ states (each edge in the tree is a transition). It doesn't work ++ very hard to optimize the weights, so the returned plan is ++ possible, but might not be optimal. *) ++ ++type ('name, 'value) tag = 'name * 'value ++ ++type ('name, 'value) tags = ('name, 'value) tag list ++ (** An assoc-list of tags. *) ++ ++type ('name, 'value, 'task) plan = ++ (('name, 'value) tags * 'task * ('name, 'value) tags) list ++ ++type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list ++ ++val plan : ?max_depth:int -> ('name, 'value, 'task) transitions_function -> ('name, 'value) tags -> ('name, 'value) tags * ('name, 'value) tags -> ('name, 'value, 'task) plan ++(** Make a plan. ++ ++ [plan transitions itags (goal_must, goal_must_not)] works out a ++ plan, which is a list of tasks that have to be carried out in ++ order to go from the input tags to the goal. The goal is passed ++ in as a pair of lists: tags that MUST appear and tags that MUST ++ NOT appear. ++ ++ The returned value is a {!plan}. ++ ++ Raises [Failure "plan"] if no plan was found within [max_depth] ++ transitions. *) +diff --git a/po/POTFILES-ml b/po/POTFILES-ml +index a63b69a..84211b6 100644 +--- a/po/POTFILES-ml ++++ b/po/POTFILES-ml +@@ -17,6 +17,7 @@ mllib/hostname.ml + mllib/libdir.ml + mllib/password.ml + mllib/perl_edit.ml ++mllib/planner.ml + mllib/progress.ml + mllib/random_seed.ml + mllib/tTY.ml +-- +1.8.4.2 + diff --git a/0027-builder-Use-a-planner-to-work-out-how-to-convert-the.patch b/0027-builder-Use-a-planner-to-work-out-how-to-convert-the.patch deleted file mode 100644 index eada8b5..0000000 --- a/0027-builder-Use-a-planner-to-work-out-how-to-convert-the.patch +++ /dev/null @@ -1,729 +0,0 @@ -From d2327e3eff07ed25e326c52f6e3c9d22b6a61547 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 13 Dec 2013 13:18:47 +0000 -Subject: [PATCH] builder: Use a planner to work out how to convert the - template to the final image. - -The original template might be, say, xz-compressed raw of a certain -size. We need to work out how to convert it to, say, qcow2 with a -larger size, in as few operations as possible. - -Instead of using a nasty aggregation of special cases to do this, use -a breadth-first search over all possible trees to try to find an -optimal plan. - -(Actually the current implementation isn't optimal, but it's fine for -virt-builder.) - -(cherry picked from commit 62cc7d3361127b4e007f8e23028213852be09124) ---- - builder/Makefile.am | 1 + - builder/builder.ml | 403 +++++++++++++++++++++++++++++++++----------------- - mllib/Makefile.am | 5 +- - mllib/common_utils.ml | 12 ++ - mllib/planner.ml | 80 ++++++++++ - mllib/planner.mli | 78 ++++++++++ - po/POTFILES-ml | 1 + - 7 files changed, 445 insertions(+), 135 deletions(-) - create mode 100644 mllib/planner.ml - create mode 100644 mllib/planner.mli - -diff --git a/builder/Makefile.am b/builder/Makefile.am -index 30ada87..ca4a254 100644 ---- a/builder/Makefile.am -+++ b/builder/Makefile.am -@@ -74,6 +74,7 @@ OBJECTS = \ - $(top_builddir)/mllib/fsync-c.o \ - $(top_builddir)/mllib/fsync.cmx \ - $(top_builddir)/mllib/password.cmx \ -+ $(top_builddir)/mllib/planner.cmx \ - $(top_builddir)/mllib/config.cmx \ - index-scan.o \ - index-struct.o \ -diff --git a/builder/builder.ml b/builder/builder.ml -index 86e38f3..df82707 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -22,9 +22,9 @@ module G = Guestfs - - open Common_utils - open Password -+open Planner - - open Cmdline --open Pxzcat - - open Unix - open Printf -@@ -243,148 +243,281 @@ let main () = - - Sigchecker.verify_detached sigchecker template sigfile in - -- (* Plan how to create the output. This depends on: -- * - did the user specify --output? -- * - is the output a block device? -- * - did the user specify --size? -- *) -- let output, size, format, delete_output_file, do_resize, resize_sparse = -+ (* Planner: Input tags. *) -+ let itags = -+ let { Index_parser.size = size; format = format } = entry in -+ let format = match format with None -> "auto" | Some format -> format in -+ let compression_tags = -+ match detect_compression template with -+ | `XZ -> [ `XZ, "" ] -+ | `Unknown -> [] - in -+ [ `Template, ""; `Filename, template; `Size, Int64.to_string size; -+ `Format, format ] @ compression_tags in - -- let headroom = 256L *^ 1024L *^ 1024L in -+ (* Planner: Goal. *) -+ let output_size = -+ let { Index_parser.size = default_size } = entry in -+ match size with None -> default_size | Some size -> size in -+ let output_filename, output_format = -+ match output, format with -+ | None, None -> sprintf "%s.img" arg, "raw" -+ | None, Some "raw" -> sprintf "%s.img" arg, "raw" -+ | None, Some format -> sprintf "%s.%s" arg format, format -+ | Some output, None -> output, "raw" -+ | Some output, Some format -> output, format in -+ let output_is_block_dev = is_block_device output_filename in - -- match output with -- (* If the output file was specified and it exists and it's a block -- * device, then we should skip the creation step. -+ if output_is_block_dev && size <> None then ( -+ eprintf (f_"%s: you cannot use --size option with block devices\n") prog; -+ exit 1 -+ ); -+ -+ let goal = -+ (* MUST *) -+ let goal_must = [ -+ `Filename, output_filename; -+ `Size, Int64.to_string output_size; -+ `Format, output_format -+ ] in -+ -+ (* MUST NOT *) -+ let goal_must_not = [ `Template, ""; `XZ, ""; `Format, "auto" ] in -+ -+ goal_must, goal_must_not in -+ -+ (* Planner: Transitions. *) -+ let transitions itags = -+ let is t = List.mem_assoc t itags in -+ let is_not t = not (is t) in -+ let remove = List.remove_assoc in -+ let ret = ref [] in -+ let tr task weight otags = ret := (task, weight, otags) :: !ret in -+ -+ (* XXX Weights are not very smartly chosen. At the moment I'm -+ * using a range [0..100] where 0 = free and 100 = expensive. We -+ * could estimate weights better by looking at file sizes. -+ *) -+ -+ (* Since the final plan won't run in parallel, we don't only need -+ * to choose unique tempfiles per transition, so this is OK: - *) -- | Some output when is_block_device output -> -- if size <> None then ( -- eprintf (f_"%s: you cannot use --size option with block devices\n") -- prog; -- exit 1 -+ let tempfile = Filename.temp_file "vb" ".img" in -+ unlink_on_exit tempfile; -+ -+ (* Always possible to copy from one place to another. The only -+ * thing a copy does is to remove the template tag (since it's always -+ * copied out of the cache directory). -+ *) -+ tr `Copy 50 ((`Filename, output_filename) :: remove `Template itags); -+ tr `Copy 50 ((`Filename, tempfile) :: remove `Template itags); -+ -+ (* We can rename a file instead of copying, but don't rename the -+ * cache copy! (XXX Also this is not free if copying across -+ * filesystems) -+ *) -+ if is_not `Template then ( -+ if not output_is_block_dev then -+ tr `Rename 0 ((`Filename, output_filename) :: itags); -+ tr `Rename 0 ((`Filename, tempfile) :: itags); -+ ); -+ -+ if is `XZ then ( -+ (* If the input is XZ-compressed, then we can run xzcat, either -+ * to the output file or to a temp file. -+ *) -+ if not output_is_block_dev then -+ tr `Pxzcat 80 -+ ((`Filename, output_filename) :: remove `XZ (remove `Template itags)); -+ tr `Pxzcat 80 -+ ((`Filename, tempfile) :: remove `XZ (remove `Template itags)); -+ ) -+ else ( -+ (* If the input is NOT compressed then we could run virt-resize -+ * if it makes sense to resize the image. Note that virt-resize -+ * can do both size and format conversions. -+ *) -+ let old_size = Int64.of_string (List.assoc `Size itags) in -+ let headroom = 256L *^ 1024L *^ 1024L in -+ if output_size >= old_size +^ headroom then ( -+ tr `Virt_resize 100 -+ ((`Size, Int64.to_string output_size) :: -+ (`Filename, output_filename) :: -+ (`Format, output_format) :: (remove `Template itags)); -+ tr `Virt_resize 100 -+ ((`Size, Int64.to_string output_size) :: -+ (`Filename, tempfile) :: -+ (`Format, output_format) :: (remove `Template itags)) -+ ) -+ -+ (* If the size increase is smaller than the amount of headroom -+ * inside the disk image, then virt-resize won't work. However -+ * we can do a disk resize (using 'qemu-img resize') instead, -+ * although it won't resize the filesystems for the user. -+ * -+ * 'qemu-img resize' works on the file in-place and won't change -+ * the format. It must not be run on a template directly. -+ *) -+ else if output_size > old_size && is_not `Template then ( -+ tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); -+ tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); - ); -- (* XXX Should check the output size is big enough. However this -- * requires running 'blockdev --getsize64 '. -+ -+ (* qemu-img convert is always possible, and quicker. It doesn't -+ * resize, but it does change the format. - *) -+ tr `Convert 60 -+ ((`Filename, output_filename) :: (`Format, output_format) :: -+ (remove `Template itags)); -+ tr `Convert 60 -+ ((`Filename, tempfile) :: (`Format, output_format) :: -+ (remove `Template itags)); -+ ); - -- let format = match format with None -> "raw" | Some f -> f in -- -- (* Dummy: The output file is never deleted in this case. *) -- let delete_output_file = ref false in -- -- output, None, format, delete_output_file, true, false -- -- (* Regular file output. Note the file gets deleted. *) -- | _ -> -- (* Check the --size option. *) -- let size, do_resize = -- let { Index_parser.size = default_size } = entry in -- match size with -- | None -> default_size, false -- | Some size -> -- if size < default_size +^ headroom then ( -- eprintf (f_"%s: --size is too small for this disk image, minimum size is %s\n") -- prog (human_size default_size); -- exit 1 -- ); -- size, true in -- -- (* Create the output file. *) -- let output, format = -- match output, format with -- | None, None -> sprintf "%s.img" arg, "raw" -- | None, Some "raw" -> sprintf "%s.img" arg, "raw" -- | None, Some format -> sprintf "%s.%s" arg format, format -- | Some output, None -> output, "raw" -- | Some output, Some format -> output, format in -- -- (* If the input format != output format then we must run virt-resize. *) -- let do_resize = -- let input_format = -- match entry with -- | { Index_parser.format = Some format } -> format -- | { Index_parser.format = None } -> "raw" in -- if input_format <> format then true else do_resize in -- -- msg (f_"Creating disk image: %s") output; -+ (* Return the list of possible transitions. *) -+ !ret -+ in -+ -+ (* Plan how to create the disk image. *) -+ msg (f_"Planning how to build this image"); -+ let plan = -+ try plan ~max_depth:5 transitions itags goal -+ with -+ Failure "plan" -> -+ eprintf (f_"%s: no plan could be found for making a disk image with\nthe required size, format etc. This is a bug in libguestfs!\nPlease file a bug, giving the command line arguments you used.\n") prog; -+ exit 1 -+ in -+ -+ (* Print out the plan. *) -+ if debug then ( -+ let print_tags tags = -+ (try -+ let v = List.assoc `Filename tags in eprintf " +filename=%s" v -+ with Not_found -> ()); -+ (try -+ let v = List.assoc `Size tags in eprintf " +size=%s" v -+ with Not_found -> ()); -+ (try -+ let v = List.assoc `Format tags in eprintf " +format=%s" v -+ with Not_found -> ()); -+ if List.mem_assoc `Template tags then eprintf " +template"; -+ if List.mem_assoc `XZ tags then eprintf " +xz" -+ in -+ let print_task = function -+ | `Copy -> eprintf "cp" -+ | `Rename -> eprintf "mv" -+ | `Pxzcat -> eprintf "pxzcat" -+ | `Virt_resize -> eprintf "virt-resize" -+ | `Disk_resize -> eprintf "qemu-img resize" -+ | `Convert -> eprintf "qemu-img convert" -+ in -+ -+ List.iteri ( -+ fun i (itags, task, otags) -> -+ eprintf "%d: itags:" i; -+ print_tags itags; -+ eprintf "\n"; -+ eprintf "%d: task : " i; -+ print_task task; -+ eprintf "\n"; -+ eprintf "%d: otags:" i; -+ print_tags otags; -+ eprintf "\n\n" -+ ) plan -+ ); -+ -+ (* Delete the output file before we finish. However don't delete it -+ * if it's block device. -+ *) -+ let delete_output_file = ref (not output_is_block_dev) in -+ let delete_file () = -+ if !delete_output_file then -+ try unlink output_filename with _ -> () -+ in -+ at_exit delete_file; -+ -+ (* Carry out the plan. *) -+ List.iter ( -+ function -+ | itags, `Copy, otags -> -+ let ifile = List.assoc `Filename itags in -+ let ofile = List.assoc `Filename otags in -+ msg (f_"Copying"); -+ let cmd = sprintf "cp %s %s" (quote ifile) (quote ofile) in -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1 -+ -+ | itags, `Rename, otags -> -+ let ifile = List.assoc `Filename itags in -+ let ofile = List.assoc `Filename otags in -+ let cmd = sprintf "mv %s %s" (quote ifile) (quote ofile) in -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1 -+ -+ | itags, `Pxzcat, otags -> -+ let ifile = List.assoc `Filename itags in -+ let ofile = List.assoc `Filename otags in -+ msg (f_"Uncompressing"); -+ Pxzcat.pxzcat ifile ofile -+ -+ | itags, `Virt_resize, otags -> -+ let ifile = List.assoc `Filename itags in -+ let iformat = List.assoc `Format itags in -+ let ofile = List.assoc `Filename otags in -+ let osize = Int64.of_string (List.assoc `Size otags) in -+ let osize = roundup64 osize 512L in -+ let oformat = List.assoc `Format otags in -+ let { Index_parser.expand = expand; lvexpand = lvexpand } = entry in -+ msg (f_"Resizing (using virt-resize) to expand the disk to %s") -+ (human_size osize); - let cmd = - sprintf "qemu-img create -f %s%s %s %Ld%s" -- (quote format) -- (if format = "qcow2" then " -o preallocation=metadata" else "") -- (quote output) size -+ (quote oformat) -+ (if oformat = "qcow2" then " -o preallocation=metadata" else "") -+ (quote ofile) osize - (if debug then "" else " >/dev/null 2>&1") in -- let r = Sys.command cmd in -- if r <> 0 then ( -- eprintf (f_"%s: error: could not create output file '%s'\n") -- prog output; -- exit 1 -- ); -- (* This ensures the output file will be deleted on failure, -- * until we set !delete_output_file = false at the end of the build. -- *) -- let delete_output_file = ref true in -- let delete_file () = -- if !delete_output_file then -- try unlink output with _ -> () -- in -- at_exit delete_file; -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1; -+ let cmd = -+ sprintf "virt-resize%s%s --format %s --output-format %s%s%s %s %s" -+ (if debug then " --verbose" else " --quiet") -+ (if output_is_block_dev then " --no-sparse" else "") -+ (quote iformat) -+ (quote oformat) -+ (match expand with -+ | None -> "" -+ | Some expand -> sprintf " --expand %s" (quote expand)) -+ (match lvexpand with -+ | None -> "" -+ | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand)) -+ (quote ifile) (quote ofile) in -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1 - -- output, Some size, format, delete_output_file, do_resize, true in -+ | itags, `Disk_resize, otags -> -+ let ofile = List.assoc `Filename otags in -+ let osize = Int64.of_string (List.assoc `Size otags) in -+ let osize = roundup64 osize 512L in -+ msg (f_"Resizing container (but not filesystems) to expand the disk to %s") -+ (human_size osize); -+ let cmd = sprintf "qemu-img resize %s %Ld%s" -+ (quote ofile) osize (if debug then "" else " >/dev/null") in -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1 - -- if not do_resize then ( -- (* If the user did not specify --size and the output is a regular -- * file and the format is raw, then we just uncompress the template -- * directly to the output file. This is fast but less flexible. -- *) -- let { Index_parser.file_uri = file_uri } = entry in -- msg (f_"Uncompressing: %s") file_uri; -- pxzcat template output -- ) else ( -- (* If none of the above apply, uncompress to a temporary file and -- * run virt-resize on the result. -- *) -- let tmpfile = -- (* Uncompress it to a temporary file. *) -- let { Index_parser.file_uri = file_uri } = entry in -- let tmpfile = Filename.temp_file "vbsrc" ".img" in -- msg (f_"Uncompressing: %s") file_uri; -- pxzcat template tmpfile; -- unlink_on_exit tmpfile; -- tmpfile in -- -- (* Resize the source to the output file. *) -- (match size with -- | None -> -- msg (f_"Running virt-resize to expand the disk") -- | Some size -> -- msg (f_"Running virt-resize to expand the disk to %s") (human_size size) -- ); -- -- let { Index_parser.expand = expand; lvexpand = lvexpand; -- format = input_format } = -- entry in -- let cmd = -- sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" -- (if debug then " --verbose" else " --quiet") -- (if not resize_sparse then " --no-sparse" else "") -- (match input_format with -- | None -> "" -- | Some input_format -> sprintf " --format %s" (quote input_format)) -- (quote format) -- (match expand with -- | None -> "" -- | Some expand -> sprintf " --expand %s" (quote expand)) -- (match lvexpand with -- | None -> "" -- | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand)) -- (quote tmpfile) (quote output) in -- if debug then eprintf "%s\n%!" cmd; -- let r = Sys.command cmd in -- if r <> 0 then ( -- eprintf (f_"%s: error: virt-resize failed\n") prog; -- exit 1 -- ) -- ); -+ | itags, `Convert, otags -> -+ let ifile = List.assoc `Filename itags in -+ let iformat = List.assoc `Format itags in -+ let ofile = List.assoc `Filename otags in -+ let oformat = List.assoc `Format otags in -+ msg (f_"Converting %s to %s") iformat oformat; -+ let cmd = sprintf "qemu-img convert -f %s %s -O %s %s%s" -+ (quote iformat) (quote ifile) -+ (quote oformat) (quote ofile) -+ (if debug then "" else " >/dev/null 2>&1") in -+ if debug then eprintf "%s\n%!" cmd; -+ if Sys.command cmd <> 0 then exit 1 -+ ) plan; - - (* Now mount the output disk so we can make changes. *) - msg (f_"Opening the new disk"); -@@ -397,7 +530,7 @@ let main () = - g#set_network network; - - (* The output disk is being created, so use cache=unsafe here. *) -- g#add_drive_opts ~format ~cachemode:"unsafe" output; -+ g#add_drive_opts ~format:output_format ~cachemode:"unsafe" output_filename; - - (* Attach ISOs, if we have any. *) - List.iter ( -@@ -690,7 +823,9 @@ exec >>%s 2>&1 - - Some ( - String.concat "\n" [ -- sprintf (f_"Output: %s") output; -+ sprintf (f_"Output: %s") output_filename; -+ sprintf (f_"Output size: %s") (human_size output_size); -+ sprintf (f_"Output format: %s") output_format; - sprintf (f_"Total usable space: %s") - (human_size total_bytes); - sprintf (f_"Free space: %s (%Ld%%)") -@@ -729,7 +864,7 @@ exec >>%s 2>&1 - * use cache=none. - *) - if sync then -- Fsync.file output; -+ Fsync.file output_filename; - - (* Now that we've finished the build, don't delete the output file on - * exit. -diff --git a/mllib/Makefile.am b/mllib/Makefile.am -index 1103ffb..67027d2 100644 ---- a/mllib/Makefile.am -+++ b/mllib/Makefile.am -@@ -40,6 +40,8 @@ SOURCES = \ - hostname.ml \ - password.mli \ - password.ml \ -+ planner.mli \ -+ planner.ml \ - progress-c.c \ - progress.mli \ - progress.ml \ -@@ -81,7 +83,8 @@ OBJECTS = \ - progress.cmx \ - uRI.cmx \ - crypt.cmx \ -- password.cmx -+ password.cmx \ -+ planner.cmx - - noinst_SCRIPTS = dummy - -diff --git a/mllib/common_utils.ml b/mllib/common_utils.ml -index 357ffba..3943417 100644 ---- a/mllib/common_utils.ml -+++ b/mllib/common_utils.ml -@@ -401,6 +401,18 @@ let rm_rf_only_files (g : Guestfs.guestfs) dir = - List.iter g#rm files - ) - -+(* Detect compression of a file. -+ * -+ * Only detects the formats we need in virt-builder so far. -+ *) -+let detect_compression filename = -+ let chan = open_in filename in -+ let buf = String.create 6 in -+ really_input chan buf 0 6; -+ close_in chan; -+ if buf = "\2537zXZ\000" then `XZ -+ else `Unknown -+ - let is_block_device file = - try (Unix.stat file).Unix.st_kind = Unix.S_BLK - with Unix.Unix_error _ -> false -diff --git a/mllib/planner.ml b/mllib/planner.ml -new file mode 100644 -index 0000000..0121b84 ---- /dev/null -+++ b/mllib/planner.ml -@@ -0,0 +1,80 @@ -+(* virt-builder -+ * Copyright (C) 2012-2013 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+type ('name, 'value) tag = 'name * 'value -+ -+type ('name, 'value) tags = ('name, 'value) tag list -+ -+type ('name, 'value, 'task) plan = -+ (('name, 'value) tags * 'task * ('name, 'value) tags) list -+ -+type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list -+ -+let plan ?(max_depth = 10) transitions itags (goal_must, goal_must_not) = -+ (* Do the given output tags match the finish condition? *) -+ let finished (otags, _, _) = -+ let must = -+ (* All tags from the MUST list must be present with the given values. *) -+ List.for_all ( -+ fun (name, value) -> -+ try List.assoc name otags = value with Not_found -> false -+ ) goal_must in -+ -+ let must_not = -+ (* No tag from the MUST NOT list can appear. *) -+ List.for_all ( -+ fun (name, value) -> -+ try List.assoc name otags <> value with Not_found -> true -+ ) goal_must_not in -+ -+ must && must_not -+ in -+ -+ (* Breadth-first search. *) -+ let rec search depth paths = -+ if depth >= max_depth then failwith "plan" -+ else ( -+ let paths = -+ List.map ( -+ fun (itags, weight, preds) -> -+ let ts = transitions itags in -+ List.map (fun (task, w, otags) -> -+ otags, weight + w, (itags, task, otags) :: preds -+ ) ts -+ ) paths in -+ let paths = List.flatten paths in -+ -+ (* Did any path reach the finish? If so, pick the path with the -+ * smallest weight and we're done. -+ *) -+ let finished_paths = List.filter finished paths in -+ let finished_paths = -+ List.sort (fun (_,w1,_) (_,w2,_) -> compare w1 w2) finished_paths in -+ match finished_paths with -+ | [] -> -+ (* No path reached the finish, so go deeper. *) -+ search (depth+1) paths -+ | (_, _, ret) :: _ -> -+ (* Return the shortest path, but we have to reverse it because -+ * we built it backwards. -+ *) -+ List.rev ret -+ ) -+ in -+ -+ search 0 [itags, 0, []] -diff --git a/mllib/planner.mli b/mllib/planner.mli -new file mode 100644 -index 0000000..770a00f ---- /dev/null -+++ b/mllib/planner.mli -@@ -0,0 +1,78 @@ -+(* virt-builder -+ * Copyright (C) 2012-2013 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+(** The Planner can plan how to reach a goal by carrying out a series -+ of operations. You tag the input state and the output state, and -+ give it a list of permitted transitions, and it will return a -+ multi-step plan (list of transitions) from the input state to the -+ output state. -+ -+ For example: -+ -+ Input tags: xz cached size=4G format=raw -+ -+ Output tags: -xz -cached +size=8G +format=raw -+ -+ (In this case the "-" before an output tag means the tag MUST NOT -+ appear, and the "+" before an output tag means the tag MUST -+ appear). -+ -+ The plan produced might be: -+ -+ (1) Run xzcat (removes xz and cached tags). -+ -+ (2) Run virt-resize (changes size=4G to size=8G) -+ -+ Tags are described as OCaml association lists. See the OCaml -+ {!List} module. -+ -+ Transitions are defined by a function (that the caller supplies) -+ which returns the possible transitions for a given set of tags, -+ and for each possible transition, the weight (higher number = -+ higher cost), and the tag state after that transition. -+ -+ The returned plan is a list of transitions. -+ -+ The implementation is a simple breadth-first search of the tree of -+ states (each edge in the tree is a transition). It doesn't work -+ very hard to optimize the weights, so the returned plan is -+ possible, but might not be optimal. *) -+ -+type ('name, 'value) tag = 'name * 'value -+ -+type ('name, 'value) tags = ('name, 'value) tag list -+ (** An assoc-list of tags. *) -+ -+type ('name, 'value, 'task) plan = -+ (('name, 'value) tags * 'task * ('name, 'value) tags) list -+ -+type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list -+ -+val plan : ?max_depth:int -> ('name, 'value, 'task) transitions_function -> ('name, 'value) tags -> ('name, 'value) tags * ('name, 'value) tags -> ('name, 'value, 'task) plan -+(** Make a plan. -+ -+ [plan transitions itags (goal_must, goal_must_not)] works out a -+ plan, which is a list of tasks that have to be carried out in -+ order to go from the input tags to the goal. The goal is passed -+ in as a pair of lists: tags that MUST appear and tags that MUST -+ NOT appear. -+ -+ The returned value is a {!plan}. -+ -+ Raises [Failure "plan"] if no plan was found within [max_depth] -+ transitions. *) -diff --git a/po/POTFILES-ml b/po/POTFILES-ml -index efeb75d..8ae6ea9 100644 ---- a/po/POTFILES-ml -+++ b/po/POTFILES-ml -@@ -17,6 +17,7 @@ mllib/fsync.ml - mllib/hostname.ml - mllib/libdir.ml - mllib/password.ml -+mllib/planner.ml - mllib/progress.ml - mllib/random_seed.ml - mllib/tTY.ml --- -1.8.4.2 - diff --git a/0027-builder-planner-Handle-no-format-in-source-case-corr.patch b/0027-builder-planner-Handle-no-format-in-source-case-corr.patch new file mode 100644 index 0000000..aca4e38 --- /dev/null +++ b/0027-builder-planner-Handle-no-format-in-source-case-corr.patch @@ -0,0 +1,110 @@ +From 5b5b2fbc97d47741d1684afd6435f1484ea900af Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 15:49:25 +0000 +Subject: [PATCH] builder: planner: Handle no format= in source case correctly. + +(cherry picked from commit 0af1e55e68c7cdaecc0af22e8bc41b8cff197e44) +--- + builder/builder.ml | 44 ++++++++++++++++++++++++++++---------------- + 1 file changed, 28 insertions(+), 16 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 71dfe13..4176457 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -248,14 +248,16 @@ let main () = + (* Planner: Input tags. *) + let itags = + let { Index_parser.size = size; format = format } = entry in +- let format = match format with None -> "auto" | Some format -> format in +- let compression_tags = ++ let format_tag = ++ match format with ++ | None -> [] ++ | Some format -> [`Format, format] in ++ let compression_tag = + match detect_compression template with + | `XZ -> [ `XZ, "" ] +- | `Unknown -> [] +- in +- [ `Template, ""; `Filename, template; `Size, Int64.to_string size; +- `Format, format ] @ compression_tags in ++ | `Unknown -> [] in ++ [ `Template, ""; `Filename, template; `Size, Int64.to_string size ] @ ++ format_tag @ compression_tag in + + (* Planner: Goal. *) + let output_size = +@@ -284,7 +286,7 @@ let main () = + ] in + + (* MUST NOT *) +- let goal_must_not = [ `Template, ""; `XZ, ""; `Format, "auto" ] in ++ let goal_must_not = [ `Template, ""; `XZ, "" ] in + + goal_must, goal_must_not in + +@@ -359,8 +361,11 @@ let main () = + * + * 'qemu-img resize' works on the file in-place and won't change + * the format. It must not be run on a template directly. ++ * ++ * Don't run 'qemu-img resize' on an auto format. This is to ++ * force an explicit conversion step to a real format. + *) +- else if output_size > old_size && is_not `Template then ( ++ else if output_size > old_size && is_not `Template && List.mem_assoc `Format itags then ( + tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); + tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); + ); +@@ -464,7 +469,8 @@ let main () = + + | itags, `Virt_resize, otags -> + let ifile = List.assoc `Filename itags in +- let iformat = List.assoc `Format itags in ++ let iformat = ++ try Some (List.assoc `Format itags) with Not_found -> None in + let ofile = List.assoc `Filename otags in + let osize = Int64.of_string (List.assoc `Size otags) in + let osize = roundup64 osize 512L in +@@ -481,10 +487,12 @@ let main () = + if debug then eprintf "%s\n%!" cmd; + if Sys.command cmd <> 0 then exit 1; + let cmd = +- sprintf "virt-resize%s%s --format %s --output-format %s%s%s %s %s" ++ sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" + (if debug then " --verbose" else " --quiet") + (if output_is_block_dev then " --no-sparse" else "") +- (quote iformat) ++ (match iformat with ++ | None -> "" ++ | Some iformat -> sprintf " --format %s" (quote iformat)) + (quote oformat) + (match expand with + | None -> "" +@@ -509,13 +517,17 @@ let main () = + + | itags, `Convert, otags -> + let ifile = List.assoc `Filename itags in +- let iformat = List.assoc `Format itags in ++ let iformat = ++ try Some (List.assoc `Format itags) with Not_found -> None in + let ofile = List.assoc `Filename otags in + let oformat = List.assoc `Format otags in +- msg (f_"Converting %s to %s") iformat oformat; +- let cmd = sprintf "qemu-img convert -f %s %s -O %s %s%s" +- (quote iformat) (quote ifile) +- (quote oformat) (quote ofile) ++ msg (f_"Converting %s to %s") ++ (match iformat with None -> "auto" | Some f -> f) oformat; ++ let cmd = sprintf "qemu-img convert%s %s -O %s %s%s" ++ (match iformat with ++ | None -> "" ++ | Some iformat -> sprintf " -f %s" (quote iformat)) ++ (quote ifile) (quote oformat) (quote ofile) + (if debug then "" else " >/dev/null 2>&1") in + if debug then eprintf "%s\n%!" cmd; + if Sys.command cmd <> 0 then exit 1 +-- +1.8.4.2 + diff --git a/0028-builder-Flush-debug-info-after-printing-it.patch b/0028-builder-Flush-debug-info-after-printing-it.patch new file mode 100644 index 0000000..f3a1035 --- /dev/null +++ b/0028-builder-Flush-debug-info-after-printing-it.patch @@ -0,0 +1,26 @@ +From 6017ceac7a8b5b41863cb6901204153961b4ad30 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 15:50:04 +0000 +Subject: [PATCH] builder: Flush debug info after printing it. + +(cherry picked from commit 7af9cabadeb1da329de4411d7eaea2e347496446) +--- + builder/builder.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 4176457..854093d 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -429,7 +429,7 @@ let main () = + eprintf "\n"; + eprintf "%d: otags:" i; + print_tags otags; +- eprintf "\n\n" ++ eprintf "\n\n%!" + ) plan + ); + +-- +1.8.4.2 + diff --git a/0028-builder-planner-Handle-no-format-in-source-case-corr.patch b/0028-builder-planner-Handle-no-format-in-source-case-corr.patch deleted file mode 100644 index 10731ef..0000000 --- a/0028-builder-planner-Handle-no-format-in-source-case-corr.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 80671be3c32a4d95801448815435f4ee708b446b Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 15:49:25 +0000 -Subject: [PATCH] builder: planner: Handle no format= in source case correctly. - -(cherry picked from commit 0af1e55e68c7cdaecc0af22e8bc41b8cff197e44) ---- - builder/builder.ml | 44 ++++++++++++++++++++++++++++---------------- - 1 file changed, 28 insertions(+), 16 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index df82707..f5a8df4 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -246,14 +246,16 @@ let main () = - (* Planner: Input tags. *) - let itags = - let { Index_parser.size = size; format = format } = entry in -- let format = match format with None -> "auto" | Some format -> format in -- let compression_tags = -+ let format_tag = -+ match format with -+ | None -> [] -+ | Some format -> [`Format, format] in -+ let compression_tag = - match detect_compression template with - | `XZ -> [ `XZ, "" ] -- | `Unknown -> [] -- in -- [ `Template, ""; `Filename, template; `Size, Int64.to_string size; -- `Format, format ] @ compression_tags in -+ | `Unknown -> [] in -+ [ `Template, ""; `Filename, template; `Size, Int64.to_string size ] @ -+ format_tag @ compression_tag in - - (* Planner: Goal. *) - let output_size = -@@ -282,7 +284,7 @@ let main () = - ] in - - (* MUST NOT *) -- let goal_must_not = [ `Template, ""; `XZ, ""; `Format, "auto" ] in -+ let goal_must_not = [ `Template, ""; `XZ, "" ] in - - goal_must, goal_must_not in - -@@ -357,8 +359,11 @@ let main () = - * - * 'qemu-img resize' works on the file in-place and won't change - * the format. It must not be run on a template directly. -+ * -+ * Don't run 'qemu-img resize' on an auto format. This is to -+ * force an explicit conversion step to a real format. - *) -- else if output_size > old_size && is_not `Template then ( -+ else if output_size > old_size && is_not `Template && List.mem_assoc `Format itags then ( - tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); - tr `Disk_resize 60 ((`Size, Int64.to_string output_size) :: itags); - ); -@@ -462,7 +467,8 @@ let main () = - - | itags, `Virt_resize, otags -> - let ifile = List.assoc `Filename itags in -- let iformat = List.assoc `Format itags in -+ let iformat = -+ try Some (List.assoc `Format itags) with Not_found -> None in - let ofile = List.assoc `Filename otags in - let osize = Int64.of_string (List.assoc `Size otags) in - let osize = roundup64 osize 512L in -@@ -479,10 +485,12 @@ let main () = - if debug then eprintf "%s\n%!" cmd; - if Sys.command cmd <> 0 then exit 1; - let cmd = -- sprintf "virt-resize%s%s --format %s --output-format %s%s%s %s %s" -+ sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" - (if debug then " --verbose" else " --quiet") - (if output_is_block_dev then " --no-sparse" else "") -- (quote iformat) -+ (match iformat with -+ | None -> "" -+ | Some iformat -> sprintf " --format %s" (quote iformat)) - (quote oformat) - (match expand with - | None -> "" -@@ -507,13 +515,17 @@ let main () = - - | itags, `Convert, otags -> - let ifile = List.assoc `Filename itags in -- let iformat = List.assoc `Format itags in -+ let iformat = -+ try Some (List.assoc `Format itags) with Not_found -> None in - let ofile = List.assoc `Filename otags in - let oformat = List.assoc `Format otags in -- msg (f_"Converting %s to %s") iformat oformat; -- let cmd = sprintf "qemu-img convert -f %s %s -O %s %s%s" -- (quote iformat) (quote ifile) -- (quote oformat) (quote ofile) -+ msg (f_"Converting %s to %s") -+ (match iformat with None -> "auto" | Some f -> f) oformat; -+ let cmd = sprintf "qemu-img convert%s %s -O %s %s%s" -+ (match iformat with -+ | None -> "" -+ | Some iformat -> sprintf " -f %s" (quote iformat)) -+ (quote ifile) (quote oformat) (quote ofile) - (if debug then "" else " >/dev/null 2>&1") in - if debug then eprintf "%s\n%!" cmd; - if Sys.command cmd <> 0 then exit 1 --- -1.8.4.2 - diff --git a/0029-builder-Add-a-test-of-the-planner.patch b/0029-builder-Add-a-test-of-the-planner.patch new file mode 100644 index 0000000..9235d7b --- /dev/null +++ b/0029-builder-Add-a-test-of-the-planner.patch @@ -0,0 +1,173 @@ +From 1ca9b9ef1a0e8972420a2756fc39b401d61a8963 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 15:50:37 +0000 +Subject: [PATCH] builder: Add a test of the planner. + +This tries out many combinations of size/format and ensures +that the planner can deal with them. + +(cherry picked from commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da) +--- + .gitignore | 1 + + builder/Makefile.am | 24 ++++++++++++++--- + builder/test-index.in | 26 ++++++++++++++++++ + builder/test-virt-builder-planner.sh | 51 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 98 insertions(+), 4 deletions(-) + create mode 100755 builder/test-virt-builder-planner.sh + +diff --git a/.gitignore b/.gitignore +index 8f0cda3..6e04072 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -61,6 +61,7 @@ Makefile.in + /builder/index-parse.c + /builder/index-parse.h + /builder/index-scan.c ++/builder/*.qcow2 + /builder/stamp-virt-builder.pod + /builder/stamp-virt-index-validate.pod + /builder/test-index +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 0d9ea75..6ec4b2b 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -141,15 +141,28 @@ CLEANFILES += stamp-virt-builder.pod + + TESTS_ENVIRONMENT = $(top_builddir)/run --test + +-all_disk_images := debian.xz fedora.xz ubuntu.xz windows.xz +-disk_images := $(shell for f in $(all_disk_images); do b=`basename $$f .xz`; if [ -f "../tests/guests/$$b.img" ]; then echo $$f; fi; done) ++disk_images := \ ++ $(shell for f in debian fedora ubuntu windows; do if [ -s "../tests/guests/$$f.img" ]; then echo $$f.xz; fi; done) \ ++ $(shell if [ -s "../tests/guests/fedora.img" ]; then echo fedora.qcow2 fedora.qcow2.xz; fi) + +-CLEANFILES += $(all_disk_images) ++CLEANFILES += *.qcow2 *.xz + + check_DATA = $(disk_images) + ++fedora.qcow2: ../tests/guests/fedora.img ++ rm -f $@ $@-t ++ qemu-img convert -f raw -O qcow2 $< $@-t ++ mv $@-t $@ ++ ++fedora.qcow2.xz: fedora.qcow2 ++ rm -f $@ $@-t ++ xz --best --block-size=16777216 -c $< > $@-t ++ mv $@-t $@ ++ + %.xz: ../tests/guests/%.img +- xz --best --block-size=16777216 -c $< > $@ ++ rm -f $@ $@-t ++ xz --best --block-size=16777216 -c $< > $@-t ++ mv $@-t $@ + + TESTS = test-virt-builder-list.sh + +@@ -160,6 +173,9 @@ endif ENABLE_APPLIANCE + check-valgrind: + $(MAKE) VG="$(top_builddir)/run @VG@" check + ++check-slow: ++ $(MAKE) TESTS="test-virt-builder-planner.sh" check ++ + # Dependencies. + depend: .depend + +diff --git a/builder/test-index.in b/builder/test-index.in +index 21e2ca3..1bca6b8 100644 +--- a/builder/test-index.in ++++ b/builder/test-index.in +@@ -16,6 +16,32 @@ expand=/dev/sda2 + lvexpand=/dev/VG/Root + notes=Phony Fedora look-alike used for testing. + ++[phony-fedora-qcow2] ++name=Phony Fedora qcow2 ++file=fedora.qcow2.xz ++format=qcow2 ++size=1073741824 ++expand=/dev/sda2 ++lvexpand=/dev/VG/Root ++notes=Phony Fedora look-alike used for testing. ++ ++[phony-fedora-qcow2-uncompressed] ++name=Phony Fedora qcow2 uncompressed ++file=fedora.qcow2 ++format=qcow2 ++size=1073741824 ++expand=/dev/sda2 ++lvexpand=/dev/VG/Root ++notes=Phony Fedora look-alike used for testing. ++ ++[phony-fedora-no-format] ++name=Phony Fedora ++file=fedora.qcow2.xz ++size=1073741824 ++expand=/dev/sda2 ++lvexpand=/dev/VG/Root ++notes=Phony Fedora look-alike used for testing. ++ + [phony-ubuntu] + name=Phony Ubuntu + file=ubuntu.xz +diff --git a/builder/test-virt-builder-planner.sh b/builder/test-virt-builder-planner.sh +new file mode 100755 +index 0000000..738b299 +--- /dev/null ++++ b/builder/test-virt-builder-planner.sh +@@ -0,0 +1,51 @@ ++#!/bin/bash - ++# libguestfs virt-builder test script ++# Copyright (C) 2013 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++export LANG=C ++set -e ++ ++abs_builddir=$(pwd) ++ ++export VIRT_BUILDER_SOURCE=file://$abs_builddir/test-index ++ ++if [ ! -f fedora.xz -o ! -f fedora.qcow2 -o ! -f fedora.qcow2.xz ]; then ++ echo "$0: test skipped because there is no fedora.xz, fedora.qcow2 or fedora.qcow2.xz in the build directory" ++ exit 77 ++fi ++ ++if [ "$(../fish/guestfish get-backend)" = "uml" ]; then ++ echo "$0: test skipped because backend is UML" ++ exit 77 ++fi ++ ++rm -f planner-output ++ ++for input in phony-fedora phony-fedora-qcow2 phony-fedora-qcow2-uncompressed phony-fedora-no-format; do ++ for size in none 1G 1.1G 2G; do ++ for format in none raw qcow2; do ++ args="--output planner-output --no-cache --no-check-signature" ++ if [ "$size" != "none" ]; then args="$args --size $size"; fi ++ if [ "$format" != "none" ]; then args="$args --format $format"; fi ++ ++ echo $VG ./virt-builder $input $args ++ $VG ./virt-builder $input $args ++ done ++ done ++done ++ ++rm planner-output +-- +1.8.4.2 + diff --git a/0029-builder-Flush-debug-info-after-printing-it.patch b/0029-builder-Flush-debug-info-after-printing-it.patch deleted file mode 100644 index aa1a5e7..0000000 --- a/0029-builder-Flush-debug-info-after-printing-it.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 2e7013906f7e1eb6f11fe63196eb07e414cc584a Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 15:50:04 +0000 -Subject: [PATCH] builder: Flush debug info after printing it. - -(cherry picked from commit 7af9cabadeb1da329de4411d7eaea2e347496446) ---- - builder/builder.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index f5a8df4..5106263 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -427,7 +427,7 @@ let main () = - eprintf "\n"; - eprintf "%d: otags:" i; - print_tags otags; -- eprintf "\n\n" -+ eprintf "\n\n%!" - ) plan - ); - --- -1.8.4.2 - diff --git a/0030-builder-Add-a-test-of-the-planner.patch b/0030-builder-Add-a-test-of-the-planner.patch deleted file mode 100644 index 46bed19..0000000 --- a/0030-builder-Add-a-test-of-the-planner.patch +++ /dev/null @@ -1,173 +0,0 @@ -From b50e02ca9354ebd173bc47684eaec41fa250215f Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 15:50:37 +0000 -Subject: [PATCH] builder: Add a test of the planner. - -This tries out many combinations of size/format and ensures -that the planner can deal with them. - -(cherry picked from commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da) ---- - .gitignore | 1 + - builder/Makefile.am | 24 ++++++++++++++--- - builder/test-index.in | 26 ++++++++++++++++++ - builder/test-virt-builder-planner.sh | 51 ++++++++++++++++++++++++++++++++++++ - 4 files changed, 98 insertions(+), 4 deletions(-) - create mode 100755 builder/test-virt-builder-planner.sh - -diff --git a/.gitignore b/.gitignore -index 4a77963..32b8662 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -61,6 +61,7 @@ Makefile.in - /builder/index-parse.c - /builder/index-parse.h - /builder/index-scan.c -+/builder/*.qcow2 - /builder/stamp-virt-builder.pod - /builder/stamp-virt-index-validate.pod - /builder/test-index -diff --git a/builder/Makefile.am b/builder/Makefile.am -index ca4a254..11967e9 100644 ---- a/builder/Makefile.am -+++ b/builder/Makefile.am -@@ -143,15 +143,28 @@ CLEANFILES += stamp-virt-builder.pod - - TESTS_ENVIRONMENT = $(top_builddir)/run --test - --all_disk_images := debian.xz fedora.xz ubuntu.xz windows.xz --disk_images := $(shell for f in $(all_disk_images); do b=`basename $$f .xz`; if [ -f "../tests/guests/$$b.img" ]; then echo $$f; fi; done) -+disk_images := \ -+ $(shell for f in debian fedora ubuntu windows; do if [ -s "../tests/guests/$$f.img" ]; then echo $$f.xz; fi; done) \ -+ $(shell if [ -s "../tests/guests/fedora.img" ]; then echo fedora.qcow2 fedora.qcow2.xz; fi) - --CLEANFILES += $(all_disk_images) -+CLEANFILES += *.qcow2 *.xz - - check_DATA = $(disk_images) - -+fedora.qcow2: ../tests/guests/fedora.img -+ rm -f $@ $@-t -+ qemu-img convert -f raw -O qcow2 $< $@-t -+ mv $@-t $@ -+ -+fedora.qcow2.xz: fedora.qcow2 -+ rm -f $@ $@-t -+ xz --best --block-size=16777216 -c $< > $@-t -+ mv $@-t $@ -+ - %.xz: ../tests/guests/%.img -- xz --best --block-size=16777216 -c $< > $@ -+ rm -f $@ $@-t -+ xz --best --block-size=16777216 -c $< > $@-t -+ mv $@-t $@ - - TESTS = test-virt-builder-list.sh - -@@ -162,6 +175,9 @@ endif ENABLE_APPLIANCE - check-valgrind: - $(MAKE) VG="$(top_builddir)/run @VG@" check - -+check-slow: -+ $(MAKE) TESTS="test-virt-builder-planner.sh" check -+ - # Dependencies. - depend: .depend - -diff --git a/builder/test-index.in b/builder/test-index.in -index 21e2ca3..1bca6b8 100644 ---- a/builder/test-index.in -+++ b/builder/test-index.in -@@ -16,6 +16,32 @@ expand=/dev/sda2 - lvexpand=/dev/VG/Root - notes=Phony Fedora look-alike used for testing. - -+[phony-fedora-qcow2] -+name=Phony Fedora qcow2 -+file=fedora.qcow2.xz -+format=qcow2 -+size=1073741824 -+expand=/dev/sda2 -+lvexpand=/dev/VG/Root -+notes=Phony Fedora look-alike used for testing. -+ -+[phony-fedora-qcow2-uncompressed] -+name=Phony Fedora qcow2 uncompressed -+file=fedora.qcow2 -+format=qcow2 -+size=1073741824 -+expand=/dev/sda2 -+lvexpand=/dev/VG/Root -+notes=Phony Fedora look-alike used for testing. -+ -+[phony-fedora-no-format] -+name=Phony Fedora -+file=fedora.qcow2.xz -+size=1073741824 -+expand=/dev/sda2 -+lvexpand=/dev/VG/Root -+notes=Phony Fedora look-alike used for testing. -+ - [phony-ubuntu] - name=Phony Ubuntu - file=ubuntu.xz -diff --git a/builder/test-virt-builder-planner.sh b/builder/test-virt-builder-planner.sh -new file mode 100755 -index 0000000..738b299 ---- /dev/null -+++ b/builder/test-virt-builder-planner.sh -@@ -0,0 +1,51 @@ -+#!/bin/bash - -+# libguestfs virt-builder test script -+# Copyright (C) 2013 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+export LANG=C -+set -e -+ -+abs_builddir=$(pwd) -+ -+export VIRT_BUILDER_SOURCE=file://$abs_builddir/test-index -+ -+if [ ! -f fedora.xz -o ! -f fedora.qcow2 -o ! -f fedora.qcow2.xz ]; then -+ echo "$0: test skipped because there is no fedora.xz, fedora.qcow2 or fedora.qcow2.xz in the build directory" -+ exit 77 -+fi -+ -+if [ "$(../fish/guestfish get-backend)" = "uml" ]; then -+ echo "$0: test skipped because backend is UML" -+ exit 77 -+fi -+ -+rm -f planner-output -+ -+for input in phony-fedora phony-fedora-qcow2 phony-fedora-qcow2-uncompressed phony-fedora-no-format; do -+ for size in none 1G 1.1G 2G; do -+ for format in none raw qcow2; do -+ args="--output planner-output --no-cache --no-check-signature" -+ if [ "$size" != "none" ]; then args="$args --size $size"; fi -+ if [ "$format" != "none" ]; then args="$args --format $format"; fi -+ -+ echo $VG ./virt-builder $input $args -+ $VG ./virt-builder $input $args -+ done -+ done -+done -+ -+rm planner-output --- -1.8.4.2 - diff --git a/0030-builder-tests-Fix-virt-builder-list-output.patch b/0030-builder-tests-Fix-virt-builder-list-output.patch new file mode 100644 index 0000000..c4137dd --- /dev/null +++ b/0030-builder-tests-Fix-virt-builder-list-output.patch @@ -0,0 +1,60 @@ +From 4c834e9703fea0bab32e2360c40caa7ca3a5a2c2 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 16:18:23 +0000 +Subject: [PATCH] builder: tests: Fix virt-builder --list output. + +This fixes commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da. + +(cherry picked from commit 3f433d90f208da8e2b7ea397485dfd8d415726a0) +--- + builder/test-virt-builder-list.sh | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh +index ff16abe..083c035 100755 +--- a/builder/test-virt-builder-list.sh ++++ b/builder/test-virt-builder-list.sh +@@ -29,6 +29,9 @@ short_list=$($VG ./virt-builder --no-check-signature --no-cache --list) + + if [ "$short_list" != "phony-debian Phony Debian + phony-fedora Phony Fedora ++phony-fedora-qcow2 Phony Fedora qcow2 ++phony-fedora-qcow2-uncompressed Phony Fedora qcow2 uncompressed ++phony-fedora-no-format Phony Fedora + phony-ubuntu Phony Ubuntu + phony-windows Phony Windows" ]; then + echo "$0: unexpected --list output:" +@@ -57,6 +60,30 @@ Notes: + + Phony Fedora look-alike used for testing. + ++os-version: phony-fedora-qcow2 ++Full name: Phony Fedora qcow2 ++Minimum/default size: 1.0G ++ ++Notes: ++ ++Phony Fedora look-alike used for testing. ++ ++os-version: phony-fedora-qcow2-uncompressed ++Full name: Phony Fedora qcow2 uncompressed ++Minimum/default size: 1.0G ++ ++Notes: ++ ++Phony Fedora look-alike used for testing. ++ ++os-version: phony-fedora-no-format ++Full name: Phony Fedora ++Minimum/default size: 1.0G ++ ++Notes: ++ ++Phony Fedora look-alike used for testing. ++ + os-version: phony-ubuntu + Full name: Phony Ubuntu + Minimum/default size: 512.0M +-- +1.8.4.2 + diff --git a/0031-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch b/0031-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch new file mode 100644 index 0000000..e415a62 --- /dev/null +++ b/0031-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch @@ -0,0 +1,30 @@ +From d0f2d9c2e1468e2761cdc89940e5f989d971483f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 16:18:50 +0000 +Subject: [PATCH] builder: tests: Add test-virt-builder-planner.sh to + EXTRA_DIST. + +This fixes commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da. + +(cherry picked from commit 6901cd2250fc25c1761f191fb02db74fecf4703d) +--- + builder/Makefile.am | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 6ec4b2b..f5e7d80 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -30,7 +30,8 @@ EXTRA_DIST = \ + virt-builder.pod \ + virt-index-validate.pod \ + test-virt-builder.sh \ +- test-virt-builder-list.sh ++ test-virt-builder-list.sh \ ++ test-virt-builder-planner.sh + + CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-builder + +-- +1.8.4.2 + diff --git a/0031-builder-tests-Fix-virt-builder-list-output.patch b/0031-builder-tests-Fix-virt-builder-list-output.patch deleted file mode 100644 index 425f185..0000000 --- a/0031-builder-tests-Fix-virt-builder-list-output.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 44cc06949962243ac0d262a9b1c6166a7840a147 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 16:18:23 +0000 -Subject: [PATCH] builder: tests: Fix virt-builder --list output. - -This fixes commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da. - -(cherry picked from commit 3f433d90f208da8e2b7ea397485dfd8d415726a0) ---- - builder/test-virt-builder-list.sh | 27 +++++++++++++++++++++++++++ - 1 file changed, 27 insertions(+) - -diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh -index ff16abe..083c035 100755 ---- a/builder/test-virt-builder-list.sh -+++ b/builder/test-virt-builder-list.sh -@@ -29,6 +29,9 @@ short_list=$($VG ./virt-builder --no-check-signature --no-cache --list) - - if [ "$short_list" != "phony-debian Phony Debian - phony-fedora Phony Fedora -+phony-fedora-qcow2 Phony Fedora qcow2 -+phony-fedora-qcow2-uncompressed Phony Fedora qcow2 uncompressed -+phony-fedora-no-format Phony Fedora - phony-ubuntu Phony Ubuntu - phony-windows Phony Windows" ]; then - echo "$0: unexpected --list output:" -@@ -57,6 +60,30 @@ Notes: - - Phony Fedora look-alike used for testing. - -+os-version: phony-fedora-qcow2 -+Full name: Phony Fedora qcow2 -+Minimum/default size: 1.0G -+ -+Notes: -+ -+Phony Fedora look-alike used for testing. -+ -+os-version: phony-fedora-qcow2-uncompressed -+Full name: Phony Fedora qcow2 uncompressed -+Minimum/default size: 1.0G -+ -+Notes: -+ -+Phony Fedora look-alike used for testing. -+ -+os-version: phony-fedora-no-format -+Full name: Phony Fedora -+Minimum/default size: 1.0G -+ -+Notes: -+ -+Phony Fedora look-alike used for testing. -+ - os-version: phony-ubuntu - Full name: Phony Ubuntu - Minimum/default size: 512.0M --- -1.8.4.2 - diff --git a/0032-builder-Add-a-link-to-blog-posting-about-the-planner.patch b/0032-builder-Add-a-link-to-blog-posting-about-the-planner.patch new file mode 100644 index 0000000..d0e5f2d --- /dev/null +++ b/0032-builder-Add-a-link-to-blog-posting-about-the-planner.patch @@ -0,0 +1,60 @@ +From 4842105b79ba74b18c926416e3dc02f978e7e80b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 16:43:40 +0000 +Subject: [PATCH] builder: Add a link to blog posting about the planner. + +http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ +should help people to understand how this code works. + +(cherry picked from commit d5d1dac3ac1e3027dc507b1343022f6bcea20822) +--- + builder/builder.ml | 4 ++++ + mllib/planner.mli | 17 ++--------------- + 2 files changed, 6 insertions(+), 15 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 854093d..8951be5 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -245,6 +245,10 @@ let main () = + + Sigchecker.verify_detached sigchecker template sigfile in + ++ (* For an explanation of the Planner, see: ++ * http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ ++ *) ++ + (* Planner: Input tags. *) + let itags = + let { Index_parser.size = size; format = format } = entry in +diff --git a/mllib/planner.mli b/mllib/planner.mli +index 770a00f..8c77acd 100644 +--- a/mllib/planner.mli ++++ b/mllib/planner.mli +@@ -22,21 +22,8 @@ + multi-step plan (list of transitions) from the input state to the + output state. + +- For example: +- +- Input tags: xz cached size=4G format=raw +- +- Output tags: -xz -cached +size=8G +format=raw +- +- (In this case the "-" before an output tag means the tag MUST NOT +- appear, and the "+" before an output tag means the tag MUST +- appear). +- +- The plan produced might be: +- +- (1) Run xzcat (removes xz and cached tags). +- +- (2) Run virt-resize (changes size=4G to size=8G) ++ For an explanation of the Planner, see: ++ http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ + + Tags are described as OCaml association lists. See the OCaml + {!List} module. +-- +1.8.4.2 + diff --git a/0032-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch b/0032-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch deleted file mode 100644 index 9beba6d..0000000 --- a/0032-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch +++ /dev/null @@ -1,30 +0,0 @@ -From c6a116452d896f8b164806ad440091732b8645f5 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 16:18:50 +0000 -Subject: [PATCH] builder: tests: Add test-virt-builder-planner.sh to - EXTRA_DIST. - -This fixes commit a27963b67ba1140c29c145a1ce14dbfc05f8d7da. - -(cherry picked from commit 6901cd2250fc25c1761f191fb02db74fecf4703d) ---- - builder/Makefile.am | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/builder/Makefile.am b/builder/Makefile.am -index 11967e9..3f35cc6 100644 ---- a/builder/Makefile.am -+++ b/builder/Makefile.am -@@ -30,7 +30,8 @@ EXTRA_DIST = \ - virt-builder.pod \ - virt-index-validate.pod \ - test-virt-builder.sh \ -- test-virt-builder-list.sh -+ test-virt-builder-list.sh \ -+ test-virt-builder-planner.sh - - CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-builder - --- -1.8.4.2 - diff --git a/0033-builder-Add-a-link-to-blog-posting-about-the-planner.patch b/0033-builder-Add-a-link-to-blog-posting-about-the-planner.patch deleted file mode 100644 index a779097..0000000 --- a/0033-builder-Add-a-link-to-blog-posting-about-the-planner.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 86ac9a614d3791df16eb307f0c7fb6aef29ca0b8 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 16:43:40 +0000 -Subject: [PATCH] builder: Add a link to blog posting about the planner. - -http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ -should help people to understand how this code works. - -(cherry picked from commit d5d1dac3ac1e3027dc507b1343022f6bcea20822) ---- - builder/builder.ml | 4 ++++ - mllib/planner.mli | 17 ++--------------- - 2 files changed, 6 insertions(+), 15 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 5106263..77b18ce 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -243,6 +243,10 @@ let main () = - - Sigchecker.verify_detached sigchecker template sigfile in - -+ (* For an explanation of the Planner, see: -+ * http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ -+ *) -+ - (* Planner: Input tags. *) - let itags = - let { Index_parser.size = size; format = format } = entry in -diff --git a/mllib/planner.mli b/mllib/planner.mli -index 770a00f..8c77acd 100644 ---- a/mllib/planner.mli -+++ b/mllib/planner.mli -@@ -22,21 +22,8 @@ - multi-step plan (list of transitions) from the input state to the - output state. - -- For example: -- -- Input tags: xz cached size=4G format=raw -- -- Output tags: -xz -cached +size=8G +format=raw -- -- (In this case the "-" before an output tag means the tag MUST NOT -- appear, and the "+" before an output tag means the tag MUST -- appear). -- -- The plan produced might be: -- -- (1) Run xzcat (removes xz and cached tags). -- -- (2) Run virt-resize (changes size=4G to size=8G) -+ For an explanation of the Planner, see: -+ http://rwmj.wordpress.com/2013/12/14/writing-a-planner-to-solve-a-tricky-programming-optimization-problem/ - - Tags are described as OCaml association lists. See the OCaml - {!List} module. --- -1.8.4.2 - diff --git a/0033-builder-Only-use-virt-resize-no-sparse-when-writing-.patch b/0033-builder-Only-use-virt-resize-no-sparse-when-writing-.patch new file mode 100644 index 0000000..1f485c1 --- /dev/null +++ b/0033-builder-Only-use-virt-resize-no-sparse-when-writing-.patch @@ -0,0 +1,33 @@ +From 47b170768af8b09fb3185f1e21d129f06c44faff Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 18:53:20 +0000 +Subject: [PATCH] builder: Only use virt-resize --no-sparse when writing to a + block device. + +Previously we would use the virt-resize --no-sparse option if the +final output file was a block device. This is safe, but unnecessary +for example if virt-resize was used as an intermediate step. So only +use this option if virt-resize is actually writing to the block +device. + +(cherry picked from commit 0037820ee003bfbc71bf35b18fb3a066cbf298f8) +--- + builder/builder.ml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 8951be5..148c9bf 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -493,7 +493,7 @@ let main () = + let cmd = + sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" + (if debug then " --verbose" else " --quiet") +- (if output_is_block_dev then " --no-sparse" else "") ++ (if is_block_device ofile then " --no-sparse" else "") + (match iformat with + | None -> "" + | Some iformat -> sprintf " --format %s" (quote iformat)) +-- +1.8.4.2 + diff --git a/0034-builder-Only-use-virt-resize-no-sparse-when-writing-.patch b/0034-builder-Only-use-virt-resize-no-sparse-when-writing-.patch deleted file mode 100644 index 7207020..0000000 --- a/0034-builder-Only-use-virt-resize-no-sparse-when-writing-.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 7b618e1d4da8407652f74a5a7d466ff50bcb71b7 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 18:53:20 +0000 -Subject: [PATCH] builder: Only use virt-resize --no-sparse when writing to a - block device. - -Previously we would use the virt-resize --no-sparse option if the -final output file was a block device. This is safe, but unnecessary -for example if virt-resize was used as an intermediate step. So only -use this option if virt-resize is actually writing to the block -device. - -(cherry picked from commit 0037820ee003bfbc71bf35b18fb3a066cbf298f8) ---- - builder/builder.ml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 77b18ce..5c2b27a 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -491,7 +491,7 @@ let main () = - let cmd = - sprintf "virt-resize%s%s%s --output-format %s%s%s %s %s" - (if debug then " --verbose" else " --quiet") -- (if output_is_block_dev then " --no-sparse" else "") -+ (if is_block_device ofile then " --no-sparse" else "") - (match iformat with - | None -> "" - | Some iformat -> sprintf " --format %s" (quote iformat)) --- -1.8.4.2 - diff --git a/0034-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch b/0034-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch new file mode 100644 index 0000000..dbf24d7 --- /dev/null +++ b/0034-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch @@ -0,0 +1,33 @@ +From 26c861ed189888c1fa25e7a250d333a5cac257ba Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sat, 14 Dec 2013 18:54:56 +0000 +Subject: [PATCH] builder: Refuse to write to a char device or /dev/null. + +virt-builder --output /dev/null is tempting, but not possible, and +might result in /dev/null being deleted(!) Check for this case and +prevent it happening. + +(cherry picked from commit 3cf5a25e3f63ea6832b96468a94cdb13dbd26e92) +--- + builder/builder.ml | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 148c9bf..5d8ad09 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -281,6 +281,11 @@ let main () = + exit 1 + ); + ++ if is_char_device output_filename then ( ++ eprintf (f_"%s: cannot output to a character device or /dev/null\n") prog; ++ exit 1 ++ ); ++ + let goal = + (* MUST *) + let goal_must = [ +-- +1.8.4.2 + diff --git a/0035-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch b/0035-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch deleted file mode 100644 index f4a16ff..0000000 --- a/0035-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 9fdc0f1303626742595e8d25a3359736037204df Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sat, 14 Dec 2013 18:54:56 +0000 -Subject: [PATCH] builder: Refuse to write to a char device or /dev/null. - -virt-builder --output /dev/null is tempting, but not possible, and -might result in /dev/null being deleted(!) Check for this case and -prevent it happening. - -(cherry picked from commit 3cf5a25e3f63ea6832b96468a94cdb13dbd26e92) ---- - builder/builder.ml | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 5c2b27a..5947667 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -279,6 +279,11 @@ let main () = - exit 1 - ); - -+ if is_char_device output_filename then ( -+ eprintf (f_"%s: cannot output to a character device or /dev/null\n") prog; -+ exit 1 -+ ); -+ - let goal = - (* MUST *) - let goal_must = [ --- -1.8.4.2 - diff --git a/0035-builder-Remove-blank-line.patch b/0035-builder-Remove-blank-line.patch new file mode 100644 index 0000000..3faf21b --- /dev/null +++ b/0035-builder-Remove-blank-line.patch @@ -0,0 +1,25 @@ +From 0331c729237b94df8db7a936aefde6c5270d4da0 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 16 Dec 2013 14:14:01 +0000 +Subject: [PATCH] builder: Remove blank line. + +(cherry picked from commit c4fdb4023eed45dbf905526da4a91b846792079d) +--- + builder/builder.ml | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 5d8ad09..1551b72 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -58,7 +58,6 @@ let main () = + ) sources + ); + +- + (* Handle some modes here, some later on. *) + let mode = + match mode with +-- +1.8.4.2 + diff --git a/0036-builder-Add-update-option-to-update-template-core-pa.patch b/0036-builder-Add-update-option-to-update-template-core-pa.patch new file mode 100644 index 0000000..b15a2d0 --- /dev/null +++ b/0036-builder-Add-update-option-to-update-template-core-pa.patch @@ -0,0 +1,265 @@ +From a7a1577b86da7b90de88d39431035fa92cc022f9 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 19 Dec 2013 11:17:43 +0000 +Subject: [PATCH] builder: Add --update option to update template/core + packages. + +(cherry picked from commit b46a5511b3a98c0d811353b1bc0c7745fa972dc6) +--- + builder/builder.ml | 40 ++++++++++++++++++++++++++++- + builder/cmdline.ml | 5 +++- + builder/virt-builder.pod | 67 +++++++++++++++++++++++++++++++++--------------- + 3 files changed, 90 insertions(+), 22 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 1551b72..1cd007f 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -41,7 +41,7 @@ let main () = + attach, cache, check_signature, curl, debug, delete, edit, + firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, upload, writes = ++ scrub_logfile, size, smp, sources, sync, update, upload, writes = + parse_cmdline () in + + (* Timestamped messages in ordinary, non-debug non-quiet mode. *) +@@ -669,6 +669,7 @@ exec >>%s 2>&1 + exit 1 + in + ++ (* http://distrowatch.com/dwres.php?resource=package-management *) + let guest_install_command packages = + let quoted_args = String.concat " " (List.map quote packages) in + match g#inspect_get_package_management root with +@@ -699,8 +700,45 @@ exec >>%s 2>&1 + eprintf (f_"%s: sorry, don't know how to use --install with the '%s' package manager\n") + prog pm; + exit 1 ++ ++ and guest_update_command () = ++ match g#inspect_get_package_management root with ++ | "apt" -> ++ (* http://unix.stackexchange.com/questions/22820 *) ++ sprintf " ++ export DEBIAN_FRONTEND=noninteractive ++ apt_opts='-q -y -o Dpkg::Options::=--force-confnew' ++ apt-get $apt_opts update ++ apt-get $apt_opts upgrade ++ " ++ | "pisi" -> ++ sprintf "pisi upgrade" ++ | "pacman" -> ++ sprintf "pacman -Su" ++ | "urpmi" -> ++ sprintf "urpmi --auto-select" ++ | "yum" -> ++ sprintf "yum -y update" ++ | "zypper" -> ++ sprintf "zypper update" ++ | "unknown" -> ++ eprintf (f_"%s: --update is not supported for this guest operating system\n") ++ prog; ++ exit 1 ++ | pm -> ++ eprintf (f_"%s: sorry, don't know how to use --update with the '%s' package manager\n") ++ prog pm; ++ exit 1 + in + ++ (* Update core/template packages. *) ++ if update then ( ++ msg (f_"Updating core packages"); ++ ++ let cmd = guest_update_command () in ++ do_run ~display:cmd cmd ++ ); ++ + (* Install packages. *) + if install <> [] then ( + msg (f_"Installing packages: %s") (String.concat " " install); +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index b4e21fc..f25280c 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -169,6 +169,7 @@ let parse_cmdline () = + let add_source arg = sources := arg :: !sources in + + let sync = ref true in ++ let update = ref false in + + let upload = ref [] in + let add_upload arg = +@@ -259,6 +260,7 @@ let parse_cmdline () = + "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; + "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; + "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit"; ++ "--update", Arg.Set update, " " ^ s_"Update core packages"; + "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest"; + "-v", Arg.Set debug, " " ^ s_"Enable debugging messages"; + "--verbose", Arg.Set debug, ditto; +@@ -319,6 +321,7 @@ read the man page virt-builder(1). + let smp = !smp in + let sources = List.rev !sources in + let sync = !sync in ++ let update = !update in + let upload = List.rev !upload in + let writes = List.rev !writes in + +@@ -418,4 +421,4 @@ read the man page virt-builder(1). + attach, cache, check_signature, curl, debug, delete, edit, + firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, upload, writes ++ scrub_logfile, size, smp, sources, sync, update, upload, writes +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 817ddd4..094f028 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly + [--attach ISOFILE] + [--root-password SELECTOR] + [--hostname HOSTNAME] ++ [--update] + [--install PKG,[PKG...]] + [--mkdir DIR] + [--write FILE:CONTENT] +@@ -215,7 +216,7 @@ I<--no-cache> disables template caching. + Download all templates to the cache and then exit. See L. + + Note this doesn't cache everything. More templates might be uploaded. +-Also this doesn't cache packages (the I<--install> option). ++Also this doesn't cache packages (the I<--install>, I<--update> options). + + =item B<--check-signature> + +@@ -349,6 +350,8 @@ installed during the image build using the guest's package manager + For an overview on the different ways to install packages, see + L. + ++See also I<--update>. ++ + =item B<-l> + + =item B<--list> +@@ -580,6 +583,14 @@ Note that you should not point I<--source> to sources that you don't + trust (unless the source is signed by someone you do trust). See also + the I<--no-network> option. + ++=item B<--update> ++ ++Do the equivalent of C, C, or whatever ++command is required to update the packages already installed in the ++template to their latest versions. ++ ++See also I<--install>. ++ + =item B<--upload> FILE:DEST + + Upload local file C to destination C in the disk image. +@@ -634,6 +645,18 @@ you can use I<--install> to install packages like this: + This uses the guest's package manager and the host's network + connection. + ++=head3 Updating packages at build time ++ ++To update the core set of packages in the template at build time: ++ ++ virt-builder fedora-20 --update ++ ++Most of the templates that ship with virt-builder come with a very ++minimal selection of packages (known as a "JEOS" or "Just Enough ++Operating System"), which are up to date at the time the template is ++created, but could be out of date by the time you come to install an ++OS from the template. This option updates those template packages. ++ + =head3 Installing packages at first boot + + Another option is to install the packages when the guest first boots: +@@ -757,8 +780,8 @@ are other ways to manage passwords, see L for details. + =head2 LOG FILE + + Scripts and package installation that runs at build time (I<--run>, +-I<--run-command>, I<--install>, but I firstboot) is logged in one +-of the following locations: ++I<--run-command>, I<--install>, I<--update>, but I firstboot) is ++logged in one of the following locations: + + =over 4 + +@@ -823,6 +846,10 @@ The root password is changed (I<--root-password>). + + =item * + ++Core packages are updated (I<--update>). ++ ++=item * ++ + Packages are installed (I<--install>). + + =item * +@@ -1342,9 +1369,9 @@ are not cached. + + Virt-builder uses L to download files and it also uses the + current C (etc) settings when installing packages +-(I<--install>). You may therefore want to set those environment +-variables in order to maximize the amount of local caching that +-happens. See L and L. ++(I<--install>, I<--update>). You may therefore want to set those ++environment variables in order to maximize the amount of local caching ++that happens. See L and L. + + =head2 DIGITAL SIGNATURES + +@@ -1379,8 +1406,8 @@ host architecture is. For example an x86-64 guest on an ARM host. + + However certain options may not work correctly, specifically options + that require running commands in the guest during the build process: +-I<--install>, I<--run>, I<--run-command>. You may need to replace +-these with their firstboot-equivalents. ++I<--install>, I<--update>, I<--run>, I<--run-command>. You may need ++to replace these with their firstboot-equivalents. + + An x86-64 host building 32 bit i686 guests should work without any + special steps. +@@ -1390,11 +1417,11 @@ special steps. + Virt-builder does not need to run as root (in fact, should not be run + as root), and doesn't use setuid, C or any similar mechanism. + +-I<--install>, I<--run> and I<--run-command> are implemented using an +-appliance (a small virtual machine) so these commands do not run on +-the host. If you are using the libguestfs libvirt backend and have +-SELinux enabled then the virtual machine is additionally encapsulated +-in an SELinux container (sVirt). ++I<--install>, I<--update>, I<--run> and I<--run-command> are ++implemented using an appliance (a small virtual machine) so these ++commands do not run on the host. If you are using the libguestfs ++libvirt backend and have SELinux enabled then the virtual machine is ++additionally encapsulated in an SELinux container (sVirt). + + However these options will have access to the host's network and since + the template may contain untrusted code, the code might try to access +@@ -1435,13 +1462,13 @@ Templates gets downloaded into the cache the first time they are used, + or if you use the I<--cache-all-templates> option. See L + above for further information. + +-Packages required for the I<--install> option are downloaded using the +-host network connection. Setting the C, C +-and C environment variables to point to a local web cache +-may ensure they only need to be downloaded once. You can also try +-using a local package repository, although this can be complex to set +-up and varies according to which Linux distro you are trying to +-install. ++Packages required for the I<--install> and I<--update> options are ++downloaded using the host network connection. Setting the ++C, C and C environment variables ++to point to a local web cache may ensure they only need to be ++downloaded once. You can also try using a local package repository, ++although this can be complex to set up and varies according to which ++Linux distro you are trying to install. + + =head3 Skipping virt-resize + +-- +1.8.4.2 + diff --git a/0036-builder-Remove-blank-line.patch b/0036-builder-Remove-blank-line.patch deleted file mode 100644 index c7938eb..0000000 --- a/0036-builder-Remove-blank-line.patch +++ /dev/null @@ -1,25 +0,0 @@ -From aeebf2b7118591ed0588c394adfcb1c75f350cef Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 16 Dec 2013 14:14:01 +0000 -Subject: [PATCH] builder: Remove blank line. - -(cherry picked from commit c4fdb4023eed45dbf905526da4a91b846792079d) ---- - builder/builder.ml | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 5947667..f6e3595 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -56,7 +56,6 @@ let main () = - ) sources - ); - -- - (* Handle some modes here, some later on. *) - let mode = - match mode with --- -1.8.4.2 - diff --git a/0037-builder-Add-update-option-to-update-template-core-pa.patch b/0037-builder-Add-update-option-to-update-template-core-pa.patch deleted file mode 100644 index 3878e90..0000000 --- a/0037-builder-Add-update-option-to-update-template-core-pa.patch +++ /dev/null @@ -1,265 +0,0 @@ -From ec21401178ef8ac0b1b2ebf5d9e4680bf16c4665 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 19 Dec 2013 11:17:43 +0000 -Subject: [PATCH] builder: Add --update option to update template/core - packages. - -(cherry picked from commit b46a5511b3a98c0d811353b1bc0c7745fa972dc6) ---- - builder/builder.ml | 40 ++++++++++++++++++++++++++++- - builder/cmdline.ml | 5 +++- - builder/virt-builder.pod | 67 +++++++++++++++++++++++++++++++++--------------- - 3 files changed, 90 insertions(+), 22 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index f6e3595..0f8e069 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -39,7 +39,7 @@ let main () = - attach, cache, check_signature, curl, debug, delete, edit, - firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, -- scrub_logfile, size, smp, sources, sync, upload, writes = -+ scrub_logfile, size, smp, sources, sync, update, upload, writes = - parse_cmdline () in - - (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -667,6 +667,7 @@ exec >>%s 2>&1 - exit 1 - in - -+ (* http://distrowatch.com/dwres.php?resource=package-management *) - let guest_install_command packages = - let quoted_args = String.concat " " (List.map quote packages) in - match g#inspect_get_package_management root with -@@ -697,8 +698,45 @@ exec >>%s 2>&1 - eprintf (f_"%s: sorry, don't know how to use --install with the '%s' package manager\n") - prog pm; - exit 1 -+ -+ and guest_update_command () = -+ match g#inspect_get_package_management root with -+ | "apt" -> -+ (* http://unix.stackexchange.com/questions/22820 *) -+ sprintf " -+ export DEBIAN_FRONTEND=noninteractive -+ apt_opts='-q -y -o Dpkg::Options::=--force-confnew' -+ apt-get $apt_opts update -+ apt-get $apt_opts upgrade -+ " -+ | "pisi" -> -+ sprintf "pisi upgrade" -+ | "pacman" -> -+ sprintf "pacman -Su" -+ | "urpmi" -> -+ sprintf "urpmi --auto-select" -+ | "yum" -> -+ sprintf "yum -y update" -+ | "zypper" -> -+ sprintf "zypper update" -+ | "unknown" -> -+ eprintf (f_"%s: --update is not supported for this guest operating system\n") -+ prog; -+ exit 1 -+ | pm -> -+ eprintf (f_"%s: sorry, don't know how to use --update with the '%s' package manager\n") -+ prog pm; -+ exit 1 - in - -+ (* Update core/template packages. *) -+ if update then ( -+ msg (f_"Updating core packages"); -+ -+ let cmd = guest_update_command () in -+ do_run ~display:cmd cmd -+ ); -+ - (* Install packages. *) - if install <> [] then ( - msg (f_"Installing packages: %s") (String.concat " " install); -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index b4e21fc..f25280c 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -169,6 +169,7 @@ let parse_cmdline () = - let add_source arg = sources := arg :: !sources in - - let sync = ref true in -+ let update = ref false in - - let upload = ref [] in - let add_upload arg = -@@ -259,6 +260,7 @@ let parse_cmdline () = - "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; - "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; - "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit"; -+ "--update", Arg.Set update, " " ^ s_"Update core packages"; - "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest"; - "-v", Arg.Set debug, " " ^ s_"Enable debugging messages"; - "--verbose", Arg.Set debug, ditto; -@@ -319,6 +321,7 @@ read the man page virt-builder(1). - let smp = !smp in - let sources = List.rev !sources in - let sync = !sync in -+ let update = !update in - let upload = List.rev !upload in - let writes = List.rev !writes in - -@@ -418,4 +421,4 @@ read the man page virt-builder(1). - attach, cache, check_signature, curl, debug, delete, edit, - firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, -- scrub_logfile, size, smp, sources, sync, upload, writes -+ scrub_logfile, size, smp, sources, sync, update, upload, writes -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 02b07e4..f72e284 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly - [--attach ISOFILE] - [--root-password SELECTOR] - [--hostname HOSTNAME] -+ [--update] - [--install PKG,[PKG...]] - [--mkdir DIR] - [--write FILE:CONTENT] -@@ -215,7 +216,7 @@ I<--no-cache> disables template caching. - Download all templates to the cache and then exit. See L. - - Note this doesn't cache everything. More templates might be uploaded. --Also this doesn't cache packages (the I<--install> option). -+Also this doesn't cache packages (the I<--install>, I<--update> options). - - =item B<--check-signature> - -@@ -349,6 +350,8 @@ installed during the image build using the guest's package manager - For an overview on the different ways to install packages, see - L. - -+See also I<--update>. -+ - =item B<-l> - - =item B<--list> -@@ -580,6 +583,14 @@ Note that you should not point I<--source> to sources that you don't - trust (unless the source is signed by someone you do trust). See also - the I<--no-network> option. - -+=item B<--update> -+ -+Do the equivalent of C, C, or whatever -+command is required to update the packages already installed in the -+template to their latest versions. -+ -+See also I<--install>. -+ - =item B<--upload> FILE:DEST - - Upload local file C to destination C in the disk image. -@@ -634,6 +645,18 @@ you can use I<--install> to install packages like this: - This uses the guest's package manager and the host's network - connection. - -+=head3 Updating packages at build time -+ -+To update the core set of packages in the template at build time: -+ -+ virt-builder fedora-20 --update -+ -+Most of the templates that ship with virt-builder come with a very -+minimal selection of packages (known as a "JEOS" or "Just Enough -+Operating System"), which are up to date at the time the template is -+created, but could be out of date by the time you come to install an -+OS from the template. This option updates those template packages. -+ - =head3 Installing packages at first boot - - Another option is to install the packages when the guest first boots: -@@ -757,8 +780,8 @@ are other ways to manage passwords, see L for details. - =head2 LOG FILE - - Scripts and package installation that runs at build time (I<--run>, --I<--run-command>, I<--install>, but I firstboot) is logged in one --of the following locations: -+I<--run-command>, I<--install>, I<--update>, but I firstboot) is -+logged in one of the following locations: - - =over 4 - -@@ -823,6 +846,10 @@ The root password is changed (I<--root-password>). - - =item * - -+Core packages are updated (I<--update>). -+ -+=item * -+ - Packages are installed (I<--install>). - - =item * -@@ -1342,9 +1369,9 @@ are not cached. - - Virt-builder uses L to download files and it also uses the - current C (etc) settings when installing packages --(I<--install>). You may therefore want to set those environment --variables in order to maximize the amount of local caching that --happens. See L and L. -+(I<--install>, I<--update>). You may therefore want to set those -+environment variables in order to maximize the amount of local caching -+that happens. See L and L. - - =head2 DIGITAL SIGNATURES - -@@ -1379,8 +1406,8 @@ host architecture is. For example an x86-64 guest on an ARM host. - - However certain options may not work correctly, specifically options - that require running commands in the guest during the build process: --I<--install>, I<--run>, I<--run-command>. You may need to replace --these with their firstboot-equivalents. -+I<--install>, I<--update>, I<--run>, I<--run-command>. You may need -+to replace these with their firstboot-equivalents. - - An x86-64 host building 32 bit i686 guests should work without any - special steps. -@@ -1390,11 +1417,11 @@ special steps. - Virt-builder does not need to run as root (in fact, should not be run - as root), and doesn't use setuid, C or any similar mechanism. - --I<--install>, I<--run> and I<--run-command> are implemented using an --appliance (a small virtual machine) so these commands do not run on --the host. If you are using the libguestfs libvirt backend and have --SELinux enabled then the virtual machine is additionally encapsulated --in an SELinux container (sVirt). -+I<--install>, I<--update>, I<--run> and I<--run-command> are -+implemented using an appliance (a small virtual machine) so these -+commands do not run on the host. If you are using the libguestfs -+libvirt backend and have SELinux enabled then the virtual machine is -+additionally encapsulated in an SELinux container (sVirt). - - However these options will have access to the host's network and since - the template may contain untrusted code, the code might try to access -@@ -1417,13 +1444,13 @@ Templates gets downloaded into the cache the first time they are used, - or if you use the I<--cache-all-templates> option. See L - above for further information. - --Packages required for the I<--install> option are downloaded using the --host network connection. Setting the C, C --and C environment variables to point to a local web cache --may ensure they only need to be downloaded once. You can also try --using a local package repository, although this can be complex to set --up and varies according to which Linux distro you are trying to --install. -+Packages required for the I<--install> and I<--update> options are -+downloaded using the host network connection. Setting the -+C, C and C environment variables -+to point to a local web cache may ensure they only need to be -+downloaded once. You can also try using a local package repository, -+although this can be complex to set up and varies according to which -+Linux distro you are trying to install. - - =head3 Skipping virt-resize - --- -1.8.4.2 - diff --git a/0037-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch b/0037-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch new file mode 100644 index 0000000..2e27f77 --- /dev/null +++ b/0037-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch @@ -0,0 +1,92 @@ +From acd1f5bde638bf8e9e8ed4f914a051e6f3d2e605 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 19 Dec 2013 14:22:26 +0000 +Subject: [PATCH] launch: libvirt: Don't default to using NULL for libvirt + connection URI (RHBZ#1045033). + +NULL means that libvirt gets to guess what connection URI we meant. +Currently it guesses qemu:///session for non-root and qemu:///system +for root. Except if LIBVIRT_DEFAULT_URI is set in which case this is +used even if it's not appropriate. Except if Xen is installed in +which case it guesses xen:/// which is not helpful at all. + +Instead use qemu:///session (or qemu:///system for root -- that's +likely to be wrong, but we can't help that). + +If the user really wants to use NULL and let libvirt guess, then they +can now specify the libvirt:null backend. + +See: + +https://bugzilla.redhat.com/show_bug.cgi?id=1045033 +https://bugzilla.redhat.com/show_bug.cgi?id=886915 + +A good way to test this is: + +LIBVIRT_DEFAULT_URI=iambroken libguestfs-test-tool + +The libguestfs libvirt backend should (after this commit) ignore +LIBVIRT_DEFAULT_URI. However other parts of libguestfs will still use +it, eg. guestfs_add_drive_opts, guestfish '-d' option. + +(cherry picked from commit d16db5a6180305543658f3a50657c70bbdf81b40) +--- + src/guestfs.pod | 16 +++++++++++++--- + src/launch-libvirt.c | 10 ++++++++++ + 2 files changed, 23 insertions(+), 3 deletions(-) + +diff --git a/src/guestfs.pod b/src/guestfs.pod +index 6909b50..1931055 100644 +--- a/src/guestfs.pod ++++ b/src/guestfs.pod +@@ -1429,13 +1429,23 @@ note below. + + =item C + ++=item C ++ + =item C> + + Use libvirt to launch and manage the appliance. + +-The optional I is the libvirt connection URI to use (see +-L). The typical libvirt backend +-with a URI would be C ++C causes libguestfs to choose a suitable URI for creating ++session guests. If using the libvirt backend, you almost always ++should use this. ++ ++C causes libguestfs to use the C connection URI, ++which causes libvirt to try to guess what the user meant. You ++probably don't want to use this. ++ ++C> uses I as the libvirt connection URI (see ++L). The typical libvirt backend with a ++URI would be C + + The libvirt backend supports more features, including + hotplugging (see L) and sVirt. +diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c +index b78590a..729f437 100644 +--- a/src/launch-libvirt.c ++++ b/src/launch-libvirt.c +@@ -216,6 +216,16 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri) + if (g->verbose) + guestfs___print_timestamped_message (g, "connect to libvirt"); + ++ /* Decode the URI string. */ ++ if (!libvirt_uri) { /* "libvirt" */ ++ if (!params.current_proc_is_root) ++ libvirt_uri = "qemu:///session"; ++ else ++ libvirt_uri = "qemu:///system"; ++ } else if (STREQ (libvirt_uri, "null")) { /* libvirt:null */ ++ libvirt_uri = NULL; ++ } /* else nothing */ ++ + /* Connect to libvirt, get capabilities. */ + conn = guestfs___open_libvirt_connection (g, libvirt_uri, 0); + if (!conn) { +-- +1.8.4.2 + diff --git a/0038-builder-Fix-handling-of-size-parameter.patch b/0038-builder-Fix-handling-of-size-parameter.patch new file mode 100644 index 0000000..bc7628f --- /dev/null +++ b/0038-builder-Fix-handling-of-size-parameter.patch @@ -0,0 +1,96 @@ +From 9f1e955555f460c9cf1f89fcd6f6fad46eebe0db Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Tue, 7 Jan 2014 17:32:04 +0000 +Subject: [PATCH] builder: Fix handling of --size parameter. + +It now matches the documentation: + + "Select the size of the output disk, [...] + + Virt-builder will resize filesystems inside the disk image + automatically. + + If the size is not specified, then one of two things happens. If + the output is a file, then the size is the same as the template. If + the output is a device, partition, etc then the size of that device + is used." + +This also adds checks to make sure that users don't try to shrink a +disk (which is not possible), and they don't try to resize larger than +the output block device. + +(cherry picked from commit 06f7bea14883c4903c58077757179341c0e1471a) +--- + builder/builder.ml | 43 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 34 insertions(+), 9 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 1cd007f..0c1f1e0 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -263,9 +263,6 @@ let main () = + format_tag @ compression_tag in + + (* Planner: Goal. *) +- let output_size = +- let { Index_parser.size = default_size } = entry in +- match size with None -> default_size | Some size -> size in + let output_filename, output_format = + match output, format with + | None, None -> sprintf "%s.img" arg, "raw" +@@ -273,18 +270,46 @@ let main () = + | None, Some format -> sprintf "%s.%s" arg format, format + | Some output, None -> output, "raw" + | Some output, Some format -> output, format in +- let output_is_block_dev = is_block_device output_filename in +- +- if output_is_block_dev && size <> None then ( +- eprintf (f_"%s: you cannot use --size option with block devices\n") prog; +- exit 1 +- ); + + if is_char_device output_filename then ( + eprintf (f_"%s: cannot output to a character device or /dev/null\n") prog; + exit 1 + ); + ++ let blockdev_getsize64 dev = ++ let cmd = sprintf "blockdev --getsize64 %s" (quote dev) in ++ let lines = external_command ~prog cmd in ++ assert (List.length lines >= 1); ++ Int64.of_string (List.hd lines) ++ in ++ let output_is_block_dev, blockdev_size = ++ let b = is_block_device output_filename in ++ let sz = if b then blockdev_getsize64 output_filename else 0L in ++ b, sz in ++ ++ let output_size = ++ let { Index_parser.size = original_image_size } = entry in ++ ++ let size = ++ match size with ++ | Some size -> size ++ (* --size parameter missing, output to file: use original image size *) ++ | None when not output_is_block_dev -> original_image_size ++ (* --size parameter missing, block device: use block device size *) ++ | None -> blockdev_size in ++ ++ if size < original_image_size then ( ++ eprintf (f_"%s: images cannot be shrunk, the output size is too small for this image. Requested size = %s, minimum size = %s\n") ++ prog (human_size size) (human_size original_image_size); ++ exit 1 ++ ) ++ else if output_is_block_dev && output_format = "raw" && size > blockdev_size then ( ++ eprintf (f_"%s: output size is too large for this block device. Requested size = %s, output block device = %s, output block device size = %s\n") ++ prog (human_size size) output_filename (human_size blockdev_size); ++ exit 1 ++ ); ++ size in ++ + let goal = + (* MUST *) + let goal_must = [ +-- +1.8.4.2 + diff --git a/0038-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch b/0038-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch deleted file mode 100644 index 1fd5cf5..0000000 --- a/0038-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 5482bfb88f6c07675f4ca9073d0f3faca733fc15 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 19 Dec 2013 14:22:26 +0000 -Subject: [PATCH] launch: libvirt: Don't default to using NULL for libvirt - connection URI (RHBZ#1045033). - -NULL means that libvirt gets to guess what connection URI we meant. -Currently it guesses qemu:///session for non-root and qemu:///system -for root. Except if LIBVIRT_DEFAULT_URI is set in which case this is -used even if it's not appropriate. Except if Xen is installed in -which case it guesses xen:/// which is not helpful at all. - -Instead use qemu:///session (or qemu:///system for root -- that's -likely to be wrong, but we can't help that). - -If the user really wants to use NULL and let libvirt guess, then they -can now specify the libvirt:null backend. - -See: - -https://bugzilla.redhat.com/show_bug.cgi?id=1045033 -https://bugzilla.redhat.com/show_bug.cgi?id=886915 - -A good way to test this is: - -LIBVIRT_DEFAULT_URI=iambroken libguestfs-test-tool - -The libguestfs libvirt backend should (after this commit) ignore -LIBVIRT_DEFAULT_URI. However other parts of libguestfs will still use -it, eg. guestfs_add_drive_opts, guestfish '-d' option. - -(cherry picked from commit d16db5a6180305543658f3a50657c70bbdf81b40) ---- - src/guestfs.pod | 16 +++++++++++++--- - src/launch-libvirt.c | 10 ++++++++++ - 2 files changed, 23 insertions(+), 3 deletions(-) - -diff --git a/src/guestfs.pod b/src/guestfs.pod -index 6909b50..1931055 100644 ---- a/src/guestfs.pod -+++ b/src/guestfs.pod -@@ -1429,13 +1429,23 @@ note below. - - =item C - -+=item C -+ - =item C> - - Use libvirt to launch and manage the appliance. - --The optional I is the libvirt connection URI to use (see --L). The typical libvirt backend --with a URI would be C -+C causes libguestfs to choose a suitable URI for creating -+session guests. If using the libvirt backend, you almost always -+should use this. -+ -+C causes libguestfs to use the C connection URI, -+which causes libvirt to try to guess what the user meant. You -+probably don't want to use this. -+ -+C> uses I as the libvirt connection URI (see -+L). The typical libvirt backend with a -+URI would be C - - The libvirt backend supports more features, including - hotplugging (see L) and sVirt. -diff --git a/src/launch-libvirt.c b/src/launch-libvirt.c -index b78590a..729f437 100644 ---- a/src/launch-libvirt.c -+++ b/src/launch-libvirt.c -@@ -216,6 +216,16 @@ launch_libvirt (guestfs_h *g, void *datav, const char *libvirt_uri) - if (g->verbose) - guestfs___print_timestamped_message (g, "connect to libvirt"); - -+ /* Decode the URI string. */ -+ if (!libvirt_uri) { /* "libvirt" */ -+ if (!params.current_proc_is_root) -+ libvirt_uri = "qemu:///session"; -+ else -+ libvirt_uri = "qemu:///system"; -+ } else if (STREQ (libvirt_uri, "null")) { /* libvirt:null */ -+ libvirt_uri = NULL; -+ } /* else nothing */ -+ - /* Connect to libvirt, get capabilities. */ - conn = guestfs___open_libvirt_connection (g, libvirt_uri, 0); - if (!conn) { --- -1.8.4.2 - diff --git a/0039-builder-Fix-handling-of-size-parameter.patch b/0039-builder-Fix-handling-of-size-parameter.patch deleted file mode 100644 index 78f8e57..0000000 --- a/0039-builder-Fix-handling-of-size-parameter.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 4a6606e18882c7dfd8de84b2a081e8c6caeadcd4 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Tue, 7 Jan 2014 17:32:04 +0000 -Subject: [PATCH] builder: Fix handling of --size parameter. - -It now matches the documentation: - - "Select the size of the output disk, [...] - - Virt-builder will resize filesystems inside the disk image - automatically. - - If the size is not specified, then one of two things happens. If - the output is a file, then the size is the same as the template. If - the output is a device, partition, etc then the size of that device - is used." - -This also adds checks to make sure that users don't try to shrink a -disk (which is not possible), and they don't try to resize larger than -the output block device. - -(cherry picked from commit 06f7bea14883c4903c58077757179341c0e1471a) ---- - builder/builder.ml | 43 ++++++++++++++++++++++++++++++++++--------- - 1 file changed, 34 insertions(+), 9 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 0f8e069..f007b46 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -261,9 +261,6 @@ let main () = - format_tag @ compression_tag in - - (* Planner: Goal. *) -- let output_size = -- let { Index_parser.size = default_size } = entry in -- match size with None -> default_size | Some size -> size in - let output_filename, output_format = - match output, format with - | None, None -> sprintf "%s.img" arg, "raw" -@@ -271,18 +268,46 @@ let main () = - | None, Some format -> sprintf "%s.%s" arg format, format - | Some output, None -> output, "raw" - | Some output, Some format -> output, format in -- let output_is_block_dev = is_block_device output_filename in -- -- if output_is_block_dev && size <> None then ( -- eprintf (f_"%s: you cannot use --size option with block devices\n") prog; -- exit 1 -- ); - - if is_char_device output_filename then ( - eprintf (f_"%s: cannot output to a character device or /dev/null\n") prog; - exit 1 - ); - -+ let blockdev_getsize64 dev = -+ let cmd = sprintf "blockdev --getsize64 %s" (quote dev) in -+ let lines = external_command ~prog cmd in -+ assert (List.length lines >= 1); -+ Int64.of_string (List.hd lines) -+ in -+ let output_is_block_dev, blockdev_size = -+ let b = is_block_device output_filename in -+ let sz = if b then blockdev_getsize64 output_filename else 0L in -+ b, sz in -+ -+ let output_size = -+ let { Index_parser.size = original_image_size } = entry in -+ -+ let size = -+ match size with -+ | Some size -> size -+ (* --size parameter missing, output to file: use original image size *) -+ | None when not output_is_block_dev -> original_image_size -+ (* --size parameter missing, block device: use block device size *) -+ | None -> blockdev_size in -+ -+ if size < original_image_size then ( -+ eprintf (f_"%s: images cannot be shrunk, the output size is too small for this image. Requested size = %s, minimum size = %s\n") -+ prog (human_size size) (human_size original_image_size); -+ exit 1 -+ ) -+ else if output_is_block_dev && output_format = "raw" && size > blockdev_size then ( -+ eprintf (f_"%s: output size is too large for this block device. Requested size = %s, output block device = %s, output block device size = %s\n") -+ prog (human_size size) output_filename (human_size blockdev_size); -+ exit 1 -+ ); -+ size in -+ - let goal = - (* MUST *) - let goal_must = [ --- -1.8.4.2 - diff --git a/0039-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch b/0039-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch new file mode 100644 index 0000000..f2cccdf --- /dev/null +++ b/0039-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch @@ -0,0 +1,122 @@ +From 528be4e716fab77ab36258382bcb114c1acf277c Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 2 Jan 2014 12:20:18 +0000 +Subject: [PATCH] libvirt-auth: Provide a friendlier wrapper around + virConnectAuthPtrDefault (RHBZ#1044014). + +(cherry picked from commit 4125064554c8cb1b96680e24e49d74ee6024f761) +--- + src/guestfs-internal.h | 1 + + src/libvirt-auth.c | 55 +++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 46 insertions(+), 10 deletions(-) + +diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h +index 3501ed5..cde1277 100644 +--- a/src/guestfs-internal.h ++++ b/src/guestfs-internal.h +@@ -469,6 +469,7 @@ struct guestfs_h + unsigned int nr_supported_credentials; + int supported_credentials[NR_CREDENTIAL_TYPES]; + const char *saved_libvirt_uri; /* Doesn't need to be freed. */ ++ bool wrapper_warning_done; + unsigned int nr_requested_credentials; + virConnectCredentialPtr requested_credentials; + #endif +diff --git a/src/libvirt-auth.c b/src/libvirt-auth.c +index fb18f8a..f8ed1b1 100644 +--- a/src/libvirt-auth.c ++++ b/src/libvirt-auth.c +@@ -20,6 +20,7 @@ + + #include + #include ++#include + + #ifdef HAVE_LIBVIRT + #include +@@ -147,6 +148,34 @@ libvirt_auth_callback (virConnectCredentialPtr cred, + return 0; + } + ++/* Libvirt provides a default authentication handler. However it is ++ * confusing to end-users ++ * (https://bugzilla.redhat.com/show_bug.cgi?id=1044014#c0). ++ * ++ * Unfortunately #1 the libvirt handler cannot easily be modified to ++ * make it non-confusing, but unfortunately #2 we have to actually ++ * call it because it handles all the policykit crap. ++ * ++ * Therefore we add a wrapper around it here. ++ */ ++static int ++libvirt_auth_default_wrapper (virConnectCredentialPtr cred, ++ unsigned int ncred, ++ void *gv) ++{ ++ guestfs_h *g = gv; ++ ++ if (!g->wrapper_warning_done) { ++ printf (_("libvirt needs authentication to connect to libvirt URI %s\n" ++ "(see also: http://libvirt.org/auth.html http://libvirt.org/uri.html)\n"), ++ g->saved_libvirt_uri ? g->saved_libvirt_uri : "NULL"); ++ g->wrapper_warning_done = true; ++ } ++ ++ return virConnectAuthPtrDefault->cb (cred, ncred, ++ virConnectAuthPtrDefault->cbdata); ++} ++ + static int + exists_libvirt_auth_event (guestfs_h *g) + { +@@ -165,31 +194,37 @@ guestfs___open_libvirt_connection (guestfs_h *g, const char *uri, + unsigned int flags) + { + virConnectAuth authdata; +- virConnectAuthPtr authdataptr; + virConnectPtr conn; ++ const char *authtype; ++ ++ g->saved_libvirt_uri = uri; ++ g->wrapper_warning_done = false; + + /* Did the caller register a GUESTFS_EVENT_LIBVIRT_AUTH event and + * call guestfs_set_libvirt_supported_credentials? + */ + if (g->nr_supported_credentials > 0 && exists_libvirt_auth_event (g)) { ++ authtype = "custom"; + memset (&authdata, 0, sizeof authdata); + authdata.credtype = g->supported_credentials; + authdata.ncredtype = g->nr_supported_credentials; + authdata.cb = libvirt_auth_callback; + authdata.cbdata = g; +- authdataptr = &authdata; +- g->saved_libvirt_uri = uri; + } +- else +- authdataptr = virConnectAuthPtrDefault; ++ else { ++ /* Wrapper around libvirt's virConnectAuthPtrDefault, see comment ++ * above. ++ */ ++ authtype = "default+wrapper"; ++ authdata = *virConnectAuthPtrDefault; ++ authdata.cb = libvirt_auth_default_wrapper; ++ authdata.cbdata = g; ++ } + + debug (g, "opening libvirt handle: URI = %s, auth = %s, flags = %u", +- uri ? uri : "NULL", +- authdataptr == virConnectAuthPtrDefault +- ? "virConnectAuthPtrDefault" : "", +- flags); ++ uri ? uri : "NULL", authtype, flags); + +- conn = virConnectOpenAuth (uri, authdataptr, flags); ++ conn = virConnectOpenAuth (uri, &authdata, flags); + + if (conn) + debug (g, "successfully opened libvirt handle: conn = %p", conn); +-- +1.8.4.2 + diff --git a/0040-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch b/0040-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch deleted file mode 100644 index bf09a35..0000000 --- a/0040-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch +++ /dev/null @@ -1,122 +0,0 @@ -From a9da4193cf0c11b85d24f088458224be129cd550 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 2 Jan 2014 12:20:18 +0000 -Subject: [PATCH] libvirt-auth: Provide a friendlier wrapper around - virConnectAuthPtrDefault (RHBZ#1044014). - -(cherry picked from commit 4125064554c8cb1b96680e24e49d74ee6024f761) ---- - src/guestfs-internal.h | 1 + - src/libvirt-auth.c | 55 +++++++++++++++++++++++++++++++++++++++++--------- - 2 files changed, 46 insertions(+), 10 deletions(-) - -diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h -index 8888603..a1f3f02 100644 ---- a/src/guestfs-internal.h -+++ b/src/guestfs-internal.h -@@ -469,6 +469,7 @@ struct guestfs_h - unsigned int nr_supported_credentials; - int supported_credentials[NR_CREDENTIAL_TYPES]; - const char *saved_libvirt_uri; /* Doesn't need to be freed. */ -+ bool wrapper_warning_done; - unsigned int nr_requested_credentials; - virConnectCredentialPtr requested_credentials; - #endif -diff --git a/src/libvirt-auth.c b/src/libvirt-auth.c -index fb18f8a..f8ed1b1 100644 ---- a/src/libvirt-auth.c -+++ b/src/libvirt-auth.c -@@ -20,6 +20,7 @@ - - #include - #include -+#include - - #ifdef HAVE_LIBVIRT - #include -@@ -147,6 +148,34 @@ libvirt_auth_callback (virConnectCredentialPtr cred, - return 0; - } - -+/* Libvirt provides a default authentication handler. However it is -+ * confusing to end-users -+ * (https://bugzilla.redhat.com/show_bug.cgi?id=1044014#c0). -+ * -+ * Unfortunately #1 the libvirt handler cannot easily be modified to -+ * make it non-confusing, but unfortunately #2 we have to actually -+ * call it because it handles all the policykit crap. -+ * -+ * Therefore we add a wrapper around it here. -+ */ -+static int -+libvirt_auth_default_wrapper (virConnectCredentialPtr cred, -+ unsigned int ncred, -+ void *gv) -+{ -+ guestfs_h *g = gv; -+ -+ if (!g->wrapper_warning_done) { -+ printf (_("libvirt needs authentication to connect to libvirt URI %s\n" -+ "(see also: http://libvirt.org/auth.html http://libvirt.org/uri.html)\n"), -+ g->saved_libvirt_uri ? g->saved_libvirt_uri : "NULL"); -+ g->wrapper_warning_done = true; -+ } -+ -+ return virConnectAuthPtrDefault->cb (cred, ncred, -+ virConnectAuthPtrDefault->cbdata); -+} -+ - static int - exists_libvirt_auth_event (guestfs_h *g) - { -@@ -165,31 +194,37 @@ guestfs___open_libvirt_connection (guestfs_h *g, const char *uri, - unsigned int flags) - { - virConnectAuth authdata; -- virConnectAuthPtr authdataptr; - virConnectPtr conn; -+ const char *authtype; -+ -+ g->saved_libvirt_uri = uri; -+ g->wrapper_warning_done = false; - - /* Did the caller register a GUESTFS_EVENT_LIBVIRT_AUTH event and - * call guestfs_set_libvirt_supported_credentials? - */ - if (g->nr_supported_credentials > 0 && exists_libvirt_auth_event (g)) { -+ authtype = "custom"; - memset (&authdata, 0, sizeof authdata); - authdata.credtype = g->supported_credentials; - authdata.ncredtype = g->nr_supported_credentials; - authdata.cb = libvirt_auth_callback; - authdata.cbdata = g; -- authdataptr = &authdata; -- g->saved_libvirt_uri = uri; - } -- else -- authdataptr = virConnectAuthPtrDefault; -+ else { -+ /* Wrapper around libvirt's virConnectAuthPtrDefault, see comment -+ * above. -+ */ -+ authtype = "default+wrapper"; -+ authdata = *virConnectAuthPtrDefault; -+ authdata.cb = libvirt_auth_default_wrapper; -+ authdata.cbdata = g; -+ } - - debug (g, "opening libvirt handle: URI = %s, auth = %s, flags = %u", -- uri ? uri : "NULL", -- authdataptr == virConnectAuthPtrDefault -- ? "virConnectAuthPtrDefault" : "", -- flags); -+ uri ? uri : "NULL", authtype, flags); - -- conn = virConnectOpenAuth (uri, authdataptr, flags); -+ conn = virConnectOpenAuth (uri, &authdata, flags); - - if (conn) - debug (g, "successfully opened libvirt handle: conn = %p", conn); --- -1.8.4.2 - diff --git a/0040-tests-Add-a-regression-test-of-libvirt-authenticatio.patch b/0040-tests-Add-a-regression-test-of-libvirt-authenticatio.patch new file mode 100644 index 0000000..5a94925 --- /dev/null +++ b/0040-tests-Add-a-regression-test-of-libvirt-authenticatio.patch @@ -0,0 +1,303 @@ +From aba8944fca9dbf366f64c0d9c41bf9a41ef0d0d4 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 8 Jan 2014 19:36:00 +0000 +Subject: [PATCH] tests: Add a regression test of libvirt authentication + events. + +This requires a change to libvirt (in libvirt >= 1.2.1), see: + +https://www.redhat.com/archives/libvir-list/2014-January/msg00378.html +(cherry picked from commit 873db60c0e52893a38c374d867d0a305e5419d6a) +--- + .gitignore | 1 + + tests/events/Makefile.am | 36 ++++-- + tests/events/libvirt-auth.xml | 22 ++++ + tests/events/test-libvirt-auth-callbacks.c | 185 +++++++++++++++++++++++++++++ + 4 files changed, 237 insertions(+), 7 deletions(-) + create mode 100644 tests/events/libvirt-auth.xml + create mode 100644 tests/events/test-libvirt-auth-callbacks.c + +diff --git a/.gitignore b/.gitignore +index 6e04072..bce35f0 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -463,6 +463,7 @@ Makefile.in + /tests/data/initrd-x86_64.img.gz + /tests/data/test-grep.txt.gz + /tests/data/test.iso ++/tests/events/test-libvirt-auth-callbacks + /tests/guests/blank-*.img + /tests/guests/debian.img + /tests/guests/fedora.img +diff --git a/tests/events/Makefile.am b/tests/events/Makefile.am +index 9f6e5aa..9751edc 100644 +--- a/tests/events/Makefile.am ++++ b/tests/events/Makefile.am +@@ -1,5 +1,5 @@ + # libguestfs +-# Copyright (C) 2013 Red Hat Inc. ++# Copyright (C) 2013-2014 Red Hat Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -17,10 +17,32 @@ + + include $(top_srcdir)/subdir-rules.mk + +-TESTS = \ +- test-console-debug.pl +- +-TESTS_ENVIRONMENT = $(top_builddir)/run --test +- + EXTRA_DIST = \ +- $(TESTS) ++ test-console-debug.pl \ ++ libvirt-auth.xml ++ ++TESTS_ENVIRONMENT = $(top_builddir)/run --test ++ ++check_PROGRAMS = ++ ++TESTS = test-console-debug.pl ++ ++if HAVE_LIBVIRT ++TESTS += test-libvirt-auth-callbacks ++check_PROGRAMS += test-libvirt-auth-callbacks ++ ++test_libvirt_auth_callbacks_SOURCES = test-libvirt-auth-callbacks.c ++test_libvirt_auth_callbacks_CPPFLAGS = \ ++ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ ++ -I$(top_srcdir)/src -I$(top_builddir)/src ++test_libvirt_auth_callbacks_CFLAGS = \ ++ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ ++ $(GPROF_CFLAGS) $(GCOV_CFLAGS) \ ++ $(LIBVIRT_CFLAGS) ++test_libvirt_auth_callbacks_LDADD = \ ++ $(top_builddir)/src/libutils.la \ ++ $(top_builddir)/src/libguestfs.la \ ++ $(LIBVIRT_LIBS) \ ++ $(LIBXML2_LIBS) \ ++ $(top_builddir)/gnulib/lib/libgnu.la ++endif +diff --git a/tests/events/libvirt-auth.xml b/tests/events/libvirt-auth.xml +new file mode 100644 +index 0000000..d138d4d +--- /dev/null ++++ b/tests/events/libvirt-auth.xml +@@ -0,0 +1,22 @@ ++ ++ ++ test ++ 1048576 ++ ++ hvm ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ rich ++ jane ++ ++ +diff --git a/tests/events/test-libvirt-auth-callbacks.c b/tests/events/test-libvirt-auth-callbacks.c +new file mode 100644 +index 0000000..7c26bbe +--- /dev/null ++++ b/tests/events/test-libvirt-auth-callbacks.c +@@ -0,0 +1,185 @@ ++/* libguestfs ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "guestfs.h" ++#include "guestfs-internal-frontend.h" ++ ++#define EXPECT_OK 1 ++#define EXPECT_FAIL -1 ++ ++struct auth_data { ++ const char *username; ++ const char *password; ++}; ++ ++static void do_test (const char *prog, const char *libvirt_uri, const struct auth_data *auth_data, int expected); ++static void auth_callback (guestfs_h *g, void *opaque, uint64_t event, int event_handle, int flags, const char *buf, size_t buf_len, const uint64_t *array, size_t array_len); ++ ++int ++main (int argc, char *argv[]) ++{ ++ unsigned long ver; ++ const char *srcdir; ++ char *cwd; ++ char *test_uri; ++ ++ virInitialize (); ++ ++ /* Check that the version of libvirt we are linked against ++ * supports the new test-driver auth feature. ++ */ ++ virGetVersion (&ver, NULL, NULL); ++ if (ver < 1002001) { ++ fprintf (stderr, "%s: test skipped because libvirt is too old (%lu)\n", ++ argv[0], ver); ++ exit (77); ++ } ++ ++ /* $srcdir must have been passed (by automake). */ ++ srcdir = getenv ("srcdir"); ++ if (!srcdir) { ++ fprintf (stderr, ++ "%s: environment variable $srcdir is not defined.\n" ++ "Normally it is defined by automake. If you are running the\n" ++ "tests directly, set $srcdir to point to the source tests/events\n" ++ "directory.\n", argv[0]); ++ exit (EXIT_FAILURE); ++ } ++ ++ cwd = get_current_dir_name (); ++ if (cwd == NULL) { ++ perror ("get_current_dir_name"); ++ exit (EXIT_FAILURE); ++ } ++ ++ if (asprintf (&test_uri, "test://%s/%s/libvirt-auth.xml", cwd, srcdir) == -1) { ++ perror ("asprintf"); ++ exit (EXIT_FAILURE); ++ } ++ ++ free (cwd); ++ ++ /* Perform the tests. */ ++ struct auth_data ad1 = { .username = "rich", .password = "123456" }; ++ do_test (argv[0], test_uri, &ad1, EXPECT_OK); ++ struct auth_data ad2 = { .username = "rich", .password = "654321" }; ++ do_test (argv[0], test_uri, &ad2, EXPECT_FAIL); ++ struct auth_data ad3 = { .username = "jane", .password = NULL }; ++ do_test (argv[0], test_uri, &ad3, EXPECT_OK); ++ struct auth_data ad4 = { .username = "nouser", .password = "123456" }; ++ do_test (argv[0], test_uri, &ad4, EXPECT_FAIL); ++ ++ free (test_uri); ++ exit (EXIT_SUCCESS); ++} ++ ++static void ++do_test (const char *prog, const char *libvirt_uri, ++ const struct auth_data *auth_data, ++ int expected) ++{ ++ guestfs_h *g; ++ const char *creds[] = ++ { "authname", "passphrase", "noechoprompt", NULL }; ++ int r, eh; ++ ++ g = guestfs_create (); ++ if (!g) ++ exit (EXIT_FAILURE); ++ ++ r = guestfs_set_libvirt_supported_credentials (g, (char **) creds); ++ if (r == -1) ++ exit (EXIT_FAILURE); ++ ++ eh = guestfs_set_event_callback (g, auth_callback, ++ GUESTFS_EVENT_LIBVIRT_AUTH, 0, ++ (void *) auth_data); ++ if (eh == -1) ++ exit (EXIT_FAILURE); ++ ++ r = guestfs_add_domain (g, "test", ++ GUESTFS_ADD_DOMAIN_LIBVIRTURI, libvirt_uri, ++ GUESTFS_ADD_DOMAIN_READONLY, 1, ++ -1); ++ if (r != expected) { ++ fprintf (stderr, ++ "%s: test failed: u=%s p=%s: got %d expected %d\n", ++ prog, auth_data->username, auth_data->password ? : "(none)", ++ r, expected); ++ exit (EXIT_FAILURE); ++ } ++ ++ guestfs_close (g); ++} ++ ++static void ++auth_callback (guestfs_h *g, void *opaque, ++ uint64_t event, int event_handle, ++ int flags, ++ const char *buf, size_t buf_len, ++ const uint64_t *array, size_t array_len) ++{ ++ CLEANUP_FREE_STRING_LIST char **creds = NULL; ++ const struct auth_data *auth_data = opaque; ++ size_t i; ++ int r; ++ const char *reply; ++ size_t len; ++ ++ /* Ask libguestfs what credentials libvirt is demanding. */ ++ creds = guestfs_get_libvirt_requested_credentials (g); ++ if (creds == NULL) ++ exit (EXIT_FAILURE); ++ ++ /* Try to answer from the authentication data. */ ++ for (i = 0; creds[i] != NULL; ++i) { ++ if (STREQ (creds[i], "authname")) { ++ reply = auth_data->username; ++ len = strlen (reply); ++ } ++ else if (STREQ (creds[i], "passphrase") || ++ STREQ (creds[i], "noechoprompt")) { ++ if (!auth_data->password) { ++ fprintf (stderr, "test failed: libvirt asked for a password, but auth_data->password == NULL\n"); ++ exit (EXIT_FAILURE); ++ } ++ ++ reply = auth_data->password; ++ len = strlen (reply); ++ } ++ else { ++ fprintf (stderr, "test failed: libvirt asked for '%s' which is not in creds list\n(This is probably a libvirt bug)\n", ++ creds[i]); ++ exit (EXIT_FAILURE); ++ } ++ ++ r = guestfs_set_libvirt_requested_credential (g, i, ++ reply, len); ++ if (r == -1) ++ exit (EXIT_FAILURE); ++ } ++} +-- +1.8.4.2 + diff --git a/0041-tests-Add-a-regression-test-for-libvirt-authenticati.patch b/0041-tests-Add-a-regression-test-for-libvirt-authenticati.patch new file mode 100644 index 0000000..915d81b --- /dev/null +++ b/0041-tests-Add-a-regression-test-for-libvirt-authenticati.patch @@ -0,0 +1,267 @@ +From bb6a15c77501b78ade92adb11c6fac93682a7944 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Wed, 8 Jan 2014 20:22:21 +0000 +Subject: [PATCH] tests: Add a regression test for libvirt authentication + (RHBZ#1044014). + +This tests the virConnectAuthPtrDefault wrapper path. + +(cherry picked from commit 746a0b1f19667606ee63c8d3ab6a75531a8bd71c) +--- + .gitignore | 2 ++ + tests/regressions/Makefile.am | 28 ++++++++++++++++ + tests/regressions/rhbz1044014.c | 69 ++++++++++++++++++++++++++++++++++++++ + tests/regressions/rhbz1044014.in | 1 + + tests/regressions/rhbz1044014.sh | 70 +++++++++++++++++++++++++++++++++++++++ + tests/regressions/rhbz1044014.xml | 5 +++ + 6 files changed, 175 insertions(+) + create mode 100644 tests/regressions/rhbz1044014.c + create mode 100644 tests/regressions/rhbz1044014.in + create mode 100755 tests/regressions/rhbz1044014.sh + create mode 100644 tests/regressions/rhbz1044014.xml + +diff --git a/.gitignore b/.gitignore +index bce35f0..2d61d77 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -485,6 +485,8 @@ Makefile.in + /tests/regressions/rhbz501893 + /tests/regressions/rhbz790721 + /tests/regressions/rhbz914931 ++/tests/regressions/rhbz1044014 ++/tests/regressions/rhbz1044014.out + /tests/regressions/rhbz1055452 + /tests/rsync/rsyncd.pid + /tests/syslinux/extlinux-guest.img +diff --git a/tests/regressions/Makefile.am b/tests/regressions/Makefile.am +index 15333b7..563f87f 100644 +--- a/tests/regressions/Makefile.am ++++ b/tests/regressions/Makefile.am +@@ -35,6 +35,9 @@ EXTRA_DIST = \ + rhbz957772.sh \ + rhbz975797.sh \ + rhbz1001875.sh \ ++ rhbz1044014.sh \ ++ rhbz1044014.in \ ++ rhbz1044014.xml \ + test-noexec-stack.pl + + TESTS = \ +@@ -57,6 +60,10 @@ TESTS = \ + rhbz1055452 \ + test-noexec-stack.pl + ++if HAVE_LIBVIRT ++TESTS += rhbz1044014.sh ++endif ++ + tests_not_run = \ + rhbz727178.sh \ + rhbz909624.sh +@@ -71,6 +78,10 @@ check_PROGRAMS = \ + rhbz914931 \ + rhbz1055452 + ++if HAVE_LIBVIRT ++check_PROGRAMS += rhbz1044014 ++endif ++ + rhbz501893_SOURCES = rhbz501893.c + rhbz501893_CPPFLAGS = \ + -I$(top_srcdir)/src -I$(top_builddir)/src +@@ -101,6 +112,23 @@ rhbz914931_CFLAGS = \ + rhbz914931_LDADD = \ + $(top_builddir)/src/libguestfs.la + ++if HAVE_LIBVIRT ++rhbz1044014_SOURCES = rhbz1044014.c ++rhbz1044014_CPPFLAGS = \ ++ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ ++ -I$(top_srcdir)/src -I$(top_builddir)/src ++rhbz1044014_CFLAGS = \ ++ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ ++ $(GPROF_CFLAGS) $(GCOV_CFLAGS) \ ++ $(LIBVIRT_CFLAGS) ++rhbz1044014_LDADD = \ ++ $(top_builddir)/src/libutils.la \ ++ $(top_builddir)/src/libguestfs.la \ ++ $(LIBVIRT_LIBS) \ ++ $(LIBXML2_LIBS) \ ++ $(top_builddir)/gnulib/lib/libgnu.la ++endif ++ + rhbz1055452_SOURCES = rhbz1055452.c + rhbz1055452_CPPFLAGS = \ + -I$(top_srcdir)/src -I$(top_builddir)/src \ +diff --git a/tests/regressions/rhbz1044014.c b/tests/regressions/rhbz1044014.c +new file mode 100644 +index 0000000..18ce4a7 +--- /dev/null ++++ b/tests/regressions/rhbz1044014.c +@@ -0,0 +1,69 @@ ++/* libguestfs ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++/* Regression test for RHBZ#1044014. ++ * ++ * The only reason to write this in C is so we can easily check the ++ * version of libvirt >= 1.2.1. In the future when we can assume a ++ * newer libvirt, we can just have the main rhbz1044014.sh script set ++ * some environment variables and use guestfish. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "guestfs.h" ++#include "guestfs-internal-frontend.h" ++ ++int ++main (int argc, char *argv[]) ++{ ++ unsigned long ver; ++ guestfs_h *g; ++ ++ virInitialize (); ++ ++ /* Check that the version of libvirt we are linked against ++ * supports the new test-driver auth feature. ++ */ ++ virGetVersion (&ver, NULL, NULL); ++ if (ver < 1002001) { ++ fprintf (stderr, "%s: test skipped because libvirt is too old (%lu)\n", ++ argv[0], ver); ++ exit (77); ++ } ++ ++ g = guestfs_create (); ++ if (!g) ++ exit (EXIT_FAILURE); ++ ++ /* This will ask the user for credentials. It will also fail ++ * (expectedly) because the test driver does not support qemu/KVM. ++ */ ++ guestfs_launch (g); ++ ++ guestfs_close (g); ++ exit (EXIT_SUCCESS); ++} +diff --git a/tests/regressions/rhbz1044014.in b/tests/regressions/rhbz1044014.in +new file mode 100644 +index 0000000..3f382dd +--- /dev/null ++++ b/tests/regressions/rhbz1044014.in +@@ -0,0 +1 @@ ++rich +diff --git a/tests/regressions/rhbz1044014.sh b/tests/regressions/rhbz1044014.sh +new file mode 100755 +index 0000000..f1e458c +--- /dev/null ++++ b/tests/regressions/rhbz1044014.sh +@@ -0,0 +1,70 @@ ++#!/bin/bash - ++# libguestfs ++# Copyright (C) 2014 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++# Regression test for: ++# https://bugzilla.redhat.com/show_bug.cgi?id=1044014 ++ ++set -e ++export LANG=C ++ ++if [ -n "$SKIP_TEST_RHBZ1044014_SH" ]; then ++ echo "$0: test skipped because environment variable is set." ++ exit 77 ++fi ++ ++# Check we are running against the libvirt backend. ++backend="$(../../fish/guestfish get-backend)" ++if [[ ! ( "$backend" =~ ^libvirt ) ]]; then ++ echo "$0: test skipped because backend ($backend) is not libvirt." ++ exit 77 ++fi ++ ++# Set the backend to the test driver. ++export LIBGUESTFS_BACKEND="libvirt:test://$(pwd)/$srcdir/rhbz1044014.xml" ++ ++rm -f rhbz1044014.out ++ ++./rhbz1044014 < $srcdir/rhbz1044014.in > rhbz1044014.out 2>&1 || { ++ r=$? ++ if [ $r -ne 0 ]; then ++ cat rhbz1044014.out ++ exit $r ++ fi ++} ++ ++# We are expecting this message to be printed (see commit which fixed ++# RHBZ#1044014). ++grep "libvirt needs authentication to connect to libvirt URI" rhbz1044014.out || { ++ echo "$0: expecting to see message from commit which fixed RHBZ#1044014" ++ echo ++ echo "actual output was:" ++ echo ++ cat rhbz1044014.out ++ exit 1 ++} ++ ++# This is the error we are expecting to see. If we see it then it ++# indicates that authentication was successful. ++grep "error: libvirt hypervisor doesn't support qemu or KVM" rhbz1044014.out || { ++ echo "$0: unexpected output:" ++ echo ++ cat rhbz1044014.out ++ exit 1 ++} ++ ++rm rhbz1044014.out +diff --git a/tests/regressions/rhbz1044014.xml b/tests/regressions/rhbz1044014.xml +new file mode 100644 +index 0000000..72feaf4 +--- /dev/null ++++ b/tests/regressions/rhbz1044014.xml +@@ -0,0 +1,5 @@ ++ ++ ++ rich ++ ++ +-- +1.8.4.2 + diff --git a/0041-tests-Add-a-regression-test-of-libvirt-authenticatio.patch b/0041-tests-Add-a-regression-test-of-libvirt-authenticatio.patch deleted file mode 100644 index 66b6f41..0000000 --- a/0041-tests-Add-a-regression-test-of-libvirt-authenticatio.patch +++ /dev/null @@ -1,303 +0,0 @@ -From 76ce46c587e5e8ec45acc10b6578a59b9651d454 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Wed, 8 Jan 2014 19:36:00 +0000 -Subject: [PATCH] tests: Add a regression test of libvirt authentication - events. - -This requires a change to libvirt (in libvirt >= 1.2.1), see: - -https://www.redhat.com/archives/libvir-list/2014-January/msg00378.html -(cherry picked from commit 873db60c0e52893a38c374d867d0a305e5419d6a) ---- - .gitignore | 1 + - tests/events/Makefile.am | 36 ++++-- - tests/events/libvirt-auth.xml | 22 ++++ - tests/events/test-libvirt-auth-callbacks.c | 185 +++++++++++++++++++++++++++++ - 4 files changed, 237 insertions(+), 7 deletions(-) - create mode 100644 tests/events/libvirt-auth.xml - create mode 100644 tests/events/test-libvirt-auth-callbacks.c - -diff --git a/.gitignore b/.gitignore -index 32b8662..3d429de 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -462,6 +462,7 @@ Makefile.in - /tests/data/initrd-x86_64.img.gz - /tests/data/test-grep.txt.gz - /tests/data/test.iso -+/tests/events/test-libvirt-auth-callbacks - /tests/guests/blank-*.img - /tests/guests/debian.img - /tests/guests/fedora.img -diff --git a/tests/events/Makefile.am b/tests/events/Makefile.am -index 9f6e5aa..9751edc 100644 ---- a/tests/events/Makefile.am -+++ b/tests/events/Makefile.am -@@ -1,5 +1,5 @@ - # libguestfs --# Copyright (C) 2013 Red Hat Inc. -+# Copyright (C) 2013-2014 Red Hat Inc. - # - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -17,10 +17,32 @@ - - include $(top_srcdir)/subdir-rules.mk - --TESTS = \ -- test-console-debug.pl -- --TESTS_ENVIRONMENT = $(top_builddir)/run --test -- - EXTRA_DIST = \ -- $(TESTS) -+ test-console-debug.pl \ -+ libvirt-auth.xml -+ -+TESTS_ENVIRONMENT = $(top_builddir)/run --test -+ -+check_PROGRAMS = -+ -+TESTS = test-console-debug.pl -+ -+if HAVE_LIBVIRT -+TESTS += test-libvirt-auth-callbacks -+check_PROGRAMS += test-libvirt-auth-callbacks -+ -+test_libvirt_auth_callbacks_SOURCES = test-libvirt-auth-callbacks.c -+test_libvirt_auth_callbacks_CPPFLAGS = \ -+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ -+ -I$(top_srcdir)/src -I$(top_builddir)/src -+test_libvirt_auth_callbacks_CFLAGS = \ -+ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ -+ $(GPROF_CFLAGS) $(GCOV_CFLAGS) \ -+ $(LIBVIRT_CFLAGS) -+test_libvirt_auth_callbacks_LDADD = \ -+ $(top_builddir)/src/libutils.la \ -+ $(top_builddir)/src/libguestfs.la \ -+ $(LIBVIRT_LIBS) \ -+ $(LIBXML2_LIBS) \ -+ $(top_builddir)/gnulib/lib/libgnu.la -+endif -diff --git a/tests/events/libvirt-auth.xml b/tests/events/libvirt-auth.xml -new file mode 100644 -index 0000000..d138d4d ---- /dev/null -+++ b/tests/events/libvirt-auth.xml -@@ -0,0 +1,22 @@ -+ -+ -+ test -+ 1048576 -+ -+ hvm -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ rich -+ jane -+ -+ -diff --git a/tests/events/test-libvirt-auth-callbacks.c b/tests/events/test-libvirt-auth-callbacks.c -new file mode 100644 -index 0000000..7c26bbe ---- /dev/null -+++ b/tests/events/test-libvirt-auth-callbacks.c -@@ -0,0 +1,185 @@ -+/* libguestfs -+ * Copyright (C) 2014 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "guestfs.h" -+#include "guestfs-internal-frontend.h" -+ -+#define EXPECT_OK 1 -+#define EXPECT_FAIL -1 -+ -+struct auth_data { -+ const char *username; -+ const char *password; -+}; -+ -+static void do_test (const char *prog, const char *libvirt_uri, const struct auth_data *auth_data, int expected); -+static void auth_callback (guestfs_h *g, void *opaque, uint64_t event, int event_handle, int flags, const char *buf, size_t buf_len, const uint64_t *array, size_t array_len); -+ -+int -+main (int argc, char *argv[]) -+{ -+ unsigned long ver; -+ const char *srcdir; -+ char *cwd; -+ char *test_uri; -+ -+ virInitialize (); -+ -+ /* Check that the version of libvirt we are linked against -+ * supports the new test-driver auth feature. -+ */ -+ virGetVersion (&ver, NULL, NULL); -+ if (ver < 1002001) { -+ fprintf (stderr, "%s: test skipped because libvirt is too old (%lu)\n", -+ argv[0], ver); -+ exit (77); -+ } -+ -+ /* $srcdir must have been passed (by automake). */ -+ srcdir = getenv ("srcdir"); -+ if (!srcdir) { -+ fprintf (stderr, -+ "%s: environment variable $srcdir is not defined.\n" -+ "Normally it is defined by automake. If you are running the\n" -+ "tests directly, set $srcdir to point to the source tests/events\n" -+ "directory.\n", argv[0]); -+ exit (EXIT_FAILURE); -+ } -+ -+ cwd = get_current_dir_name (); -+ if (cwd == NULL) { -+ perror ("get_current_dir_name"); -+ exit (EXIT_FAILURE); -+ } -+ -+ if (asprintf (&test_uri, "test://%s/%s/libvirt-auth.xml", cwd, srcdir) == -1) { -+ perror ("asprintf"); -+ exit (EXIT_FAILURE); -+ } -+ -+ free (cwd); -+ -+ /* Perform the tests. */ -+ struct auth_data ad1 = { .username = "rich", .password = "123456" }; -+ do_test (argv[0], test_uri, &ad1, EXPECT_OK); -+ struct auth_data ad2 = { .username = "rich", .password = "654321" }; -+ do_test (argv[0], test_uri, &ad2, EXPECT_FAIL); -+ struct auth_data ad3 = { .username = "jane", .password = NULL }; -+ do_test (argv[0], test_uri, &ad3, EXPECT_OK); -+ struct auth_data ad4 = { .username = "nouser", .password = "123456" }; -+ do_test (argv[0], test_uri, &ad4, EXPECT_FAIL); -+ -+ free (test_uri); -+ exit (EXIT_SUCCESS); -+} -+ -+static void -+do_test (const char *prog, const char *libvirt_uri, -+ const struct auth_data *auth_data, -+ int expected) -+{ -+ guestfs_h *g; -+ const char *creds[] = -+ { "authname", "passphrase", "noechoprompt", NULL }; -+ int r, eh; -+ -+ g = guestfs_create (); -+ if (!g) -+ exit (EXIT_FAILURE); -+ -+ r = guestfs_set_libvirt_supported_credentials (g, (char **) creds); -+ if (r == -1) -+ exit (EXIT_FAILURE); -+ -+ eh = guestfs_set_event_callback (g, auth_callback, -+ GUESTFS_EVENT_LIBVIRT_AUTH, 0, -+ (void *) auth_data); -+ if (eh == -1) -+ exit (EXIT_FAILURE); -+ -+ r = guestfs_add_domain (g, "test", -+ GUESTFS_ADD_DOMAIN_LIBVIRTURI, libvirt_uri, -+ GUESTFS_ADD_DOMAIN_READONLY, 1, -+ -1); -+ if (r != expected) { -+ fprintf (stderr, -+ "%s: test failed: u=%s p=%s: got %d expected %d\n", -+ prog, auth_data->username, auth_data->password ? : "(none)", -+ r, expected); -+ exit (EXIT_FAILURE); -+ } -+ -+ guestfs_close (g); -+} -+ -+static void -+auth_callback (guestfs_h *g, void *opaque, -+ uint64_t event, int event_handle, -+ int flags, -+ const char *buf, size_t buf_len, -+ const uint64_t *array, size_t array_len) -+{ -+ CLEANUP_FREE_STRING_LIST char **creds = NULL; -+ const struct auth_data *auth_data = opaque; -+ size_t i; -+ int r; -+ const char *reply; -+ size_t len; -+ -+ /* Ask libguestfs what credentials libvirt is demanding. */ -+ creds = guestfs_get_libvirt_requested_credentials (g); -+ if (creds == NULL) -+ exit (EXIT_FAILURE); -+ -+ /* Try to answer from the authentication data. */ -+ for (i = 0; creds[i] != NULL; ++i) { -+ if (STREQ (creds[i], "authname")) { -+ reply = auth_data->username; -+ len = strlen (reply); -+ } -+ else if (STREQ (creds[i], "passphrase") || -+ STREQ (creds[i], "noechoprompt")) { -+ if (!auth_data->password) { -+ fprintf (stderr, "test failed: libvirt asked for a password, but auth_data->password == NULL\n"); -+ exit (EXIT_FAILURE); -+ } -+ -+ reply = auth_data->password; -+ len = strlen (reply); -+ } -+ else { -+ fprintf (stderr, "test failed: libvirt asked for '%s' which is not in creds list\n(This is probably a libvirt bug)\n", -+ creds[i]); -+ exit (EXIT_FAILURE); -+ } -+ -+ r = guestfs_set_libvirt_requested_credential (g, i, -+ reply, len); -+ if (r == -1) -+ exit (EXIT_FAILURE); -+ } -+} --- -1.8.4.2 - diff --git a/0042-sysprep-builder-Add-timezone-option-to-set-timezone-.patch b/0042-sysprep-builder-Add-timezone-option-to-set-timezone-.patch new file mode 100644 index 0000000..f44a5f2 --- /dev/null +++ b/0042-sysprep-builder-Add-timezone-option-to-set-timezone-.patch @@ -0,0 +1,363 @@ +From 7d813866eeefe02646de7ff2c73a2e31076a5afd Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 12:12:30 +0000 +Subject: [PATCH] sysprep, builder: Add --timezone option to set timezone of + guest. + +You can use it like this: + + virt-sysprep --timezone Europe/London ... + virt-builder --timezone Europe/London ... + +(cherry picked from commit dd1bfea513658368afd3728e0c5bf8ab6041cd1f) +--- + builder/Makefile.am | 1 + + builder/builder.ml | 12 ++++++- + builder/cmdline.ml | 9 ++++- + builder/test-virt-builder.sh | 1 + + builder/virt-builder.pod | 8 ++++- + mllib/Makefile.am | 3 ++ + mllib/timezone.ml | 39 +++++++++++++++++++++ + mllib/timezone.mli | 22 ++++++++++++ + po/POTFILES-ml | 2 ++ + sysprep/Makefile.am | 2 ++ + sysprep/sysprep_operation_timezone.ml | 66 +++++++++++++++++++++++++++++++++++ + 11 files changed, 162 insertions(+), 3 deletions(-) + create mode 100644 mllib/timezone.ml + create mode 100644 mllib/timezone.mli + create mode 100644 sysprep/sysprep_operation_timezone.ml + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index f5e7d80..d718c22 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -67,6 +67,7 @@ OBJECTS = \ + $(top_builddir)/mllib/urandom.cmx \ + $(top_builddir)/mllib/random_seed.cmx \ + $(top_builddir)/mllib/hostname.cmx \ ++ $(top_builddir)/mllib/timezone.cmx \ + $(top_builddir)/mllib/firstboot.cmx \ + $(top_builddir)/mllib/perl_edit.cmx \ + $(top_builddir)/mllib/crypt-c.o \ +diff --git a/builder/builder.ml b/builder/builder.ml +index 0c1f1e0..daf355c 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -41,7 +41,8 @@ let main () = + attach, cache, check_signature, curl, debug, delete, edit, + firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, update, upload, writes = ++ scrub_logfile, size, smp, sources, sync, timezone, update, upload, ++ writes = + parse_cmdline () in + + (* Timestamped messages in ordinary, non-debug non-quiet mode. *) +@@ -621,6 +622,15 @@ let main () = + eprintf (f_"%s: warning: hostname could not be set for this type of guest\n%!") prog + ); + ++ (* Set the timezone. *) ++ (match timezone with ++ | None -> () ++ | Some timezone -> ++ msg (f_"Setting the timezone: %s") timezone; ++ if not (Timezone.set_timezone ~prog g root timezone) then ++ eprintf (f_"%s: warning: timezone could not be set for this type of guest\n%!") prog ++ ); ++ + (* Root password. + * Note 'None' means that we randomize the root password. + *) +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index f25280c..813fbd8 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -169,6 +169,10 @@ let parse_cmdline () = + let add_source arg = sources := arg :: !sources in + + let sync = ref true in ++ ++ let timezone = ref None in ++ let set_timezone s = timezone := Some s in ++ + let update = ref false in + + let upload = ref [] in +@@ -260,6 +264,7 @@ let parse_cmdline () = + "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; + "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; + "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit"; ++ "--timezone",Arg.String set_timezone, "timezone" ^ " " ^ s_"Set the default timezone"; + "--update", Arg.Set update, " " ^ s_"Update core packages"; + "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest"; + "-v", Arg.Set debug, " " ^ s_"Enable debugging messages"; +@@ -321,6 +326,7 @@ read the man page virt-builder(1). + let smp = !smp in + let sources = List.rev !sources in + let sync = !sync in ++ let timezone = !timezone in + let update = !update in + let upload = List.rev !upload in + let writes = List.rev !writes in +@@ -421,4 +427,5 @@ read the man page virt-builder(1). + attach, cache, check_signature, curl, debug, delete, edit, + firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, update, upload, writes ++ scrub_logfile, size, smp, sources, sync, timezone, update, upload, ++ writes +diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh +index 438f2e9..8d2766a 100755 +--- a/builder/test-virt-builder.sh ++++ b/builder/test-virt-builder.sh +@@ -53,6 +53,7 @@ $VG ./virt-builder phony-fedora \ + -v --no-cache --no-check-signature $no_network \ + -o $output --size 2G --format $format \ + --hostname test.example.com \ ++ --timezone Europe/London \ + --root-password password:123456 \ + --mkdir /etc/foo/bar/baz \ + --write '/etc/foo/bar/baz/foo:Hello World' \ +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 094f028..f98ffdb 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly + [--attach ISOFILE] + [--root-password SELECTOR] + [--hostname HOSTNAME] ++ [--timezone TIMEZONE] + [--update] + [--install PKG,[PKG...]] + [--mkdir DIR] +@@ -583,6 +584,11 @@ Note that you should not point I<--source> to sources that you don't + trust (unless the source is signed by someone you do trust). See also + the I<--no-network> option. + ++=item B<--timezone> TIMEZONE ++ ++Set the default timezone of the guest to C. Use a location ++string like C ++ + =item B<--update> + + Do the equivalent of C, C, or whatever +@@ -838,7 +844,7 @@ A new random seed is generated for the guest. + + =item * + +-The hostname is set (I<--hostname>). ++The hostname and timezone are set (I<--hostname>, I<--timezone>). + + =item * + +diff --git a/mllib/Makefile.am b/mllib/Makefile.am +index 9719273..67f0a0a 100644 +--- a/mllib/Makefile.am ++++ b/mllib/Makefile.am +@@ -49,6 +49,8 @@ SOURCES = \ + progress.ml \ + random_seed.mli \ + random_seed.ml \ ++ timezone.mli \ ++ timezone.ml \ + tty-c.c \ + tTY.mli \ + tTY.ml \ +@@ -79,6 +81,7 @@ OBJECTS = \ + urandom.cmx \ + random_seed.cmx \ + hostname.cmx \ ++ timezone.cmx \ + firstboot.cmx \ + perl_edit.cmx \ + tTY.cmx \ +diff --git a/mllib/timezone.ml b/mllib/timezone.ml +new file mode 100644 +index 0000000..8b302d9 +--- /dev/null ++++ b/mllib/timezone.ml +@@ -0,0 +1,39 @@ ++(* Set timezone in virt-sysprep and virt-builder. ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Common_utils ++ ++open Printf ++ ++let set_timezone ~prog (g : Guestfs.guestfs) root timezone = ++ let typ = g#inspect_get_type root in ++ ++ match typ with ++ (* Every known Linux has /etc/localtime be either a copy of or a ++ * symlink to a timezone file in /usr/share/zoneinfo. ++ * Even systemd didn't fuck this up. ++ *) ++ | "linux" -> ++ let target = sprintf "/usr/share/zoneinfo/%s" timezone in ++ if not (g#exists target) then ++ error ~prog "timezone '%s' does not exist, use a location like 'Europe/London'" timezone; ++ g#ln_sf target "/etc/localtime"; ++ true ++ ++ | _ -> ++ false +diff --git a/mllib/timezone.mli b/mllib/timezone.mli +new file mode 100644 +index 0000000..ad0d4b2 +--- /dev/null ++++ b/mllib/timezone.mli +@@ -0,0 +1,22 @@ ++(* Set timezone in virt-sysprep and virt-builder. ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++val set_timezone : prog:string -> Guestfs.guestfs -> string -> string -> bool ++(** [set_timezone ~prog g root "Europe/London"] sets the default timezone ++ of the guest. Returns [true] if it was able to set the ++ timezone or [false] if not. *) +diff --git a/po/POTFILES-ml b/po/POTFILES-ml +index 84211b6..564404b 100644 +--- a/po/POTFILES-ml ++++ b/po/POTFILES-ml +@@ -21,6 +21,7 @@ mllib/planner.ml + mllib/progress.ml + mllib/random_seed.ml + mllib/tTY.ml ++mllib/timezone.ml + mllib/uRI.ml + mllib/urandom.ml + resize/resize.ml +@@ -62,6 +63,7 @@ sysprep/sysprep_operation_smolt_uuid.ml + sysprep/sysprep_operation_ssh_hostkeys.ml + sysprep/sysprep_operation_ssh_userdir.ml + sysprep/sysprep_operation_sssd_db_log.ml ++sysprep/sysprep_operation_timezone.ml + sysprep/sysprep_operation_tmp_files.ml + sysprep/sysprep_operation_udev_persistent_net.ml + sysprep/sysprep_operation_user_account.ml +diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am +index 24654cb..7ab2277 100644 +--- a/sysprep/Makefile.am ++++ b/sysprep/Makefile.am +@@ -66,6 +66,7 @@ operations = \ + ssh_hostkeys \ + ssh_userdir \ + sssd_db_log \ ++ timezone \ + tmp_files \ + udev_persistent_net \ + user_account \ +@@ -93,6 +94,7 @@ OBJECTS = \ + $(top_builddir)/mllib/password.cmx \ + $(top_builddir)/mllib/random_seed.cmx \ + $(top_builddir)/mllib/hostname.cmx \ ++ $(top_builddir)/mllib/timezone.cmx \ + $(top_builddir)/mllib/firstboot.cmx \ + $(top_builddir)/mllib/config.cmx \ + sysprep_operation.cmx \ +diff --git a/sysprep/sysprep_operation_timezone.ml b/sysprep/sysprep_operation_timezone.ml +new file mode 100644 +index 0000000..7557f44 +--- /dev/null ++++ b/sysprep/sysprep_operation_timezone.ml +@@ -0,0 +1,66 @@ ++(* virt-sysprep ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++open Printf ++ ++open Common_utils ++open Sysprep_operation ++open Common_gettext.Gettext ++ ++module G = Guestfs ++ ++let timezone = ref None ++ ++let timezone_perform (g : Guestfs.guestfs) root = ++ match !timezone with ++ | None -> [] ++ | Some tz -> ++ if Timezone.set_timezone ~prog g root tz then [ `Created_files ] else [] ++ ++let op = { ++ defaults with ++ name = "timezone"; ++ enabled_by_default = true; ++ heading = s_"Change the default timezone of the guest"; ++ ++ pod_description = Some (s_"\ ++This operation changes the default timezone of the guest to the value ++given in the I<--timezone> parameter. ++ ++If the I<--timezone> parameter is not given, then the timezone is not ++changed. ++ ++This parameter affects the default timezone that users see when they log ++in, but they can still change their timezone per-user account."); ++ ++ pod_notes = Some (s_"\ ++Currently this can only set the timezone on Linux guests."); ++ ++ extra_args = [ ++ let set_timezone str = timezone := Some str in ++ { extra_argspec = "--timezone", Arg.String set_timezone, s_"timezone" ^ " " ^ s_"New timezone"; ++ extra_pod_argval = Some "TIMEZONE"; ++ extra_pod_description = s_"\ ++Change the timezone. Use a location string such as C" ++ } ++ ]; ++ ++ perform_on_filesystems = Some timezone_perform; ++} ++ ++let () = register_operation op +-- +1.8.4.2 + diff --git a/0042-tests-Add-a-regression-test-for-libvirt-authenticati.patch b/0042-tests-Add-a-regression-test-for-libvirt-authenticati.patch deleted file mode 100644 index b6ca4e3..0000000 --- a/0042-tests-Add-a-regression-test-for-libvirt-authenticati.patch +++ /dev/null @@ -1,268 +0,0 @@ -From 3323012c8d90c570770049d6f68f6fb686fa0166 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Wed, 8 Jan 2014 20:22:21 +0000 -Subject: [PATCH] tests: Add a regression test for libvirt authentication - (RHBZ#1044014). - -This tests the virConnectAuthPtrDefault wrapper path. - -(cherry picked from commit 746a0b1f19667606ee63c8d3ab6a75531a8bd71c) ---- - .gitignore | 2 ++ - tests/regressions/Makefile.am | 29 +++++++++++++++- - tests/regressions/rhbz1044014.c | 69 ++++++++++++++++++++++++++++++++++++++ - tests/regressions/rhbz1044014.in | 1 + - tests/regressions/rhbz1044014.sh | 70 +++++++++++++++++++++++++++++++++++++++ - tests/regressions/rhbz1044014.xml | 5 +++ - 6 files changed, 175 insertions(+), 1 deletion(-) - create mode 100644 tests/regressions/rhbz1044014.c - create mode 100644 tests/regressions/rhbz1044014.in - create mode 100755 tests/regressions/rhbz1044014.sh - create mode 100644 tests/regressions/rhbz1044014.xml - -diff --git a/.gitignore b/.gitignore -index 3d429de..985795f 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -484,6 +484,8 @@ Makefile.in - /tests/regressions/rhbz501893 - /tests/regressions/rhbz790721 - /tests/regressions/rhbz914931 -+/tests/regressions/rhbz1044014 -+/tests/regressions/rhbz1044014.out - /tests/regressions/rhbz1055452 - /tests/rsync/rsyncd.pid - /tests/syslinux/extlinux-guest.img -diff --git a/tests/regressions/Makefile.am b/tests/regressions/Makefile.am -index 97bc64e..3cd121a 100644 ---- a/tests/regressions/Makefile.am -+++ b/tests/regressions/Makefile.am -@@ -37,6 +37,10 @@ TESTS = \ - rhbz1055452 \ - test-noexec-stack.pl - -+if HAVE_LIBVIRT -+TESTS += rhbz1044014.sh -+endif -+ - tests_not_run = \ - rhbz727178.sh \ - rhbz909624.sh -@@ -51,6 +55,10 @@ check_PROGRAMS = \ - rhbz914931 \ - rhbz1055452 - -+if HAVE_LIBVIRT -+check_PROGRAMS += rhbz1044014 -+endif -+ - rhbz501893_SOURCES = rhbz501893.c - rhbz501893_CPPFLAGS = \ - -I$(top_srcdir)/src -I$(top_builddir)/src -@@ -81,6 +89,23 @@ rhbz914931_CFLAGS = \ - rhbz914931_LDADD = \ - $(top_builddir)/src/libguestfs.la - -+if HAVE_LIBVIRT -+rhbz1044014_SOURCES = rhbz1044014.c -+rhbz1044014_CPPFLAGS = \ -+ -I$(top_srcdir)/gnulib/lib -I$(top_builddir)/gnulib/lib \ -+ -I$(top_srcdir)/src -I$(top_builddir)/src -+rhbz1044014_CFLAGS = \ -+ $(WARN_CFLAGS) $(WERROR_CFLAGS) \ -+ $(GPROF_CFLAGS) $(GCOV_CFLAGS) \ -+ $(LIBVIRT_CFLAGS) -+rhbz1044014_LDADD = \ -+ $(top_builddir)/src/libutils.la \ -+ $(top_builddir)/src/libguestfs.la \ -+ $(LIBVIRT_LIBS) \ -+ $(LIBXML2_LIBS) \ -+ $(top_builddir)/gnulib/lib/libgnu.la -+endif -+ - rhbz1055452_SOURCES = rhbz1055452.c - rhbz1055452_CPPFLAGS = \ - -I$(top_srcdir)/src -I$(top_builddir)/src \ -@@ -96,7 +121,9 @@ EXTRA_DIST = \ - $(TESTS) \ - $(tests_not_run) \ - rhbz557655-expected.stdout \ -- rhbz557655-expected.stderr -+ rhbz557655-expected.stderr \ -+ rhbz1044014.in \ -+ rhbz1044014.xml - - check-slow: - $(MAKE) TESTS="rhbz909624.sh" check -diff --git a/tests/regressions/rhbz1044014.c b/tests/regressions/rhbz1044014.c -new file mode 100644 -index 0000000..18ce4a7 ---- /dev/null -+++ b/tests/regressions/rhbz1044014.c -@@ -0,0 +1,69 @@ -+/* libguestfs -+ * Copyright (C) 2014 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ */ -+ -+/* Regression test for RHBZ#1044014. -+ * -+ * The only reason to write this in C is so we can easily check the -+ * version of libvirt >= 1.2.1. In the future when we can assume a -+ * newer libvirt, we can just have the main rhbz1044014.sh script set -+ * some environment variables and use guestfish. -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "guestfs.h" -+#include "guestfs-internal-frontend.h" -+ -+int -+main (int argc, char *argv[]) -+{ -+ unsigned long ver; -+ guestfs_h *g; -+ -+ virInitialize (); -+ -+ /* Check that the version of libvirt we are linked against -+ * supports the new test-driver auth feature. -+ */ -+ virGetVersion (&ver, NULL, NULL); -+ if (ver < 1002001) { -+ fprintf (stderr, "%s: test skipped because libvirt is too old (%lu)\n", -+ argv[0], ver); -+ exit (77); -+ } -+ -+ g = guestfs_create (); -+ if (!g) -+ exit (EXIT_FAILURE); -+ -+ /* This will ask the user for credentials. It will also fail -+ * (expectedly) because the test driver does not support qemu/KVM. -+ */ -+ guestfs_launch (g); -+ -+ guestfs_close (g); -+ exit (EXIT_SUCCESS); -+} -diff --git a/tests/regressions/rhbz1044014.in b/tests/regressions/rhbz1044014.in -new file mode 100644 -index 0000000..3f382dd ---- /dev/null -+++ b/tests/regressions/rhbz1044014.in -@@ -0,0 +1 @@ -+rich -diff --git a/tests/regressions/rhbz1044014.sh b/tests/regressions/rhbz1044014.sh -new file mode 100755 -index 0000000..f1e458c ---- /dev/null -+++ b/tests/regressions/rhbz1044014.sh -@@ -0,0 +1,70 @@ -+#!/bin/bash - -+# libguestfs -+# Copyright (C) 2014 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Regression test for: -+# https://bugzilla.redhat.com/show_bug.cgi?id=1044014 -+ -+set -e -+export LANG=C -+ -+if [ -n "$SKIP_TEST_RHBZ1044014_SH" ]; then -+ echo "$0: test skipped because environment variable is set." -+ exit 77 -+fi -+ -+# Check we are running against the libvirt backend. -+backend="$(../../fish/guestfish get-backend)" -+if [[ ! ( "$backend" =~ ^libvirt ) ]]; then -+ echo "$0: test skipped because backend ($backend) is not libvirt." -+ exit 77 -+fi -+ -+# Set the backend to the test driver. -+export LIBGUESTFS_BACKEND="libvirt:test://$(pwd)/$srcdir/rhbz1044014.xml" -+ -+rm -f rhbz1044014.out -+ -+./rhbz1044014 < $srcdir/rhbz1044014.in > rhbz1044014.out 2>&1 || { -+ r=$? -+ if [ $r -ne 0 ]; then -+ cat rhbz1044014.out -+ exit $r -+ fi -+} -+ -+# We are expecting this message to be printed (see commit which fixed -+# RHBZ#1044014). -+grep "libvirt needs authentication to connect to libvirt URI" rhbz1044014.out || { -+ echo "$0: expecting to see message from commit which fixed RHBZ#1044014" -+ echo -+ echo "actual output was:" -+ echo -+ cat rhbz1044014.out -+ exit 1 -+} -+ -+# This is the error we are expecting to see. If we see it then it -+# indicates that authentication was successful. -+grep "error: libvirt hypervisor doesn't support qemu or KVM" rhbz1044014.out || { -+ echo "$0: unexpected output:" -+ echo -+ cat rhbz1044014.out -+ exit 1 -+} -+ -+rm rhbz1044014.out -diff --git a/tests/regressions/rhbz1044014.xml b/tests/regressions/rhbz1044014.xml -new file mode 100644 -index 0000000..72feaf4 ---- /dev/null -+++ b/tests/regressions/rhbz1044014.xml -@@ -0,0 +1,5 @@ -+ -+ -+ rich -+ -+ --- -1.8.4.2 - diff --git a/0043-builder-Document-how-to-change-keyboard-layout.patch b/0043-builder-Document-how-to-change-keyboard-layout.patch new file mode 100644 index 0000000..34fcf73 --- /dev/null +++ b/0043-builder-Document-how-to-change-keyboard-layout.patch @@ -0,0 +1,69 @@ +From 724d233849fe146761fe46b2499cec3a4aa9b729 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 14:21:17 +0000 +Subject: [PATCH] builder: Document how to change keyboard layout. + +This is too complex to implement directly in virt-builder. + +Instead we just document how to do it for some common Linux distros +using --run-command, --edit etc. + +(cherry picked from commit 8ae6b6c9ff855f5eaf3f16188b1bcb4ddba095c5) +--- + builder/virt-builder.pod | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index f98ffdb..fc6ad40 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -783,6 +783,46 @@ The above command will create an C account with no password, + and force the user to set a password when they first log in. There + are other ways to manage passwords, see L for details. + ++=head2 KEYBOARD LAYOUT ++ ++Because there are so many different ways to set the keyboard layout in ++Linux distributions, virt-builder does not yet attempt to have a ++simple command line option. This section describes how to set the ++keyboard for some common Linux distributions. ++ ++=head3 Keyboard layout with systemd ++ ++For distros that use systemd C, use a command like this: ++ ++ virt-builder fedora-20 \ ++ --firstboot-command 'localectl set-keymap uk' ++ ++See L and ++L ++for more details. ++ ++=head3 Keyboard layout using C ++ ++For RHEL E 6, Fedora E 18 and similar, upload or modify the ++keyboard configuration file using the I<--upload>, I<--write> or ++I<--edit> options. For example: ++ ++ virt-builder centos-6 \ ++ --edit '/etc/sysconfig/keyboard: s/^KEYTABLE=.*/KEYTABLE="uk"/' ++ ++The format of this file can be found documented in many places online. ++ ++=head3 Keyboard layout with Debian-derived distros ++ ++For Debian-derived distros using C, upload or ++modify the keyboard file using the I<--upload>, I<--write> or ++I<--edit> options. For example: ++ ++ virt-builder debian-7 \ ++ --edit '/etc/default/keyboard: s/^XKBLAYOUT=.*/XKBLAYOUT="gb"/' ++ ++See L. ++ + =head2 LOG FILE + + Scripts and package installation that runs at build time (I<--run>, +-- +1.8.4.2 + diff --git a/0043-sysprep-builder-Add-timezone-option-to-set-timezone-.patch b/0043-sysprep-builder-Add-timezone-option-to-set-timezone-.patch deleted file mode 100644 index 3c44135..0000000 --- a/0043-sysprep-builder-Add-timezone-option-to-set-timezone-.patch +++ /dev/null @@ -1,363 +0,0 @@ -From 076cffb5802a01a2908fcc8d0f20b1331e3d4bf5 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 10 Jan 2014 12:12:30 +0000 -Subject: [PATCH] sysprep, builder: Add --timezone option to set timezone of - guest. - -You can use it like this: - - virt-sysprep --timezone Europe/London ... - virt-builder --timezone Europe/London ... - -(cherry picked from commit dd1bfea513658368afd3728e0c5bf8ab6041cd1f) ---- - builder/Makefile.am | 1 + - builder/builder.ml | 12 ++++++- - builder/cmdline.ml | 9 ++++- - builder/test-virt-builder.sh | 1 + - builder/virt-builder.pod | 8 ++++- - mllib/Makefile.am | 3 ++ - mllib/timezone.ml | 39 +++++++++++++++++++++ - mllib/timezone.mli | 22 ++++++++++++ - po/POTFILES-ml | 2 ++ - sysprep/Makefile.am | 2 ++ - sysprep/sysprep_operation_timezone.ml | 66 +++++++++++++++++++++++++++++++++++ - 11 files changed, 162 insertions(+), 3 deletions(-) - create mode 100644 mllib/timezone.ml - create mode 100644 mllib/timezone.mli - create mode 100644 sysprep/sysprep_operation_timezone.ml - -diff --git a/builder/Makefile.am b/builder/Makefile.am -index 3f35cc6..fc4c552 100644 ---- a/builder/Makefile.am -+++ b/builder/Makefile.am -@@ -69,6 +69,7 @@ OBJECTS = \ - $(top_builddir)/mllib/urandom.cmx \ - $(top_builddir)/mllib/random_seed.cmx \ - $(top_builddir)/mllib/hostname.cmx \ -+ $(top_builddir)/mllib/timezone.cmx \ - $(top_builddir)/mllib/firstboot.cmx \ - $(top_builddir)/mllib/crypt-c.o \ - $(top_builddir)/mllib/crypt.cmx \ -diff --git a/builder/builder.ml b/builder/builder.ml -index f007b46..90300a3 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -39,7 +39,8 @@ let main () = - attach, cache, check_signature, curl, debug, delete, edit, - firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, -- scrub_logfile, size, smp, sources, sync, update, upload, writes = -+ scrub_logfile, size, smp, sources, sync, timezone, update, upload, -+ writes = - parse_cmdline () in - - (* Timestamped messages in ordinary, non-debug non-quiet mode. *) -@@ -619,6 +620,15 @@ let main () = - eprintf (f_"%s: warning: hostname could not be set for this type of guest\n%!") prog - ); - -+ (* Set the timezone. *) -+ (match timezone with -+ | None -> () -+ | Some timezone -> -+ msg (f_"Setting the timezone: %s") timezone; -+ if not (Timezone.set_timezone ~prog g root timezone) then -+ eprintf (f_"%s: warning: timezone could not be set for this type of guest\n%!") prog -+ ); -+ - (* Root password. - * Note 'None' means that we randomize the root password. - *) -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index f25280c..813fbd8 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -169,6 +169,10 @@ let parse_cmdline () = - let add_source arg = sources := arg :: !sources in - - let sync = ref true in -+ -+ let timezone = ref None in -+ let set_timezone s = timezone := Some s in -+ - let update = ref false in - - let upload = ref [] in -@@ -260,6 +264,7 @@ let parse_cmdline () = - "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; - "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; - "--no-sync", Arg.Clear sync, " " ^ s_"Do not fsync output file on exit"; -+ "--timezone",Arg.String set_timezone, "timezone" ^ " " ^ s_"Set the default timezone"; - "--update", Arg.Set update, " " ^ s_"Update core packages"; - "--upload", Arg.String add_upload, "file:dest" ^ " " ^ s_"Upload file to dest"; - "-v", Arg.Set debug, " " ^ s_"Enable debugging messages"; -@@ -321,6 +326,7 @@ read the man page virt-builder(1). - let smp = !smp in - let sources = List.rev !sources in - let sync = !sync in -+ let timezone = !timezone in - let update = !update in - let upload = List.rev !upload in - let writes = List.rev !writes in -@@ -421,4 +427,5 @@ read the man page virt-builder(1). - attach, cache, check_signature, curl, debug, delete, edit, - firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, -- scrub_logfile, size, smp, sources, sync, update, upload, writes -+ scrub_logfile, size, smp, sources, sync, timezone, update, upload, -+ writes -diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh -index 438f2e9..8d2766a 100755 ---- a/builder/test-virt-builder.sh -+++ b/builder/test-virt-builder.sh -@@ -53,6 +53,7 @@ $VG ./virt-builder phony-fedora \ - -v --no-cache --no-check-signature $no_network \ - -o $output --size 2G --format $format \ - --hostname test.example.com \ -+ --timezone Europe/London \ - --root-password password:123456 \ - --mkdir /etc/foo/bar/baz \ - --write '/etc/foo/bar/baz/foo:Hello World' \ -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index f72e284..3558119 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly - [--attach ISOFILE] - [--root-password SELECTOR] - [--hostname HOSTNAME] -+ [--timezone TIMEZONE] - [--update] - [--install PKG,[PKG...]] - [--mkdir DIR] -@@ -583,6 +584,11 @@ Note that you should not point I<--source> to sources that you don't - trust (unless the source is signed by someone you do trust). See also - the I<--no-network> option. - -+=item B<--timezone> TIMEZONE -+ -+Set the default timezone of the guest to C. Use a location -+string like C -+ - =item B<--update> - - Do the equivalent of C, C, or whatever -@@ -838,7 +844,7 @@ A new random seed is generated for the guest. - - =item * - --The hostname is set (I<--hostname>). -+The hostname and timezone are set (I<--hostname>, I<--timezone>). - - =item * - -diff --git a/mllib/Makefile.am b/mllib/Makefile.am -index 67027d2..5568e02 100644 ---- a/mllib/Makefile.am -+++ b/mllib/Makefile.am -@@ -47,6 +47,8 @@ SOURCES = \ - progress.ml \ - random_seed.mli \ - random_seed.ml \ -+ timezone.mli \ -+ timezone.ml \ - tty-c.c \ - tTY.mli \ - tTY.ml \ -@@ -77,6 +79,7 @@ OBJECTS = \ - urandom.cmx \ - random_seed.cmx \ - hostname.cmx \ -+ timezone.cmx \ - firstboot.cmx \ - tTY.cmx \ - fsync.cmx \ -diff --git a/mllib/timezone.ml b/mllib/timezone.ml -new file mode 100644 -index 0000000..8b302d9 ---- /dev/null -+++ b/mllib/timezone.ml -@@ -0,0 +1,39 @@ -+(* Set timezone in virt-sysprep and virt-builder. -+ * Copyright (C) 2014 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+open Common_utils -+ -+open Printf -+ -+let set_timezone ~prog (g : Guestfs.guestfs) root timezone = -+ let typ = g#inspect_get_type root in -+ -+ match typ with -+ (* Every known Linux has /etc/localtime be either a copy of or a -+ * symlink to a timezone file in /usr/share/zoneinfo. -+ * Even systemd didn't fuck this up. -+ *) -+ | "linux" -> -+ let target = sprintf "/usr/share/zoneinfo/%s" timezone in -+ if not (g#exists target) then -+ error ~prog "timezone '%s' does not exist, use a location like 'Europe/London'" timezone; -+ g#ln_sf target "/etc/localtime"; -+ true -+ -+ | _ -> -+ false -diff --git a/mllib/timezone.mli b/mllib/timezone.mli -new file mode 100644 -index 0000000..ad0d4b2 ---- /dev/null -+++ b/mllib/timezone.mli -@@ -0,0 +1,22 @@ -+(* Set timezone in virt-sysprep and virt-builder. -+ * Copyright (C) 2014 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+val set_timezone : prog:string -> Guestfs.guestfs -> string -> string -> bool -+(** [set_timezone ~prog g root "Europe/London"] sets the default timezone -+ of the guest. Returns [true] if it was able to set the -+ timezone or [false] if not. *) -diff --git a/po/POTFILES-ml b/po/POTFILES-ml -index 8ae6ea9..4c69258 100644 ---- a/po/POTFILES-ml -+++ b/po/POTFILES-ml -@@ -21,6 +21,7 @@ mllib/planner.ml - mllib/progress.ml - mllib/random_seed.ml - mllib/tTY.ml -+mllib/timezone.ml - mllib/uRI.ml - mllib/urandom.ml - resize/resize.ml -@@ -62,6 +63,7 @@ sysprep/sysprep_operation_smolt_uuid.ml - sysprep/sysprep_operation_ssh_hostkeys.ml - sysprep/sysprep_operation_ssh_userdir.ml - sysprep/sysprep_operation_sssd_db_log.ml -+sysprep/sysprep_operation_timezone.ml - sysprep/sysprep_operation_tmp_files.ml - sysprep/sysprep_operation_udev_persistent_net.ml - sysprep/sysprep_operation_user_account.ml -diff --git a/sysprep/Makefile.am b/sysprep/Makefile.am -index 621d2b6..835d4a6 100644 ---- a/sysprep/Makefile.am -+++ b/sysprep/Makefile.am -@@ -65,6 +65,7 @@ operations = \ - ssh_hostkeys \ - ssh_userdir \ - sssd_db_log \ -+ timezone \ - tmp_files \ - udev_persistent_net \ - user_account \ -@@ -92,6 +93,7 @@ OBJECTS = \ - $(top_builddir)/mllib/password.cmx \ - $(top_builddir)/mllib/random_seed.cmx \ - $(top_builddir)/mllib/hostname.cmx \ -+ $(top_builddir)/mllib/timezone.cmx \ - $(top_builddir)/mllib/firstboot.cmx \ - $(top_builddir)/mllib/config.cmx \ - sysprep_operation.cmx \ -diff --git a/sysprep/sysprep_operation_timezone.ml b/sysprep/sysprep_operation_timezone.ml -new file mode 100644 -index 0000000..7557f44 ---- /dev/null -+++ b/sysprep/sysprep_operation_timezone.ml -@@ -0,0 +1,66 @@ -+(* virt-sysprep -+ * Copyright (C) 2014 Red Hat Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License along -+ * with this program; if not, write to the Free Software Foundation, Inc., -+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ *) -+ -+open Printf -+ -+open Common_utils -+open Sysprep_operation -+open Common_gettext.Gettext -+ -+module G = Guestfs -+ -+let timezone = ref None -+ -+let timezone_perform (g : Guestfs.guestfs) root = -+ match !timezone with -+ | None -> [] -+ | Some tz -> -+ if Timezone.set_timezone ~prog g root tz then [ `Created_files ] else [] -+ -+let op = { -+ defaults with -+ name = "timezone"; -+ enabled_by_default = true; -+ heading = s_"Change the default timezone of the guest"; -+ -+ pod_description = Some (s_"\ -+This operation changes the default timezone of the guest to the value -+given in the I<--timezone> parameter. -+ -+If the I<--timezone> parameter is not given, then the timezone is not -+changed. -+ -+This parameter affects the default timezone that users see when they log -+in, but they can still change their timezone per-user account."); -+ -+ pod_notes = Some (s_"\ -+Currently this can only set the timezone on Linux guests."); -+ -+ extra_args = [ -+ let set_timezone str = timezone := Some str in -+ { extra_argspec = "--timezone", Arg.String set_timezone, s_"timezone" ^ " " ^ s_"New timezone"; -+ extra_pod_argval = Some "TIMEZONE"; -+ extra_pod_description = s_"\ -+Change the timezone. Use a location string such as C" -+ } -+ ]; -+ -+ perform_on_filesystems = Some timezone_perform; -+} -+ -+let () = register_operation op --- -1.8.4.2 - diff --git a/0044-builder-Add-link-option-for-creating-symbolic-links.patch b/0044-builder-Add-link-option-for-creating-symbolic-links.patch new file mode 100644 index 0000000..414f775 --- /dev/null +++ b/0044-builder-Add-link-option-for-creating-symbolic-links.patch @@ -0,0 +1,147 @@ +From 0f91372e5e6c4a8428918264574ac9ae874b622b Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 21:18:07 +0000 +Subject: [PATCH] builder: Add --link option for creating symbolic links. + +This is useful for configuring systemd services. + +(cherry picked from commit 6d4ac696e54902baf7d76de527b3df3d66c7dfa1) +--- + builder/builder.ml | 13 ++++++++++++- + builder/cmdline.ml | 16 +++++++++++++++- + builder/test-virt-builder.sh | 2 ++ + builder/virt-builder.pod | 12 ++++++++++++ + 4 files changed, 41 insertions(+), 2 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index daf355c..6105c75 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -39,7 +39,8 @@ let main () = + (* Command line argument parsing - see cmdline.ml. *) + let mode, arg, + attach, cache, check_signature, curl, debug, delete, edit, +- firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, ++ firstboot, run, format, gpg, hostname, install, list_long, links, ++ memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, + writes = +@@ -839,6 +840,16 @@ exec >>%s 2>&1 + g#rm_rf file + ) delete; + ++ (* Symbolic links. *) ++ List.iter ( ++ fun (target, links) -> ++ List.iter ( ++ fun link -> ++ msg (f_"Linking: %s -> %s") link target; ++ g#ln_sf target link ++ ) links ++ ) links; ++ + (* Scrub files. *) + List.iter ( + fun file -> +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index 813fbd8..58e8a6b 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -117,6 +117,17 @@ let parse_cmdline () = + install := pkgs @ !install + in + ++ let links = ref [] in ++ let add_link arg = ++ let target, lns = ++ match string_nsplit ":" arg with ++ | [] | [_] -> ++ eprintf (f_"%s: invalid --link format, see the man page.\n") prog; ++ exit 1 ++ | target :: lns -> target, lns in ++ links := (target, lns) :: !links ++ in ++ + let list_long = ref false in + + let memsize = ref None in +@@ -237,6 +248,7 @@ let parse_cmdline () = + "--gpg", Arg.Set_string gpg, "gpg" ^ " " ^ s_"Set GPG binary/command"; + "--hostname", Arg.String set_hostname, "hostname" ^ " " ^ s_"Set the hostname"; + "--install", Arg.String add_install, "pkg,pkg" ^ " " ^ s_"Add package(s) to install"; ++ "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; + "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; + "--list", Arg.Unit list_mode, ditto; + "--long", Arg.Set list_long, ditto; +@@ -313,6 +325,7 @@ read the man page virt-builder(1). + let hostname = !hostname in + let install = List.rev !install in + let list_long = !list_long in ++ let links = List.rev !links in + let memsize = !memsize in + let mkdirs = List.rev !mkdirs in + let network = !network in +@@ -425,7 +438,8 @@ read the man page virt-builder(1). + + mode, arg, + attach, cache, check_signature, curl, debug, delete, edit, +- firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, ++ firstboot, run, format, gpg, hostname, install, list_long, links, ++ memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, + writes +diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh +index 8d2766a..47d20a4 100755 +--- a/builder/test-virt-builder.sh ++++ b/builder/test-virt-builder.sh +@@ -60,6 +60,8 @@ $VG ./virt-builder phony-fedora \ + --upload Makefile:/Makefile \ + --upload Makefile:/etc/foo/bar/baz \ + --delete /Makefile \ ++ --link /etc/foo/bar/baz/foo:/foo \ ++ --link /etc/foo/bar/baz/foo:/foo1:/foo2:/foo3 \ + --firstboot Makefile --firstboot-command 'echo "hello"' \ + --firstboot-install "minicom,inkscape" + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index fc6ad40..0fd865f 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -24,6 +24,7 @@ virt-builder - Build virtual machine images quickly + [--mkdir DIR] + [--write FILE:CONTENT] + [--upload FILE:DEST] ++ [--link TARGET:LINK[:LINK]] + [--edit FILE:EXPR] + [--delete FILE] [--scrub FILE] + [--run SCRIPT] [--run-command 'CMD ARGS ...'] +@@ -353,6 +354,13 @@ L. + + See also I<--update>. + ++=item B<--link TARGET:LINK> ++ ++=item B<--link TARGET:LINK[:LINK...]> ++ ++Create symbolic link(s) in the guest, starting at C and ++pointing at C. ++ + =item B<-l> + + =item B<--list> +@@ -920,6 +928,10 @@ Files are deleted (I<--delete>, I<--scrub>). + + =item * + ++Symbolic links are created (I<--link). ++ ++=item * ++ + Firstboot scripts are installed (I<--firstboot>, + I<--firstboot-command>, I<--firstboot-install>). + +-- +1.8.4.2 + diff --git a/0044-builder-Document-how-to-change-keyboard-layout.patch b/0044-builder-Document-how-to-change-keyboard-layout.patch deleted file mode 100644 index 59063d5..0000000 --- a/0044-builder-Document-how-to-change-keyboard-layout.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 742a5e9fa5efdc5ba406687690c0d68a39fa7d45 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 10 Jan 2014 14:21:17 +0000 -Subject: [PATCH] builder: Document how to change keyboard layout. - -This is too complex to implement directly in virt-builder. - -Instead we just document how to do it for some common Linux distros -using --run-command, --edit etc. - -(cherry picked from commit 8ae6b6c9ff855f5eaf3f16188b1bcb4ddba095c5) ---- - builder/virt-builder.pod | 40 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 40 insertions(+) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 3558119..7d91daf 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -783,6 +783,46 @@ The above command will create an C account with no password, - and force the user to set a password when they first log in. There - are other ways to manage passwords, see L for details. - -+=head2 KEYBOARD LAYOUT -+ -+Because there are so many different ways to set the keyboard layout in -+Linux distributions, virt-builder does not yet attempt to have a -+simple command line option. This section describes how to set the -+keyboard for some common Linux distributions. -+ -+=head3 Keyboard layout with systemd -+ -+For distros that use systemd C, use a command like this: -+ -+ virt-builder fedora-20 \ -+ --firstboot-command 'localectl set-keymap uk' -+ -+See L and -+L -+for more details. -+ -+=head3 Keyboard layout using C -+ -+For RHEL E 6, Fedora E 18 and similar, upload or modify the -+keyboard configuration file using the I<--upload>, I<--write> or -+I<--edit> options. For example: -+ -+ virt-builder centos-6 \ -+ --edit '/etc/sysconfig/keyboard: s/^KEYTABLE=.*/KEYTABLE="uk"/' -+ -+The format of this file can be found documented in many places online. -+ -+=head3 Keyboard layout with Debian-derived distros -+ -+For Debian-derived distros using C, upload or -+modify the keyboard file using the I<--upload>, I<--write> or -+I<--edit> options. For example: -+ -+ virt-builder debian-7 \ -+ --edit '/etc/default/keyboard: s/^XKBLAYOUT=.*/XKBLAYOUT="gb"/' -+ -+See L. -+ - =head2 LOG FILE - - Scripts and package installation that runs at build time (I<--run>, --- -1.8.4.2 - diff --git a/0045-builder-Add-link-option-for-creating-symbolic-links.patch b/0045-builder-Add-link-option-for-creating-symbolic-links.patch deleted file mode 100644 index 44621ee..0000000 --- a/0045-builder-Add-link-option-for-creating-symbolic-links.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 7087b9287f9381af0e16b14bcedefaa9b2776f0a Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 10 Jan 2014 21:18:07 +0000 -Subject: [PATCH] builder: Add --link option for creating symbolic links. - -This is useful for configuring systemd services. - -(cherry picked from commit 6d4ac696e54902baf7d76de527b3df3d66c7dfa1) ---- - builder/builder.ml | 13 ++++++++++++- - builder/cmdline.ml | 16 +++++++++++++++- - builder/test-virt-builder.sh | 2 ++ - builder/virt-builder.pod | 12 ++++++++++++ - 4 files changed, 41 insertions(+), 2 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 90300a3..16ffa7a 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -37,7 +37,8 @@ let main () = - (* Command line argument parsing - see cmdline.ml. *) - let mode, arg, - attach, cache, check_signature, curl, debug, delete, edit, -- firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, -+ firstboot, run, format, gpg, hostname, install, list_long, links, -+ memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, - writes = -@@ -837,6 +838,16 @@ exec >>%s 2>&1 - g#rm_rf file - ) delete; - -+ (* Symbolic links. *) -+ List.iter ( -+ fun (target, links) -> -+ List.iter ( -+ fun link -> -+ msg (f_"Linking: %s -> %s") link target; -+ g#ln_sf target link -+ ) links -+ ) links; -+ - (* Scrub files. *) - List.iter ( - fun file -> -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index 813fbd8..58e8a6b 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -117,6 +117,17 @@ let parse_cmdline () = - install := pkgs @ !install - in - -+ let links = ref [] in -+ let add_link arg = -+ let target, lns = -+ match string_nsplit ":" arg with -+ | [] | [_] -> -+ eprintf (f_"%s: invalid --link format, see the man page.\n") prog; -+ exit 1 -+ | target :: lns -> target, lns in -+ links := (target, lns) :: !links -+ in -+ - let list_long = ref false in - - let memsize = ref None in -@@ -237,6 +248,7 @@ let parse_cmdline () = - "--gpg", Arg.Set_string gpg, "gpg" ^ " " ^ s_"Set GPG binary/command"; - "--hostname", Arg.String set_hostname, "hostname" ^ " " ^ s_"Set the hostname"; - "--install", Arg.String add_install, "pkg,pkg" ^ " " ^ s_"Add package(s) to install"; -+ "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; - "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; - "--list", Arg.Unit list_mode, ditto; - "--long", Arg.Set list_long, ditto; -@@ -313,6 +325,7 @@ read the man page virt-builder(1). - let hostname = !hostname in - let install = List.rev !install in - let list_long = !list_long in -+ let links = List.rev !links in - let memsize = !memsize in - let mkdirs = List.rev !mkdirs in - let network = !network in -@@ -425,7 +438,8 @@ read the man page virt-builder(1). - - mode, arg, - attach, cache, check_signature, curl, debug, delete, edit, -- firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs, -+ firstboot, run, format, gpg, hostname, install, list_long, links, -+ memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, - writes -diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh -index 8d2766a..47d20a4 100755 ---- a/builder/test-virt-builder.sh -+++ b/builder/test-virt-builder.sh -@@ -60,6 +60,8 @@ $VG ./virt-builder phony-fedora \ - --upload Makefile:/Makefile \ - --upload Makefile:/etc/foo/bar/baz \ - --delete /Makefile \ -+ --link /etc/foo/bar/baz/foo:/foo \ -+ --link /etc/foo/bar/baz/foo:/foo1:/foo2:/foo3 \ - --firstboot Makefile --firstboot-command 'echo "hello"' \ - --firstboot-install "minicom,inkscape" - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 7d91daf..3405c62 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -24,6 +24,7 @@ virt-builder - Build virtual machine images quickly - [--mkdir DIR] - [--write FILE:CONTENT] - [--upload FILE:DEST] -+ [--link TARGET:LINK[:LINK]] - [--edit FILE:EXPR] - [--delete FILE] [--scrub FILE] - [--run SCRIPT] [--run-command 'CMD ARGS ...'] -@@ -353,6 +354,13 @@ L. - - See also I<--update>. - -+=item B<--link TARGET:LINK> -+ -+=item B<--link TARGET:LINK[:LINK...]> -+ -+Create symbolic link(s) in the guest, starting at C and -+pointing at C. -+ - =item B<-l> - - =item B<--list> -@@ -920,6 +928,10 @@ Files are deleted (I<--delete>, I<--scrub>). - - =item * - -+Symbolic links are created (I<--link). -+ -+=item * -+ - Firstboot scripts are installed (I<--firstboot>, - I<--firstboot-command>, I<--firstboot-install>). - --- -1.8.4.2 - diff --git a/0045-builder-Document-how-to-change-the-language-locale-o.patch b/0045-builder-Document-how-to-change-the-language-locale-o.patch new file mode 100644 index 0000000..0336459 --- /dev/null +++ b/0045-builder-Document-how-to-change-the-language-locale-o.patch @@ -0,0 +1,55 @@ +From d1660ab9ac97a4b173ee1a9dc5ce55a4144a00ff Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 19:48:28 +0000 +Subject: [PATCH] builder: Document how to change the language/locale of a new + guest. + +(cherry picked from commit 7e8ad13e863a5c87e3da47288bcecdb88ca0e4cb) +--- + builder/virt-builder.pod | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 0fd865f..4a86fd1 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -831,6 +831,36 @@ I<--edit> options. For example: + + See L. + ++=head2 LANGUAGE ++ ++Most Linux distributions support multiple locale settings so that you ++can have guest messages printed in another language such as Russian. ++However there is no single setting which controls this, since extra ++packages may need to be installed to support console and X fonts and ++keyboard input methods. The packages required, and their ++configuration is highly distro-specific, and it is outside the scope ++of virt-builder to do this. ++ ++=begin comment ++ ++This section contains examples for some common Linux distributions. ++ ++=head3 Setting Japanese in Fedora 20 ++ ++XXX This does not work. ++ ++ virt-builder fedora-20 \ ++ --size 20G \ ++ --update \ ++ --install @gnome-desktop --install @japanese-support \ ++ --firstboot-command 'localectl set-locale LANG=ja_JP.utf8' \ ++ --firstboot-command 'localectl set-keymap jp' \ ++ --firstboot-command 'systemctl enable gdm.service' \ ++ --firstboot-command 'systemctl start gdm.service' \ ++ --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target ++ ++=end comment ++ + =head2 LOG FILE + + Scripts and package installation that runs at build time (I<--run>, +-- +1.8.4.2 + diff --git a/0046-builder-Document-how-to-change-the-language-locale-o.patch b/0046-builder-Document-how-to-change-the-language-locale-o.patch deleted file mode 100644 index cfc21c7..0000000 --- a/0046-builder-Document-how-to-change-the-language-locale-o.patch +++ /dev/null @@ -1,55 +0,0 @@ -From fd4138919f32d4cc0b9d3fa0007b8c327afff29a Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 10 Jan 2014 19:48:28 +0000 -Subject: [PATCH] builder: Document how to change the language/locale of a new - guest. - -(cherry picked from commit 7e8ad13e863a5c87e3da47288bcecdb88ca0e4cb) ---- - builder/virt-builder.pod | 30 ++++++++++++++++++++++++++++++ - 1 file changed, 30 insertions(+) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 3405c62..6d1e25f 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -831,6 +831,36 @@ I<--edit> options. For example: - - See L. - -+=head2 LANGUAGE -+ -+Most Linux distributions support multiple locale settings so that you -+can have guest messages printed in another language such as Russian. -+However there is no single setting which controls this, since extra -+packages may need to be installed to support console and X fonts and -+keyboard input methods. The packages required, and their -+configuration is highly distro-specific, and it is outside the scope -+of virt-builder to do this. -+ -+=begin comment -+ -+This section contains examples for some common Linux distributions. -+ -+=head3 Setting Japanese in Fedora 20 -+ -+XXX This does not work. -+ -+ virt-builder fedora-20 \ -+ --size 20G \ -+ --update \ -+ --install @gnome-desktop --install @japanese-support \ -+ --firstboot-command 'localectl set-locale LANG=ja_JP.utf8' \ -+ --firstboot-command 'localectl set-keymap jp' \ -+ --firstboot-command 'systemctl enable gdm.service' \ -+ --firstboot-command 'systemctl start gdm.service' \ -+ --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target -+ -+=end comment -+ - =head2 LOG FILE - - Scripts and package installation that runs at build time (I<--run>, --- -1.8.4.2 - diff --git a/0046-builder-Document-how-to-set-up-local-mirrors-for-per.patch b/0046-builder-Document-how-to-set-up-local-mirrors-for-per.patch new file mode 100644 index 0000000..cd658ec --- /dev/null +++ b/0046-builder-Document-how-to-set-up-local-mirrors-for-per.patch @@ -0,0 +1,86 @@ +From bfa71840cebd0af88e727207268bf00cdf31dc5f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 19:49:02 +0000 +Subject: [PATCH] builder: Document how to set up local mirrors for performance + and reliability. + +(cherry picked from commit f40e44c2f97a7fa17e6078d958ae2779b7ca83c7) +--- + builder/virt-builder.pod | 52 +++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 49 insertions(+), 3 deletions(-) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 4a86fd1..e539f2d 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -1431,6 +1431,8 @@ The index is always encoded in UTF-8. + + =head2 CACHING + ++=head3 Caching templates ++ + Since the templates are usually very large, downloaded templates are + cached in the user's home directory. + +@@ -1455,11 +1457,55 @@ To disable the template cache, use I<--no-cache>. + Only templates are cached. The index and detached digital signatures + are not cached. + ++=head3 Caching packages ++ + Virt-builder uses L to download files and it also uses the + current C (etc) settings when installing packages +-(I<--install>, I<--update>). You may therefore want to set those +-environment variables in order to maximize the amount of local caching +-that happens. See L and L. ++(I<--install>, I<--update>). ++ ++You may therefore want to set those environment variables in order to ++maximize the amount of local caching that happens. See ++L and L. ++ ++=head3 Local mirrors ++ ++To increase both speed and reliability of installing packages, you can ++set up a local mirror of the target distribution, and point the guest ++package manager at that. ++ ++Because of the order in which each phase of installation happens, you ++cannot use I<--write> (to point the package manager at a repo) ++followed by I<--install> (to install from that repo). The I<--write> ++and I<--install> steps run in the opposite order, regardless of their ++order on the command line. You have to do this using I<--run-command> ++instead of I<--install>. ++ ++=head4 Using a local mirror with Fedora ++ ++To install a Fedora guest using a local mirror: ++ ++ virt-builder fedora 20 \ ++ --edit '/etc/yum.repos.d/fedora.repo: ++ s{.*baseurl=.*}{baseurl=http://example.com/mirror/}; ++ s{.*metalink=.*}{}; ++ ' \ ++ --edit '/etc/yum.repos.d/fedora-updates.repo: ++ s{.*baseurl=.*}{baseurl=http://example.com/mirror-updates/}; ++ s{.*metalink=.*}{}; ++ ' \ ++ --run-command 'yum -y update' \ ++ --run-command 'yum -y install pkg1 pkg2 ...' ++ ++=head4 Using a local mirror with Debian ++ ++Assuming that you are using C to mirror the repository, you ++should create a new C file to point to your proxy (see ++L) and then do: ++ ++ virt-builder fedora 20 \ ++ --upload sources.list:/etc/apt/sources.list \ ++ --run-command 'apt-get -y update' \ ++ --run-command 'apt-get -y install pkg1 pkg2 ...' + + =head2 DIGITAL SIGNATURES + +-- +1.8.4.2 + diff --git a/0047-builder-Document-how-to-set-Japanese-language-suppor.patch b/0047-builder-Document-how-to-set-Japanese-language-suppor.patch new file mode 100644 index 0000000..f706009 --- /dev/null +++ b/0047-builder-Document-how-to-set-Japanese-language-suppor.patch @@ -0,0 +1,59 @@ +From 91c1ec932cbf768145c902a4da520d33c727ba16 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sun, 12 Jan 2014 17:06:02 +0000 +Subject: [PATCH] builder: Document how to set Japanese language support in + Fedora 20. + +This updates/fixes commit 7e8ad13e863a5c87e3da47288bcecdb88ca0e4cb. + +(cherry picked from commit fcdea83c6b9dc94a565a819a9f42e0c4721166e8) +--- + builder/virt-builder.pod | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index e539f2d..38e26a8 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -835,31 +835,27 @@ See L. + + Most Linux distributions support multiple locale settings so that you + can have guest messages printed in another language such as Russian. ++ + However there is no single setting which controls this, since extra +-packages may need to be installed to support console and X fonts and ++packages may need to be installed to support console and X fonts, and + keyboard input methods. The packages required, and their + configuration is highly distro-specific, and it is outside the scope + of virt-builder to do this. + +-=begin comment +- + This section contains examples for some common Linux distributions. + + =head3 Setting Japanese in Fedora 20 + +-XXX This does not work. +- + virt-builder fedora-20 \ + --size 20G \ + --update \ +- --install @gnome-desktop --install @japanese-support \ ++ --install @japanese-support \ ++ --install @xfce \ ++ --install xorg-x11-server-Xorg,xorg-x11-drivers,rsyslog \ ++ --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target \ + --firstboot-command 'localectl set-locale LANG=ja_JP.utf8' \ + --firstboot-command 'localectl set-keymap jp' \ +- --firstboot-command 'systemctl enable gdm.service' \ +- --firstboot-command 'systemctl start gdm.service' \ +- --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target +- +-=end comment ++ --firstboot-command 'systemctl isolate graphical.target' + + =head2 LOG FILE + +-- +1.8.4.2 + diff --git a/0047-builder-Document-how-to-set-up-local-mirrors-for-per.patch b/0047-builder-Document-how-to-set-up-local-mirrors-for-per.patch deleted file mode 100644 index 612524d..0000000 --- a/0047-builder-Document-how-to-set-up-local-mirrors-for-per.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 9170c90b419162ba3c234d83cb679c3dba801152 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Fri, 10 Jan 2014 19:49:02 +0000 -Subject: [PATCH] builder: Document how to set up local mirrors for performance - and reliability. - -(cherry picked from commit f40e44c2f97a7fa17e6078d958ae2779b7ca83c7) ---- - builder/virt-builder.pod | 52 +++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 49 insertions(+), 3 deletions(-) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 6d1e25f..2ee6db9 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -1431,6 +1431,8 @@ The index is always encoded in UTF-8. - - =head2 CACHING - -+=head3 Caching templates -+ - Since the templates are usually very large, downloaded templates are - cached in the user's home directory. - -@@ -1455,11 +1457,55 @@ To disable the template cache, use I<--no-cache>. - Only templates are cached. The index and detached digital signatures - are not cached. - -+=head3 Caching packages -+ - Virt-builder uses L to download files and it also uses the - current C (etc) settings when installing packages --(I<--install>, I<--update>). You may therefore want to set those --environment variables in order to maximize the amount of local caching --that happens. See L and L. -+(I<--install>, I<--update>). -+ -+You may therefore want to set those environment variables in order to -+maximize the amount of local caching that happens. See -+L and L. -+ -+=head3 Local mirrors -+ -+To increase both speed and reliability of installing packages, you can -+set up a local mirror of the target distribution, and point the guest -+package manager at that. -+ -+Because of the order in which each phase of installation happens, you -+cannot use I<--write> (to point the package manager at a repo) -+followed by I<--install> (to install from that repo). The I<--write> -+and I<--install> steps run in the opposite order, regardless of their -+order on the command line. You have to do this using I<--run-command> -+instead of I<--install>. -+ -+=head4 Using a local mirror with Fedora -+ -+To install a Fedora guest using a local mirror: -+ -+ virt-builder fedora 20 \ -+ --edit '/etc/yum.repos.d/fedora.repo: -+ s{.*baseurl=.*}{baseurl=http://example.com/mirror/}; -+ s{.*metalink=.*}{}; -+ ' \ -+ --edit '/etc/yum.repos.d/fedora-updates.repo: -+ s{.*baseurl=.*}{baseurl=http://example.com/mirror-updates/}; -+ s{.*metalink=.*}{}; -+ ' \ -+ --run-command 'yum -y update' \ -+ --run-command 'yum -y install pkg1 pkg2 ...' -+ -+=head4 Using a local mirror with Debian -+ -+Assuming that you are using C to mirror the repository, you -+should create a new C file to point to your proxy (see -+L) and then do: -+ -+ virt-builder fedora 20 \ -+ --upload sources.list:/etc/apt/sources.list \ -+ --run-command 'apt-get -y update' \ -+ --run-command 'apt-get -y install pkg1 pkg2 ...' - - =head2 DIGITAL SIGNATURES - --- -1.8.4.2 - diff --git a/0048-builder-Document-how-to-set-Japanese-language-suppor.patch b/0048-builder-Document-how-to-set-Japanese-language-suppor.patch deleted file mode 100644 index dd6a7b0..0000000 --- a/0048-builder-Document-how-to-set-Japanese-language-suppor.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 1db9c09f74eea29cc7b23469b3c711ff623744c3 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sun, 12 Jan 2014 17:06:02 +0000 -Subject: [PATCH] builder: Document how to set Japanese language support in - Fedora 20. - -This updates/fixes commit 7e8ad13e863a5c87e3da47288bcecdb88ca0e4cb. - -(cherry picked from commit fcdea83c6b9dc94a565a819a9f42e0c4721166e8) ---- - builder/virt-builder.pod | 18 +++++++----------- - 1 file changed, 7 insertions(+), 11 deletions(-) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 2ee6db9..4f57d20 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -835,31 +835,27 @@ See L. - - Most Linux distributions support multiple locale settings so that you - can have guest messages printed in another language such as Russian. -+ - However there is no single setting which controls this, since extra --packages may need to be installed to support console and X fonts and -+packages may need to be installed to support console and X fonts, and - keyboard input methods. The packages required, and their - configuration is highly distro-specific, and it is outside the scope - of virt-builder to do this. - --=begin comment -- - This section contains examples for some common Linux distributions. - - =head3 Setting Japanese in Fedora 20 - --XXX This does not work. -- - virt-builder fedora-20 \ - --size 20G \ - --update \ -- --install @gnome-desktop --install @japanese-support \ -+ --install @japanese-support \ -+ --install @xfce \ -+ --install xorg-x11-server-Xorg,xorg-x11-drivers,rsyslog \ -+ --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target \ - --firstboot-command 'localectl set-locale LANG=ja_JP.utf8' \ - --firstboot-command 'localectl set-keymap jp' \ -- --firstboot-command 'systemctl enable gdm.service' \ -- --firstboot-command 'systemctl start gdm.service' \ -- --link /usr/lib/systemd/system/graphical.target:/etc/systemd/system/default.target -- --=end comment -+ --firstboot-command 'systemctl isolate graphical.target' - - =head2 LOG FILE - --- -1.8.4.2 - diff --git a/0048-builder-Fix-virt-builder-test.patch b/0048-builder-Fix-virt-builder-test.patch new file mode 100644 index 0000000..03df79a --- /dev/null +++ b/0048-builder-Fix-virt-builder-test.patch @@ -0,0 +1,40 @@ +From b0c988b0d9cb0bc176a673ae96a0e717e58f2d5f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Sun, 12 Jan 2014 17:49:48 +0000 +Subject: [PATCH] builder: Fix virt-builder test. + +Add Europe/London timezone to phony Fedora guest. + +This fixes commit dd1bfea513658368afd3728e0c5bf8ab6041cd1f. + +(cherry picked from commit 7500ae3f75f4650c18f2a8433c6b5edcca6e88a6) +--- + tests/guests/guest-aux/make-fedora-img.pl | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/tests/guests/guest-aux/make-fedora-img.pl b/tests/guests/guest-aux/make-fedora-img.pl +index 7c96eb8..0537bd2 100755 +--- a/tests/guests/guest-aux/make-fedora-img.pl ++++ b/tests/guests/guest-aux/make-fedora-img.pl +@@ -1,6 +1,6 @@ + #!/usr/bin/perl + # libguestfs +-# Copyright (C) 2010-2012 Red Hat Inc. ++# Copyright (C) 2010-2014 Red Hat Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -201,6 +201,10 @@ $g->mkdir ('/bin'); + $g->mkdir ('/etc'); + $g->mkdir ('/etc/sysconfig'); + $g->mkdir ('/usr'); ++$g->mkdir ('/usr/share'); ++$g->mkdir ('/usr/share/zoneinfo'); ++$g->mkdir ('/usr/share/zoneinfo/Europe'); ++$g->touch ('/usr/share/zoneinfo/Europe/London'); + $g->mkdir_p ('/var/lib/rpm'); + $g->mkdir_p ('/var/log/journal'); + +-- +1.8.4.2 + diff --git a/0049-builder-Document-how-to-set-Japanese-in-Debian-7.patch b/0049-builder-Document-how-to-set-Japanese-in-Debian-7.patch new file mode 100644 index 0000000..2553452 --- /dev/null +++ b/0049-builder-Document-how-to-set-Japanese-in-Debian-7.patch @@ -0,0 +1,45 @@ +From 0124cc39c8c82e5862898503f8b3e3c591404bff Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 13 Jan 2014 16:19:51 +0000 +Subject: [PATCH] builder: Document how to set Japanese in Debian 7. + +(cherry picked from commit d885d6f6a97ee119fe1751df6f7d04844bfbf6be) +--- + builder/virt-builder.pod | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 38e26a8..ec41078 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -857,6 +857,27 @@ This section contains examples for some common Linux distributions. + --firstboot-command 'localectl set-keymap jp' \ + --firstboot-command 'systemctl isolate graphical.target' + ++=head3 Setting Japanese in Debian 7 (Wheezy) ++ ++Note that although this enables Japanese in the text console too, it ++is unlikely that you will see properly rendered Japanese there. ++However Japanese is properly rendered in X applications and terminals. ++ ++ pkgs=locales,xfce4,\ ++ ibus,ibus-anthy,\ ++ ttf-sazanami-gothic,ttf-sazanami-mincho,\ ++ fonts-takao-mincho,\ ++ xfonts-intl-japanese,xfonts-intl-japanese-big,\ ++ iceweasel-l10n-ja,manpages-ja ++ ++ virt-builder debian-7 \ ++ --size 20G \ ++ --install $pkgs \ ++ --edit '/etc/inittab: s,^#([1-9].*respawn.*/sbin/getty.*),$1,' \ ++ --edit '/etc/locale.gen: s,^#\s*ja,ja,' \ ++ --write '/etc/default/locale:LANG="ja_JP.UTF-8"' \ ++ --run-command "locale-gen" ++ + =head2 LOG FILE + + Scripts and package installation that runs at build time (I<--run>, +-- +1.8.4.2 + diff --git a/0049-builder-Fix-virt-builder-test.patch b/0049-builder-Fix-virt-builder-test.patch deleted file mode 100644 index 7343de7..0000000 --- a/0049-builder-Fix-virt-builder-test.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 43de2c5184fbc73ea6e2a9c0f057044a6d841c4b Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Sun, 12 Jan 2014 17:49:48 +0000 -Subject: [PATCH] builder: Fix virt-builder test. - -Add Europe/London timezone to phony Fedora guest. - -This fixes commit dd1bfea513658368afd3728e0c5bf8ab6041cd1f. - -(cherry picked from commit 7500ae3f75f4650c18f2a8433c6b5edcca6e88a6) ---- - tests/guests/guest-aux/make-fedora-img.pl | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/tests/guests/guest-aux/make-fedora-img.pl b/tests/guests/guest-aux/make-fedora-img.pl -index 7c96eb8..0537bd2 100755 ---- a/tests/guests/guest-aux/make-fedora-img.pl -+++ b/tests/guests/guest-aux/make-fedora-img.pl -@@ -1,6 +1,6 @@ - #!/usr/bin/perl - # libguestfs --# Copyright (C) 2010-2012 Red Hat Inc. -+# Copyright (C) 2010-2014 Red Hat Inc. - # - # This program is free software; you can redistribute it and/or modify - # it under the terms of the GNU General Public License as published by -@@ -201,6 +201,10 @@ $g->mkdir ('/bin'); - $g->mkdir ('/etc'); - $g->mkdir ('/etc/sysconfig'); - $g->mkdir ('/usr'); -+$g->mkdir ('/usr/share'); -+$g->mkdir ('/usr/share/zoneinfo'); -+$g->mkdir ('/usr/share/zoneinfo/Europe'); -+$g->touch ('/usr/share/zoneinfo/Europe/London'); - $g->mkdir_p ('/var/lib/rpm'); - $g->mkdir_p ('/var/log/journal'); - --- -1.8.4.2 - diff --git a/0050-builder-Add-no-delete-on-failure-option-to-aid-debug.patch b/0050-builder-Add-no-delete-on-failure-option-to-aid-debug.patch new file mode 100644 index 0000000..980650b --- /dev/null +++ b/0050-builder-Add-no-delete-on-failure-option-to-aid-debug.patch @@ -0,0 +1,122 @@ +From 1eb009accb06dde100b390ad1b1aaabf12fe9927 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 13 Jan 2014 20:29:50 +0000 +Subject: [PATCH] builder: Add --no-delete-on-failure option to aid debugging. + +This lets you debug failures in virt-builder, especially when scripts +or installing packages fails. + +(cherry picked from commit 5136de98e7f4bd7a967da5b3ede72c729aa7805e) +--- + builder/builder.ml | 9 +++++---- + builder/cmdline.ml | 9 +++++++-- + builder/virt-builder.pod | 17 +++++++++++++++-- + 3 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 6105c75..79f82a2 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -38,8 +38,8 @@ let () = Random.self_init () + let main () = + (* Command line argument parsing - see cmdline.ml. *) + let mode, arg, +- attach, cache, check_signature, curl, debug, delete, edit, +- firstboot, run, format, gpg, hostname, install, list_long, links, ++ attach, cache, check_signature, curl, debug, delete, delete_on_failure, ++ edit, firstboot, run, format, gpg, hostname, install, list_long, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, +@@ -469,9 +469,10 @@ let main () = + ); + + (* Delete the output file before we finish. However don't delete it +- * if it's block device. ++ * if it's block device, or if --no-delete-on-failure is set. + *) +- let delete_output_file = ref (not output_is_block_dev) in ++ let delete_output_file = ++ ref (delete_on_failure && not output_is_block_dev) in + let delete_file () = + if !delete_output_file then + try unlink output_filename with _ -> () +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index 58e8a6b..67b142a 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -72,6 +72,8 @@ let parse_cmdline () = + let delete = ref [] in + let add_delete s = delete := s :: !delete in + ++ let delete_on_failure = ref true in ++ + let edit = ref [] in + let add_edit arg = + let i = +@@ -235,6 +237,8 @@ let parse_cmdline () = + "--delete", Arg.String add_delete, "name" ^ " " ^ s_"Delete a file or dir"; + "--delete-cache", Arg.Unit delete_cache_mode, + " " ^ s_"Delete the template cache"; ++ "--no-delete-on-failure", Arg.Clear delete_on_failure, ++ " " ^ s_"Don't delete output file on failure"; + "--edit", Arg.String add_edit, "file:expr" ^ " " ^ s_"Edit file with Perl expr"; + "--fingerprint", Arg.String add_fingerprint, + "AAAA.." ^ " " ^ s_"Fingerprint of valid signing key"; +@@ -316,6 +320,7 @@ read the man page virt-builder(1). + let curl = !curl in + let debug = !debug in + let delete = List.rev !delete in ++ let delete_on_failure = !delete_on_failure in + let edit = List.rev !edit in + let fingerprints = List.rev !fingerprints in + let firstboot = List.rev !firstboot in +@@ -437,8 +442,8 @@ read the man page virt-builder(1). + List.combine sources fingerprints in + + mode, arg, +- attach, cache, check_signature, curl, debug, delete, edit, +- firstboot, run, format, gpg, hostname, install, list_long, links, ++ attach, cache, check_signature, curl, debug, delete, delete_on_failure, ++ edit, firstboot, run, format, gpg, hostname, install, list_long, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index ec41078..f3ddce5 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -250,6 +250,15 @@ See also: I<--upload>, I<--scrub>. + + Delete the template cache. See L. + ++=item B<--no-delete-on-failure> ++ ++Don't delete the output file on failure to build. You can use this to ++debug failures to run scripts. See L for ways to ++debug images. ++ ++The default is to delete the output file if virt-builder fails (or, ++for example, some script that it runs fails). ++ + =item B<--edit> FILE:EXPR + + Edit C using the Perl expression C. +@@ -1065,8 +1074,12 @@ chosen. It will be C unless the I<--format> option was used. + + =head2 DEBUGGING BUILDS + +-If virt-builder fails with an error, then enable debugging (I<-v>) and +-report a bug (see L below). ++If virt-builder itself fails, then enable debugging (I<-v>) and report ++a bug (see L below). ++ ++If virt-builder fails because some script or package it is installing ++fails, try using I<--no-delete-on-failure> to preserve the output ++file, and continue reading this section. + + If virt-builder is successful but the image doesn't work, here are + some things to try: +-- +1.8.4.2 + diff --git a/0050-builder-Document-how-to-set-Japanese-in-Debian-7.patch b/0050-builder-Document-how-to-set-Japanese-in-Debian-7.patch deleted file mode 100644 index ead863a..0000000 --- a/0050-builder-Document-how-to-set-Japanese-in-Debian-7.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 510ff9fec3653b54663749adc1dd653f170ba328 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 16:19:51 +0000 -Subject: [PATCH] builder: Document how to set Japanese in Debian 7. - -(cherry picked from commit d885d6f6a97ee119fe1751df6f7d04844bfbf6be) ---- - builder/virt-builder.pod | 21 +++++++++++++++++++++ - 1 file changed, 21 insertions(+) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 4f57d20..3972391 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -857,6 +857,27 @@ This section contains examples for some common Linux distributions. - --firstboot-command 'localectl set-keymap jp' \ - --firstboot-command 'systemctl isolate graphical.target' - -+=head3 Setting Japanese in Debian 7 (Wheezy) -+ -+Note that although this enables Japanese in the text console too, it -+is unlikely that you will see properly rendered Japanese there. -+However Japanese is properly rendered in X applications and terminals. -+ -+ pkgs=locales,xfce4,\ -+ ibus,ibus-anthy,\ -+ ttf-sazanami-gothic,ttf-sazanami-mincho,\ -+ fonts-takao-mincho,\ -+ xfonts-intl-japanese,xfonts-intl-japanese-big,\ -+ iceweasel-l10n-ja,manpages-ja -+ -+ virt-builder debian-7 \ -+ --size 20G \ -+ --install $pkgs \ -+ --edit '/etc/inittab: s,^#([1-9].*respawn.*/sbin/getty.*),$1,' \ -+ --edit '/etc/locale.gen: s,^#\s*ja,ja,' \ -+ --write '/etc/default/locale:LANG="ja_JP.UTF-8"' \ -+ --run-command "locale-gen" -+ - =head2 LOG FILE - - Scripts and package installation that runs at build time (I<--run>, --- -1.8.4.2 - diff --git a/0051-builder-Add-no-delete-on-failure-option-to-aid-debug.patch b/0051-builder-Add-no-delete-on-failure-option-to-aid-debug.patch deleted file mode 100644 index 93b475a..0000000 --- a/0051-builder-Add-no-delete-on-failure-option-to-aid-debug.patch +++ /dev/null @@ -1,122 +0,0 @@ -From 274c1063ef59156570196b55e1549cbecf216c38 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 20:29:50 +0000 -Subject: [PATCH] builder: Add --no-delete-on-failure option to aid debugging. - -This lets you debug failures in virt-builder, especially when scripts -or installing packages fails. - -(cherry picked from commit 5136de98e7f4bd7a967da5b3ede72c729aa7805e) ---- - builder/builder.ml | 9 +++++---- - builder/cmdline.ml | 9 +++++++-- - builder/virt-builder.pod | 17 +++++++++++++++-- - 3 files changed, 27 insertions(+), 8 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 16ffa7a..0160818 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -36,8 +36,8 @@ let prog = Filename.basename Sys.executable_name - let main () = - (* Command line argument parsing - see cmdline.ml. *) - let mode, arg, -- attach, cache, check_signature, curl, debug, delete, edit, -- firstboot, run, format, gpg, hostname, install, list_long, links, -+ attach, cache, check_signature, curl, debug, delete, delete_on_failure, -+ edit, firstboot, run, format, gpg, hostname, install, list_long, links, - memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, -@@ -467,9 +467,10 @@ let main () = - ); - - (* Delete the output file before we finish. However don't delete it -- * if it's block device. -+ * if it's block device, or if --no-delete-on-failure is set. - *) -- let delete_output_file = ref (not output_is_block_dev) in -+ let delete_output_file = -+ ref (delete_on_failure && not output_is_block_dev) in - let delete_file () = - if !delete_output_file then - try unlink output_filename with _ -> () -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index 58e8a6b..67b142a 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -72,6 +72,8 @@ let parse_cmdline () = - let delete = ref [] in - let add_delete s = delete := s :: !delete in - -+ let delete_on_failure = ref true in -+ - let edit = ref [] in - let add_edit arg = - let i = -@@ -235,6 +237,8 @@ let parse_cmdline () = - "--delete", Arg.String add_delete, "name" ^ " " ^ s_"Delete a file or dir"; - "--delete-cache", Arg.Unit delete_cache_mode, - " " ^ s_"Delete the template cache"; -+ "--no-delete-on-failure", Arg.Clear delete_on_failure, -+ " " ^ s_"Don't delete output file on failure"; - "--edit", Arg.String add_edit, "file:expr" ^ " " ^ s_"Edit file with Perl expr"; - "--fingerprint", Arg.String add_fingerprint, - "AAAA.." ^ " " ^ s_"Fingerprint of valid signing key"; -@@ -316,6 +320,7 @@ read the man page virt-builder(1). - let curl = !curl in - let debug = !debug in - let delete = List.rev !delete in -+ let delete_on_failure = !delete_on_failure in - let edit = List.rev !edit in - let fingerprints = List.rev !fingerprints in - let firstboot = List.rev !firstboot in -@@ -437,8 +442,8 @@ read the man page virt-builder(1). - List.combine sources fingerprints in - - mode, arg, -- attach, cache, check_signature, curl, debug, delete, edit, -- firstboot, run, format, gpg, hostname, install, list_long, links, -+ attach, cache, check_signature, curl, debug, delete, delete_on_failure, -+ edit, firstboot, run, format, gpg, hostname, install, list_long, links, - memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 3972391..81db516 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -250,6 +250,15 @@ See also: I<--upload>, I<--scrub>. - - Delete the template cache. See L. - -+=item B<--no-delete-on-failure> -+ -+Don't delete the output file on failure to build. You can use this to -+debug failures to run scripts. See L for ways to -+debug images. -+ -+The default is to delete the output file if virt-builder fails (or, -+for example, some script that it runs fails). -+ - =item B<--edit> FILE:EXPR - - Edit C using the Perl expression C. -@@ -1065,8 +1074,12 @@ chosen. It will be C unless the I<--format> option was used. - - =head2 DEBUGGING BUILDS - --If virt-builder fails with an error, then enable debugging (I<-v>) and --report a bug (see L below). -+If virt-builder itself fails, then enable debugging (I<-v>) and report -+a bug (see L below). -+ -+If virt-builder fails because some script or package it is installing -+fails, try using I<--no-delete-on-failure> to preserve the output -+file, and continue reading this section. - - If virt-builder is successful but the image doesn't work, here are - some things to try: --- -1.8.4.2 - diff --git a/0051-builder-For-performance-recommend-using-the-no-sync-.patch b/0051-builder-For-performance-recommend-using-the-no-sync-.patch new file mode 100644 index 0000000..6f12ad3 --- /dev/null +++ b/0051-builder-For-performance-recommend-using-the-no-sync-.patch @@ -0,0 +1,30 @@ +From c6648611837833375447812ff97e34ad3d78930a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 13 Jan 2014 20:42:48 +0000 +Subject: [PATCH] builder: For performance, recommend using the --no-sync + option. + +(cherry picked from commit 69d9c8515c32dcc67e4ce752215e18eb811f8029) +--- + builder/virt-builder.pod | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index f3ddce5..0d9b33f 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -1634,6 +1634,11 @@ downloaded once. You can also try using a local package repository, + although this can be complex to set up and varies according to which + Linux distro you are trying to install. + ++=head3 Using I<--no-sync> ++ ++Use I<--no-sync>. However read the caveats in the L section ++above, since this can cause disk corruption if not used correctly. ++ + =head3 Skipping virt-resize + + Virt-builder can skip the virt-resize step under certain conditions. +-- +1.8.4.2 + diff --git a/0052-builder-For-performance-recommend-using-the-no-sync-.patch b/0052-builder-For-performance-recommend-using-the-no-sync-.patch deleted file mode 100644 index c72bd89..0000000 --- a/0052-builder-For-performance-recommend-using-the-no-sync-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From caaed7ea75b82f89aec818bf000fe476febe118f Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 20:42:48 +0000 -Subject: [PATCH] builder: For performance, recommend using the --no-sync - option. - -(cherry picked from commit 69d9c8515c32dcc67e4ce752215e18eb811f8029) ---- - builder/virt-builder.pod | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 81db516..9cbfbab 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -1616,6 +1616,11 @@ downloaded once. You can also try using a local package repository, - although this can be complex to set up and varies according to which - Linux distro you are trying to install. - -+=head3 Using I<--no-sync> -+ -+Use I<--no-sync>. However read the caveats in the L section -+above, since this can cause disk corruption if not used correctly. -+ - =head3 Skipping virt-resize - - Virt-builder can skip the virt-resize step under certain conditions. --- -1.8.4.2 - diff --git a/0052-builder-planner-Whitespace-change.patch b/0052-builder-planner-Whitespace-change.patch new file mode 100644 index 0000000..de00208 --- /dev/null +++ b/0052-builder-planner-Whitespace-change.patch @@ -0,0 +1,42 @@ +From bc6de5b386ff250b9f5f5f1d703e7493283514cd Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 13 Jan 2014 20:58:08 +0000 +Subject: [PATCH] builder: planner: Whitespace change. + +(cherry picked from commit e664739a578f31c3f97073e713f9f33d4eb62d8d) +--- + mllib/planner.ml | 3 ++- + mllib/planner.mli | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/mllib/planner.ml b/mllib/planner.ml +index 0121b84..9405dab 100644 +--- a/mllib/planner.ml ++++ b/mllib/planner.ml +@@ -23,7 +23,8 @@ type ('name, 'value) tags = ('name, 'value) tag list + type ('name, 'value, 'task) plan = + (('name, 'value) tags * 'task * ('name, 'value) tags) list + +-type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list ++type ('name, 'value, 'task) transitions_function = ++ ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list + + let plan ?(max_depth = 10) transitions itags (goal_must, goal_must_not) = + (* Do the given output tags match the finish condition? *) +diff --git a/mllib/planner.mli b/mllib/planner.mli +index 8c77acd..7a502fb 100644 +--- a/mllib/planner.mli ++++ b/mllib/planner.mli +@@ -48,7 +48,8 @@ type ('name, 'value) tags = ('name, 'value) tag list + type ('name, 'value, 'task) plan = + (('name, 'value) tags * 'task * ('name, 'value) tags) list + +-type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list ++type ('name, 'value, 'task) transitions_function = ++ ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list + + val plan : ?max_depth:int -> ('name, 'value, 'task) transitions_function -> ('name, 'value) tags -> ('name, 'value) tags * ('name, 'value) tags -> ('name, 'value, 'task) plan + (** Make a plan. +-- +1.8.4.2 + diff --git a/0053-builder-planner-Whitespace-change.patch b/0053-builder-planner-Whitespace-change.patch deleted file mode 100644 index 3eaedec..0000000 --- a/0053-builder-planner-Whitespace-change.patch +++ /dev/null @@ -1,42 +0,0 @@ -From f1690a36e0bf84d1ed2f85c209d4b0fd6c25f1a2 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 20:58:08 +0000 -Subject: [PATCH] builder: planner: Whitespace change. - -(cherry picked from commit e664739a578f31c3f97073e713f9f33d4eb62d8d) ---- - mllib/planner.ml | 3 ++- - mllib/planner.mli | 3 ++- - 2 files changed, 4 insertions(+), 2 deletions(-) - -diff --git a/mllib/planner.ml b/mllib/planner.ml -index 0121b84..9405dab 100644 ---- a/mllib/planner.ml -+++ b/mllib/planner.ml -@@ -23,7 +23,8 @@ type ('name, 'value) tags = ('name, 'value) tag list - type ('name, 'value, 'task) plan = - (('name, 'value) tags * 'task * ('name, 'value) tags) list - --type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list -+type ('name, 'value, 'task) transitions_function = -+ ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list - - let plan ?(max_depth = 10) transitions itags (goal_must, goal_must_not) = - (* Do the given output tags match the finish condition? *) -diff --git a/mllib/planner.mli b/mllib/planner.mli -index 8c77acd..7a502fb 100644 ---- a/mllib/planner.mli -+++ b/mllib/planner.mli -@@ -48,7 +48,8 @@ type ('name, 'value) tags = ('name, 'value) tag list - type ('name, 'value, 'task) plan = - (('name, 'value) tags * 'task * ('name, 'value) tags) list - --type ('name, 'value, 'task) transitions_function = ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list -+type ('name, 'value, 'task) transitions_function = -+ ('name, 'value) tags -> ('task * int * ('name, 'value) tags) list - - val plan : ?max_depth:int -> ('name, 'value, 'task) transitions_function -> ('name, 'value) tags -> ('name, 'value) tags * ('name, 'value) tags -> ('name, 'value, 'task) plan - (** Make a plan. --- -1.8.4.2 - diff --git a/0053-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch b/0053-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch new file mode 100644 index 0000000..70f7bb2 --- /dev/null +++ b/0053-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch @@ -0,0 +1,142 @@ +From 4769fd8c53a4a95313125995b36f65cc80facfdf Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 9 Jan 2014 18:59:19 +0100 +Subject: [PATCH] daemon: xattr: simplify the enabling of the linuxxattrs + features + +Instead of enable them when having one of the two headers for it but +still checking for the HAVE_* availability of each *xattr() function +used, just enable the linuxxattrs as a whole when having any of the +needed headers (like before) and all the needed functions. + +This might cause the linuxxattrs to not be available anymore on systems +without the whole set of *xattr() functions implemented, but OTOH it +simplifies the xattr.c implementations. + +(cherry picked from commit 7630a7bbbdceee8e6aad08511e752f5fcb273416) +--- + daemon/xattr.c | 49 +++++++++++-------------------------------------- + 1 file changed, 11 insertions(+), 38 deletions(-) + +diff --git a/daemon/xattr.c b/daemon/xattr.c +index 7004566..2f642db 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -27,7 +27,15 @@ + #include "actions.h" + #include "optgroups.h" + +-#if defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) ++#if (defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)) && \ ++ defined(HAVE_LISTXATTR) && defined(HAVE_LLISTXATTR) && \ ++ defined(HAVE_GETXATTR) && defined(HAVE_LGETXATTR) && \ ++ defined(HAVE_REMOVEXATTR) && defined(HAVE_LREMOVEXATTR) && \ ++ defined(HAVE_SETXATTR) && defined(HAVE_LSETXATTR) ++# define HAVE_LINUX_XATTRS ++#endif ++ ++#ifdef HAVE_LINUX_XATTRS + + # ifdef HAVE_ATTR_XATTR_H + # include +@@ -50,67 +58,37 @@ static int _removexattr (const char *xattr, const char *path, int (*removexattr) + guestfs_int_xattr_list * + do_getxattrs (const char *path) + { +-#if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR) + return getxattrs (path, listxattr, getxattr); +-#else +- reply_with_error ("no support for listxattr and getxattr"); +- return NULL; +-#endif + } + + guestfs_int_xattr_list * + do_lgetxattrs (const char *path) + { +-#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) + return getxattrs (path, llistxattr, lgetxattr); +-#else +- reply_with_error ("no support for llistxattr and lgetxattr"); +- return NULL; +-#endif + } + + int + do_setxattr (const char *xattr, const char *val, int vallen, const char *path) + { +-#if defined(HAVE_SETXATTR) + return _setxattr (xattr, val, vallen, path, setxattr); +-#else +- reply_with_error ("no support for setxattr"); +- return -1; +-#endif + } + + int + do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path) + { +-#if defined(HAVE_LSETXATTR) + return _setxattr (xattr, val, vallen, path, lsetxattr); +-#else +- reply_with_error ("no support for lsetxattr"); +- return -1; +-#endif + } + + int + do_removexattr (const char *xattr, const char *path) + { +-#if defined(HAVE_REMOVEXATTR) + return _removexattr (xattr, path, removexattr); +-#else +- reply_with_error ("no support for removexattr"); +- return -1; +-#endif + } + + int + do_lremovexattr (const char *xattr, const char *path) + { +-#if defined(HAVE_LREMOVEXATTR) + return _removexattr (xattr, path, lremovexattr); +-#else +- reply_with_error ("no support for lremovexattr"); +- return -1; +-#endif + } + + static guestfs_int_xattr_list * +@@ -262,7 +240,6 @@ _removexattr (const char *xattr, const char *path, + guestfs_int_xattr_list * + do_internal_lxattrlist (const char *path, char *const *names) + { +-#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) + guestfs_int_xattr_list *ret = NULL; + size_t i, j; + size_t k, m, nr_attrs; +@@ -425,10 +402,6 @@ do_internal_lxattrlist (const char *path, char *const *names) + free (ret); + } + return NULL; +-#else +- reply_with_error ("no support for llistxattr and lgetxattr"); +- return NULL; +-#endif + } + + char * +@@ -527,8 +500,8 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r) + return buf; /* caller frees */ + } + +-#else /* no xattr.h */ ++#else /* no HAVE_LINUX_XATTRS */ + + OPTGROUP_LINUXXATTRS_NOT_AVAILABLE + +-#endif /* no xattr.h */ ++#endif /* no HAVE_LINUX_XATTRS */ +-- +1.8.4.2 + diff --git a/0054-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch b/0054-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch new file mode 100644 index 0000000..8185244 --- /dev/null +++ b/0054-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch @@ -0,0 +1,108 @@ +From bc846d70f3eab0752c0c49de20751daa5bca613c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Fri, 10 Jan 2014 15:10:03 +0100 +Subject: [PATCH] daemon: xattr: move the listxattrs code in an own function + +Move in an own function the code that does the (l)listxattrs allocating +the buffer of the right legth, as it will be useful later. + +No functional changes, just code motion. + +(cherry picked from commit 59d8cf62cb67688cea42a985029adea874f0b7a2) +--- + daemon/xattr.c | 64 ++++++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 44 insertions(+), 20 deletions(-) + +diff --git a/daemon/xattr.c b/daemon/xattr.c +index 2f642db..768f780 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -54,6 +54,7 @@ optgroup_linuxxattrs_available (void) + static guestfs_int_xattr_list *getxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size)); + static int _setxattr (const char *xattr, const char *val, int vallen, const char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags)); + static int _removexattr (const char *xattr, const char *path, int (*removexattr) (const char *path, const char *name)); ++static char *_listxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t *size); + + guestfs_int_xattr_list * + do_getxattrs (const char *path) +@@ -102,27 +103,10 @@ getxattrs (const char *path, + size_t i, j; + guestfs_int_xattr_list *r = NULL; + +- CHROOT_IN; +- len = listxattr (path, NULL, 0); +- CHROOT_OUT; +- if (len == -1) { +- reply_with_perror ("listxattr: %s", path); ++ buf = _listxattrs (path, listxattr, &len); ++ if (buf == NULL) ++ /* _listxattrs issues reply_with_perror already. */ + goto error; +- } +- +- buf = malloc (len); +- if (buf == NULL) { +- reply_with_perror ("malloc"); +- goto error; +- } +- +- CHROOT_IN; +- len = listxattr (path, buf, len); +- CHROOT_OUT; +- if (len == -1) { +- reply_with_perror ("listxattr: %s", path); +- goto error; +- } + + r = calloc (1, sizeof (*r)); + if (r == NULL) { +@@ -237,6 +221,46 @@ _removexattr (const char *xattr, const char *path, + return 0; + } + ++static char * ++_listxattrs (const char *path, ++ ssize_t (*listxattr) (const char *path, char *list, size_t size), ++ ssize_t *size) ++{ ++ int r; ++ char *buf = NULL; ++ ssize_t len; ++ ++ CHROOT_IN; ++ len = listxattr (path, NULL, 0); ++ CHROOT_OUT; ++ if (len == -1) { ++ reply_with_perror ("listxattr: %s", path); ++ goto error; ++ } ++ ++ buf = malloc (len); ++ if (buf == NULL) { ++ reply_with_perror ("malloc"); ++ goto error; ++ } ++ ++ CHROOT_IN; ++ len = listxattr (path, buf, len); ++ CHROOT_OUT; ++ if (len == -1) { ++ reply_with_perror ("listxattr: %s", path); ++ goto error; ++ } ++ ++ if (size) ++ *size = len; ++ return buf; ++ ++ error: ++ free (buf); ++ return NULL; ++} ++ + guestfs_int_xattr_list * + do_internal_lxattrlist (const char *path, char *const *names) + { +-- +1.8.4.2 + diff --git a/0054-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch b/0054-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch deleted file mode 100644 index 1800f5a..0000000 --- a/0054-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch +++ /dev/null @@ -1,142 +0,0 @@ -From aa4b2af3d6b1936b2fdd37290a6db4262ed115d0 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 9 Jan 2014 18:59:19 +0100 -Subject: [PATCH] daemon: xattr: simplify the enabling of the linuxxattrs - features - -Instead of enable them when having one of the two headers for it but -still checking for the HAVE_* availability of each *xattr() function -used, just enable the linuxxattrs as a whole when having any of the -needed headers (like before) and all the needed functions. - -This might cause the linuxxattrs to not be available anymore on systems -without the whole set of *xattr() functions implemented, but OTOH it -simplifies the xattr.c implementations. - -(cherry picked from commit 7630a7bbbdceee8e6aad08511e752f5fcb273416) ---- - daemon/xattr.c | 49 +++++++++++-------------------------------------- - 1 file changed, 11 insertions(+), 38 deletions(-) - -diff --git a/daemon/xattr.c b/daemon/xattr.c -index 7004566..2f642db 100644 ---- a/daemon/xattr.c -+++ b/daemon/xattr.c -@@ -27,7 +27,15 @@ - #include "actions.h" - #include "optgroups.h" - --#if defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H) -+#if (defined(HAVE_ATTR_XATTR_H) || defined(HAVE_SYS_XATTR_H)) && \ -+ defined(HAVE_LISTXATTR) && defined(HAVE_LLISTXATTR) && \ -+ defined(HAVE_GETXATTR) && defined(HAVE_LGETXATTR) && \ -+ defined(HAVE_REMOVEXATTR) && defined(HAVE_LREMOVEXATTR) && \ -+ defined(HAVE_SETXATTR) && defined(HAVE_LSETXATTR) -+# define HAVE_LINUX_XATTRS -+#endif -+ -+#ifdef HAVE_LINUX_XATTRS - - # ifdef HAVE_ATTR_XATTR_H - # include -@@ -50,67 +58,37 @@ static int _removexattr (const char *xattr, const char *path, int (*removexattr) - guestfs_int_xattr_list * - do_getxattrs (const char *path) - { --#if defined(HAVE_LISTXATTR) && defined(HAVE_GETXATTR) - return getxattrs (path, listxattr, getxattr); --#else -- reply_with_error ("no support for listxattr and getxattr"); -- return NULL; --#endif - } - - guestfs_int_xattr_list * - do_lgetxattrs (const char *path) - { --#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) - return getxattrs (path, llistxattr, lgetxattr); --#else -- reply_with_error ("no support for llistxattr and lgetxattr"); -- return NULL; --#endif - } - - int - do_setxattr (const char *xattr, const char *val, int vallen, const char *path) - { --#if defined(HAVE_SETXATTR) - return _setxattr (xattr, val, vallen, path, setxattr); --#else -- reply_with_error ("no support for setxattr"); -- return -1; --#endif - } - - int - do_lsetxattr (const char *xattr, const char *val, int vallen, const char *path) - { --#if defined(HAVE_LSETXATTR) - return _setxattr (xattr, val, vallen, path, lsetxattr); --#else -- reply_with_error ("no support for lsetxattr"); -- return -1; --#endif - } - - int - do_removexattr (const char *xattr, const char *path) - { --#if defined(HAVE_REMOVEXATTR) - return _removexattr (xattr, path, removexattr); --#else -- reply_with_error ("no support for removexattr"); -- return -1; --#endif - } - - int - do_lremovexattr (const char *xattr, const char *path) - { --#if defined(HAVE_LREMOVEXATTR) - return _removexattr (xattr, path, lremovexattr); --#else -- reply_with_error ("no support for lremovexattr"); -- return -1; --#endif - } - - static guestfs_int_xattr_list * -@@ -262,7 +240,6 @@ _removexattr (const char *xattr, const char *path, - guestfs_int_xattr_list * - do_internal_lxattrlist (const char *path, char *const *names) - { --#if defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) - guestfs_int_xattr_list *ret = NULL; - size_t i, j; - size_t k, m, nr_attrs; -@@ -425,10 +402,6 @@ do_internal_lxattrlist (const char *path, char *const *names) - free (ret); - } - return NULL; --#else -- reply_with_error ("no support for llistxattr and lgetxattr"); -- return NULL; --#endif - } - - char * -@@ -527,8 +500,8 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r) - return buf; /* caller frees */ - } - --#else /* no xattr.h */ -+#else /* no HAVE_LINUX_XATTRS */ - - OPTGROUP_LINUXXATTRS_NOT_AVAILABLE - --#endif /* no xattr.h */ -+#endif /* no HAVE_LINUX_XATTRS */ --- -1.8.4.2 - diff --git a/0055-daemon-xattr-Remove-unused-variable.patch b/0055-daemon-xattr-Remove-unused-variable.patch new file mode 100644 index 0000000..3702152 --- /dev/null +++ b/0055-daemon-xattr-Remove-unused-variable.patch @@ -0,0 +1,27 @@ +From 0d17b0b51b8f290941cfd2d80a4239d99134439a Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 10 Jan 2014 21:19:43 +0000 +Subject: [PATCH] daemon: xattr: Remove unused variable. + +Revealed by using ./configure --enable-gcc-warnings. + +(cherry picked from commit cea270de3be3ca3c2b2e6555418c4b4eb8da7509) +--- + daemon/xattr.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/daemon/xattr.c b/daemon/xattr.c +index 768f780..dc024d3 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -226,7 +226,6 @@ _listxattrs (const char *path, + ssize_t (*listxattr) (const char *path, char *list, size_t size), + ssize_t *size) + { +- int r; + char *buf = NULL; + ssize_t len; + +-- +1.8.4.2 + diff --git a/0055-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch b/0055-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch deleted file mode 100644 index 3980f02..0000000 --- a/0055-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 3451e68c1599bb3ebd9cfb2be37be81a3a6d7774 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Fri, 10 Jan 2014 15:10:03 +0100 -Subject: [PATCH] daemon: xattr: move the listxattrs code in an own function - -Move in an own function the code that does the (l)listxattrs allocating -the buffer of the right legth, as it will be useful later. - -No functional changes, just code motion. - -(cherry picked from commit 59d8cf62cb67688cea42a985029adea874f0b7a2) ---- - daemon/xattr.c | 64 ++++++++++++++++++++++++++++++++++++++++------------------ - 1 file changed, 44 insertions(+), 20 deletions(-) - -diff --git a/daemon/xattr.c b/daemon/xattr.c -index 2f642db..768f780 100644 ---- a/daemon/xattr.c -+++ b/daemon/xattr.c -@@ -54,6 +54,7 @@ optgroup_linuxxattrs_available (void) - static guestfs_int_xattr_list *getxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t (*getxattr) (const char *path, const char *name, void *value, size_t size)); - static int _setxattr (const char *xattr, const char *val, int vallen, const char *path, int (*setxattr) (const char *path, const char *name, const void *value, size_t size, int flags)); - static int _removexattr (const char *xattr, const char *path, int (*removexattr) (const char *path, const char *name)); -+static char *_listxattrs (const char *path, ssize_t (*listxattr) (const char *path, char *list, size_t size), ssize_t *size); - - guestfs_int_xattr_list * - do_getxattrs (const char *path) -@@ -102,27 +103,10 @@ getxattrs (const char *path, - size_t i, j; - guestfs_int_xattr_list *r = NULL; - -- CHROOT_IN; -- len = listxattr (path, NULL, 0); -- CHROOT_OUT; -- if (len == -1) { -- reply_with_perror ("listxattr: %s", path); -+ buf = _listxattrs (path, listxattr, &len); -+ if (buf == NULL) -+ /* _listxattrs issues reply_with_perror already. */ - goto error; -- } -- -- buf = malloc (len); -- if (buf == NULL) { -- reply_with_perror ("malloc"); -- goto error; -- } -- -- CHROOT_IN; -- len = listxattr (path, buf, len); -- CHROOT_OUT; -- if (len == -1) { -- reply_with_perror ("listxattr: %s", path); -- goto error; -- } - - r = calloc (1, sizeof (*r)); - if (r == NULL) { -@@ -237,6 +221,46 @@ _removexattr (const char *xattr, const char *path, - return 0; - } - -+static char * -+_listxattrs (const char *path, -+ ssize_t (*listxattr) (const char *path, char *list, size_t size), -+ ssize_t *size) -+{ -+ int r; -+ char *buf = NULL; -+ ssize_t len; -+ -+ CHROOT_IN; -+ len = listxattr (path, NULL, 0); -+ CHROOT_OUT; -+ if (len == -1) { -+ reply_with_perror ("listxattr: %s", path); -+ goto error; -+ } -+ -+ buf = malloc (len); -+ if (buf == NULL) { -+ reply_with_perror ("malloc"); -+ goto error; -+ } -+ -+ CHROOT_IN; -+ len = listxattr (path, buf, len); -+ CHROOT_OUT; -+ if (len == -1) { -+ reply_with_perror ("listxattr: %s", path); -+ goto error; -+ } -+ -+ if (size) -+ *size = len; -+ return buf; -+ -+ error: -+ free (buf); -+ return NULL; -+} -+ - guestfs_int_xattr_list * - do_internal_lxattrlist (const char *path, char *const *names) - { --- -1.8.4.2 - diff --git a/0056-New-API-copy-attributes.patch b/0056-New-API-copy-attributes.patch new file mode 100644 index 0000000..6ed996e --- /dev/null +++ b/0056-New-API-copy-attributes.patch @@ -0,0 +1,437 @@ +From fc9329fe2c788a799c598b9c6f90ba9aeaf60082 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 13 Jan 2014 14:41:28 +0100 +Subject: [PATCH] New API: copy-attributes. + +This allows one to copy attributes (like permissions, xattrs, +ownership) from a file to another. + +(cherry picked from commit efb5f1841524ec75d765368b447270b8a3aff8ac) +--- + daemon/daemon.h | 3 + + daemon/file.c | 72 ++++++++++++++++++++++ + daemon/xattr.c | 69 +++++++++++++++++++++ + fish/Makefile.am | 1 + + fish/test-file-attrs.sh | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ + generator/actions.ml | 38 ++++++++++++ + src/MAX_PROC_NR | 2 +- + 7 files changed, 341 insertions(+), 1 deletion(-) + create mode 100755 fish/test-file-attrs.sh + +diff --git a/daemon/daemon.h b/daemon/daemon.h +index b77d764..6535658 100644 +--- a/daemon/daemon.h ++++ b/daemon/daemon.h +@@ -231,6 +231,9 @@ extern void journal_finalize (void); + /*-- in proto.c --*/ + extern void main_loop (int sock) __attribute__((noreturn)); + ++/*-- in xattr.c --*/ ++extern int copy_xattrs (const char *src, const char *dest); ++ + /* ordinary daemon functions use these to indicate errors + * NB: you don't need to prefix the string with the current command, + * it is added automatically by the client-side RPC stubs. +diff --git a/daemon/file.c b/daemon/file.c +index f348f87..856ab5f 100644 +--- a/daemon/file.c ++++ b/daemon/file.c +@@ -28,6 +28,7 @@ + #include "guestfs_protocol.h" + #include "daemon.h" + #include "actions.h" ++#include "optgroups.h" + + GUESTFSD_EXT_CMD(str_file, file); + GUESTFSD_EXT_CMD(str_zcat, zcat); +@@ -584,3 +585,74 @@ do_filesize (const char *path) + + return buf.st_size; + } ++ ++int ++do_copy_attributes (const char *src, const char *dest, int all, int mode, int xattributes, int ownership) ++{ ++ int r; ++ struct stat srcstat, deststat; ++ ++ static const unsigned int file_mask = 07777; ++ ++ /* If it was specified to copy everything, manually enable all the flags ++ * not manually specified to avoid checking for flag || all everytime. ++ */ ++ if (all) { ++ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_MODE_BITMASK)) ++ mode = 1; ++ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_XATTRIBUTES_BITMASK)) ++ xattributes = 1; ++ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_OWNERSHIP_BITMASK)) ++ ownership = 1; ++ } ++ ++ CHROOT_IN; ++ r = stat (src, &srcstat); ++ CHROOT_OUT; ++ ++ if (r == -1) { ++ reply_with_perror ("stat: %s", src); ++ return -1; ++ } ++ ++ CHROOT_IN; ++ r = stat (dest, &deststat); ++ CHROOT_OUT; ++ ++ if (r == -1) { ++ reply_with_perror ("stat: %s", dest); ++ return -1; ++ } ++ ++ if (mode && ++ ((srcstat.st_mode & file_mask) != (deststat.st_mode & file_mask))) { ++ CHROOT_IN; ++ r = chmod (dest, (srcstat.st_mode & file_mask)); ++ CHROOT_OUT; ++ ++ if (r == -1) { ++ reply_with_perror ("chmod: %s", dest); ++ return -1; ++ } ++ } ++ ++ if (ownership && ++ (srcstat.st_uid != deststat.st_uid || srcstat.st_gid != deststat.st_gid)) { ++ CHROOT_IN; ++ r = chown (dest, srcstat.st_uid, srcstat.st_gid); ++ CHROOT_OUT; ++ ++ if (r == -1) { ++ reply_with_perror ("chown: %s", dest); ++ return -1; ++ } ++ } ++ ++ if (xattributes && optgroup_linuxxattrs_available ()) { ++ if (!copy_xattrs (src, dest)) ++ /* copy_xattrs replies with an error already. */ ++ return -1; ++ } ++ ++ return 0; ++} +diff --git a/daemon/xattr.c b/daemon/xattr.c +index dc024d3..fdc43b3 100644 +--- a/daemon/xattr.c ++++ b/daemon/xattr.c +@@ -523,8 +523,77 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r) + return buf; /* caller frees */ + } + ++int ++copy_xattrs (const char *src, const char *dest) ++{ ++ ssize_t len, vlen, ret, attrval_len = 0; ++ CLEANUP_FREE char *buf = NULL, *attrval = NULL; ++ size_t i; ++ ++ buf = _listxattrs (src, listxattr, &len); ++ if (buf == NULL) ++ /* _listxattrs issues reply_with_perror already. */ ++ goto error; ++ ++ /* What we get from the kernel is a string "foo\0bar\0baz" of length ++ * len. ++ */ ++ for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) { ++ CHROOT_IN; ++ vlen = getxattr (src, &buf[i], NULL, 0); ++ CHROOT_OUT; ++ if (vlen == -1) { ++ reply_with_perror ("getxattr: %s, %s", src, &buf[i]); ++ goto error; ++ } ++ ++ if (vlen > XATTR_SIZE_MAX) { ++ /* The next call to getxattr will fail anyway, so ... */ ++ reply_with_error ("extended attribute is too large"); ++ goto error; ++ } ++ ++ if (vlen > attrval_len) { ++ char *new = realloc (attrval, vlen); ++ if (new == NULL) { ++ reply_with_perror ("realloc"); ++ goto error; ++ } ++ attrval = new; ++ attrval_len = vlen; ++ } ++ ++ CHROOT_IN; ++ vlen = getxattr (src, &buf[i], attrval, vlen); ++ CHROOT_OUT; ++ if (vlen == -1) { ++ reply_with_perror ("getxattr: %s, %s", src, &buf[i]); ++ goto error; ++ } ++ ++ CHROOT_IN; ++ ret = setxattr (dest, &buf[i], attrval, vlen, 0); ++ CHROOT_OUT; ++ if (ret == -1) { ++ reply_with_perror ("setxattr: %s, %s", dest, &buf[i]); ++ goto error; ++ } ++ } ++ ++ return 1; ++ ++ error: ++ return 0; ++} ++ + #else /* no HAVE_LINUX_XATTRS */ + + OPTGROUP_LINUXXATTRS_NOT_AVAILABLE + ++int ++copy_xattrs (const char *src, const char *dest) ++{ ++ abort (); ++} ++ + #endif /* no HAVE_LINUX_XATTRS */ +diff --git a/fish/Makefile.am b/fish/Makefile.am +index bd0485f..fb0e99e 100644 +--- a/fish/Makefile.am ++++ b/fish/Makefile.am +@@ -279,6 +279,7 @@ if ENABLE_APPLIANCE + TESTS += \ + test-copy.sh \ + test-edit.sh \ ++ test-file-attrs.sh \ + test-find0.sh \ + test-inspect.sh \ + test-glob.sh \ +diff --git a/fish/test-file-attrs.sh b/fish/test-file-attrs.sh +new file mode 100755 +index 0000000..78bd817 +--- /dev/null ++++ b/fish/test-file-attrs.sh +@@ -0,0 +1,157 @@ ++#!/bin/bash - ++# libguestfs ++# Copyright (C) 2014 Red Hat Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ ++# Test guestfish file attributes commands (chmod, copy-attributes, etc). ++ ++set -e ++export LANG=C ++ ++rm -f test.out ++ ++$VG ./guestfish > test.out < -Date: Fri, 10 Jan 2014 21:19:43 +0000 -Subject: [PATCH] daemon: xattr: Remove unused variable. - -Revealed by using ./configure --enable-gcc-warnings. - -(cherry picked from commit cea270de3be3ca3c2b2e6555418c4b4eb8da7509) ---- - daemon/xattr.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/daemon/xattr.c b/daemon/xattr.c -index 768f780..dc024d3 100644 ---- a/daemon/xattr.c -+++ b/daemon/xattr.c -@@ -226,7 +226,6 @@ _listxattrs (const char *path, - ssize_t (*listxattr) (const char *path, char *list, size_t size), - ssize_t *size) - { -- int r; - char *buf = NULL; - ssize_t len; - --- -1.8.4.2 - diff --git a/0057-New-API-copy-attributes.patch b/0057-New-API-copy-attributes.patch deleted file mode 100644 index 7571aa0..0000000 --- a/0057-New-API-copy-attributes.patch +++ /dev/null @@ -1,437 +0,0 @@ -From 338301295f0c6180edb7702882aab600d339ef4d Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Mon, 13 Jan 2014 14:41:28 +0100 -Subject: [PATCH] New API: copy-attributes. - -This allows one to copy attributes (like permissions, xattrs, -ownership) from a file to another. - -(cherry picked from commit efb5f1841524ec75d765368b447270b8a3aff8ac) ---- - daemon/daemon.h | 3 + - daemon/file.c | 72 ++++++++++++++++++++++ - daemon/xattr.c | 69 +++++++++++++++++++++ - fish/Makefile.am | 1 + - fish/test-file-attrs.sh | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ - generator/actions.ml | 38 ++++++++++++ - src/MAX_PROC_NR | 2 +- - 7 files changed, 341 insertions(+), 1 deletion(-) - create mode 100755 fish/test-file-attrs.sh - -diff --git a/daemon/daemon.h b/daemon/daemon.h -index b77d764..6535658 100644 ---- a/daemon/daemon.h -+++ b/daemon/daemon.h -@@ -231,6 +231,9 @@ extern void journal_finalize (void); - /*-- in proto.c --*/ - extern void main_loop (int sock) __attribute__((noreturn)); - -+/*-- in xattr.c --*/ -+extern int copy_xattrs (const char *src, const char *dest); -+ - /* ordinary daemon functions use these to indicate errors - * NB: you don't need to prefix the string with the current command, - * it is added automatically by the client-side RPC stubs. -diff --git a/daemon/file.c b/daemon/file.c -index f348f87..856ab5f 100644 ---- a/daemon/file.c -+++ b/daemon/file.c -@@ -28,6 +28,7 @@ - #include "guestfs_protocol.h" - #include "daemon.h" - #include "actions.h" -+#include "optgroups.h" - - GUESTFSD_EXT_CMD(str_file, file); - GUESTFSD_EXT_CMD(str_zcat, zcat); -@@ -584,3 +585,74 @@ do_filesize (const char *path) - - return buf.st_size; - } -+ -+int -+do_copy_attributes (const char *src, const char *dest, int all, int mode, int xattributes, int ownership) -+{ -+ int r; -+ struct stat srcstat, deststat; -+ -+ static const unsigned int file_mask = 07777; -+ -+ /* If it was specified to copy everything, manually enable all the flags -+ * not manually specified to avoid checking for flag || all everytime. -+ */ -+ if (all) { -+ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_MODE_BITMASK)) -+ mode = 1; -+ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_XATTRIBUTES_BITMASK)) -+ xattributes = 1; -+ if (!(optargs_bitmask & GUESTFS_COPY_ATTRIBUTES_OWNERSHIP_BITMASK)) -+ ownership = 1; -+ } -+ -+ CHROOT_IN; -+ r = stat (src, &srcstat); -+ CHROOT_OUT; -+ -+ if (r == -1) { -+ reply_with_perror ("stat: %s", src); -+ return -1; -+ } -+ -+ CHROOT_IN; -+ r = stat (dest, &deststat); -+ CHROOT_OUT; -+ -+ if (r == -1) { -+ reply_with_perror ("stat: %s", dest); -+ return -1; -+ } -+ -+ if (mode && -+ ((srcstat.st_mode & file_mask) != (deststat.st_mode & file_mask))) { -+ CHROOT_IN; -+ r = chmod (dest, (srcstat.st_mode & file_mask)); -+ CHROOT_OUT; -+ -+ if (r == -1) { -+ reply_with_perror ("chmod: %s", dest); -+ return -1; -+ } -+ } -+ -+ if (ownership && -+ (srcstat.st_uid != deststat.st_uid || srcstat.st_gid != deststat.st_gid)) { -+ CHROOT_IN; -+ r = chown (dest, srcstat.st_uid, srcstat.st_gid); -+ CHROOT_OUT; -+ -+ if (r == -1) { -+ reply_with_perror ("chown: %s", dest); -+ return -1; -+ } -+ } -+ -+ if (xattributes && optgroup_linuxxattrs_available ()) { -+ if (!copy_xattrs (src, dest)) -+ /* copy_xattrs replies with an error already. */ -+ return -1; -+ } -+ -+ return 0; -+} -diff --git a/daemon/xattr.c b/daemon/xattr.c -index dc024d3..fdc43b3 100644 ---- a/daemon/xattr.c -+++ b/daemon/xattr.c -@@ -523,8 +523,77 @@ do_lgetxattr (const char *path, const char *name, size_t *size_r) - return buf; /* caller frees */ - } - -+int -+copy_xattrs (const char *src, const char *dest) -+{ -+ ssize_t len, vlen, ret, attrval_len = 0; -+ CLEANUP_FREE char *buf = NULL, *attrval = NULL; -+ size_t i; -+ -+ buf = _listxattrs (src, listxattr, &len); -+ if (buf == NULL) -+ /* _listxattrs issues reply_with_perror already. */ -+ goto error; -+ -+ /* What we get from the kernel is a string "foo\0bar\0baz" of length -+ * len. -+ */ -+ for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) { -+ CHROOT_IN; -+ vlen = getxattr (src, &buf[i], NULL, 0); -+ CHROOT_OUT; -+ if (vlen == -1) { -+ reply_with_perror ("getxattr: %s, %s", src, &buf[i]); -+ goto error; -+ } -+ -+ if (vlen > XATTR_SIZE_MAX) { -+ /* The next call to getxattr will fail anyway, so ... */ -+ reply_with_error ("extended attribute is too large"); -+ goto error; -+ } -+ -+ if (vlen > attrval_len) { -+ char *new = realloc (attrval, vlen); -+ if (new == NULL) { -+ reply_with_perror ("realloc"); -+ goto error; -+ } -+ attrval = new; -+ attrval_len = vlen; -+ } -+ -+ CHROOT_IN; -+ vlen = getxattr (src, &buf[i], attrval, vlen); -+ CHROOT_OUT; -+ if (vlen == -1) { -+ reply_with_perror ("getxattr: %s, %s", src, &buf[i]); -+ goto error; -+ } -+ -+ CHROOT_IN; -+ ret = setxattr (dest, &buf[i], attrval, vlen, 0); -+ CHROOT_OUT; -+ if (ret == -1) { -+ reply_with_perror ("setxattr: %s, %s", dest, &buf[i]); -+ goto error; -+ } -+ } -+ -+ return 1; -+ -+ error: -+ return 0; -+} -+ - #else /* no HAVE_LINUX_XATTRS */ - - OPTGROUP_LINUXXATTRS_NOT_AVAILABLE - -+int -+copy_xattrs (const char *src, const char *dest) -+{ -+ abort (); -+} -+ - #endif /* no HAVE_LINUX_XATTRS */ -diff --git a/fish/Makefile.am b/fish/Makefile.am -index bd0485f..fb0e99e 100644 ---- a/fish/Makefile.am -+++ b/fish/Makefile.am -@@ -279,6 +279,7 @@ if ENABLE_APPLIANCE - TESTS += \ - test-copy.sh \ - test-edit.sh \ -+ test-file-attrs.sh \ - test-find0.sh \ - test-inspect.sh \ - test-glob.sh \ -diff --git a/fish/test-file-attrs.sh b/fish/test-file-attrs.sh -new file mode 100755 -index 0000000..78bd817 ---- /dev/null -+++ b/fish/test-file-attrs.sh -@@ -0,0 +1,157 @@ -+#!/bin/bash - -+# libguestfs -+# Copyright (C) 2014 Red Hat Inc. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 2 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -+ -+# Test guestfish file attributes commands (chmod, copy-attributes, etc). -+ -+set -e -+export LANG=C -+ -+rm -f test.out -+ -+$VG ./guestfish > test.out < +Date: Mon, 13 Jan 2014 19:26:01 +0000 +Subject: [PATCH] Update generated files for new copy-attributes API. + +This updates commit efb5f1841524ec75d765368b447270b8a3aff8ac. + +(cherry picked from commit e68baf1954f9b68a228c9ae99a738f2d750418c1) +--- + gobject/Makefile.inc | 6 ++++-- + po/POTFILES | 1 + + 2 files changed, 5 insertions(+), 2 deletions(-) + +diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc +index fbc9eb6..7024754 100644 +--- a/gobject/Makefile.inc ++++ b/gobject/Makefile.inc +@@ -92,7 +92,8 @@ guestfs_gobject_headers= \ + include/guestfs-gobject/optargs-mke2fs.h \ + include/guestfs-gobject/optargs-mktemp.h \ + include/guestfs-gobject/optargs-syslinux.h \ +- include/guestfs-gobject/optargs-remount.h ++ include/guestfs-gobject/optargs-remount.h \ ++ include/guestfs-gobject/optargs-copy_attributes.h + + guestfs_gobject_sources= \ + src/session.c \ +@@ -166,4 +167,5 @@ guestfs_gobject_sources= \ + src/optargs-mke2fs.c \ + src/optargs-mktemp.c \ + src/optargs-syslinux.c \ +- src/optargs-remount.c ++ src/optargs-remount.c \ ++ src/optargs-copy_attributes.c +diff --git a/po/POTFILES b/po/POTFILES +index 1e831ff..76c41ec 100644 +--- a/po/POTFILES ++++ b/po/POTFILES +@@ -163,6 +163,7 @@ gobject/src/optargs-btrfs_filesystem_resize.c + gobject/src/optargs-btrfs_fsck.c + gobject/src/optargs-compress_device_out.c + gobject/src/optargs-compress_out.c ++gobject/src/optargs-copy_attributes.c + gobject/src/optargs-copy_device_to_device.c + gobject/src/optargs-copy_device_to_file.c + gobject/src/optargs-copy_file_to_device.c +-- +1.8.4.2 + diff --git a/0058-Update-generated-files-for-new-copy-attributes-API.patch b/0058-Update-generated-files-for-new-copy-attributes-API.patch deleted file mode 100644 index 63a5b31..0000000 --- a/0058-Update-generated-files-for-new-copy-attributes-API.patch +++ /dev/null @@ -1,49 +0,0 @@ -From b8c496a666647bfdf2b0bc54979ef06363868e93 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 19:26:01 +0000 -Subject: [PATCH] Update generated files for new copy-attributes API. - -This updates commit efb5f1841524ec75d765368b447270b8a3aff8ac. - -(cherry picked from commit e68baf1954f9b68a228c9ae99a738f2d750418c1) ---- - gobject/Makefile.inc | 6 ++++-- - po/POTFILES | 1 + - 2 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/gobject/Makefile.inc b/gobject/Makefile.inc -index fbc9eb6..7024754 100644 ---- a/gobject/Makefile.inc -+++ b/gobject/Makefile.inc -@@ -92,7 +92,8 @@ guestfs_gobject_headers= \ - include/guestfs-gobject/optargs-mke2fs.h \ - include/guestfs-gobject/optargs-mktemp.h \ - include/guestfs-gobject/optargs-syslinux.h \ -- include/guestfs-gobject/optargs-remount.h -+ include/guestfs-gobject/optargs-remount.h \ -+ include/guestfs-gobject/optargs-copy_attributes.h - - guestfs_gobject_sources= \ - src/session.c \ -@@ -166,4 +167,5 @@ guestfs_gobject_sources= \ - src/optargs-mke2fs.c \ - src/optargs-mktemp.c \ - src/optargs-syslinux.c \ -- src/optargs-remount.c -+ src/optargs-remount.c \ -+ src/optargs-copy_attributes.c -diff --git a/po/POTFILES b/po/POTFILES -index 1e831ff..76c41ec 100644 ---- a/po/POTFILES -+++ b/po/POTFILES -@@ -163,6 +163,7 @@ gobject/src/optargs-btrfs_filesystem_resize.c - gobject/src/optargs-btrfs_fsck.c - gobject/src/optargs-compress_device_out.c - gobject/src/optargs-compress_out.c -+gobject/src/optargs-copy_attributes.c - gobject/src/optargs-copy_device_to_device.c - gobject/src/optargs-copy_device_to_file.c - gobject/src/optargs-copy_file_to_device.c --- -1.8.4.2 - diff --git a/0058-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch b/0058-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch new file mode 100644 index 0000000..841fd9a --- /dev/null +++ b/0058-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch @@ -0,0 +1,27 @@ +From 29a1bf446af1d85ac0b55697ea3bd34b2790e964 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 13 Jan 2014 22:10:39 +0000 +Subject: [PATCH] fish: Add test-file-attrs.sh to EXTRA_DIST. + +This fixes commit efb5f1841524ec75d765368b447270b8a3aff8ac. + +(cherry picked from commit aba64a0327094b6a82686411c4dfa7a30d64ecee) +--- + fish/Makefile.am | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fish/Makefile.am b/fish/Makefile.am +index fb0e99e..54ba875 100644 +--- a/fish/Makefile.am ++++ b/fish/Makefile.am +@@ -306,6 +306,7 @@ EXTRA_DIST += \ + test-edit.sh \ + test-escapes.sh \ + test-events.sh \ ++ test-file-attrs.sh \ + test-find0.sh \ + test-glob.sh \ + test-inspect.sh \ +-- +1.8.4.2 + diff --git a/0059-builder-edit-fish-use-copy-attributes.patch b/0059-builder-edit-fish-use-copy-attributes.patch new file mode 100644 index 0000000..df2f5a4 --- /dev/null +++ b/0059-builder-edit-fish-use-copy-attributes.patch @@ -0,0 +1,212 @@ +From 420c70b64d289260b9707b37141d11f5f0e61bce Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 14 Jan 2014 11:08:25 +0100 +Subject: [PATCH] builder, edit, fish: use copy-attributes + +Make use of the new copy-attributes command to properly copy all file +attributes from a file to the new version of it. + +(cherry picked from commit b7bb1f6cee19da143996c13e6cc019a039f3ee4f) +--- + edit/edit.c | 49 ++----------------------------------------------- + fish/edit.c | 54 ++---------------------------------------------------- + mllib/perl_edit.ml | 29 +---------------------------- + 3 files changed, 5 insertions(+), 127 deletions(-) + +diff --git a/edit/edit.c b/edit/edit.c +index e5e3a29..07790be 100644 +--- a/edit/edit.c ++++ b/edit/edit.c +@@ -56,7 +56,6 @@ static void edit_files (int argc, char *argv[]); + static void edit (const char *filename, const char *root); + static char *edit_interactively (const char *tmpfile); + static char *edit_non_interactively (const char *tmpfile); +-static int copy_attributes (const char *src, const char *dest); + static int is_windows (guestfs_h *g, const char *root); + static char *windows_path (guestfs_h *g, const char *root, const char *filename); + static char *generate_random_name (const char *filename); +@@ -361,7 +360,8 @@ edit (const char *filename, const char *root) + /* Set the permissions, UID, GID and SELinux context of the new + * file to match the old file (RHBZ#788641). + */ +- if (copy_attributes (filename, newname) == -1) ++ if (guestfs_copy_attributes (g, filename, newname, ++ GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1) + goto error; + + /* Backup or overwrite the file. */ +@@ -510,51 +510,6 @@ edit_non_interactively (const char *tmpfile) + } + + static int +-copy_attributes (const char *src, const char *dest) +-{ +- CLEANUP_FREE_STAT struct guestfs_stat *stat = NULL; +- const char *linuxxattrs[] = { "linuxxattrs", NULL }; +- int has_linuxxattrs; +- CLEANUP_FREE char *selinux_context = NULL; +- size_t selinux_context_size; +- +- has_linuxxattrs = guestfs_feature_available (g, (char **) linuxxattrs); +- +- /* Get the mode. */ +- stat = guestfs_stat (g, src); +- if (stat == NULL) +- return -1; +- +- /* Get the SELinux context. XXX Should we copy over other extended +- * attributes too? +- */ +- if (has_linuxxattrs) { +- guestfs_push_error_handler (g, NULL, NULL); +- +- selinux_context = guestfs_getxattr (g, src, "security.selinux", +- &selinux_context_size); +- /* selinux_context could be NULL. This isn't an error. */ +- +- guestfs_pop_error_handler (g); +- } +- +- /* Set the permissions (inc. sticky and set*id bits), UID, GID. */ +- if (guestfs_chmod (g, stat->mode & 07777, dest) == -1) +- return -1; +- if (guestfs_chown (g, stat->uid, stat->gid, dest) == -1) +- return -1; +- +- /* Set the SELinux context. */ +- if (has_linuxxattrs && selinux_context) { +- if (guestfs_setxattr (g, "security.selinux", selinux_context, +- (int) selinux_context_size, dest) == -1) +- return -1; +- } +- +- return 0; +-} +- +-static int + is_windows (guestfs_h *g, const char *root) + { + int w; +diff --git a/fish/edit.c b/fish/edit.c +index 754a34a..bd02f4b 100644 +--- a/fish/edit.c ++++ b/fish/edit.c +@@ -32,7 +32,6 @@ + #include "fish.h" + + static char *generate_random_name (const char *filename); +-static int copy_attributes (const char *src, const char *dest); + + /* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */ + +@@ -135,7 +134,8 @@ run_edit (const char *cmd, size_t argc, char *argv[]) + /* Set the permissions, UID, GID and SELinux context of the new + * file to match the old file (RHBZ#788641). + */ +- if (copy_attributes (remotefilename, newname) == -1) ++ if (guestfs_copy_attributes (g, remotefilename, newname, ++ GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1) + return -1; + + if (guestfs_mv (g, newname, remotefilename) == -1) +@@ -177,53 +177,3 @@ generate_random_name (const char *filename) + + return ret; /* caller will free */ + } +- +-static int +-copy_attributes (const char *src, const char *dest) +-{ +- struct guestfs_stat *stat; +- const char *linuxxattrs[] = { "linuxxattrs", NULL }; +- int has_linuxxattrs; +- CLEANUP_FREE char *selinux_context = NULL; +- size_t selinux_context_size; +- +- has_linuxxattrs = guestfs_feature_available (g, (char **) linuxxattrs); +- +- /* Get the mode. */ +- stat = guestfs_stat (g, src); +- if (stat == NULL) +- return -1; +- +- /* Get the SELinux context. XXX Should we copy over other extended +- * attributes too? +- */ +- if (has_linuxxattrs) { +- guestfs_push_error_handler (g, NULL, NULL); +- +- selinux_context = guestfs_getxattr (g, src, "security.selinux", +- &selinux_context_size); +- /* selinux_context could be NULL. This isn't an error. */ +- +- guestfs_pop_error_handler (g); +- } +- +- /* Set the permissions (inc. sticky and set*id bits), UID, GID. */ +- if (guestfs_chmod (g, stat->mode & 07777, dest) == -1) { +- guestfs_free_stat (stat); +- return -1; +- } +- if (guestfs_chown (g, stat->uid, stat->gid, dest) == -1) { +- guestfs_free_stat (stat); +- return -1; +- } +- guestfs_free_stat (stat); +- +- /* Set the SELinux context. */ +- if (has_linuxxattrs && selinux_context) { +- if (guestfs_setxattr (g, "security.selinux", selinux_context, +- (int) selinux_context_size, dest) == -1) +- return -1; +- } +- +- return 0; +-} +diff --git a/mllib/perl_edit.ml b/mllib/perl_edit.ml +index aa4c2e6..28e5dea 100644 +--- a/mllib/perl_edit.ml ++++ b/mllib/perl_edit.ml +@@ -42,7 +42,7 @@ let rec edit_file ~debug (g : Guestfs.guestfs) file expr = + g#upload tmpfile file; + + (* However like virt-edit we do need to copy attributes. *) +- copy_attributes g file_old file; ++ g#copy_attributes ~all:true file_old file; + g#rm file_old + + and do_perl_edit ~debug g file expr = +@@ -76,30 +76,3 @@ and do_perl_edit ~debug g file expr = + ); + + Unix.rename (file ^ ".out") file +- +-and copy_attributes g src dest = +- let has_linuxxattrs = g#feature_available [|"linuxxattrs"|] in +- +- (* Get the mode. *) +- let stat = g#stat src in +- +- (* Get the SELinux context. XXX Should we copy over other extended +- * attributes too? +- *) +- let selinux_context = +- if has_linuxxattrs then ( +- try Some (g#getxattr src "security.selinux") with _ -> None +- ) else None in +- +- (* Set the permissions (inc. sticky and set*id bits), UID, GID. *) +- let mode = Int64.to_int stat.G.mode +- and uid = Int64.to_int stat.G.uid and gid = Int64.to_int stat.G.gid in +- g#chmod (mode land 0o7777) dest; +- g#chown uid gid dest; +- +- (* Set the SELinux context. *) +- match selinux_context with +- | None -> () +- | Some selinux_context -> +- g#setxattr "security.selinux" +- selinux_context (String.length selinux_context) dest +-- +1.8.4.2 + diff --git a/0059-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch b/0059-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch deleted file mode 100644 index 1a1666f..0000000 --- a/0059-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 7f3351b6c9731b553dea09244b5b0197268c0ae1 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Mon, 13 Jan 2014 22:10:39 +0000 -Subject: [PATCH] fish: Add test-file-attrs.sh to EXTRA_DIST. - -This fixes commit efb5f1841524ec75d765368b447270b8a3aff8ac. - -(cherry picked from commit aba64a0327094b6a82686411c4dfa7a30d64ecee) ---- - fish/Makefile.am | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/fish/Makefile.am b/fish/Makefile.am -index fb0e99e..54ba875 100644 ---- a/fish/Makefile.am -+++ b/fish/Makefile.am -@@ -306,6 +306,7 @@ EXTRA_DIST += \ - test-edit.sh \ - test-escapes.sh \ - test-events.sh \ -+ test-file-attrs.sh \ - test-find0.sh \ - test-glob.sh \ - test-inspect.sh \ --- -1.8.4.2 - diff --git a/0060-builder-edit-fish-use-copy-attributes.patch b/0060-builder-edit-fish-use-copy-attributes.patch deleted file mode 100644 index 23c94c9..0000000 --- a/0060-builder-edit-fish-use-copy-attributes.patch +++ /dev/null @@ -1,212 +0,0 @@ -From ef90768b6c036885d2e572bf7ea7508512bd62a5 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 14 Jan 2014 11:08:25 +0100 -Subject: [PATCH] builder, edit, fish: use copy-attributes - -Make use of the new copy-attributes command to properly copy all file -attributes from a file to the new version of it. - -(cherry picked from commit b7bb1f6cee19da143996c13e6cc019a039f3ee4f) ---- - builder/perl_edit.ml | 29 +--------------------------- - edit/edit.c | 49 ++--------------------------------------------- - fish/edit.c | 54 ++-------------------------------------------------- - 3 files changed, 5 insertions(+), 127 deletions(-) - -diff --git a/builder/perl_edit.ml b/builder/perl_edit.ml -index aa4c2e6..28e5dea 100644 ---- a/builder/perl_edit.ml -+++ b/builder/perl_edit.ml -@@ -42,7 +42,7 @@ let rec edit_file ~debug (g : Guestfs.guestfs) file expr = - g#upload tmpfile file; - - (* However like virt-edit we do need to copy attributes. *) -- copy_attributes g file_old file; -+ g#copy_attributes ~all:true file_old file; - g#rm file_old - - and do_perl_edit ~debug g file expr = -@@ -76,30 +76,3 @@ and do_perl_edit ~debug g file expr = - ); - - Unix.rename (file ^ ".out") file -- --and copy_attributes g src dest = -- let has_linuxxattrs = g#feature_available [|"linuxxattrs"|] in -- -- (* Get the mode. *) -- let stat = g#stat src in -- -- (* Get the SELinux context. XXX Should we copy over other extended -- * attributes too? -- *) -- let selinux_context = -- if has_linuxxattrs then ( -- try Some (g#getxattr src "security.selinux") with _ -> None -- ) else None in -- -- (* Set the permissions (inc. sticky and set*id bits), UID, GID. *) -- let mode = Int64.to_int stat.G.mode -- and uid = Int64.to_int stat.G.uid and gid = Int64.to_int stat.G.gid in -- g#chmod (mode land 0o7777) dest; -- g#chown uid gid dest; -- -- (* Set the SELinux context. *) -- match selinux_context with -- | None -> () -- | Some selinux_context -> -- g#setxattr "security.selinux" -- selinux_context (String.length selinux_context) dest -diff --git a/edit/edit.c b/edit/edit.c -index e5e3a29..07790be 100644 ---- a/edit/edit.c -+++ b/edit/edit.c -@@ -56,7 +56,6 @@ static void edit_files (int argc, char *argv[]); - static void edit (const char *filename, const char *root); - static char *edit_interactively (const char *tmpfile); - static char *edit_non_interactively (const char *tmpfile); --static int copy_attributes (const char *src, const char *dest); - static int is_windows (guestfs_h *g, const char *root); - static char *windows_path (guestfs_h *g, const char *root, const char *filename); - static char *generate_random_name (const char *filename); -@@ -361,7 +360,8 @@ edit (const char *filename, const char *root) - /* Set the permissions, UID, GID and SELinux context of the new - * file to match the old file (RHBZ#788641). - */ -- if (copy_attributes (filename, newname) == -1) -+ if (guestfs_copy_attributes (g, filename, newname, -+ GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1) - goto error; - - /* Backup or overwrite the file. */ -@@ -510,51 +510,6 @@ edit_non_interactively (const char *tmpfile) - } - - static int --copy_attributes (const char *src, const char *dest) --{ -- CLEANUP_FREE_STAT struct guestfs_stat *stat = NULL; -- const char *linuxxattrs[] = { "linuxxattrs", NULL }; -- int has_linuxxattrs; -- CLEANUP_FREE char *selinux_context = NULL; -- size_t selinux_context_size; -- -- has_linuxxattrs = guestfs_feature_available (g, (char **) linuxxattrs); -- -- /* Get the mode. */ -- stat = guestfs_stat (g, src); -- if (stat == NULL) -- return -1; -- -- /* Get the SELinux context. XXX Should we copy over other extended -- * attributes too? -- */ -- if (has_linuxxattrs) { -- guestfs_push_error_handler (g, NULL, NULL); -- -- selinux_context = guestfs_getxattr (g, src, "security.selinux", -- &selinux_context_size); -- /* selinux_context could be NULL. This isn't an error. */ -- -- guestfs_pop_error_handler (g); -- } -- -- /* Set the permissions (inc. sticky and set*id bits), UID, GID. */ -- if (guestfs_chmod (g, stat->mode & 07777, dest) == -1) -- return -1; -- if (guestfs_chown (g, stat->uid, stat->gid, dest) == -1) -- return -1; -- -- /* Set the SELinux context. */ -- if (has_linuxxattrs && selinux_context) { -- if (guestfs_setxattr (g, "security.selinux", selinux_context, -- (int) selinux_context_size, dest) == -1) -- return -1; -- } -- -- return 0; --} -- --static int - is_windows (guestfs_h *g, const char *root) - { - int w; -diff --git a/fish/edit.c b/fish/edit.c -index 754a34a..bd02f4b 100644 ---- a/fish/edit.c -+++ b/fish/edit.c -@@ -32,7 +32,6 @@ - #include "fish.h" - - static char *generate_random_name (const char *filename); --static int copy_attributes (const char *src, const char *dest); - - /* guestfish edit command, suggested by Ján Ondrej, implemented by RWMJ */ - -@@ -135,7 +134,8 @@ run_edit (const char *cmd, size_t argc, char *argv[]) - /* Set the permissions, UID, GID and SELinux context of the new - * file to match the old file (RHBZ#788641). - */ -- if (copy_attributes (remotefilename, newname) == -1) -+ if (guestfs_copy_attributes (g, remotefilename, newname, -+ GUESTFS_COPY_ATTRIBUTES_ALL, 1, -1) == -1) - return -1; - - if (guestfs_mv (g, newname, remotefilename) == -1) -@@ -177,53 +177,3 @@ generate_random_name (const char *filename) - - return ret; /* caller will free */ - } -- --static int --copy_attributes (const char *src, const char *dest) --{ -- struct guestfs_stat *stat; -- const char *linuxxattrs[] = { "linuxxattrs", NULL }; -- int has_linuxxattrs; -- CLEANUP_FREE char *selinux_context = NULL; -- size_t selinux_context_size; -- -- has_linuxxattrs = guestfs_feature_available (g, (char **) linuxxattrs); -- -- /* Get the mode. */ -- stat = guestfs_stat (g, src); -- if (stat == NULL) -- return -1; -- -- /* Get the SELinux context. XXX Should we copy over other extended -- * attributes too? -- */ -- if (has_linuxxattrs) { -- guestfs_push_error_handler (g, NULL, NULL); -- -- selinux_context = guestfs_getxattr (g, src, "security.selinux", -- &selinux_context_size); -- /* selinux_context could be NULL. This isn't an error. */ -- -- guestfs_pop_error_handler (g); -- } -- -- /* Set the permissions (inc. sticky and set*id bits), UID, GID. */ -- if (guestfs_chmod (g, stat->mode & 07777, dest) == -1) { -- guestfs_free_stat (stat); -- return -1; -- } -- if (guestfs_chown (g, stat->uid, stat->gid, dest) == -1) { -- guestfs_free_stat (stat); -- return -1; -- } -- guestfs_free_stat (stat); -- -- /* Set the SELinux context. */ -- if (has_linuxxattrs && selinux_context) { -- if (guestfs_setxattr (g, "security.selinux", selinux_context, -- (int) selinux_context_size, dest) == -1) -- return -1; -- } -- -- return 0; --} --- -1.8.4.2 - diff --git a/0060-builder-test-virt-builder-check-some-results.patch b/0060-builder-test-virt-builder-check-some-results.patch new file mode 100644 index 0000000..51a2909 --- /dev/null +++ b/0060-builder-test-virt-builder-check-some-results.patch @@ -0,0 +1,73 @@ +From f3a0124fe2cc47c7ae3a0b40fc77de2a7203566e Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 14 Jan 2014 13:30:19 +0100 +Subject: [PATCH] builder: test-virt-builder: check some results + +Check at least some basic modifications in the image created with +virt-builder. + +(cherry picked from commit 775c6daf22884edad8ede4b0916024d3d7c04585) +--- + builder/test-virt-builder.sh | 47 +++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 46 insertions(+), 1 deletion(-) + +diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh +index 47d20a4..3c8eb60 100755 +--- a/builder/test-virt-builder.sh ++++ b/builder/test-virt-builder.sh +@@ -65,6 +65,51 @@ $VG ./virt-builder phony-fedora \ + --firstboot Makefile --firstboot-command 'echo "hello"' \ + --firstboot-install "minicom,inkscape" + +-# XXX Test that the modifications were made. ++# Check that some modifications were made. ++$VG ../fish/guestfish --ro -i -a $output > test.out < +Date: Thu, 16 Jan 2014 11:49:05 +0100 +Subject: [PATCH] builder: small refactor of the list output + +Switch from a boolean for the short/long list output to labels for the +actual format. Also, split the output of each list format to an own +function for easier maintaineance. + +(cherry picked from commit 91aae893c70b3877b31803800ba77836fd7a45e8) +--- + builder/builder.ml | 4 +-- + builder/cmdline.ml | 9 +++--- + builder/list_entries.ml | 82 +++++++++++++++++++++++++++--------------------- + builder/list_entries.mli | 2 +- + 4 files changed, 54 insertions(+), 43 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 79f82a2..7e1c614 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -39,7 +39,7 @@ let main () = + (* Command line argument parsing - see cmdline.ml. *) + let mode, arg, + attach, cache, check_signature, curl, debug, delete, delete_on_failure, +- edit, firstboot, run, format, gpg, hostname, install, list_long, links, ++ edit, firstboot, run, format, gpg, hostname, install, list_format, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, +@@ -150,7 +150,7 @@ let main () = + let mode = + match mode with + | `List -> (* --list *) +- List_entries.list_entries ~list_long ~sources index; ++ List_entries.list_entries ~list_format ~sources index; + exit 0 + + | `Print_cache -> (* --print-cache *) +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index 67b142a..f199f03 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -130,7 +130,8 @@ let parse_cmdline () = + links := (target, lns) :: !links + in + +- let list_long = ref false in ++ let list_format = ref `Short in ++ let list_set_long () = list_format := `Long in + + let memsize = ref None in + let set_memsize arg = memsize := Some arg in +@@ -255,7 +256,7 @@ let parse_cmdline () = + "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; + "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; + "--list", Arg.Unit list_mode, ditto; +- "--long", Arg.Set list_long, ditto; ++ "--long", Arg.Unit list_set_long, " " ^ s_"List available templates, in long textual form"; + "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; + "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; + "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; +@@ -329,7 +330,7 @@ read the man page virt-builder(1). + let gpg = !gpg in + let hostname = !hostname in + let install = List.rev !install in +- let list_long = !list_long in ++ let list_format = !list_format in + let links = List.rev !links in + let memsize = !memsize in + let mkdirs = List.rev !mkdirs in +@@ -443,7 +444,7 @@ read the man page virt-builder(1). + + mode, arg, + attach, cache, check_signature, curl, debug, delete, delete_on_failure, +- edit, firstboot, run, format, gpg, hostname, install, list_long, links, ++ edit, firstboot, run, format, gpg, hostname, install, list_format, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, + scrub_logfile, size, smp, sources, sync, timezone, update, upload, +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index 87001c0..97ab201 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -21,15 +21,35 @@ open Common_utils + + open Printf + +-let list_entries ?(list_long = false) ~sources index = +- if list_long then ( +- List.iter ( +- fun (source, fingerprint) -> +- printf (f_"Source URI: %s\n") source; +- printf (f_"Fingerprint: %s\n") fingerprint; ++let rec list_entries ~list_format ~sources index = ++ match list_format with ++ | `Short -> list_entries_short index ++ | `Long -> list_entries_long ~sources index ++ ++and list_entries_short index = ++ List.iter ( ++ fun (name, { Index_parser.printable_name = printable_name; ++ size = size; ++ compressed_size = compressed_size; ++ notes = notes; ++ hidden = hidden }) -> ++ if not hidden then ( ++ printf "%-24s" name; ++ (match printable_name with ++ | None -> () ++ | Some s -> printf " %s" s ++ ); + printf "\n" +- ) sources +- ); ++ ) ++ ) index ++ ++and list_entries_long ~sources index = ++ List.iter ( ++ fun (source, fingerprint) -> ++ printf (f_"Source URI: %s\n") source; ++ printf (f_"Fingerprint: %s\n") fingerprint; ++ printf "\n" ++ ) sources; + + List.iter ( + fun (name, { Index_parser.printable_name = printable_name; +@@ -38,33 +58,23 @@ let list_entries ?(list_long = false) ~sources index = + notes = notes; + hidden = hidden }) -> + if not hidden then ( +- if not list_long then ( (* Short *) +- printf "%-24s" name; +- (match printable_name with +- | None -> () +- | Some s -> printf " %s" s +- ); +- printf "\n" +- ) +- else ( (* Long *) +- printf "%-24s %s\n" "os-version:" name; +- (match printable_name with +- | None -> () +- | Some name -> printf "%-24s %s\n" (s_"Full name:") name; +- ); +- printf "%-24s %s\n" (s_"Minimum/default size:") (human_size size); +- (match compressed_size with +- | None -> () +- | Some size -> +- printf "%-24s %s\n" (s_"Download size:") (human_size size); +- ); +- (match notes with +- | None -> () +- | Some notes -> +- printf "\n"; +- printf (f_"Notes:\n\n%s\n") notes +- ); +- printf "\n" +- ) ++ printf "%-24s %s\n" "os-version:" name; ++ (match printable_name with ++ | None -> () ++ | Some name -> printf "%-24s %s\n" (s_"Full name:") name; ++ ); ++ printf "%-24s %s\n" (s_"Minimum/default size:") (human_size size); ++ (match compressed_size with ++ | None -> () ++ | Some size -> ++ printf "%-24s %s\n" (s_"Download size:") (human_size size); ++ ); ++ (match notes with ++ | None -> () ++ | Some notes -> ++ printf "\n"; ++ printf (f_"Notes:\n\n%s\n") notes ++ ); ++ printf "\n" + ) + ) index +diff --git a/builder/list_entries.mli b/builder/list_entries.mli +index d9486b0..41d0bff 100644 +--- a/builder/list_entries.mli ++++ b/builder/list_entries.mli +@@ -16,4 +16,4 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +-val list_entries : ?list_long:bool -> sources:(string * string) list -> Index_parser.index -> unit ++val list_entries : list_format:([ `Short | `Long ]) -> sources:(string * string) list -> Index_parser.index -> unit +-- +1.8.4.2 + diff --git a/0061-builder-test-virt-builder-check-some-results.patch b/0061-builder-test-virt-builder-check-some-results.patch deleted file mode 100644 index 9926749..0000000 --- a/0061-builder-test-virt-builder-check-some-results.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 10e2bc794e15a8d64d06e0fe79cc2a7b94d7c44a Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Tue, 14 Jan 2014 13:30:19 +0100 -Subject: [PATCH] builder: test-virt-builder: check some results - -Check at least some basic modifications in the image created with -virt-builder. - -(cherry picked from commit 775c6daf22884edad8ede4b0916024d3d7c04585) ---- - builder/test-virt-builder.sh | 47 +++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 46 insertions(+), 1 deletion(-) - -diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh -index 47d20a4..3c8eb60 100755 ---- a/builder/test-virt-builder.sh -+++ b/builder/test-virt-builder.sh -@@ -65,6 +65,51 @@ $VG ./virt-builder phony-fedora \ - --firstboot Makefile --firstboot-command 'echo "hello"' \ - --firstboot-install "minicom,inkscape" - --# XXX Test that the modifications were made. -+# Check that some modifications were made. -+$VG ../fish/guestfish --ro -i -a $output > test.out < +Date: Thu, 16 Jan 2014 12:34:48 +0100 +Subject: [PATCH] builder: add --list-format + +Add a --list-format which allows to choose which in format should be the +output of --list. + +(cherry picked from commit e45bfe0d36c9f50143b13921a498f00ee06ca27d) +--- + builder/cmdline.ml | 11 ++++++++++- + builder/virt-builder.pod | 24 +++++++++++++++++++++--- + 2 files changed, 31 insertions(+), 4 deletions(-) + +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index f199f03..6d6439f 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -132,6 +132,13 @@ let parse_cmdline () = + + let list_format = ref `Short in + let list_set_long () = list_format := `Long in ++ let list_set_format arg = ++ list_format := match arg with ++ | "short" -> `Short ++ | "long" -> `Long ++ | fmt -> ++ eprintf (f_"%s: invalid --list-format type '%s', see the man page.\n") prog fmt; ++ exit 1 in + + let memsize = ref None in + let set_memsize arg = memsize := Some arg in +@@ -256,7 +263,9 @@ let parse_cmdline () = + "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; + "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; + "--list", Arg.Unit list_mode, ditto; +- "--long", Arg.Unit list_set_long, " " ^ s_"List available templates, in long textual form"; ++ "--long", Arg.Unit list_set_long, " " ^ s_"Shortcut for --list-format short"; ++ "--list-format", Arg.String list_set_format, ++ "short|long" ^ " " ^ s_"Set the format for --list (default: short)"; + "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; + "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; + "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 0d9b33f..8e60d30 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -31,7 +31,7 @@ virt-builder - Build virtual machine images quickly + [--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...'] + [--firstboot-install PKG,[PKG...]] + +- virt-builder -l|--list [--long] ++ virt-builder -l|--list [--long] [--list-format short|long] + + virt-builder --notes os-version + +@@ -374,12 +374,30 @@ pointing at C. + + =item B<--list> + ++=item B<--list --format> format ++ + =item B<--list --long> + + List available templates. + +-The alternative I<--list --long> form shows lots more details about +-each operating system option. ++It is possible to choose with I<--format> the output format for the list ++templates: ++ ++=over 4 ++ ++=item B ++ ++The default format, prints only the template identifier and, next to it, ++its short description. ++ ++=item B ++ ++Prints a textual list with the details of the available sources, followed ++by the details of the available templates. ++ ++=back ++ ++I<--long> is a shorthand for the C format. + + See also: I<--source>, I<--notes>, L. + +-- +1.8.4.2 + diff --git a/0062-builder-small-refactor-of-the-list-output.patch b/0062-builder-small-refactor-of-the-list-output.patch deleted file mode 100644 index ddb8c83..0000000 --- a/0062-builder-small-refactor-of-the-list-output.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 5948434bbf95ed9f39aac705c9898f55d9294806 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 16 Jan 2014 11:49:05 +0100 -Subject: [PATCH] builder: small refactor of the list output - -Switch from a boolean for the short/long list output to labels for the -actual format. Also, split the output of each list format to an own -function for easier maintaineance. - -(cherry picked from commit 91aae893c70b3877b31803800ba77836fd7a45e8) ---- - builder/builder.ml | 4 +-- - builder/cmdline.ml | 9 +++--- - builder/list_entries.ml | 82 +++++++++++++++++++++++++++--------------------- - builder/list_entries.mli | 2 +- - 4 files changed, 54 insertions(+), 43 deletions(-) - -diff --git a/builder/builder.ml b/builder/builder.ml -index 0160818..0aaa287 100644 ---- a/builder/builder.ml -+++ b/builder/builder.ml -@@ -37,7 +37,7 @@ let main () = - (* Command line argument parsing - see cmdline.ml. *) - let mode, arg, - attach, cache, check_signature, curl, debug, delete, delete_on_failure, -- edit, firstboot, run, format, gpg, hostname, install, list_long, links, -+ edit, firstboot, run, format, gpg, hostname, install, list_format, links, - memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, -@@ -148,7 +148,7 @@ let main () = - let mode = - match mode with - | `List -> (* --list *) -- List_entries.list_entries ~list_long ~sources index; -+ List_entries.list_entries ~list_format ~sources index; - exit 0 - - | `Print_cache -> (* --print-cache *) -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index 67b142a..f199f03 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -130,7 +130,8 @@ let parse_cmdline () = - links := (target, lns) :: !links - in - -- let list_long = ref false in -+ let list_format = ref `Short in -+ let list_set_long () = list_format := `Long in - - let memsize = ref None in - let set_memsize arg = memsize := Some arg in -@@ -255,7 +256,7 @@ let parse_cmdline () = - "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; - "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; - "--list", Arg.Unit list_mode, ditto; -- "--long", Arg.Set list_long, ditto; -+ "--long", Arg.Unit list_set_long, " " ^ s_"List available templates, in long textual form"; - "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; - "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; - "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; -@@ -329,7 +330,7 @@ read the man page virt-builder(1). - let gpg = !gpg in - let hostname = !hostname in - let install = List.rev !install in -- let list_long = !list_long in -+ let list_format = !list_format in - let links = List.rev !links in - let memsize = !memsize in - let mkdirs = List.rev !mkdirs in -@@ -443,7 +444,7 @@ read the man page virt-builder(1). - - mode, arg, - attach, cache, check_signature, curl, debug, delete, delete_on_failure, -- edit, firstboot, run, format, gpg, hostname, install, list_long, links, -+ edit, firstboot, run, format, gpg, hostname, install, list_format, links, - memsize, mkdirs, - network, output, password_crypto, quiet, root_password, scrub, - scrub_logfile, size, smp, sources, sync, timezone, update, upload, -diff --git a/builder/list_entries.ml b/builder/list_entries.ml -index 87001c0..97ab201 100644 ---- a/builder/list_entries.ml -+++ b/builder/list_entries.ml -@@ -21,15 +21,35 @@ open Common_utils - - open Printf - --let list_entries ?(list_long = false) ~sources index = -- if list_long then ( -- List.iter ( -- fun (source, fingerprint) -> -- printf (f_"Source URI: %s\n") source; -- printf (f_"Fingerprint: %s\n") fingerprint; -+let rec list_entries ~list_format ~sources index = -+ match list_format with -+ | `Short -> list_entries_short index -+ | `Long -> list_entries_long ~sources index -+ -+and list_entries_short index = -+ List.iter ( -+ fun (name, { Index_parser.printable_name = printable_name; -+ size = size; -+ compressed_size = compressed_size; -+ notes = notes; -+ hidden = hidden }) -> -+ if not hidden then ( -+ printf "%-24s" name; -+ (match printable_name with -+ | None -> () -+ | Some s -> printf " %s" s -+ ); - printf "\n" -- ) sources -- ); -+ ) -+ ) index -+ -+and list_entries_long ~sources index = -+ List.iter ( -+ fun (source, fingerprint) -> -+ printf (f_"Source URI: %s\n") source; -+ printf (f_"Fingerprint: %s\n") fingerprint; -+ printf "\n" -+ ) sources; - - List.iter ( - fun (name, { Index_parser.printable_name = printable_name; -@@ -38,33 +58,23 @@ let list_entries ?(list_long = false) ~sources index = - notes = notes; - hidden = hidden }) -> - if not hidden then ( -- if not list_long then ( (* Short *) -- printf "%-24s" name; -- (match printable_name with -- | None -> () -- | Some s -> printf " %s" s -- ); -- printf "\n" -- ) -- else ( (* Long *) -- printf "%-24s %s\n" "os-version:" name; -- (match printable_name with -- | None -> () -- | Some name -> printf "%-24s %s\n" (s_"Full name:") name; -- ); -- printf "%-24s %s\n" (s_"Minimum/default size:") (human_size size); -- (match compressed_size with -- | None -> () -- | Some size -> -- printf "%-24s %s\n" (s_"Download size:") (human_size size); -- ); -- (match notes with -- | None -> () -- | Some notes -> -- printf "\n"; -- printf (f_"Notes:\n\n%s\n") notes -- ); -- printf "\n" -- ) -+ printf "%-24s %s\n" "os-version:" name; -+ (match printable_name with -+ | None -> () -+ | Some name -> printf "%-24s %s\n" (s_"Full name:") name; -+ ); -+ printf "%-24s %s\n" (s_"Minimum/default size:") (human_size size); -+ (match compressed_size with -+ | None -> () -+ | Some size -> -+ printf "%-24s %s\n" (s_"Download size:") (human_size size); -+ ); -+ (match notes with -+ | None -> () -+ | Some notes -> -+ printf "\n"; -+ printf (f_"Notes:\n\n%s\n") notes -+ ); -+ printf "\n" - ) - ) index -diff --git a/builder/list_entries.mli b/builder/list_entries.mli -index d9486b0..41d0bff 100644 ---- a/builder/list_entries.mli -+++ b/builder/list_entries.mli -@@ -16,4 +16,4 @@ - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - --val list_entries : ?list_long:bool -> sources:(string * string) list -> Index_parser.index -> unit -+val list_entries : list_format:([ `Short | `Long ]) -> sources:(string * string) list -> Index_parser.index -> unit --- -1.8.4.2 - diff --git a/0063-builder-add-a-JSON-output-for-list.patch b/0063-builder-add-a-JSON-output-for-list.patch new file mode 100644 index 0000000..bb4bc5c --- /dev/null +++ b/0063-builder-add-a-JSON-output-for-list.patch @@ -0,0 +1,232 @@ +From d0c8b9952c4d279475611926f4f1d07448f65ec5 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 16 Jan 2014 14:58:25 +0100 +Subject: [PATCH] builder: add a JSON output for --list + +Simple JSON output for sources and templates, to be able to query them +with no need to parse unstructured outputs like the "--list-format long" +one. + +(cherry picked from commit 5b42351294f4d0ace6960b9f31215f3f97c5259d) +--- + builder/cmdline.ml | 3 +- + builder/list_entries.ml | 60 +++++++++++++++++++++++++++++++++++ + builder/list_entries.mli | 2 +- + builder/test-virt-builder-list.sh | 67 +++++++++++++++++++++++++++++++++++++++ + builder/virt-builder.pod | 12 ++++++- + 5 files changed, 141 insertions(+), 3 deletions(-) + +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index 6d6439f..e3b1484 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -136,6 +136,7 @@ let parse_cmdline () = + list_format := match arg with + | "short" -> `Short + | "long" -> `Long ++ | "json" -> `Json + | fmt -> + eprintf (f_"%s: invalid --list-format type '%s', see the man page.\n") prog fmt; + exit 1 in +@@ -265,7 +266,7 @@ let parse_cmdline () = + "--list", Arg.Unit list_mode, ditto; + "--long", Arg.Unit list_set_long, " " ^ s_"Shortcut for --list-format short"; + "--list-format", Arg.String list_set_format, +- "short|long" ^ " " ^ s_"Set the format for --list (default: short)"; ++ "short|long|json" ^ " " ^ s_"Set the format for --list (default: short)"; + "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; + "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; + "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index 97ab201..7369e6c 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -25,6 +25,7 @@ let rec list_entries ~list_format ~sources index = + match list_format with + | `Short -> list_entries_short index + | `Long -> list_entries_long ~sources index ++ | `Json -> list_entries_json ~sources index + + and list_entries_short index = + List.iter ( +@@ -78,3 +79,62 @@ and list_entries_long ~sources index = + printf "\n" + ) + ) index ++ ++and list_entries_json ~sources index = ++ let trailing_comma index size = ++ if index = size - 1 then "" else "," in ++ let json_string_of_bool b = ++ if b then "true" else "false" in ++ let json_string_escape str = ++ let res = ref "" in ++ for i = 0 to String.length str - 1 do ++ res := !res ^ (match str.[i] with ++ | '"' -> "\\\"" ++ | '\\' -> "\\\\" ++ | '\b' -> "\\b" ++ | '\n' -> "\\n" ++ | '\r' -> "\\r" ++ | '\t' -> "\\t" ++ | c -> String.make 1 c) ++ done; ++ !res in ++ let json_optional_printf_string key value = ++ match value with ++ | None -> () ++ | Some str -> ++ printf " \"%s\": \"%s\",\n" key (json_string_escape str) in ++ let json_optional_printf_int64 key value = ++ match value with ++ | None -> () ++ | Some n -> ++ printf " \"%s\": \"%Ld\",\n" key n in ++ ++ printf "{\n"; ++ printf " \"version\": %d,\n" 1; ++ printf " \"sources\": [\n"; ++ iteri ( ++ fun i (source, fingerprint) -> ++ printf " {\n"; ++ printf " \"uri\": \"%s\",\n" source; ++ printf " \"fingerprint\": \"%s\"\n" fingerprint; ++ printf " }%s\n" (trailing_comma i (List.length sources)) ++ ) sources; ++ printf " ],\n"; ++ printf " \"templates\": [\n"; ++ iteri ( ++ fun i (name, { Index_parser.printable_name = printable_name; ++ size = size; ++ compressed_size = compressed_size; ++ notes = notes; ++ hidden = hidden }) -> ++ printf " {\n"; ++ printf " \"os-version\": \"%s\",\n" name; ++ json_optional_printf_string "full-name" printable_name; ++ printf " \"size\": %Ld,\n" size; ++ json_optional_printf_int64 "compressed-size" compressed_size; ++ json_optional_printf_string "notes" notes; ++ printf " \"hidden\": %s\n" (json_string_of_bool hidden); ++ printf " }%s\n" (trailing_comma i (List.length index)) ++ ) index; ++ printf " ]\n"; ++ printf "}\n" +diff --git a/builder/list_entries.mli b/builder/list_entries.mli +index 41d0bff..e7c32f1 100644 +--- a/builder/list_entries.mli ++++ b/builder/list_entries.mli +@@ -16,4 +16,4 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + *) + +-val list_entries : list_format:([ `Short | `Long ]) -> sources:(string * string) list -> Index_parser.index -> unit ++val list_entries : list_format:([ `Short | `Long | `Json ]) -> sources:(string * string) list -> Index_parser.index -> unit +diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh +index 083c035..c3b791f 100755 +--- a/builder/test-virt-builder-list.sh ++++ b/builder/test-virt-builder-list.sh +@@ -103,3 +103,70 @@ Phony Windows look-alike used for testing." ]; then + echo "$long_list" + exit 1 + fi ++ ++json_list=$(./virt-builder --no-check-signature --no-cache --list --list-format json) ++ ++if [ "$json_list" != "{ ++ \"version\": 1, ++ \"sources\": [ ++ { ++ \"uri\": \"$VIRT_BUILDER_SOURCE\", ++ \"fingerprint\": \"F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0\" ++ } ++ ], ++ \"templates\": [ ++ { ++ \"os-version\": \"phony-debian\", ++ \"full-name\": \"Phony Debian\", ++ \"size\": 536870912, ++ \"notes\": \"Phony Debian look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-fedora\", ++ \"full-name\": \"Phony Fedora\", ++ \"size\": 1073741824, ++ \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-fedora-qcow2\", ++ \"full-name\": \"Phony Fedora qcow2\", ++ \"size\": 1073741824, ++ \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-fedora-qcow2-uncompressed\", ++ \"full-name\": \"Phony Fedora qcow2 uncompressed\", ++ \"size\": 1073741824, ++ \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-fedora-no-format\", ++ \"full-name\": \"Phony Fedora\", ++ \"size\": 1073741824, ++ \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-ubuntu\", ++ \"full-name\": \"Phony Ubuntu\", ++ \"size\": 536870912, ++ \"notes\": \"Phony Ubuntu look-alike used for testing.\", ++ \"hidden\": false ++ }, ++ { ++ \"os-version\": \"phony-windows\", ++ \"full-name\": \"Phony Windows\", ++ \"size\": 536870912, ++ \"notes\": \"Phony Windows look-alike used for testing.\", ++ \"hidden\": false ++ } ++ ] ++}" ]; then ++ echo "$0: unexpected --list --format json output:" ++ echo "$json_list" ++ exit 1 ++fi +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 8e60d30..6f835ed 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -31,7 +31,7 @@ virt-builder - Build virtual machine images quickly + [--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...'] + [--firstboot-install PKG,[PKG...]] + +- virt-builder -l|--list [--long] [--list-format short|long] ++ virt-builder -l|--list [--long] [--list-format short|long|json] + + virt-builder --notes os-version + +@@ -395,6 +395,16 @@ its short description. + Prints a textual list with the details of the available sources, followed + by the details of the available templates. + ++=item B ++ ++Prints a JSON object with the details of the available sources and ++the details of the available templates. ++ ++The C key in the main object represents the "compatibility version", ++and it is bumped every time the resulting JSON output is incompatible with ++the previous versions (for example the structure has changed, or non-optional ++keys are no more present). ++ + =back + + I<--long> is a shorthand for the C format. +-- +1.8.4.2 + diff --git a/0063-builder-add-list-format.patch b/0063-builder-add-list-format.patch deleted file mode 100644 index 6c5ea43..0000000 --- a/0063-builder-add-list-format.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 2067ada4285db0b22d5532681ab0d7f8c6f78af0 Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 16 Jan 2014 12:34:48 +0100 -Subject: [PATCH] builder: add --list-format - -Add a --list-format which allows to choose which in format should be the -output of --list. - -(cherry picked from commit e45bfe0d36c9f50143b13921a498f00ee06ca27d) ---- - builder/cmdline.ml | 11 ++++++++++- - builder/virt-builder.pod | 24 +++++++++++++++++++++--- - 2 files changed, 31 insertions(+), 4 deletions(-) - -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index f199f03..6d6439f 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -132,6 +132,13 @@ let parse_cmdline () = - - let list_format = ref `Short in - let list_set_long () = list_format := `Long in -+ let list_set_format arg = -+ list_format := match arg with -+ | "short" -> `Short -+ | "long" -> `Long -+ | fmt -> -+ eprintf (f_"%s: invalid --list-format type '%s', see the man page.\n") prog fmt; -+ exit 1 in - - let memsize = ref None in - let set_memsize arg = memsize := Some arg in -@@ -256,7 +263,9 @@ let parse_cmdline () = - "--link", Arg.String add_link, "target:link.." ^ " " ^ s_"Create symbolic links"; - "-l", Arg.Unit list_mode, " " ^ s_"List available templates"; - "--list", Arg.Unit list_mode, ditto; -- "--long", Arg.Unit list_set_long, " " ^ s_"List available templates, in long textual form"; -+ "--long", Arg.Unit list_set_long, " " ^ s_"Shortcut for --list-format short"; -+ "--list-format", Arg.String list_set_format, -+ "short|long" ^ " " ^ s_"Set the format for --list (default: short)"; - "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; - "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; - "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 9cbfbab..05abcc6 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -31,7 +31,7 @@ virt-builder - Build virtual machine images quickly - [--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...'] - [--firstboot-install PKG,[PKG...]] - -- virt-builder -l|--list [--long] -+ virt-builder -l|--list [--long] [--list-format short|long] - - virt-builder --notes os-version - -@@ -374,12 +374,30 @@ pointing at C. - - =item B<--list> - -+=item B<--list --format> format -+ - =item B<--list --long> - - List available templates. - --The alternative I<--list --long> form shows lots more details about --each operating system option. -+It is possible to choose with I<--format> the output format for the list -+templates: -+ -+=over 4 -+ -+=item B -+ -+The default format, prints only the template identifier and, next to it, -+its short description. -+ -+=item B -+ -+Prints a textual list with the details of the available sources, followed -+by the details of the available templates. -+ -+=back -+ -+I<--long> is a shorthand for the C format. - - See also: I<--source>, I<--notes>, L. - --- -1.8.4.2 - diff --git a/0064-builder-Fix-unterminated-I-.-in-man-page.patch b/0064-builder-Fix-unterminated-I-.-in-man-page.patch new file mode 100644 index 0000000..07505c3 --- /dev/null +++ b/0064-builder-Fix-unterminated-I-.-in-man-page.patch @@ -0,0 +1,27 @@ +From 41c857fb7672379d7036cf73e4de9808a900bc22 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Thu, 16 Jan 2014 18:01:20 +0000 +Subject: [PATCH] builder: Fix unterminated I<...> in man page. + +Thanks: Lukas Zapletal. +(cherry picked from commit b3cf877e58cbcc4f6fd5d228028e19c1b294b1ac) +--- + builder/virt-builder.pod | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 6f835ed..918f372 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -1012,7 +1012,7 @@ Files are deleted (I<--delete>, I<--scrub>). + + =item * + +-Symbolic links are created (I<--link). ++Symbolic links are created (I<--link>). + + =item * + +-- +1.8.4.2 + diff --git a/0064-builder-add-a-JSON-output-for-list.patch b/0064-builder-add-a-JSON-output-for-list.patch deleted file mode 100644 index e00e590..0000000 --- a/0064-builder-add-a-JSON-output-for-list.patch +++ /dev/null @@ -1,232 +0,0 @@ -From 1ae52065ca3d8415ea81278224b04269e4221dab Mon Sep 17 00:00:00 2001 -From: Pino Toscano -Date: Thu, 16 Jan 2014 14:58:25 +0100 -Subject: [PATCH] builder: add a JSON output for --list - -Simple JSON output for sources and templates, to be able to query them -with no need to parse unstructured outputs like the "--list-format long" -one. - -(cherry picked from commit 5b42351294f4d0ace6960b9f31215f3f97c5259d) ---- - builder/cmdline.ml | 3 +- - builder/list_entries.ml | 60 +++++++++++++++++++++++++++++++++++ - builder/list_entries.mli | 2 +- - builder/test-virt-builder-list.sh | 67 +++++++++++++++++++++++++++++++++++++++ - builder/virt-builder.pod | 12 ++++++- - 5 files changed, 141 insertions(+), 3 deletions(-) - -diff --git a/builder/cmdline.ml b/builder/cmdline.ml -index 6d6439f..e3b1484 100644 ---- a/builder/cmdline.ml -+++ b/builder/cmdline.ml -@@ -136,6 +136,7 @@ let parse_cmdline () = - list_format := match arg with - | "short" -> `Short - | "long" -> `Long -+ | "json" -> `Json - | fmt -> - eprintf (f_"%s: invalid --list-format type '%s', see the man page.\n") prog fmt; - exit 1 in -@@ -265,7 +266,7 @@ let parse_cmdline () = - "--list", Arg.Unit list_mode, ditto; - "--long", Arg.Unit list_set_long, " " ^ s_"Shortcut for --list-format short"; - "--list-format", Arg.String list_set_format, -- "short|long" ^ " " ^ s_"Set the format for --list (default: short)"; -+ "short|long|json" ^ " " ^ s_"Set the format for --list (default: short)"; - "--no-logfile", Arg.Set scrub_logfile, " " ^ s_"Scrub build log file"; - "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options"; - "-m", Arg.Int set_memsize, "mb" ^ " " ^ s_"Set memory size"; -diff --git a/builder/list_entries.ml b/builder/list_entries.ml -index 97ab201..7369e6c 100644 ---- a/builder/list_entries.ml -+++ b/builder/list_entries.ml -@@ -25,6 +25,7 @@ let rec list_entries ~list_format ~sources index = - match list_format with - | `Short -> list_entries_short index - | `Long -> list_entries_long ~sources index -+ | `Json -> list_entries_json ~sources index - - and list_entries_short index = - List.iter ( -@@ -78,3 +79,62 @@ and list_entries_long ~sources index = - printf "\n" - ) - ) index -+ -+and list_entries_json ~sources index = -+ let trailing_comma index size = -+ if index = size - 1 then "" else "," in -+ let json_string_of_bool b = -+ if b then "true" else "false" in -+ let json_string_escape str = -+ let res = ref "" in -+ for i = 0 to String.length str - 1 do -+ res := !res ^ (match str.[i] with -+ | '"' -> "\\\"" -+ | '\\' -> "\\\\" -+ | '\b' -> "\\b" -+ | '\n' -> "\\n" -+ | '\r' -> "\\r" -+ | '\t' -> "\\t" -+ | c -> String.make 1 c) -+ done; -+ !res in -+ let json_optional_printf_string key value = -+ match value with -+ | None -> () -+ | Some str -> -+ printf " \"%s\": \"%s\",\n" key (json_string_escape str) in -+ let json_optional_printf_int64 key value = -+ match value with -+ | None -> () -+ | Some n -> -+ printf " \"%s\": \"%Ld\",\n" key n in -+ -+ printf "{\n"; -+ printf " \"version\": %d,\n" 1; -+ printf " \"sources\": [\n"; -+ iteri ( -+ fun i (source, fingerprint) -> -+ printf " {\n"; -+ printf " \"uri\": \"%s\",\n" source; -+ printf " \"fingerprint\": \"%s\"\n" fingerprint; -+ printf " }%s\n" (trailing_comma i (List.length sources)) -+ ) sources; -+ printf " ],\n"; -+ printf " \"templates\": [\n"; -+ iteri ( -+ fun i (name, { Index_parser.printable_name = printable_name; -+ size = size; -+ compressed_size = compressed_size; -+ notes = notes; -+ hidden = hidden }) -> -+ printf " {\n"; -+ printf " \"os-version\": \"%s\",\n" name; -+ json_optional_printf_string "full-name" printable_name; -+ printf " \"size\": %Ld,\n" size; -+ json_optional_printf_int64 "compressed-size" compressed_size; -+ json_optional_printf_string "notes" notes; -+ printf " \"hidden\": %s\n" (json_string_of_bool hidden); -+ printf " }%s\n" (trailing_comma i (List.length index)) -+ ) index; -+ printf " ]\n"; -+ printf "}\n" -diff --git a/builder/list_entries.mli b/builder/list_entries.mli -index 41d0bff..e7c32f1 100644 ---- a/builder/list_entries.mli -+++ b/builder/list_entries.mli -@@ -16,4 +16,4 @@ - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - *) - --val list_entries : list_format:([ `Short | `Long ]) -> sources:(string * string) list -> Index_parser.index -> unit -+val list_entries : list_format:([ `Short | `Long | `Json ]) -> sources:(string * string) list -> Index_parser.index -> unit -diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh -index 083c035..c3b791f 100755 ---- a/builder/test-virt-builder-list.sh -+++ b/builder/test-virt-builder-list.sh -@@ -103,3 +103,70 @@ Phony Windows look-alike used for testing." ]; then - echo "$long_list" - exit 1 - fi -+ -+json_list=$(./virt-builder --no-check-signature --no-cache --list --list-format json) -+ -+if [ "$json_list" != "{ -+ \"version\": 1, -+ \"sources\": [ -+ { -+ \"uri\": \"$VIRT_BUILDER_SOURCE\", -+ \"fingerprint\": \"F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0\" -+ } -+ ], -+ \"templates\": [ -+ { -+ \"os-version\": \"phony-debian\", -+ \"full-name\": \"Phony Debian\", -+ \"size\": 536870912, -+ \"notes\": \"Phony Debian look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-fedora\", -+ \"full-name\": \"Phony Fedora\", -+ \"size\": 1073741824, -+ \"notes\": \"Phony Fedora look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-fedora-qcow2\", -+ \"full-name\": \"Phony Fedora qcow2\", -+ \"size\": 1073741824, -+ \"notes\": \"Phony Fedora look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-fedora-qcow2-uncompressed\", -+ \"full-name\": \"Phony Fedora qcow2 uncompressed\", -+ \"size\": 1073741824, -+ \"notes\": \"Phony Fedora look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-fedora-no-format\", -+ \"full-name\": \"Phony Fedora\", -+ \"size\": 1073741824, -+ \"notes\": \"Phony Fedora look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-ubuntu\", -+ \"full-name\": \"Phony Ubuntu\", -+ \"size\": 536870912, -+ \"notes\": \"Phony Ubuntu look-alike used for testing.\", -+ \"hidden\": false -+ }, -+ { -+ \"os-version\": \"phony-windows\", -+ \"full-name\": \"Phony Windows\", -+ \"size\": 536870912, -+ \"notes\": \"Phony Windows look-alike used for testing.\", -+ \"hidden\": false -+ } -+ ] -+}" ]; then -+ echo "$0: unexpected --list --format json output:" -+ echo "$json_list" -+ exit 1 -+fi -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index 05abcc6..ded045b 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -31,7 +31,7 @@ virt-builder - Build virtual machine images quickly - [--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...'] - [--firstboot-install PKG,[PKG...]] - -- virt-builder -l|--list [--long] [--list-format short|long] -+ virt-builder -l|--list [--long] [--list-format short|long|json] - - virt-builder --notes os-version - -@@ -395,6 +395,16 @@ its short description. - Prints a textual list with the details of the available sources, followed - by the details of the available templates. - -+=item B -+ -+Prints a JSON object with the details of the available sources and -+the details of the available templates. -+ -+The C key in the main object represents the "compatibility version", -+and it is bumped every time the resulting JSON output is incompatible with -+the previous versions (for example the structure has changed, or non-optional -+keys are no more present). -+ - =back - - I<--long> is a shorthand for the C format. --- -1.8.4.2 - diff --git a/0065-builder-Fix-unterminated-I-.-in-man-page.patch b/0065-builder-Fix-unterminated-I-.-in-man-page.patch deleted file mode 100644 index 7cfc8a8..0000000 --- a/0065-builder-Fix-unterminated-I-.-in-man-page.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 504bc13a693fd95fb2b97f18f4a6400250216145 Mon Sep 17 00:00:00 2001 -From: "Richard W.M. Jones" -Date: Thu, 16 Jan 2014 18:01:20 +0000 -Subject: [PATCH] builder: Fix unterminated I<...> in man page. - -Thanks: Lukas Zapletal. -(cherry picked from commit b3cf877e58cbcc4f6fd5d228028e19c1b294b1ac) ---- - builder/virt-builder.pod | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod -index ded045b..9e433e4 100644 ---- a/builder/virt-builder.pod -+++ b/builder/virt-builder.pod -@@ -1012,7 +1012,7 @@ Files are deleted (I<--delete>, I<--scrub>). - - =item * - --Symbolic links are created (I<--link). -+Symbolic links are created (I<--link>). - - =item * - --- -1.8.4.2 - diff --git a/0065-builder-add-index-struct.h-as-dependency-for-index-p.patch b/0065-builder-add-index-struct.h-as-dependency-for-index-p.patch new file mode 100644 index 0000000..8bd1f80 --- /dev/null +++ b/0065-builder-add-index-struct.h-as-dependency-for-index-p.patch @@ -0,0 +1,31 @@ +From 3d05b9c7d85f58b03a3949951be3a885a459129b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 21 Jan 2014 10:54:19 +0100 +Subject: [PATCH] builder: add index-struct.h as dependency for + index-parser-c.c + +Just like with index-parse.h, also index-struct.h is a dependency of +index-parser-c.c which automake cannot generate correctly. +Thus, add it manually. + +(cherry picked from commit e2cc8b6465a400024fe2f0fcce0d0ff5f7e7719c) +--- + builder/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index d718c22..4777619 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -229,7 +229,7 @@ CLEANFILES += \ + + # Fix dependencies which automake doesn't generate correctly. + if HAVE_OCAML +-index-parser-c.o: index-parse.h ++index-parser-c.o: index-parse.h index-struct.h + index-scan.o: index-parse.h + endif + index-validate.o: index-parse.h +-- +1.8.4.2 + diff --git a/0066-builder-allow-more-empty-lines-in-index-files.patch b/0066-builder-allow-more-empty-lines-in-index-files.patch new file mode 100644 index 0000000..01cf117 --- /dev/null +++ b/0066-builder-allow-more-empty-lines-in-index-files.patch @@ -0,0 +1,48 @@ +From 773d8f3738d189bd710ff2c11976e913f870364d Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 21 Jan 2014 17:54:23 +0100 +Subject: [PATCH] builder: allow more empty lines in index files + +Improve the index grammar to allow more than one empty line between +sections, and to allow any number of empty lines at the end of the file +(after the last section). + +(cherry picked from commit 4505f61979a9737da53cdad419ae6d22538780d5) +--- + builder/index-parse.y | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/builder/index-parse.y b/builder/index-parse.y +index f5e551b..a8d2f62 100644 +--- a/builder/index-parse.y ++++ b/builder/index-parse.y +@@ -80,10 +80,10 @@ index: + { parsed_index = $2; } + + sections: +- section ++ section emptylines + { $$ = $1; } +- | section EMPTY_LINE sections +- { $$ = $1; $$->next = $3; } ++ | section EMPTY_LINE emptylines sections ++ { $$ = $1; $$->next = $4; } + + section: + SECTION_HEADER fields +@@ -113,6 +113,12 @@ continuations: + free ($1); + free ($2); } + ++emptylines: ++ /* empty */ ++ {} ++ | EMPTY_LINE emptylines ++ {} ++ + %% + + void +-- +1.8.4.2 + diff --git a/0067-builder-proper-consider-subkeys-in-index-files.patch b/0067-builder-proper-consider-subkeys-in-index-files.patch new file mode 100644 index 0000000..ea51a00 --- /dev/null +++ b/0067-builder-proper-consider-subkeys-in-index-files.patch @@ -0,0 +1,214 @@ +From 7685b022e3fb49c69c8222950462ad4165d18133 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 21 Jan 2014 18:52:42 +0100 +Subject: [PATCH] builder: proper consider subkeys in index files + +The index files already allowed the 'key[subkey]=...' syntax for keys, +but considering such string as whole key. Proper split the parsing and +the handling of the subkeys, so they can be searched a bit easier. + +This causes no actual behaviour changes, it is just internal +micro-refactoring. (Thanks Rich for the hints, too.) + +(cherry picked from commit 5cbdf35d651b6c730d62d9af4876039faa122efc) +--- + builder/index-parser-c.c | 15 +++++++++++---- + builder/index-scan.l | 9 ++++++++- + builder/index-struct.c | 1 + + builder/index-struct.h | 1 + + builder/index_parser.ml | 44 +++++++++++++++++++++++++------------------- + 5 files changed, 46 insertions(+), 24 deletions(-) + +diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c +index 17e680b..fbbebff 100644 +--- a/builder/index-parser-c.c ++++ b/builder/index-parser-c.c +@@ -49,7 +49,7 @@ value + virt_builder_parse_index (value filenamev) + { + CAMLparam1 (filenamev); +- CAMLlocal4 (rv, v, sv, fv); ++ CAMLlocal5 (rv, v, sv, sv2, fv); + struct section *sections; + size_t i, nr_sections; + +@@ -83,11 +83,18 @@ virt_builder_parse_index (value filenamev) + + for (j = 0, fields = sections->fields; fields != NULL; + j++, fields = fields->next) { +- v = caml_alloc_tuple (2); ++ v = caml_alloc_tuple (3); + sv = caml_copy_string (fields->key); +- Store_field (v, 0, sv); /* (key, value) */ +- sv = caml_copy_string (fields->value); ++ Store_field (v, 0, sv); /* (key, Some subkey, value) */ ++ if (fields->subkey) { ++ sv2 = caml_copy_string (fields->subkey); ++ sv = caml_alloc (1, 0); ++ Store_field (sv, 0, sv2); ++ } else ++ sv = Val_int (0); + Store_field (v, 1, sv); ++ sv = caml_copy_string (fields->value); ++ Store_field (v, 2, sv); + Store_field (fv, j, v); /* assign to return array of fields */ + } + +diff --git a/builder/index-scan.l b/builder/index-scan.l +index 9a6a0e3..7a9618f 100644 +--- a/builder/index-scan.l ++++ b/builder/index-scan.l +@@ -58,10 +58,17 @@ extern void yyerror (const char *); + + /* field=value or field[subfield]=value */ + ^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n { +- size_t i = strcspn (yytext, "="); ++ size_t i = strcspn (yytext, "=["); + yylval.field = malloc (sizeof (struct field)); + yylval.field->next = NULL; + yylval.field->key = strndup (yytext, i); ++ if (yytext[i] == '[') { ++ size_t j = strcspn (yytext+i+1, "]"); ++ yylval.field->subkey = strndup (yytext+i+1, j); ++ i += 1+j+2; ++ } else { ++ yylval.field->subkey = NULL; ++ } + /* Note we chop the final \n off here. */ + yylval.field->value = strndup (yytext+i+1, yyleng-(i+2)); + return FIELD; +diff --git a/builder/index-struct.c b/builder/index-struct.c +index 26bed24..fe5b0e3 100644 +--- a/builder/index-struct.c ++++ b/builder/index-struct.c +@@ -52,6 +52,7 @@ free_field (struct field *field) + if (field) { + free_field (field->next); + free (field->key); ++ free (field->subkey); + free (field->value); + free (field); + } +diff --git a/builder/index-struct.h b/builder/index-struct.h +index ac8a3dd..f92e01d 100644 +--- a/builder/index-struct.h ++++ b/builder/index-struct.h +@@ -32,6 +32,7 @@ struct section { + struct field { + struct field *next; + char *key; ++ char *subkey; + char *value; + }; + +diff --git a/builder/index_parser.ml b/builder/index_parser.ml +index 453a3a1..da44b21 100644 +--- a/builder/index_parser.ml ++++ b/builder/index_parser.ml +@@ -101,7 +101,7 @@ let print_entry chan (name, { printable_name = printable_name; + type sections = section array + and section = string * fields (* [name] + fields *) + and fields = field array +-and field = string * string (* key + value *) ++and field = string * string option * string (* key + subkey + value *) + + (* Calls yyparse in the C code. *) + external parse_index : string -> sections = "virt_builder_parse_index" +@@ -149,12 +149,17 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + fun (n, fields) -> + let fseen = Hashtbl.create 13 in + List.iter ( +- fun (field, _) -> +- if Hashtbl.mem fseen field then ( +- eprintf (f_"virt-builder: index is corrupt: %s: field '%s' appears two or more times\n") n field; ++ fun (field, subkey, _) -> ++ let hashkey = (field, subkey) in ++ if Hashtbl.mem fseen hashkey then ( ++ (match subkey with ++ | Some value -> ++ eprintf (f_"virt-builder: index is corrupt: %s: field '%s[%s]' appears two or more times\n") n field value ++ | None -> ++ eprintf (f_"virt-builder: index is corrupt: %s: field '%s' appears two or more times\n") n field); + corrupt_file () + ); +- Hashtbl.add fseen field true ++ Hashtbl.add fseen hashkey true + ) fields + ) sections; + +@@ -162,25 +167,26 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + let entries = + List.map ( + fun (n, fields) -> ++ let fields = List.map (fun (k, sk, v) -> (k, sk), v) fields in + let printable_name = +- try Some (List.assoc "name" fields) with Not_found -> None in ++ try Some (List.assoc ("name", None) fields) with Not_found -> None in + let osinfo = +- try Some (List.assoc "osinfo" fields) with Not_found -> None in ++ try Some (List.assoc ("osinfo", None) fields) with Not_found -> None in + let file_uri = +- try make_absolute_uri (List.assoc "file" fields) ++ try make_absolute_uri (List.assoc ("file", None) fields) + with Not_found -> + eprintf (f_"virt-builder: no 'file' (URI) entry for '%s'\n") n; + corrupt_file () in + let signature_uri = +- try Some (make_absolute_uri (List.assoc "sig" fields)) ++ try Some (make_absolute_uri (List.assoc ("sig", None) fields)) + with Not_found -> None in + let checksum_sha512 = +- try Some (List.assoc "checksum[sha512]" fields) ++ try Some (List.assoc ("checksum", Some "sha512") fields) + with Not_found -> +- try Some (List.assoc "checksum" fields) ++ try Some (List.assoc ("checksum", None) fields) + with Not_found -> None in + let revision = +- try int_of_string (List.assoc "revision" fields) ++ try int_of_string (List.assoc ("revision", None) fields) + with + | Not_found -> 1 + | Failure "int_of_string" -> +@@ -188,9 +194,9 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + n; + corrupt_file () in + let format = +- try Some (List.assoc "format" fields) with Not_found -> None in ++ try Some (List.assoc ("format", None) fields) with Not_found -> None in + let size = +- try Int64.of_string (List.assoc "size" fields) ++ try Int64.of_string (List.assoc ("size", None) fields) + with + | Not_found -> + eprintf (f_"virt-builder: no 'size' field for '%s'\n") n; +@@ -200,7 +206,7 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + n; + corrupt_file () in + let compressed_size = +- try Some (Int64.of_string (List.assoc "compressed_size" fields)) ++ try Some (Int64.of_string (List.assoc ("compressed_size", None) fields)) + with + | Not_found -> + None +@@ -209,13 +215,13 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + n; + corrupt_file () in + let expand = +- try Some (List.assoc "expand" fields) with Not_found -> None in ++ try Some (List.assoc ("expand", None) fields) with Not_found -> None in + let lvexpand = +- try Some (List.assoc "lvexpand" fields) with Not_found -> None in ++ try Some (List.assoc ("lvexpand", None) fields) with Not_found -> None in + let notes = +- try Some (List.assoc "notes" fields) with Not_found -> None in ++ try Some (List.assoc ("notes", None) fields) with Not_found -> None in + let hidden = +- try bool_of_string (List.assoc "hidden" fields) ++ try bool_of_string (List.assoc ("hidden", None) fields) + with + | Not_found -> false + | Failure "bool_of_string" -> +-- +1.8.4.2 + diff --git a/0068-builder-fix-small-regression-in-subkey-parsing.patch b/0068-builder-fix-small-regression-in-subkey-parsing.patch new file mode 100644 index 0000000..4bb3375 --- /dev/null +++ b/0068-builder-fix-small-regression-in-subkey-parsing.patch @@ -0,0 +1,29 @@ +From 614ff644efc8d0e6a3da04663d4581fbf1c42f26 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 22 Jan 2014 15:34:22 +0100 +Subject: [PATCH] builder: fix small regression in subkey parsing + +Introduced in 5cbdf35d651b6c730d62d9af4876039faa122efc, it caused the +first character of the value to be skipped if the key has a subkey. + +(cherry picked from commit 9e4357ca54282c1ab053dd5a8ebd64a323830cf4) +--- + builder/index-scan.l | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builder/index-scan.l b/builder/index-scan.l +index 7a9618f..e43f82e 100644 +--- a/builder/index-scan.l ++++ b/builder/index-scan.l +@@ -65,7 +65,7 @@ extern void yyerror (const char *); + if (yytext[i] == '[') { + size_t j = strcspn (yytext+i+1, "]"); + yylval.field->subkey = strndup (yytext+i+1, j); +- i += 1+j+2; ++ i += 1+j+1; + } else { + yylval.field->subkey = NULL; + } +-- +1.8.4.2 + diff --git a/0069-builder-small-code-simplification.patch b/0069-builder-small-code-simplification.patch new file mode 100644 index 0000000..45b351e --- /dev/null +++ b/0069-builder-small-code-simplification.patch @@ -0,0 +1,35 @@ +From 5e42538ac42393be1a161b7eca158d4256422067 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Wed, 22 Jan 2014 23:13:24 +0100 +Subject: [PATCH] builder: small code simplification + +No actual behaviour changes, just remove extra match statements. + +(cherry picked from commit 958e84d69960faf5b321bdec92283a0b37abd858) +--- + builder/list_entries.ml | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index 7369e6c..9da7664 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -98,13 +98,11 @@ and list_entries_json ~sources index = + | c -> String.make 1 c) + done; + !res in +- let json_optional_printf_string key value = +- match value with ++ let json_optional_printf_string key = function + | None -> () + | Some str -> + printf " \"%s\": \"%s\",\n" key (json_string_escape str) in +- let json_optional_printf_int64 key value = +- match value with ++ let json_optional_printf_int64 key = function + | None -> () + | Some n -> + printf " \"%s\": \"%Ld\",\n" key n in +-- +1.8.4.2 + diff --git a/0070-builder-read-all-the-available-notes-from-the-index.patch b/0070-builder-read-all-the-available-notes-from-the-index.patch new file mode 100644 index 0000000..bc190e3 --- /dev/null +++ b/0070-builder-read-all-the-available-notes-from-the-index.patch @@ -0,0 +1,136 @@ +From 017d19ea51dc47d7539f4d68ee823049f7687a3c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 23 Jan 2014 15:36:15 +0100 +Subject: [PATCH] builder: read all the available notes from the index + +Switch the internal storage for the notes of each entry to a sorted list +with all the subkeys available (which should represent the translations +to various languages). +The current outputs are the same (i.e. still the untranslated notes), so +this is just internal refactoring/preparation. + +(cherry picked from commit b7cd63fc1dc031914e110a46de3faa431387d959) +--- + builder/builder.ml | 5 +++-- + builder/index_parser.ml | 20 ++++++++++++++++---- + builder/index_parser.mli | 2 +- + builder/list_entries.ml | 12 +++++++++--- + 4 files changed, 29 insertions(+), 10 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index 7e1c614..c0dc06d 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -202,9 +202,10 @@ let main () = + (match mode with + | `Notes -> (* --notes *) + (match entry with +- | { Index_parser.notes = Some notes } -> ++ | { Index_parser.notes = ("", notes) :: _ } -> + print_endline notes; +- | { Index_parser.notes = None } -> ++ | { Index_parser.notes = _ :: _ } ++ | { Index_parser.notes = [] } -> + printf (f_"There are no notes for %s\n") arg + ); + exit 0 +diff --git a/builder/index_parser.ml b/builder/index_parser.ml +index da44b21..d5b48ae 100644 +--- a/builder/index_parser.ml ++++ b/builder/index_parser.ml +@@ -35,7 +35,7 @@ and entry = { + compressed_size : int64 option; + expand : string option; + lvexpand : string option; +- notes : string option; ++ notes : (string * string) list; + hidden : bool; + + sigchecker : Sigchecker.t; +@@ -92,8 +92,9 @@ let print_entry chan (name, { printable_name = printable_name; + | Some lvexpand -> fp "lvexpand=%s\n" lvexpand + ); + (match notes with +- | None -> () +- | Some notes -> fp "notes=%s\n" notes ++ | ("", notes) :: _ -> fp "notes=%s\n" notes ++ | _ :: _ ++ | [] -> () + ); + if hidden then fp "hidden=true\n" + +@@ -219,7 +220,18 @@ let get_index ~prog ~debug ~downloader ~sigchecker source = + let lvexpand = + try Some (List.assoc ("lvexpand", None) fields) with Not_found -> None in + let notes = +- try Some (List.assoc ("notes", None) fields) with Not_found -> None in ++ let rec loop = function ++ | [] -> [] ++ | (("notes", subkey), value) :: xs -> ++ let subkey = match subkey with ++ | None -> "" ++ | Some v -> v in ++ (subkey, value) :: loop xs ++ | _ :: xs -> loop xs in ++ List.sort ( ++ fun (k1, _) (k2, _) -> ++ String.compare k1 k2 ++ ) (loop fields) in + let hidden = + try bool_of_string (List.assoc ("hidden", None) fields) + with +diff --git a/builder/index_parser.mli b/builder/index_parser.mli +index 54f1807..3c679b3 100644 +--- a/builder/index_parser.mli ++++ b/builder/index_parser.mli +@@ -29,7 +29,7 @@ and entry = { + compressed_size : int64 option; + expand : string option; + lvexpand : string option; +- notes : string option; ++ notes : (string * string) list; + hidden : bool; + + sigchecker : Sigchecker.t; +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index 9da7664..b947cc8 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -71,10 +71,11 @@ and list_entries_long ~sources index = + printf "%-24s %s\n" (s_"Download size:") (human_size size); + ); + (match notes with +- | None -> () +- | Some notes -> ++ | ("", notes) :: _ -> + printf "\n"; + printf (f_"Notes:\n\n%s\n") notes ++ | _ :: _ ++ | [] -> () + ); + printf "\n" + ) +@@ -106,6 +107,11 @@ and list_entries_json ~sources index = + | None -> () + | Some n -> + printf " \"%s\": \"%Ld\",\n" key n in ++ let print_notes = function ++ | ("", notes) :: _ -> ++ printf " \"notes\": \"%s\",\n" (json_string_escape notes) ++ | _ :: _ ++ | _ -> () in + + printf "{\n"; + printf " \"version\": %d,\n" 1; +@@ -130,7 +136,7 @@ and list_entries_json ~sources index = + json_optional_printf_string "full-name" printable_name; + printf " \"size\": %Ld,\n" size; + json_optional_printf_int64 "compressed-size" compressed_size; +- json_optional_printf_string "notes" notes; ++ print_notes notes; + printf " \"hidden\": %s\n" (json_string_of_bool hidden); + printf " }%s\n" (trailing_comma i (List.length index)) + ) index; +-- +1.8.4.2 + diff --git a/0071-builder-Add-selinux-relabel-option-to-perform-SELinu.patch b/0071-builder-Add-selinux-relabel-option-to-perform-SELinu.patch new file mode 100644 index 0000000..ad2d69a --- /dev/null +++ b/0071-builder-Add-selinux-relabel-option-to-perform-SELinu.patch @@ -0,0 +1,251 @@ +From e3e211cd14cecf1b54205a03f04ac311f8ce1b5f Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 24 Jan 2014 19:38:26 +0000 +Subject: [PATCH] builder: Add --selinux-relabel option to perform SELinux + relabelling. + +This adds the --selinux-relabel option which enables selinux in the +appliance and runs: + + if load_policy && fixfiles restore; then + rm -f /.autorelabel + else + touch /.autorelabel + fi + +at the end of installation. + +When possible this fixes SELinux labels in the guest and makes the +autorelabel step unnecessary. + +Notes: + + - The previous commit is required so that load_policy works. + + - During the build, SELinux is enabled but no policy is loaded. This + works because SELinux is in permissive mode. + + - This flag does not work if the appliance kernel and the guest have + greatly differing versions, eg. a RHEL 6 guest with a Fedora 20 + appliance. This is because SELinux changes the policy format and + breaks backwards compatibility. You would see errors like this: + + libsepol.policydb_write: policy version 15 cannot support MLS + libsepol.policydb_to_image: could not compute policy length + libsepol.policydb_to_image: could not create policy image + SELinux: Could not downgrade policy file /etc/selinux/targeted/policy/policy.24, searching for an older version. + SELinux: Could not open policy file <= /etc/selinux/targeted/policy/policy.24: No such file or directory + + These errors are ignored (they go to the log file) and relabelling + is done at boot instead. + + - It's not clear if loading guest policy is safe. You should trust + the virt-builder templates and to use libguestfs confinement for + additional protection. + +(cherry picked from commit 90e23b4e566f88595ac697b45d2531de851be6df) +--- + builder/builder.ml | 19 +++++++++++-- + builder/cmdline.ml | 8 ++++-- + builder/virt-builder.pod | 69 +++++++++++++++++++++++++++++++----------------- + 3 files changed, 68 insertions(+), 28 deletions(-) + +diff --git a/builder/builder.ml b/builder/builder.ml +index c0dc06d..b43bc4f 100644 +--- a/builder/builder.ml ++++ b/builder/builder.ml +@@ -42,8 +42,8 @@ let main () = + edit, firstboot, run, format, gpg, hostname, install, list_format, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, timezone, update, upload, +- writes = ++ scrub_logfile, selinux_relabel, size, smp, sources, sync, timezone, ++ update, upload, writes = + parse_cmdline () in + + (* Timestamped messages in ordinary, non-debug non-quiet mode. *) +@@ -580,6 +580,8 @@ let main () = + (match smp with None -> () | Some smp -> g#set_smp smp); + g#set_network network; + ++ g#set_selinux selinux_relabel; ++ + (* The output disk is being created, so use cache=unsafe here. *) + g#add_drive_opts ~format:output_format ~cachemode:"unsafe" output_filename; + +@@ -892,6 +894,19 @@ exec >>%s 2>&1 + do_run ~display:cmd cmd + ) run; + ++ if selinux_relabel then ( ++ msg (f_"SELinux relabelling"); ++ let cmd = sprintf " ++ if load_policy && fixfiles restore; then ++ rm -f /.autorelabel ++ else ++ touch /.autorelabel ++ echo '%s: SELinux relabelling failed, will relabel at boot instead.' ++ fi ++ " prog in ++ do_run ~display:"load_policy && fixfiles restore" cmd ++ ); ++ + (* Clean up the log file: + * + * If debugging, dump out the log file. +diff --git a/builder/cmdline.ml b/builder/cmdline.ml +index e3b1484..a6cb6c5 100644 +--- a/builder/cmdline.ml ++++ b/builder/cmdline.ml +@@ -180,6 +180,7 @@ let parse_cmdline () = + let add_scrub s = scrub := s :: !scrub in + + let scrub_logfile = ref false in ++ let selinux_relabel = ref false in + + let size = ref None in + let set_size arg = size := Some (parse_size ~prog arg) in +@@ -287,6 +288,8 @@ let parse_cmdline () = + "--run", Arg.String add_run, "script" ^ " " ^ s_"Run script in disk image"; + "--run-command", Arg.String add_run_cmd, "cmd+args" ^ " " ^ s_"Run command in disk image"; + "--scrub", Arg.String add_scrub, "name" ^ " " ^ s_"Scrub a file"; ++ "--selinux-relabel", Arg.Set selinux_relabel, ++ " " ^ s_"Relabel files with correct SELinux labels"; + "--size", Arg.String set_size, "size" ^ " " ^ s_"Set output disk size"; + "--smp", Arg.Int set_smp, "vcpus" ^ " " ^ s_"Set number of vCPUs"; + "--source", Arg.String add_source, "URL" ^ " " ^ s_"Set source URL"; +@@ -351,6 +354,7 @@ read the man page virt-builder(1). + let root_password = !root_password in + let scrub = List.rev !scrub in + let scrub_logfile = !scrub_logfile in ++ let selinux_relabel = !selinux_relabel in + let size = !size in + let smp = !smp in + let sources = List.rev !sources in +@@ -457,5 +461,5 @@ read the man page virt-builder(1). + edit, firstboot, run, format, gpg, hostname, install, list_format, links, + memsize, mkdirs, + network, output, password_crypto, quiet, root_password, scrub, +- scrub_logfile, size, smp, sources, sync, timezone, update, upload, +- writes ++ scrub_logfile, selinux_relabel, size, smp, sources, sync, timezone, ++ update, upload, writes +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 918f372..52bf536 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -27,6 +27,7 @@ virt-builder - Build virtual machine images quickly + [--link TARGET:LINK[:LINK]] + [--edit FILE:EXPR] + [--delete FILE] [--scrub FILE] ++ [--selinux-relabel] + [--run SCRIPT] [--run-command 'CMD ARGS ...'] + [--firstboot SCRIPT] [--firstboot-command 'CMD ARGS ...'] + [--firstboot-install PKG,[PKG...]] +@@ -136,6 +137,16 @@ To install packages from the ordinary (guest) software repository + (In Fedora, C<@> is used to install groups of packages. On Debian + you would install a meta-package instead.) + ++To update the core packages to the latest version: ++ ++ virt-builder debian-7 --update ++ ++For guests which use SELinux, like Fedora and Red Hat Enterprise ++Linux, you may need to do SELinux relabelling after installing or ++updating packages (see L below): ++ ++ virt-builder fedora-20 --update --selinux-relabel ++ + =head2 Customizing the installation + + There are many options that let you customize the installation. These +@@ -593,6 +604,12 @@ It cannot delete directories, only regular files. + + =back + ++=item B<--selinux-relabel> ++ ++Relabel files in the guest so that they have the correct SELinux label. ++ ++You should only use this option for guests which support SELinux. ++ + =item B<--size> SIZE + + Select the size of the output disk, where the size can be specified +@@ -1029,6 +1046,10 @@ Scripts are run (I<--run>, I<--run-command>). + + Scripts run in the order they appear on the command line. + ++=item * ++ ++SELinux relabelling is done (I<--selinux-relabel>). ++ + =back + + =head2 IMPORTING THE DISK IMAGE +@@ -1714,30 +1735,29 @@ raw-format guests. + Guests which use SELinux (such as Fedora and Red Hat Enterprise Linux) + require that each file has a correct SELinux label. + +-Since virt-builder does not know how to give new files a correct +-label, the guest templates have an empty file C and +-this causes the guest to relabel itself at first boot. +- +-This usually means that these guests will reboot themselves once the +-first time you use them. B However if +-you want to perform the relabelling at build time instead of delaying +-it to the first boot, you can boot the guest with the qemu +-I<-no-reboot> option (which means it will shut down after the relabel +-is complete without booting "for real"). Only do this if you are sure +-it is an SELinux guest: +- +- qemu-system-x86_64 \ +- -no-reboot \ +- -nographic \ +- -machine accel=kvm:tcg \ +- -cpu host \ +- -m 2048 \ +- -drive file=disk.img,format=raw,if=virtio \ +- -serial stdio \ +- -monitor none +- +-(For further information on the topic of SELinux labelling, see: +-L) ++Virt-builder does not know how to give new files a label, so there are ++two possible strategies it can use to ensure correct labelling: ++ ++=over 4 ++ ++=item Using I<--selinux-relabel> ++ ++This runs L just before finalizing the guest, which sets ++SELinux labels correctly in the disk image. ++ ++Sometimes fixfiles is not possible during installation, in which case ++this option falls back on: ++ ++=item Touching C ++ ++Guest templates may already contain a file called C, or ++it is touched if I<--selinux-relabel> cannot run fixfiles. ++ ++For guests that use SELinux, this causes fixfiles to run at first ++boot. Guests will reboot themselves once the first time you use them, ++which is normal and harmless. ++ ++=back + + =head1 ENVIRONMENT VARIABLES + +@@ -1795,6 +1815,7 @@ L, + L, + L, + L, ++L, + L. + + =head1 AUTHOR +-- +1.8.4.2 + diff --git a/0072-builder-Add-documentation-for-enabling-Puppet-agent-.patch b/0072-builder-Add-documentation-for-enabling-Puppet-agent-.patch new file mode 100644 index 0000000..c347da9 --- /dev/null +++ b/0072-builder-Add-documentation-for-enabling-Puppet-agent-.patch @@ -0,0 +1,48 @@ +From 9e521a01b89b0adb4dfb662e274476049a7566f4 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 24 Jan 2014 19:43:05 +0000 +Subject: [PATCH] builder: Add documentation for enabling Puppet (agent) in a + guest. + +(cherry picked from commit 080300dfec1dd603da2f7d53e72dd3e056317fb8) +--- + builder/virt-builder.pod | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod +index 52bf536..ed08f3d 100644 +--- a/builder/virt-builder.pod ++++ b/builder/virt-builder.pod +@@ -1121,6 +1121,29 @@ following could be used to boot the virtual machine: + As with libvirt, it is very important that the correct format is + chosen. It will be C unless the I<--format> option was used. + ++=head2 CONFIGURATION MANAGEMENT ++ ++=head3 Puppet ++ ++To enable the Puppet agent in a guest, install the package, point ++the configuration at your Puppetmaster, and ensure the agent runs ++at boot. ++ ++A typical virt-builder command would be: ++ ++ virt-builder fedora-20 \ ++ --hostname client.example.com \ ++ --update \ ++ --install puppet \ ++ --edit '/etc/puppet/puppet.conf: ++ s/^\[agent\]/[agent]\n server = puppetmaster.example.com/' \ ++ --run-command 'systemctl enable puppet' \ ++ --selinux-relabel ++ ++The precise instructions vary according to the Linux distro. For ++further information see: ++L ++ + =head2 DEBUGGING BUILDS + + If virt-builder itself fails, then enable debugging (I<-v>) and report +-- +1.8.4.2 + diff --git a/0073-daemon-Bind-mount-sys-fs-selinux-into-sysroot-when-r.patch b/0073-daemon-Bind-mount-sys-fs-selinux-into-sysroot-when-r.patch new file mode 100644 index 0000000..58bfb1b --- /dev/null +++ b/0073-daemon-Bind-mount-sys-fs-selinux-into-sysroot-when-r.patch @@ -0,0 +1,71 @@ +From a5b84503f41d715bed6573b61382cf5486673ced Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Fri, 24 Jan 2014 19:36:33 +0000 +Subject: [PATCH] daemon: Bind-mount /sys/fs/selinux into sysroot when running + commands. + +Even though we are already bind-mounting /sys, it is necessary to also +bind-mount /sys/fs/selinux in order for SELinux commands (in +particular, 'load_policy') to work. + +This fixes/reverts commit 7367729ec7a5d016878dd00b32cce45cec372931. + +(cherry picked from commit ab33653ef312e18042be08854aa0dec2c7254fc2) +--- + daemon/command.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/daemon/command.c b/daemon/command.c +index 066c773..1aa1a52 100644 +--- a/daemon/command.c ++++ b/daemon/command.c +@@ -48,7 +48,8 @@ struct bind_state { + char *sysroot_dev_pts; + char *sysroot_proc; + char *sysroot_sys; +- bool dev_ok, dev_pts_ok, proc_ok, sys_ok; ++ char *sysroot_sys_fs_selinux; ++ bool dev_ok, dev_pts_ok, proc_ok, sys_ok, sys_fs_selinux_ok; + }; + + struct resolver_state { +@@ -76,14 +77,17 @@ bind_mount (struct bind_state *bs) + bs->sysroot_dev_pts = sysroot_path ("/dev/pts"); + bs->sysroot_proc = sysroot_path ("/proc"); + bs->sysroot_sys = sysroot_path ("/sys"); ++ bs->sysroot_sys_fs_selinux = sysroot_path ("/sys/fs/selinux"); + + if (bs->sysroot_dev == NULL || bs->sysroot_dev_pts == NULL || +- bs->sysroot_proc == NULL || bs->sysroot_sys == NULL) { ++ bs->sysroot_proc == NULL || bs->sysroot_sys == NULL || ++ bs->sysroot_sys_fs_selinux == NULL) { + reply_with_perror ("malloc"); + free (bs->sysroot_dev); + free (bs->sysroot_dev_pts); + free (bs->sysroot_proc); + free (bs->sysroot_sys); ++ free (bs->sysroot_sys_fs_selinux); + return -1; + } + +@@ -95,6 +99,8 @@ bind_mount (struct bind_state *bs) + bs->proc_ok = r != -1; + r = command (NULL, NULL, str_mount, "--bind", "/sys", bs->sysroot_sys, NULL); + bs->sys_ok = r != -1; ++ r = command (NULL, NULL, str_mount, "--bind", "/sys/fs/selinux", bs->sysroot_sys_fs_selinux, NULL); ++ bs->sys_fs_selinux_ok = r != -1; + + bs->mounted = true; + +@@ -111,6 +117,8 @@ static void + free_bind_state (struct bind_state *bs) + { + if (bs->mounted) { ++ if (bs->sys_fs_selinux_ok) umount_ignore_fail (bs->sysroot_sys_fs_selinux); ++ free (bs->sysroot_sys_fs_selinux); + if (bs->sys_ok) umount_ignore_fail (bs->sysroot_sys); + free (bs->sysroot_sys); + if (bs->proc_ok) umount_ignore_fail (bs->sysroot_proc); +-- +1.8.4.2 + diff --git a/0074-daemon-If-selinux-exists-in-the-guest-bind-mount-sys.patch b/0074-daemon-If-selinux-exists-in-the-guest-bind-mount-sys.patch new file mode 100644 index 0000000..7941d74 --- /dev/null +++ b/0074-daemon-If-selinux-exists-in-the-guest-bind-mount-sys.patch @@ -0,0 +1,77 @@ +From 65dbdeecdd248d7629ab8813f061b50cba8e4093 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 27 Jan 2014 20:22:23 +0000 +Subject: [PATCH] daemon: If /selinux exists in the guest, bind-mount + /sys/fs/selinux to there. + +Commit 72afcf450a78b7e58f65b4a7aaf94d71cd25fca5 was partially +incorrect. If the guest userspace is expecting /selinux to exist, +then we should bind-mount /sys/fs/selinux from the appliance kernel +there. + +(cherry picked from commit 9df50877f8b61106248acd2375d011acc209c6b5) +--- + daemon/command.c | 16 +++++++++++++--- + 1 file changed, 13 insertions(+), 3 deletions(-) + +diff --git a/daemon/command.c b/daemon/command.c +index 1aa1a52..939bf87 100644 +--- a/daemon/command.c ++++ b/daemon/command.c +@@ -47,9 +47,10 @@ struct bind_state { + char *sysroot_dev; + char *sysroot_dev_pts; + char *sysroot_proc; ++ char *sysroot_selinux; + char *sysroot_sys; + char *sysroot_sys_fs_selinux; +- bool dev_ok, dev_pts_ok, proc_ok, sys_ok, sys_fs_selinux_ok; ++ bool dev_ok, dev_pts_ok, proc_ok, selinux_ok, sys_ok, sys_fs_selinux_ok; + }; + + struct resolver_state { +@@ -76,16 +77,18 @@ bind_mount (struct bind_state *bs) + bs->sysroot_dev = sysroot_path ("/dev"); + bs->sysroot_dev_pts = sysroot_path ("/dev/pts"); + bs->sysroot_proc = sysroot_path ("/proc"); ++ bs->sysroot_selinux = sysroot_path ("/selinux"); + bs->sysroot_sys = sysroot_path ("/sys"); + bs->sysroot_sys_fs_selinux = sysroot_path ("/sys/fs/selinux"); + + if (bs->sysroot_dev == NULL || bs->sysroot_dev_pts == NULL || +- bs->sysroot_proc == NULL || bs->sysroot_sys == NULL || +- bs->sysroot_sys_fs_selinux == NULL) { ++ bs->sysroot_proc == NULL || bs->sysroot_selinux == NULL || ++ bs->sysroot_sys == NULL || bs->sysroot_sys_fs_selinux == NULL) { + reply_with_perror ("malloc"); + free (bs->sysroot_dev); + free (bs->sysroot_dev_pts); + free (bs->sysroot_proc); ++ free (bs->sysroot_selinux); + free (bs->sysroot_sys); + free (bs->sysroot_sys_fs_selinux); + return -1; +@@ -97,6 +100,11 @@ bind_mount (struct bind_state *bs) + bs->dev_pts_ok = r != -1; + r = command (NULL, NULL, str_mount, "--bind", "/proc", bs->sysroot_proc, NULL); + bs->proc_ok = r != -1; ++ /* Note on the next line we have to bind-mount /sys/fs/selinux (appliance ++ * kernel) on top of /selinux (where guest is expecting selinux). ++ */ ++ r = command (NULL, NULL, str_mount, "--bind", "/sys/fs/selinux", bs->sysroot_selinux, NULL); ++ bs->selinux_ok = r != -1; + r = command (NULL, NULL, str_mount, "--bind", "/sys", bs->sysroot_sys, NULL); + bs->sys_ok = r != -1; + r = command (NULL, NULL, str_mount, "--bind", "/sys/fs/selinux", bs->sysroot_sys_fs_selinux, NULL); +@@ -121,6 +129,8 @@ free_bind_state (struct bind_state *bs) + free (bs->sysroot_sys_fs_selinux); + if (bs->sys_ok) umount_ignore_fail (bs->sysroot_sys); + free (bs->sysroot_sys); ++ if (bs->selinux_ok) umount_ignore_fail (bs->sysroot_selinux); ++ free (bs->sysroot_selinux); + if (bs->proc_ok) umount_ignore_fail (bs->sysroot_proc); + free (bs->sysroot_proc); + if (bs->dev_pts_ok) umount_ignore_fail (bs->sysroot_dev_pts); +-- +1.8.4.2 + diff --git a/0075-daemon-Add-a-note-about-how-mount-rbind-doesn-t-work.patch b/0075-daemon-Add-a-note-about-how-mount-rbind-doesn-t-work.patch new file mode 100644 index 0000000..951557c --- /dev/null +++ b/0075-daemon-Add-a-note-about-how-mount-rbind-doesn-t-work.patch @@ -0,0 +1,28 @@ +From 5bd9401f4a533b01fca4bee8cadc1e7f4ac85c87 Mon Sep 17 00:00:00 2001 +From: "Richard W.M. Jones" +Date: Mon, 27 Jan 2014 21:20:32 +0000 +Subject: [PATCH] daemon: Add a note about how 'mount --rbind' doesn't work. + +(cherry picked from commit d9cd2dc9b0e847fda3831c9ff13def616ca5043d) +--- + daemon/command.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/daemon/command.c b/daemon/command.c +index 939bf87..1593de9 100644 +--- a/daemon/command.c ++++ b/daemon/command.c +@@ -94,6 +94,10 @@ bind_mount (struct bind_state *bs) + return -1; + } + ++ /* Note it is tempting to use --rbind here (to bind submounts). ++ * However I have not found a reliable way to unmount the same set ++ * of directories (umount -R does NOT work). ++ */ + r = command (NULL, NULL, str_mount, "--bind", "/dev", bs->sysroot_dev, NULL); + bs->dev_ok = r != -1; + r = command (NULL, NULL, str_mount, "--bind", "/dev/pts", bs->sysroot_dev_pts, NULL); +-- +1.8.4.2 + diff --git a/0076-builder-output-translated-notes.patch b/0076-builder-output-translated-notes.patch new file mode 100644 index 0000000..2442c27 --- /dev/null +++ b/0076-builder-output-translated-notes.patch @@ -0,0 +1,404 @@ +From 37752cbfebb999527f6877964ba01896831a696f Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 30 Jan 2014 17:05:34 +0100 +Subject: [PATCH] builder: output translated notes + +Output all the translations available for the notes in the "verbose" +output and the JSON output, while trying to match the system langauge in +the "show notes" output. + +The JSON output is slightly changed to handle translations, with the +"untranslated" notes being matched as "C". The version is not bumped +though, since there have been no stable releases with the former output +yet. + +(cherry picked from commit 07ef60c63f5fd635306d199622d36f9089c75ecc) +--- + builder/Makefile.am | 5 ++++ + builder/index_parser.ml | 11 ++++---- + builder/list_entries.ml | 56 +++++++++++++++++++++++++++++++++---- + builder/setlocale-c.c | 59 +++++++++++++++++++++++++++++++++++++++ + builder/setlocale.ml | 29 +++++++++++++++++++ + builder/setlocale.mli | 30 ++++++++++++++++++++ + builder/test-virt-builder-list.sh | 28 ++++++++++++++----- + po/POTFILES | 1 + + po/POTFILES-ml | 1 + + 9 files changed, 202 insertions(+), 18 deletions(-) + create mode 100644 builder/setlocale-c.c + create mode 100644 builder/setlocale.ml + create mode 100644 builder/setlocale.mli + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 4777619..2be495b 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -51,6 +51,9 @@ SOURCES = \ + pxzcat.ml \ + pxzcat.mli \ + pxzcat-c.c \ ++ setlocale.ml \ ++ setlocale.mli \ ++ setlocale-c.c \ + sigchecker.mli \ + sigchecker.ml + +@@ -83,6 +86,8 @@ OBJECTS = \ + index-parser-c.o \ + pxzcat-c.o \ + pxzcat.cmx \ ++ setlocale-c.o \ ++ setlocale.cmx \ + get_kernel.cmx \ + downloader.cmx \ + sigchecker.cmx \ +diff --git a/builder/index_parser.ml b/builder/index_parser.ml +index d5b48ae..2d4a642 100644 +--- a/builder/index_parser.ml ++++ b/builder/index_parser.ml +@@ -91,11 +91,12 @@ let print_entry chan (name, { printable_name = printable_name; + | None -> () + | Some lvexpand -> fp "lvexpand=%s\n" lvexpand + ); +- (match notes with +- | ("", notes) :: _ -> fp "notes=%s\n" notes +- | _ :: _ +- | [] -> () +- ); ++ List.iter ( ++ fun (lang, notes) -> ++ match lang with ++ | "" -> fp "notes=%s\n" notes ++ | lang -> fp "notes[%s]=%s\n" lang notes ++ ) notes; + if hidden then fp "hidden=true\n" + + (* Types returned by the C index parser. *) +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index b947cc8..7317cc7 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -21,6 +21,24 @@ open Common_utils + + open Printf + ++let split_locale loc = ++ let regex = Str.regexp "^\\([A-Za-z]+\\)\\(_\\([A-Za-z]+\\)\\)?\\(\\.\\([A-Za-z0-9-]+\\)\\)?\\(@\\([A-Za-z]+\\)\\)?$" in ++ let l = ref [] in ++ if Str.string_match regex loc 0 then ( ++ let match_or_empty n = ++ try Str.matched_group n loc with ++ | Not_found -> "" ++ in ++ let lang = Str.matched_group 1 loc in ++ let territory = match_or_empty 3 in ++ (match territory with ++ | "" -> () ++ | territory -> l := (lang ^ "_" ^ territory) :: !l); ++ l := lang :: !l; ++ ); ++ l := "" :: !l; ++ List.rev !l ++ + let rec list_entries ~list_format ~sources index = + match list_format with + | `Short -> list_entries_short index +@@ -45,6 +63,10 @@ and list_entries_short index = + ) index + + and list_entries_long ~sources index = ++ let langs = match Setlocale.setlocale Setlocale.LC_MESSAGES None with ++ | None -> [""] ++ | Some locale -> split_locale locale in ++ + List.iter ( + fun (source, fingerprint) -> + printf (f_"Source URI: %s\n") source; +@@ -70,11 +92,23 @@ and list_entries_long ~sources index = + | Some size -> + printf "%-24s %s\n" (s_"Download size:") (human_size size); + ); ++ let notes = List.fold_left ( ++ fun acc lang -> ++ let res = List.filter ( ++ fun (langkey, _) -> ++ match langkey with ++ | "C" -> lang = "" ++ | langkey -> langkey = lang ++ ) notes in ++ match res with ++ | (_, noteskey) :: _ -> noteskey :: acc ++ | [] -> acc ++ ) [] langs in ++ let notes = List.rev notes in + (match notes with +- | ("", notes) :: _ -> ++ | notes :: _ -> + printf "\n"; + printf (f_"Notes:\n\n%s\n") notes +- | _ :: _ + | [] -> () + ); + printf "\n" +@@ -108,10 +142,20 @@ and list_entries_json ~sources index = + | Some n -> + printf " \"%s\": \"%Ld\",\n" key n in + let print_notes = function +- | ("", notes) :: _ -> +- printf " \"notes\": \"%s\",\n" (json_string_escape notes) +- | _ :: _ +- | _ -> () in ++ | [] -> () ++ | notes -> ++ printf " \"notes\": {\n"; ++ iteri ( ++ fun i (lang, langnotes) -> ++ let lang = ++ match lang with ++ | "" -> "C" ++ | x -> x in ++ printf " \"%s\": \"%s\"%s\n" ++ (json_string_escape lang) (json_string_escape langnotes) ++ (trailing_comma i (List.length notes)) ++ ) notes; ++ printf " },\n" in + + printf "{\n"; + printf " \"version\": %d,\n" 1; +diff --git a/builder/setlocale-c.c b/builder/setlocale-c.c +new file mode 100644 +index 0000000..e1ad75d +--- /dev/null ++++ b/builder/setlocale-c.c +@@ -0,0 +1,59 @@ ++/* virt-builder ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++ ++static const int lc_string_table[7] = { ++ LC_ALL, ++ LC_CTYPE, ++ LC_NUMERIC, ++ LC_TIME, ++ LC_COLLATE, ++ LC_MONETARY, ++ LC_MESSAGES ++}; ++ ++#define Val_none (Val_int (0)) ++ ++value ++virt_builder_setlocale (value val_category, value val_name) ++{ ++ CAMLparam2 (val_category, val_name); ++ CAMLlocal2 (rv, rv2); ++ char *ret, *locstring; ++ int category; ++ ++ category = lc_string_table[Int_val (val_category)]; ++ locstring = val_name == Val_none ? NULL : String_val (Field (val_name, 0)); ++ ret = setlocale (category, locstring); ++ if (ret) { ++ rv2 = caml_copy_string (ret); ++ rv = caml_alloc (1, 0); ++ Store_field (rv, 0, rv2); ++ } else ++ rv = Val_none; ++ ++ CAMLreturn (rv); ++} +diff --git a/builder/setlocale.ml b/builder/setlocale.ml +new file mode 100644 +index 0000000..9b3289d +--- /dev/null ++++ b/builder/setlocale.ml +@@ -0,0 +1,29 @@ ++(* virt-builder ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++type localecategory = ++ | LC_ALL ++ | LC_CTYPE ++ | LC_NUMERIC ++ | LC_TIME ++ | LC_COLLATE ++ | LC_MONETARY ++ | LC_MESSAGES ++;; ++ ++external setlocale : localecategory -> string option -> string option = "virt_builder_setlocale" +diff --git a/builder/setlocale.mli b/builder/setlocale.mli +new file mode 100644 +index 0000000..1e34204 +--- /dev/null ++++ b/builder/setlocale.mli +@@ -0,0 +1,30 @@ ++(* virt-builder ++ * Copyright (C) 2014 Red Hat Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ *) ++ ++type localecategory = ++ | LC_ALL ++ | LC_CTYPE ++ | LC_NUMERIC ++ | LC_TIME ++ | LC_COLLATE ++ | LC_MONETARY ++ | LC_MESSAGES ++;; ++ ++val setlocale : localecategory -> string option -> string option ++(** [setlocale category newlocale] Tiny wrapper to the C [setlocale]. *) +diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh +index c3b791f..634254d 100755 +--- a/builder/test-virt-builder-list.sh ++++ b/builder/test-virt-builder-list.sh +@@ -119,49 +119,63 @@ if [ "$json_list" != "{ + \"os-version\": \"phony-debian\", + \"full-name\": \"Phony Debian\", + \"size\": 536870912, +- \"notes\": \"Phony Debian look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Debian look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-fedora\", + \"full-name\": \"Phony Fedora\", + \"size\": 1073741824, +- \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Fedora look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-fedora-qcow2\", + \"full-name\": \"Phony Fedora qcow2\", + \"size\": 1073741824, +- \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Fedora look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-fedora-qcow2-uncompressed\", + \"full-name\": \"Phony Fedora qcow2 uncompressed\", + \"size\": 1073741824, +- \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Fedora look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-fedora-no-format\", + \"full-name\": \"Phony Fedora\", + \"size\": 1073741824, +- \"notes\": \"Phony Fedora look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Fedora look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-ubuntu\", + \"full-name\": \"Phony Ubuntu\", + \"size\": 536870912, +- \"notes\": \"Phony Ubuntu look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Ubuntu look-alike used for testing.\" ++ }, + \"hidden\": false + }, + { + \"os-version\": \"phony-windows\", + \"full-name\": \"Phony Windows\", + \"size\": 536870912, +- \"notes\": \"Phony Windows look-alike used for testing.\", ++ \"notes\": { ++ \"C\": \"Phony Windows look-alike used for testing.\" ++ }, + \"hidden\": false + } + ] +diff --git a/po/POTFILES b/po/POTFILES +index 76c41ec..d702ef0 100644 +--- a/po/POTFILES ++++ b/po/POTFILES +@@ -5,6 +5,7 @@ builder/index-scan.c + builder/index-struct.c + builder/index-validate.c + builder/pxzcat-c.c ++builder/setlocale-c.c + cat/cat.c + cat/filesystems.c + cat/ls.c +diff --git a/po/POTFILES-ml b/po/POTFILES-ml +index 564404b..d030258 100644 +--- a/po/POTFILES-ml ++++ b/po/POTFILES-ml +@@ -5,6 +5,7 @@ builder/get_kernel.ml + builder/index_parser.ml + builder/list_entries.ml + builder/pxzcat.ml ++builder/setlocale.ml + builder/sigchecker.ml + mllib/common_gettext.ml + mllib/common_utils.ml +-- +1.8.4.2 + diff --git a/0077-builder-remove-unused-variables.patch b/0077-builder-remove-unused-variables.patch new file mode 100644 index 0000000..7d0b4d9 --- /dev/null +++ b/0077-builder-remove-unused-variables.patch @@ -0,0 +1,30 @@ +From 9145966b07d09605ad026c217825cabaee1a5dea Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Thu, 30 Jan 2014 17:06:42 +0100 +Subject: [PATCH] builder: remove unused variables + +Leftovers of the list_entries_short+list_entries_long split done in +commit 91aae893c70b3877b31803800ba77836fd7a45e8. + +(cherry picked from commit bed8a168c0ed76e784adcc046256432f615e3314) +--- + builder/list_entries.ml | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/builder/list_entries.ml b/builder/list_entries.ml +index 7317cc7..27ea95e 100644 +--- a/builder/list_entries.ml ++++ b/builder/list_entries.ml +@@ -48,9 +48,6 @@ let rec list_entries ~list_format ~sources index = + and list_entries_short index = + List.iter ( + fun (name, { Index_parser.printable_name = printable_name; +- size = size; +- compressed_size = compressed_size; +- notes = notes; + hidden = hidden }) -> + if not hidden then ( + printf "%-24s" name; +-- +1.8.4.2 + diff --git a/0078-builder-isolate-C-libraries-in-an-own-OCAMLCLIBS.patch b/0078-builder-isolate-C-libraries-in-an-own-OCAMLCLIBS.patch new file mode 100644 index 0000000..aad85c2 --- /dev/null +++ b/0078-builder-isolate-C-libraries-in-an-own-OCAMLCLIBS.patch @@ -0,0 +1,36 @@ +From 0097bb2e47c81700921d1580b61914530099274d Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 11 Feb 2014 10:40:31 +0100 +Subject: [PATCH] builder: isolate C libraries in an own OCAMLCLIBS + +Just moving stuff within Makefile.am, no functional changes. + +(cherry picked from commit c66cec6ffac2af400487b7fb4ff437eddc6e7aa7) +--- + builder/Makefile.am | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 2be495b..78a9e72 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -113,10 +113,15 @@ endif + OCAMLCFLAGS = -g -warn-error CDEFLMPSUVYZX $(OCAMLPACKAGES) + OCAMLOPTFLAGS = $(OCAMLCFLAGS) + ++OCAMLCLIBS = \ ++ $(LIBLZMA_LIBS) \ ++ -pthread -lpthread \ ++ -lncurses -lcrypt ++ + virt-builder: $(OBJECTS) + $(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \ + mlguestfs.cmxa -linkpkg $^ \ +- -cclib '-pthread $(LIBLZMA_LIBS) -lncurses -lcrypt -lpthread' \ ++ -cclib '$(OCAMLCLIBS)' \ + $(OCAML_GCOV_LDFLAGS) \ + -o $@ + +-- +1.8.4.2 + diff --git a/0079-builder-prepare-for-different-per-protocol-download-.patch b/0079-builder-prepare-for-different-per-protocol-download-.patch new file mode 100644 index 0000000..08bb70d --- /dev/null +++ b/0079-builder-prepare-for-different-per-protocol-download-.patch @@ -0,0 +1,145 @@ +From d3cbd568906609d68933c46e73e142fa9ebf7627 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 11 Feb 2014 12:39:56 +0100 +Subject: [PATCH] builder: prepare for different per-protocol download actions + +Small refactor of Downloader.download_to to allow different download +actions depending on the protocol of the URI (which is now parsed). + +No actual behaviour changes, just mostly code motion. + +(cherry picked from commit ba3569704cf5f381c618b6b07c8b001bac88e18a) +--- + builder/Makefile.am | 6 ++++ + builder/downloader.ml | 84 ++++++++++++++++++++++++++++----------------------- + 2 files changed, 53 insertions(+), 37 deletions(-) + +diff --git a/builder/Makefile.am b/builder/Makefile.am +index 78a9e72..9d2dbc5 100644 +--- a/builder/Makefile.am ++++ b/builder/Makefile.am +@@ -80,6 +80,9 @@ OBJECTS = \ + $(top_builddir)/mllib/password.cmx \ + $(top_builddir)/mllib/planner.cmx \ + $(top_builddir)/mllib/config.cmx \ ++ $(top_builddir)/fish/guestfish-uri.o \ ++ $(top_builddir)/mllib/uri-c.o \ ++ $(top_builddir)/mllib/uRI.cmx \ + index-scan.o \ + index-struct.o \ + index-parse.o \ +@@ -115,6 +118,9 @@ OCAMLOPTFLAGS = $(OCAMLCFLAGS) + + OCAMLCLIBS = \ + $(LIBLZMA_LIBS) \ ++ $(LIBXML2_LIBS) \ ++ -L../src/.libs -lutils \ ++ -L../gnulib/lib/.libs -lgnu \ + -pthread -lpthread \ + -lncurses -lcrypt + +diff --git a/builder/downloader.ml b/builder/downloader.ml +index 77f48ae..95b5817 100644 +--- a/builder/downloader.ml ++++ b/builder/downloader.ml +@@ -69,50 +69,60 @@ let rec download ~prog t ?template ?progress_bar uri = + (filename, false) + + and download_to ~prog t ?(progress_bar = false) uri filename = +- (* Get the status code first to ensure the file exists. *) +- let cmd = sprintf "%s%s -g -o /dev/null -I -w '%%{http_code}' %s" +- t.curl +- (if t.debug then "" else " -s -S") +- (quote uri) in +- if t.debug then eprintf "%s\n%!" cmd; +- let lines = external_command ~prog cmd in +- if List.length lines < 1 then ( +- eprintf (f_"%s: unexpected output from curl command, enable debug and look at previous messages\n") prog; +- exit 1 +- ); +- let status_code = List.hd lines in +- let bad_status_code = function +- | "" -> true +- | s when s.[0] = '4' -> true (* 4xx *) +- | s when s.[0] = '5' -> true (* 5xx *) +- | _ -> false +- in +- if bad_status_code status_code then ( +- eprintf (f_"%s: failed to download %s: HTTP status code %s\n") +- prog uri status_code; +- exit 1 +- ); ++ let parseduri = ++ try URI.parse_uri uri ++ with Invalid_argument "URI.parse_uri" -> ++ eprintf (f_"Error parsing URI '%s'. Look for error messages printed above.\n") uri; ++ exit 1 in + +- (* Now download the file. +- * +- * Note because there may be parallel virt-builder instances running ++ (* Note because there may be parallel virt-builder instances running + * and also to avoid partial downloads in the cachedir if the network + * fails, we download to a random name in the cache and then + * atomically rename it to the final filename. + *) + let filename_new = filename ^ "." ^ string_random8 () in + unlink_on_exit filename_new; +- let cmd = sprintf "%s%s -g -o %s %s" +- t.curl +- (if t.debug then "" else if progress_bar then " -#" else " -s -S") +- (quote filename_new) (quote uri) in +- if t.debug then eprintf "%s\n%!" cmd; +- let r = Sys.command cmd in +- if r <> 0 then ( +- eprintf (f_"%s: curl (download) command failed downloading '%s'\n") +- prog uri; +- exit 1 ++ ++ (match parseduri.URI.protocol with ++ | _ -> (* Any other protocol. *) ++ (* Get the status code first to ensure the file exists. *) ++ let cmd = sprintf "%s%s -g -o /dev/null -I -w '%%{http_code}' %s" ++ t.curl ++ (if t.debug then "" else " -s -S") ++ (quote uri) in ++ if t.debug then eprintf "%s\n%!" cmd; ++ let lines = external_command ~prog cmd in ++ if List.length lines < 1 then ( ++ eprintf (f_"%s: unexpected output from curl command, enable debug and look at previous messages\n") ++ prog; ++ exit 1 ++ ); ++ let status_code = List.hd lines in ++ let bad_status_code = function ++ | "" -> true ++ | s when s.[0] = '4' -> true (* 4xx *) ++ | s when s.[0] = '5' -> true (* 5xx *) ++ | _ -> false ++ in ++ if bad_status_code status_code then ( ++ eprintf (f_"%s: failed to download %s: HTTP status code %s\n") ++ prog uri status_code; ++ exit 1 ++ ); ++ ++ (* Now download the file. *) ++ let cmd = sprintf "%s%s -g -o %s %s" ++ t.curl ++ (if t.debug then "" else if progress_bar then " -#" else " -s -S") ++ (quote filename_new) (quote uri) in ++ if t.debug then eprintf "%s\n%!" cmd; ++ let r = Sys.command cmd in ++ if r <> 0 then ( ++ eprintf (f_"%s: curl (download) command failed downloading '%s'\n") ++ prog uri; ++ exit 1 ++ ) + ); + +- (* Rename the file if curl was successful. *) ++ (* Rename the file if the download was successful. *) + rename filename_new filename +-- +1.8.4.2 + diff --git a/0080-builder-do-a-copy-when-downloading-local-files.patch b/0080-builder-do-a-copy-when-downloading-local-files.patch new file mode 100644 index 0000000..193abbc --- /dev/null +++ b/0080-builder-do-a-copy-when-downloading-local-files.patch @@ -0,0 +1,38 @@ +From 9b67e73e79b3f0bb329616c5f2f4ed265d00deb1 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Tue, 11 Feb 2014 12:52:10 +0100 +Subject: [PATCH] builder: do a copy when downloading local files + +Instead of spawning curl even to "download" file:// URIs, just copy +them. + +(cherry picked from commit 76e3e15d031df77db71b11ac1c40199eff80fa4d) +--- + builder/downloader.ml | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/builder/downloader.ml b/builder/downloader.ml +index 95b5817..e386c06 100644 +--- a/builder/downloader.ml ++++ b/builder/downloader.ml +@@ -84,6 +84,17 @@ and download_to ~prog t ?(progress_bar = false) uri filename = + unlink_on_exit filename_new; + + (match parseduri.URI.protocol with ++ | "file" -> ++ let path = parseduri.URI.path in ++ let cmd = sprintf "cp%s %s %s" ++ (if t.debug then " -v" else "") ++ (quote path) (quote filename_new) in ++ let r = Sys.command cmd in ++ if r <> 0 then ( ++ eprintf (f_"%s: cp (download) command failed copying '%s'\n") ++ prog path; ++ exit 1 ++ ) + | _ -> (* Any other protocol. *) + (* Get the status code first to ensure the file exists. *) + let cmd = sprintf "%s%s -g -o /dev/null -I -w '%%{http_code}' %s" +-- +1.8.4.2 + diff --git a/libguestfs.spec b/libguestfs.spec index 1e1f135..26f2e93 100644 --- a/libguestfs.spec +++ b/libguestfs.spec @@ -11,7 +11,7 @@ Summary: Access and modify virtual machine disk images Name: libguestfs Epoch: 1 -Version: 1.24.5 +Version: 1.24.6 Release: 1%{?dist} License: LGPLv2+ @@ -50,46 +50,61 @@ Patch0022: 0022-builder-Fail-if-bison-is-not-installed.patch Patch0023: 0023-builder-Fail-if-lex-is-not-installed.patch Patch0024: 0024-builder-sysprep-Allow-random-as-a-password-selector.patch Patch0025: 0025-builder-sysprep-Allow-accounts-to-be-locked-RHBZ-102.patch -Patch0026: 0026-builder-Move-is_block_device-function-into-common-ut.patch -Patch0027: 0027-builder-Use-a-planner-to-work-out-how-to-convert-the.patch -Patch0028: 0028-builder-planner-Handle-no-format-in-source-case-corr.patch -Patch0029: 0029-builder-Flush-debug-info-after-printing-it.patch -Patch0030: 0030-builder-Add-a-test-of-the-planner.patch -Patch0031: 0031-builder-tests-Fix-virt-builder-list-output.patch -Patch0032: 0032-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch -Patch0033: 0033-builder-Add-a-link-to-blog-posting-about-the-planner.patch -Patch0034: 0034-builder-Only-use-virt-resize-no-sparse-when-writing-.patch -Patch0035: 0035-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch -Patch0036: 0036-builder-Remove-blank-line.patch -Patch0037: 0037-builder-Add-update-option-to-update-template-core-pa.patch -Patch0038: 0038-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch -Patch0039: 0039-builder-Fix-handling-of-size-parameter.patch -Patch0040: 0040-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch -Patch0041: 0041-tests-Add-a-regression-test-of-libvirt-authenticatio.patch -Patch0042: 0042-tests-Add-a-regression-test-for-libvirt-authenticati.patch -Patch0043: 0043-sysprep-builder-Add-timezone-option-to-set-timezone-.patch -Patch0044: 0044-builder-Document-how-to-change-keyboard-layout.patch -Patch0045: 0045-builder-Add-link-option-for-creating-symbolic-links.patch -Patch0046: 0046-builder-Document-how-to-change-the-language-locale-o.patch -Patch0047: 0047-builder-Document-how-to-set-up-local-mirrors-for-per.patch -Patch0048: 0048-builder-Document-how-to-set-Japanese-language-suppor.patch -Patch0049: 0049-builder-Fix-virt-builder-test.patch -Patch0050: 0050-builder-Document-how-to-set-Japanese-in-Debian-7.patch -Patch0051: 0051-builder-Add-no-delete-on-failure-option-to-aid-debug.patch -Patch0052: 0052-builder-For-performance-recommend-using-the-no-sync-.patch -Patch0053: 0053-builder-planner-Whitespace-change.patch -Patch0054: 0054-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch -Patch0055: 0055-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch -Patch0056: 0056-daemon-xattr-Remove-unused-variable.patch -Patch0057: 0057-New-API-copy-attributes.patch -Patch0058: 0058-Update-generated-files-for-new-copy-attributes-API.patch -Patch0059: 0059-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch -Patch0060: 0060-builder-edit-fish-use-copy-attributes.patch -Patch0061: 0061-builder-test-virt-builder-check-some-results.patch -Patch0062: 0062-builder-small-refactor-of-the-list-output.patch -Patch0063: 0063-builder-add-list-format.patch -Patch0064: 0064-builder-add-a-JSON-output-for-list.patch -Patch0065: 0065-builder-Fix-unterminated-I-.-in-man-page.patch +Patch0026: 0026-builder-Use-a-planner-to-work-out-how-to-convert-the.patch +Patch0027: 0027-builder-planner-Handle-no-format-in-source-case-corr.patch +Patch0028: 0028-builder-Flush-debug-info-after-printing-it.patch +Patch0029: 0029-builder-Add-a-test-of-the-planner.patch +Patch0030: 0030-builder-tests-Fix-virt-builder-list-output.patch +Patch0031: 0031-builder-tests-Add-test-virt-builder-planner.sh-to-EX.patch +Patch0032: 0032-builder-Add-a-link-to-blog-posting-about-the-planner.patch +Patch0033: 0033-builder-Only-use-virt-resize-no-sparse-when-writing-.patch +Patch0034: 0034-builder-Refuse-to-write-to-a-char-device-or-dev-null.patch +Patch0035: 0035-builder-Remove-blank-line.patch +Patch0036: 0036-builder-Add-update-option-to-update-template-core-pa.patch +Patch0037: 0037-launch-libvirt-Don-t-default-to-using-NULL-for-libvi.patch +Patch0038: 0038-builder-Fix-handling-of-size-parameter.patch +Patch0039: 0039-libvirt-auth-Provide-a-friendlier-wrapper-around-vir.patch +Patch0040: 0040-tests-Add-a-regression-test-of-libvirt-authenticatio.patch +Patch0041: 0041-tests-Add-a-regression-test-for-libvirt-authenticati.patch +Patch0042: 0042-sysprep-builder-Add-timezone-option-to-set-timezone-.patch +Patch0043: 0043-builder-Document-how-to-change-keyboard-layout.patch +Patch0044: 0044-builder-Add-link-option-for-creating-symbolic-links.patch +Patch0045: 0045-builder-Document-how-to-change-the-language-locale-o.patch +Patch0046: 0046-builder-Document-how-to-set-up-local-mirrors-for-per.patch +Patch0047: 0047-builder-Document-how-to-set-Japanese-language-suppor.patch +Patch0048: 0048-builder-Fix-virt-builder-test.patch +Patch0049: 0049-builder-Document-how-to-set-Japanese-in-Debian-7.patch +Patch0050: 0050-builder-Add-no-delete-on-failure-option-to-aid-debug.patch +Patch0051: 0051-builder-For-performance-recommend-using-the-no-sync-.patch +Patch0052: 0052-builder-planner-Whitespace-change.patch +Patch0053: 0053-daemon-xattr-simplify-the-enabling-of-the-linuxxattr.patch +Patch0054: 0054-daemon-xattr-move-the-listxattrs-code-in-an-own-func.patch +Patch0055: 0055-daemon-xattr-Remove-unused-variable.patch +Patch0056: 0056-New-API-copy-attributes.patch +Patch0057: 0057-Update-generated-files-for-new-copy-attributes-API.patch +Patch0058: 0058-fish-Add-test-file-attrs.sh-to-EXTRA_DIST.patch +Patch0059: 0059-builder-edit-fish-use-copy-attributes.patch +Patch0060: 0060-builder-test-virt-builder-check-some-results.patch +Patch0061: 0061-builder-small-refactor-of-the-list-output.patch +Patch0062: 0062-builder-add-list-format.patch +Patch0063: 0063-builder-add-a-JSON-output-for-list.patch +Patch0064: 0064-builder-Fix-unterminated-I-.-in-man-page.patch +Patch0065: 0065-builder-add-index-struct.h-as-dependency-for-index-p.patch +Patch0066: 0066-builder-allow-more-empty-lines-in-index-files.patch +Patch0067: 0067-builder-proper-consider-subkeys-in-index-files.patch +Patch0068: 0068-builder-fix-small-regression-in-subkey-parsing.patch +Patch0069: 0069-builder-small-code-simplification.patch +Patch0070: 0070-builder-read-all-the-available-notes-from-the-index.patch +Patch0071: 0071-builder-Add-selinux-relabel-option-to-perform-SELinu.patch +Patch0072: 0072-builder-Add-documentation-for-enabling-Puppet-agent-.patch +Patch0073: 0073-daemon-Bind-mount-sys-fs-selinux-into-sysroot-when-r.patch +Patch0074: 0074-daemon-If-selinux-exists-in-the-guest-bind-mount-sys.patch +Patch0075: 0075-daemon-Add-a-note-about-how-mount-rbind-doesn-t-work.patch +Patch0076: 0076-builder-output-translated-notes.patch +Patch0077: 0077-builder-remove-unused-variables.patch +Patch0078: 0078-builder-isolate-C-libraries-in-an-own-OCAMLCLIBS.patch +Patch0079: 0079-builder-prepare-for-different-per-protocol-download-.patch +Patch0080: 0080-builder-do-a-copy-when-downloading-local-files.patch # Add any non-git patches here. # Use git for patch management. @@ -1081,6 +1096,9 @@ mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/libguestfs %changelog +* Wed Feb 12 2014 Richard W.M. Jones - 1:1.24.6-1 +- New stable branch version 1.24.6. + * Mon Jan 20 2014 Richard W.M. Jones - 1:1.24.5-1 - New stable branch version 1.24.5. - Backport more virt-builder patches from upstream to Fedora 20. diff --git a/sources b/sources index 6b9204b..53a6608 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -75d4e99b1fb57dd5dd5fc9be10a6c49d libguestfs-1.24.5.tar.gz +91aebe8a6e4c6576e88af097e62705b0 libguestfs-1.24.6.tar.gz