[libguestfs/f20] Backport virt-builder features from upstream at (multiple) users' request.

Richard W.M. Jones rjones at fedoraproject.org
Tue Nov 5 20:15:10 UTC 2013


commit 384b531c5067698a978e7cd6e9a7c2e4b3922fd9
Author: Richard W.M. Jones <rjones at redhat.com>
Date:   Tue Nov 5 19:19:39 2013 +0000

    Backport virt-builder features from upstream at (multiple) users' request.
    
    - Use git to manage patches, add copy-patches.sh script.

 ...-Don-t-run-virt-resize-when-not-necessary.patch |  150 ++
 ...e-xzcat-binary-configurable-and-use-AC_PA.patch |   73 +
 ...-pxzcat-optionally-to-speed-up-xzcat-step.patch |   74 +
 ...-Add-no-sync-option-to-avoid-sync-on-exit.patch |  101 +
 ...er-Add-mkdir-option-to-create-directories.patch |  137 ++
 0006-builder-Allow-upload-to-a-directory.patch     |   79 +
 ...-Add-write-option-to-write-a-literal-file.patch |  135 ++
 ...ument-how-to-boot-VMs-directly-in-qemu-or.patch |   39 +
 ...end-the-output-to-the-console-as-well-as-.patch |   62 +
 ...dd-a-section-on-performance-to-the-manual.patch |   69 +
 ...dd-m-memsize-and-smp-command-line-options.patch |  153 ++
 ...low-multiple-source-paths-to-be-specified.patch |  450 +++++
 ...-t-use-git-tree-libguestfs.git-to-refer-t.patch |   39 +
 ...Add-a-real-scanner-parser-for-index-files.patch | 1232 ++++++++++++
 ...-check-valgrind-so-it-does-something-in-t.patch |   41 +
 0016-builder-Fix-missing-files-in-EXTRA_DIST.patch |   35 +
 ...d-an-extra-Makefile.am-to-builder-website.patch |  141 ++
 ...-website-Add-index-validation-test-script.patch |   57 +
 ...ernal-implementation-of-parallel-xzcat-px.patch |  942 +++++++++
 ...lace-fedora-NN-shell-kickstart-with-a-sin.patch |  493 +++++
 ...eplace-ubuntu-NN-.sh-with-a-single-script.patch | 2081 ++++++++++++++++++++
 ...eplace-debian-NN-.sh-with-a-single-script.patch | 1578 +++++++++++++++
 ...-Replace-centos-6.sh-with-a-single-script.patch |  343 ++++
 ...site-Add-validate.sh-test-script-to-EXTRA.patch |   27 +
 0025-builder-Add-missing-dependency.patch          |   33 +
 ...er-Add-some-generated-files-to-CLEANFILES.patch |   29 +
 ...-dependency-from-index-parse.h-to-index-v.patch |   30 +
 ...x-centos-script-output-filename-was-wrong.patch |   28 +
 ...-dependencies-which-automake-doesn-t-gene.patch |   51 +
 copy-patches.sh                                    |   53 +
 libguestfs.spec                                    |   67 +-
 31 files changed, 8821 insertions(+), 1 deletions(-)
---
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
new file mode 100644
index 0000000..883bd09
--- /dev/null
+++ b/0001-builder-Don-t-run-virt-resize-when-not-necessary.patch
@@ -0,0 +1,150 @@
+From 1e5b73563918c762542d5251a2fc79ec609a4547 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 13:52:25 +0100
+Subject: [PATCH] builder: Don't run virt-resize when not necessary.
+
+If:
+ - the output is a regular file
+ - the output format is raw
+ - the user didn't specify the --size option
+then we don't need to run virt-resize.  Simply uncompress
+the template directly to the output file.
+
+(cherry picked from commit 2f3a3e308af8012501437f723471a66537ecbf64)
+---
+ builder/builder.ml | 65 ++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 48 insertions(+), 17 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 286fd7d..6750deb 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -232,7 +232,12 @@ let main () =
+ 
+       Sigchecker.verify_detached sigchecker template sigfile in
+ 
+-  let output, size, format, delete_output_file, resize_sparse =
++  (* 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 is_block_device file =
+       try (stat file).st_kind = S_BLK
+       with Unix_error _ -> false
+@@ -259,22 +264,22 @@ let main () =
+       (* Dummy: The output file is never deleted in this case. *)
+       let delete_output_file = ref false in
+ 
+-      output, None, format, delete_output_file, false
++      output, None, format, delete_output_file, true, false
+ 
+     (* Regular file output.  Note the file gets deleted. *)
+     | _ ->
+       (* Check the --size option. *)
+-      let size =
++      let size, do_resize =
+         let { Index_parser.size = default_size } = entry in
+         match size with
+-        | None -> default_size +^ headroom
++        | 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 in
++          size, true in
+ 
+       (* Create the output file. *)
+       let output, format =
+@@ -285,6 +290,14 @@ let main () =
+         | 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;
+       let cmd =
+         sprintf "qemu-img create -f %s%s %s %Ld%s"
+@@ -308,25 +321,42 @@ let main () =
+       in
+       at_exit delete_file;
+ 
+-      output, Some size, format, delete_output_file, true in
++      output, Some size, format, delete_output_file, do_resize, true in
+ 
+-  let source =
+-    (* Uncompress it to a temporary file. *)
++  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
+-    let tmpfile = Filename.temp_file "vbsrc" ".img" in
+-    let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++    let cmd = sprintf "xzcat %s > %s" (quote template) (quote output) in
+     if debug then eprintf "%s\n%!" cmd;
+     msg (f_"Uncompressing: %s") file_uri;
+     let r = Sys.command cmd in
+     if r <> 0 then (
+       eprintf (f_"%s: error: failed to uncompress template\n") prog;
+       exit 1
+-    );
+-    unlink_on_exit tmpfile;
+-    tmpfile in
++    )
++  ) 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
++      let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++      if debug then eprintf "%s\n%!" cmd;
++      msg (f_"Uncompressing: %s") file_uri;
++      let r = Sys.command cmd in
++      if r <> 0 then (
++        eprintf (f_"%s: error: failed to uncompress template\n") prog;
++        exit 1
++      );
++      unlink_on_exit tmpfile;
++      tmpfile in
+ 
+-  (* Resize the source to the output file. *)
+-  let () =
++    (* Resize the source to the output file. *)
+     (match size with
+     | None ->
+       msg (f_"Running virt-resize to expand the disk")
+@@ -351,13 +381,14 @@ let main () =
+         (match lvexpand with
+         | None -> ""
+         | Some lvexpand -> sprintf " --lv-expand %s" (quote lvexpand))
+-        (quote source) (quote output) in
++        (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
+-    ) in
++    )
++  );
+ 
+   (* Now mount the output disk so we can make changes. *)
+   msg (f_"Opening the new disk");
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..daf5ed0
--- /dev/null
+++ b/0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch
@@ -0,0 +1,73 @@
+From 6c92d98723e72d3e47066c53ea9fae0e95e4e7b1 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 14:09:20 +0100
+Subject: [PATCH] builder: Make xzcat binary configurable and use AC_PATH_PROG.
+
+(cherry picked from commit 0e18bccb648f8c96366ae53746d83bd009f924f7)
+---
+ builder/builder.ml | 9 +++++++--
+ configure.ac       | 4 ++++
+ mllib/config.ml.in | 2 ++
+ 3 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 6750deb..ae642d0 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -323,13 +323,18 @@ let main () =
+ 
+       output, Some size, format, delete_output_file, do_resize, true in
+ 
++  (* Create xzcat command to uncompress from input to output. *)
++  let xzcat_command input output =
++    sprintf "%s %s > %s" Config.xzcat input output
++  in
++
+   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
+-    let cmd = sprintf "xzcat %s > %s" (quote template) (quote output) in
++    let cmd = xzcat_command template output in
+     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 () =
+       (* Uncompress it to a temporary file. *)
+       let { Index_parser.file_uri = file_uri } = entry in
+       let tmpfile = Filename.temp_file "vbsrc" ".img" in
+-      let cmd = sprintf "xzcat %s > %s" (quote template) (quote tmpfile) in
++      let cmd = xzcat_command template tmpfile in
+       if debug then eprintf "%s\n%!" cmd;
+       msg (f_"Uncompressing: %s") file_uri;
+       let r = Sys.command cmd in
+diff --git a/configure.ac b/configure.ac
+index 8dc4e7f..b31abbc 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -698,6 +698,10 @@ if test "x$WRESTOOL" != "xno"; then
+     AC_DEFINE_UNQUOTED([WRESTOOL],["$WRESTOOL"],[Name of wrestool program.])
+ fi
+ 
++dnl Check for xzcat (required).
++AC_PATH_PROGS([XZCAT],[xzcat],[no])
++test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'.  Allow the user to override it.
+ qemu_system="$(
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index d18bf7b..129741d 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -18,3 +18,5 @@
+ 
+ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
++
++let xzcat = "@XZCAT@"
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..771bcb3
--- /dev/null
+++ b/0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch
@@ -0,0 +1,74 @@
+From 6ae9a5c40b4c19869e4843317c8884977cdd16b3 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 14:22:46 +0100
+Subject: [PATCH] builder: Use pxzcat (optionally) to speed up xzcat step.
+
+(cherry picked from commit d4450c6590744ab96c7e0c3b21325d1eff666f29)
+---
+ README             | 3 +++
+ builder/builder.ml | 6 ++++--
+ configure.ac       | 3 +++
+ mllib/config.ml.in | 4 ++++
+ 4 files changed, 14 insertions(+), 2 deletions(-)
+
+diff --git a/README b/README
+index 676bb2f..cdf492e 100644
+--- a/README
++++ b/README
+@@ -170,6 +170,9 @@ The full requirements are described below.
+ | gpg          |             | O | Used by virt-builder for digital        |
+ |              |             |   | signatures                              |
+ +--------------+-------------+---+-----------------------------------------+
++| pxzcat       |             | O | Can be used by virt-builder for fast    |
++|              |             |   | uncompression of templates.             |
+++--------------+-------------+---+-----------------------------------------+
+ | findlib      |             | O | For the OCaml bindings.                 |
+ +--------------+-------------+---+-----------------------------------------+
+ | ocaml-gettext|             | O | For localizing OCaml virt-* tools.      |
+diff --git a/builder/builder.ml b/builder/builder.ml
+index ae642d0..477fc3e 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -323,9 +323,11 @@ let main () =
+ 
+       output, Some size, format, delete_output_file, do_resize, true in
+ 
+-  (* Create xzcat command to uncompress from input to output. *)
++  (* Create xzcat/pxzcat command to uncompress from input to output. *)
+   let xzcat_command input output =
+-    sprintf "%s %s > %s" Config.xzcat input output
++    match Config.pxzcat with
++    | None -> sprintf "%s %s > %s" Config.xzcat input output
++    | Some pxzcat -> sprintf "%s %s -o %s" pxzcat input output
+   in
+ 
+   if not do_resize then (
+diff --git a/configure.ac b/configure.ac
+index b31abbc..00cb151 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -702,6 +702,9 @@ dnl Check for xzcat (required).
+ AC_PATH_PROGS([XZCAT],[xzcat],[no])
+ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
+ 
++dnl Check for pxzcat (optional).
++AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'.  Allow the user to override it.
+ qemu_system="$(
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index 129741d..5586c5c 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -20,3 +20,7 @@ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
+ 
+ let xzcat = "@XZCAT@"
++let pxzcat =
++  match "@PXZCAT@" with
++  | "no" -> None
++  | path -> Some path
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..827236d
--- /dev/null
+++ b/0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch
@@ -0,0 +1,101 @@
+From 5cfe8a0e678468318d8af403c197367979ba62a0 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 22 Oct 2013 22:28:27 +0100
+Subject: [PATCH] builder: Add --no-sync option to avoid sync on exit.
+
+(cherry picked from commit 3f46a92ed5737bb8d75630a39729f95bc96417f6)
+---
+ builder/builder.ml       |  5 +++--
+ builder/cmdline.ml       |  6 +++++-
+ builder/virt-builder.pod | 17 +++++++++++++++++
+ 3 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 477fc3e..7a46174 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -38,7 +38,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,
+-    upload =
++    sync, upload =
+     parse_cmdline () in
+ 
+   (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -727,7 +727,8 @@ exec >>%s 2>&1
+    * and therefore bypasses the host cache).  In general you should not
+    * use cache=none.
+    *)
+-  Fsync.file output;
++  if sync then
++    Fsync.file output;
+ 
+   (* Now that we've finished the build, don't delete the output file on
+    * exit.
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index 780e171..41d2a64 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -161,6 +161,8 @@ let parse_cmdline () =
+     with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+   let source = ref source in
+ 
++  let sync = ref true in
++
+   let upload = ref [] in
+   let add_upload arg =
+     let i =
+@@ -232,6 +234,7 @@ let parse_cmdline () =
+     "--scrub",   Arg.String add_scrub,      "name" ^ " " ^ s_"Scrub a file";
+     "--size",    Arg.String set_size,       "size" ^ " " ^ s_"Set output disk size";
+     "--source",  Arg.Set_string source,     "URL" ^ " " ^ s_"Set source URL";
++    "--no-sync", Arg.Clear sync,            " " ^ s_"Do not fsync output file on exit";
+     "--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;
+@@ -287,6 +290,7 @@ read the man page virt-builder(1).
+   let scrub_logfile = !scrub_logfile in
+   let size = !size in
+   let source = !source in
++  let sync = !sync in
+   let upload = List.rev !upload in
+ 
+   (* Check options. *)
+@@ -343,4 +347,4 @@ read the man page virt-builder(1).
+   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,
+-  upload
++  sync, upload
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 094b327..c3ea581 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).
+ 
+ =back
+ 
++=item B<--no-sync>
++
++Do not sync the output file on exit.
++
++Virt-builder fsync's the output file or disk image when it exits.
++
++The reason is that qemu/KVM's default caching mode is C<none> or
++C<directsync>, both of which bypass the host page cache.  Therefore
++these would not work correctly if you immediately started the guest
++after running virt-builder - they would not see the complete output
++file.  (Note that you should not use these caching modes - they are
++fundamentally broken for this and other reasons.)
++
++If you are not using these broken caching modes, you can use
++I<--no-sync> to avoid this unnecessary sync and gain considerable
++extra performance.
++
+ =item B<--notes> os-version
+ 
+ List any notes associated with this guest, then exit (this does not do
+-- 
+1.8.3.1
+
diff --git a/0005-builder-Add-mkdir-option-to-create-directories.patch b/0005-builder-Add-mkdir-option-to-create-directories.patch
new file mode 100644
index 0000000..690d672
--- /dev/null
+++ b/0005-builder-Add-mkdir-option-to-create-directories.patch
@@ -0,0 +1,137 @@
+From f29f1c655df5fe7beee82ae663ede60440d28d06 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 25 Oct 2013 13:35:51 +0100
+Subject: [PATCH] builder: Add --mkdir option to create directories.
+
+(cherry picked from commit 99840550d5508b228ee4b2533ad94da517873f76)
+---
+ builder/builder.ml           | 13 ++++++++++---
+ builder/cmdline.ml           | 12 +++++++++---
+ builder/test-virt-builder.sh |  1 +
+ builder/virt-builder.pod     | 12 ++++++++++++
+ 4 files changed, 32 insertions(+), 6 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 7a46174..f4f0951 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -36,9 +36,9 @@ let main () =
+   (* Command line argument parsing - see cmdline.ml. *)
+   let mode, arg,
+     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,
+-    sync, upload =
++    firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++    network, output, password_crypto, quiet, root_password, scrub,
++    scrub_logfile, size, source, sync, upload =
+     parse_cmdline () in
+ 
+   (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -582,6 +582,13 @@ exec >>%s 2>&1
+     do_run ~display:cmd cmd
+   );
+ 
++  (* Make directories. *)
++  List.iter (
++    fun dir ->
++      msg (f_"Making directory: %s") dir;
++      g#mkdir_p dir
++  ) mkdirs;
++
+   (* Upload files. *)
+   List.iter (
+     fun (file, dest) ->
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index 41d2a64..dbf49f2 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -119,6 +119,10 @@ let parse_cmdline () =
+   in
+ 
+   let list_long = ref false in
++
++  let mkdirs = ref [] in
++  let add_mkdir arg = mkdirs := arg :: !mkdirs in
++
+   let network = ref true in
+   let output = ref "" in
+ 
+@@ -217,6 +221,7 @@ let parse_cmdline () =
+     "--long",    Arg.Set list_long,         ditto;
+     "--no-logfile", Arg.Set scrub_logfile,  " " ^ s_"Scrub build log file";
+     "--long-options", Arg.Unit display_long_options, " " ^ s_"List long options";
++    "--mkdir",   Arg.String add_mkdir,      "dir" ^ " " ^ s_"Create directory";
+     "--network", Arg.Set network,           " " ^ s_"Enable appliance network (default)";
+     "--no-network", Arg.Clear network,      " " ^ s_"Disable appliance network";
+     "--notes",   Arg.Unit notes_mode,       " " ^ s_"Display installation notes";
+@@ -281,6 +286,7 @@ read the man page virt-builder(1).
+   let hostname = !hostname in
+   let install = !install in
+   let list_long = !list_long in
++  let mkdirs = List.rev !mkdirs in
+   let network = !network in
+   let output = match !output with "" -> None | s -> Some s in
+   let password_crypto = !password_crypto in
+@@ -345,6 +351,6 @@ read the man page virt-builder(1).
+ 
+   mode, arg,
+   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,
+-  sync, upload
++  firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++  network, output, password_crypto, quiet, root_password, scrub,
++  scrub_logfile, size, source, sync, upload
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index fbc52a0..a5df027 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -54,6 +54,7 @@ rm -f $output
+     -o $output --size 2G --format $format \
+     --hostname test.example.com \
+     --root-password password:123456 \
++    --mkdir /etc/foo/bar/baz \
+     --upload Makefile:/Makefile \
+     --delete /Makefile \
+     --firstboot Makefile --firstboot-command 'echo "hello"' \
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index c3ea581..42d0d8a 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -18,6 +18,7 @@ virt-builder - Build virtual machine images quickly
+     [--root-password ...]
+     [--hostname HOSTNAME]
+     [--install PKG,[PKG...]]
++    [--mkdir DIR]
+     [--upload FILE:DEST]
+     [--edit FILE:EXPR]
+     [--delete FILE] [--scrub FILE]
+@@ -364,6 +365,13 @@ the image was built, use this option.
+ 
+ See also: L</LOG FILE>.
+ 
++=item B<--mkdir> DIR
++
++Create a directory in the guest.
++
++This uses S<C<mkdir -p>> so any intermediate directories are created,
++and it also works if the directory already exists.
++
+ =item B<--network>
+ 
+ =item B<--no-network>
+@@ -749,6 +757,10 @@ Packages are installed (I<--install>).
+ 
+ =item *
+ 
++Directories are created (I<--mkdir>).
++
++=item *
++
+ Files are uploaded (I<--upload>).
+ 
+ =item *
+-- 
+1.8.3.1
+
diff --git a/0006-builder-Allow-upload-to-a-directory.patch b/0006-builder-Allow-upload-to-a-directory.patch
new file mode 100644
index 0000000..fd50106
--- /dev/null
+++ b/0006-builder-Allow-upload-to-a-directory.patch
@@ -0,0 +1,79 @@
+From ddf6681c75d3ca2a6e94a051a3d3650ac9f79d97 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 11:27:06 +0100
+Subject: [PATCH] builder: Allow --upload to a directory.
+
+Also set the owner and permissions on the destination file correctly.
+
+(cherry picked from commit 10c849ed1cb4375c5ef811197fa0a3206d365b86)
+---
+ builder/builder.ml           | 19 +++++++++++++++++--
+ builder/test-virt-builder.sh |  1 +
+ builder/virt-builder.pod     |  9 ++++++++-
+ 3 files changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index f4f0951..dab8b41 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -592,8 +592,23 @@ exec >>%s 2>&1
+   (* Upload files. *)
+   List.iter (
+     fun (file, dest) ->
+-      msg (f_"Uploading: %s") dest;
+-      g#upload file dest
++      msg (f_"Uploading: %s to %s") file dest;
++      let dest =
++        if g#is_dir dest then
++          dest ^ "/" ^ Filename.basename file
++        else
++          dest in
++      (* Do the file upload. *)
++      g#upload file dest;
++
++      (* Copy (some of) the permissions from the local file to the
++       * uploaded file.
++       *)
++      let statbuf = stat file in
++      let perms = statbuf.st_perm land 0o7777 (* sticky & set*id *) in
++      g#chmod perms dest;
++      let uid, gid = statbuf.st_uid, statbuf.st_gid in
++      g#chown uid gid dest
+   ) upload;
+ 
+   (* Edit files. *)
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index a5df027..b39bc3f 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -56,6 +56,7 @@ rm -f $output
+     --root-password password:123456 \
+     --mkdir /etc/foo/bar/baz \
+     --upload Makefile:/Makefile \
++    --upload Makefile:/etc/foo/bar/baz \
+     --delete /Makefile \
+     --firstboot Makefile --firstboot-command 'echo "hello"' \
+     --firstboot-install "minicom,inkscape"
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 42d0d8a..810cee7 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -559,7 +559,14 @@ Upload local file C<FILE> to destination C<DEST> in the disk image.
+ File owner and permissions from the original are preserved, so you
+ should set them to what you want them to be in the disk image.
+ 
+-See also: I<--delete>, I<--scrub>.
++C<DEST> could be the final filename.  This can be used to rename
++the file on upload.
++
++If C<DEST> is a directory name (which must already exist in the guest)
++then the file is uploaded into that directory, and it keeps the same
++name as on the local filesystem.
++
++See also: I<--mkdir>, I<--delete>, I<--scrub>.
+ 
+ =item B<-v>
+ 
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..0859ad0
--- /dev/null
+++ b/0007-builder-Add-write-option-to-write-a-literal-file.patch
@@ -0,0 +1,135 @@
+From 3c0dacb066a7aff4b55747862898e418f31dce9c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 11:40:48 +0100
+Subject: [PATCH] builder: Add --write option to write a literal file.
+
+(cherry picked from commit 0520aa3c42fbb174be37ef75b19390855d225897)
+---
+ builder/builder.ml           |  9 ++++++++-
+ builder/cmdline.ml           | 17 ++++++++++++++++-
+ builder/test-virt-builder.sh |  1 +
+ builder/virt-builder.pod     |  9 +++++++++
+ 4 files changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index dab8b41..803de0c 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -38,7 +38,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,
+-    scrub_logfile, size, source, sync, upload =
++    scrub_logfile, size, source, sync, upload, writes =
+     parse_cmdline () in
+ 
+   (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -589,6 +589,13 @@ exec >>%s 2>&1
+       g#mkdir_p dir
+   ) mkdirs;
+ 
++  (* Write files. *)
++  List.iter (
++    fun (file, content) ->
++      msg (f_"Writing: %s") file;
++      g#write file content
++  ) writes;
++
+   (* Upload files. *)
+   List.iter (
+     fun (file, dest) ->
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index dbf49f2..d92fcb9 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -184,6 +184,19 @@ let parse_cmdline () =
+     upload := (file, dest) :: !upload
+   in
+ 
++  let writes = ref [] in
++  let add_write arg =
++    let i =
++      try String.index arg ':'
++      with Not_found ->
++        eprintf (f_"%s: invalid --write format, see the man page.\n") prog;
++        exit 1 in
++    let len = String.length arg in
++    let file = String.sub arg 0 i in
++    let content = String.sub arg (i+1) (len-(i+1)) in
++    writes := (file, content) :: !writes
++  in
++
+   let ditto = " -\"-" in
+   let argspec = Arg.align [
+     "--attach",  Arg.String attach_disk,    "iso" ^ " " ^ s_"Attach data disk/ISO during install";
+@@ -245,6 +258,7 @@ let parse_cmdline () =
+     "--verbose", Arg.Set debug,             ditto;
+     "-V",        Arg.Unit display_version,  " " ^ s_"Display version and exit";
+     "--version", Arg.Unit display_version,  ditto;
++    "--write",   Arg.String add_write,      "file:content" ^ " " ^ s_"Write file";
+   ] in
+   long_options := argspec;
+ 
+@@ -298,6 +312,7 @@ read the man page virt-builder(1).
+   let source = !source in
+   let sync = !sync in
+   let upload = List.rev !upload in
++  let writes = List.rev !writes in
+ 
+   (* Check options. *)
+   let arg =
+@@ -353,4 +368,4 @@ read the man page virt-builder(1).
+   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,
+-  scrub_logfile, size, source, sync, upload
++  scrub_logfile, size, source, sync, upload, writes
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index b39bc3f..159f013 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -55,6 +55,7 @@ rm -f $output
+     --hostname test.example.com \
+     --root-password password:123456 \
+     --mkdir /etc/foo/bar/baz \
++    --write '/etc/foo/bar/baz/foo:Hello World' \
+     --upload Makefile:/Makefile \
+     --upload Makefile:/etc/foo/bar/baz \
+     --delete /Makefile \
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 810cee7..13d342d 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -19,6 +19,7 @@ virt-builder - Build virtual machine images quickly
+     [--hostname HOSTNAME]
+     [--install PKG,[PKG...]]
+     [--mkdir DIR]
++    [--write FILE:CONTENT]
+     [--upload FILE:DEST]
+     [--edit FILE:EXPR]
+     [--delete FILE] [--scrub FILE]
+@@ -583,6 +584,10 @@ your bug report.
+ 
+ Display version number and exit.
+ 
++=item B<--write> FILE:CONTENT
++
++Write C<CONTENT> to C<FILE>.
++
+ =back
+ 
+ =head1 REFERENCE
+@@ -768,6 +773,10 @@ Directories are created (I<--mkdir>).
+ 
+ =item *
+ 
++Files are written (I<--write>).
++
++=item *
++
+ Files are uploaded (I<--upload>).
+ 
+ =item *
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..fd3d322
--- /dev/null
+++ b/0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch
@@ -0,0 +1,39 @@
+From a80de72193e4a3fc379628b56035748436e2bcca Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 14:45:30 +0100
+Subject: [PATCH] builder: Document how to boot VMs directly in qemu or KVM.
+
+(cherry picked from commit 8b34855684fb660823a2801a4a5e8be32a6cc40f)
+---
+ builder/virt-builder.pod | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 13d342d..770d359 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -841,6 +841,21 @@ XXX
+ 
+ =end comment
+ 
++=head3 Booting directly using qemu or KVM
++
++The qemu command line is not very stable or easy to use, hence libvirt
++should be used if possible.  However a command line similar to the
++following could be used to boot the virtual machine:
++
++ qemu-system-x86_64 \
++   -machine accel=kvm:tcg \
++   -cpu host \
++   -m 2048 \
++   -drive file=disk.img,format=raw,if=virtio
++
++As with libvirt, it is very important that the correct format is
++chosen.  It will be C<raw> unless the I<--format> option was used.
++
+ =head2 DEBUGGING BUILDS
+ 
+ If virt-builder fails with an error, then enable debugging (I<-v>) and
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..d8aad17
--- /dev/null
+++ b/0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch
@@ -0,0 +1,62 @@
+From 044198313cda55e0f002d44459c7a09c3b3afdc5 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Sat, 26 Oct 2013 17:09:06 +0100
+Subject: [PATCH] firstboot: Send the output to the console as well as to the
+ log file.
+
+For systemd:
+Currently stdout+stderr go to the journal (these are effectively
+empty unless there are gross errors).  The output of the commands
+goes to the log file.
+
+With this change, the output goes to the journal, the console and
+the log file.
+
+For SysV-init:
+Currently stdout+stderr go to the console (but these are effectively
+empty).  The output of the commands goes to the log file.
+
+With this change, the output goes to the console and the log file.
+
+(cherry picked from commit f114e28cc80eabdcf47c97e7e3895065cdfe4886)
+---
+ mllib/firstboot.ml | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/mllib/firstboot.ml b/mllib/firstboot.ml
+index 0207cc1..9e4c7b6 100644
+--- a/mllib/firstboot.ml
++++ b/mllib/firstboot.ml
+@@ -45,16 +45,16 @@ let firstboot_sh = sprintf "\
+ d=%s/scripts
+ logfile=~root/virt-sysprep-firstboot.log
+ 
+-echo \"$0\" \"$@\" >>$logfile
+-echo \"Scripts dir: $d\" >>$logfile
++echo \"$0\" \"$@\" 2>&1 | tee $logfile
++echo \"Scripts dir: $d\" 2>&1 | tee $logfile
+ 
+ if test \"$1\" = \"start\"
+ then
+   for f in $d/* ; do
+     if test -x \"$f\"
+     then
+-      echo '=== Running' $f '===' >>$logfile
+-      $f >>$logfile 2>&1
++      echo '=== Running' $f '===' 2>&1 | tee $logfile
++      $f 2>&1 | tee $logfile
+       rm -f $f
+     fi
+   done
+@@ -71,6 +71,8 @@ Before=prefdm.service
+ Type=oneshot
+ ExecStart=%s/firstboot.sh start
+ RemainAfterExit=yes
++StandardOutput=journal+console
++StandardError=inherit
+ 
+ [Install]
+ WantedBy=default.target
+-- 
+1.8.3.1
+
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
new file mode 100644
index 0000000..bc581c2
--- /dev/null
+++ b/0010-builder-Add-a-section-on-performance-to-the-manual.patch
@@ -0,0 +1,69 @@
+From bf28209da7771951de0f113a5b9175fd75e27439 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+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(-)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 770d359..442bbec 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1290,7 +1290,50 @@ etc are truly random when the guest boots.
+ 
+ You should check digital signatures and not ignore any signing errors.
+ 
+-=head2 USER MODE LINUX
++=head2 PERFORMANCE
++
++The most important aspect of getting good performance is caching.
++Templates gets downloaded into the cache the first time they are used,
++or if you use the I<--cache-all-templates> option.  See L</CACHING>
++above for further information.
++
++Packages required for the I<--install> option are downloaded using the
++host network connection.  Setting the C<http_proxy>, C<https_proxy>
++and C<ftp_proxy> 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
++
++Virt-builder can skip the virt-resize step under certain conditions.
++This makes virt-builder much faster.  The conditions are:
++
++=over 4
++
++=item *
++
++the output must be a regular file (not a block device), B<and>
++
++=item *
++
++the user did B<not> use the I<--size> option, B<and>
++
++=item *
++
++the output format is the same as the template format (usually raw).
++
++=back
++
++=head3 pxzcat
++
++Virt-builder can use C<pxzcat> (parallel xzcat) if available to
++uncompress the templates.  The default is to use regular C<xzcat>
++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
+ 
+ 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.3.1
+
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
new file mode 100644
index 0000000..4d3ec5a
--- /dev/null
+++ b/0011-builder-Add-m-memsize-and-smp-command-line-options.patch
@@ -0,0 +1,153 @@
+From 8a98e37fde47ad310e8cee3c041f401d8d9739a8 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 29 Oct 2013 19:23:33 +0000
+Subject: [PATCH] builder: Add -m/--memsize and --smp command line options.
+
+(cherry picked from commit 42e445f98692c6344baafaab1da10e821288ac0a)
+---
+ builder/builder.ml       |  6 ++++--
+ builder/cmdline.ml       | 15 +++++++++++++--
+ builder/virt-builder.pod | 22 ++++++++++++++++------
+ 3 files changed, 33 insertions(+), 10 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index 803de0c..c9fd291 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -36,9 +36,9 @@ let main () =
+   (* Command line argument parsing - see cmdline.ml. *)
+   let mode, arg,
+     attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+-    firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++    firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+     network, output, password_crypto, quiet, root_password, scrub,
+-    scrub_logfile, size, source, sync, upload, writes =
++    scrub_logfile, size, smp, source, sync, upload, writes =
+     parse_cmdline () in
+ 
+   (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+@@ -403,6 +403,8 @@ let main () =
+     let g = new G.guestfs () in
+     if debug then g#set_trace true;
+ 
++    (match memsize with None -> () | Some memsize -> g#set_memsize memsize);
++    (match smp with None -> () | Some smp -> g#set_smp smp);
+     g#set_network network;
+ 
+     (* The output disk is being created, so use cache=unsafe here. *)
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index d92fcb9..f8e604e 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -120,6 +120,9 @@ let parse_cmdline () =
+ 
+   let list_long = ref false in
+ 
++  let memsize = ref None in
++  let set_memsize arg = memsize := Some arg in
++
+   let mkdirs = ref [] in
+   let add_mkdir arg = mkdirs := arg :: !mkdirs in
+ 
+@@ -160,6 +163,9 @@ let parse_cmdline () =
+   let size = ref None in
+   let set_size arg = size := Some (parse_size ~prog arg) in
+ 
++  let smp = ref None in
++  let set_smp arg = smp := Some arg in
++
+   let source =
+     try Sys.getenv "VIRT_BUILDER_SOURCE"
+     with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+@@ -234,6 +240,8 @@ let parse_cmdline () =
+     "--long",    Arg.Set list_long,         ditto;
+     "--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";
++    "--memsize", Arg.Int set_memsize,       "mb" ^ ditto;
+     "--mkdir",   Arg.String add_mkdir,      "dir" ^ " " ^ s_"Create directory";
+     "--network", Arg.Set network,           " " ^ s_"Enable appliance network (default)";
+     "--no-network", Arg.Clear network,      " " ^ s_"Disable appliance network";
+@@ -251,6 +259,7 @@ let parse_cmdline () =
+     "--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";
+     "--size",    Arg.String set_size,       "size" ^ " " ^ s_"Set output disk size";
++    "--smp",     Arg.Int set_smp,           "vcpus" ^ " " ^ s_"Set number of vCPUs";
+     "--source",  Arg.Set_string source,     "URL" ^ " " ^ s_"Set source URL";
+     "--no-sync", Arg.Clear sync,            " " ^ s_"Do not fsync output file on exit";
+     "--upload",  Arg.String add_upload,     "file:dest" ^ " " ^ s_"Upload file to dest";
+@@ -300,6 +309,7 @@ read the man page virt-builder(1).
+   let hostname = !hostname in
+   let install = !install in
+   let list_long = !list_long in
++  let memsize = !memsize in
+   let mkdirs = List.rev !mkdirs in
+   let network = !network in
+   let output = match !output with "" -> None | s -> Some s in
+@@ -309,6 +319,7 @@ read the man page virt-builder(1).
+   let scrub = List.rev !scrub in
+   let scrub_logfile = !scrub_logfile in
+   let size = !size in
++  let smp = !smp in
+   let source = !source in
+   let sync = !sync in
+   let upload = List.rev !upload in
+@@ -366,6 +377,6 @@ read the man page virt-builder(1).
+ 
+   mode, arg,
+   attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
+-  firstboot, run, format, gpg, hostname, install, list_long, mkdirs,
++  firstboot, run, format, gpg, hostname, install, list_long, memsize, mkdirs,
+   network, output, password_crypto, quiet, root_password, scrub,
+-  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 442bbec..70e19c3 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -366,6 +366,18 @@ the image was built, use this option.
+ 
+ See also: L</LOG FILE>.
+ 
++=item B<-m> MB
++
++=item B<--memsize> MB
++
++Change the amount of memory allocated to I<--run> scripts.  Increase
++this if you find that I<--run> scripts or the I<--install> option are
++running out of memory.
++
++The default can be found with this command:
++
++ guestfish get-memsize
++
+ =item B<--mkdir> DIR
+ 
+ Create a directory in the guest.
+@@ -541,6 +553,10 @@ 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.
+ 
++=item B<--smp> N
++
++Enable N E<ge> 2 virtual CPUs for I<--run> scripts to use.
++
+ =item B<--source> URL
+ 
+ Set the source URL to look for templates.  If not specified it
+@@ -1368,12 +1384,6 @@ are actually interpreted by L<curl(1)>, not virt-builder.
+ 
+ Used to determine the location of the template cache.  See L</CACHING>.
+ 
+-=item C<LIBGUESTFS_MEMSIZE>
+-
+-The size (in megabytes) of the appliance.  The default can be found
+-using the command S<C<guestfish get-memsize>>.  Increase this if you
+-find that I<--run> scripts are running out of memory.
+-
+ =item C<VIRT_BUILDER_FINGERPRINT>
+ 
+ Set the default value for the GPG signature fingerprint (see
+-- 
+1.8.3.1
+
diff --git a/0012-builder-Allow-multiple-source-paths-to-be-specified.patch b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch
new file mode 100644
index 0000000..be5152c
--- /dev/null
+++ b/0012-builder-Allow-multiple-source-paths-to-be-specified.patch
@@ -0,0 +1,450 @@
+From 2c081f7d45a250220860a3a21938a3f2d7d39a9b Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Fri, 1 Nov 2013 14:16:34 +0000
+Subject: [PATCH] builder: Allow multiple source paths to be specified.
+
+Users can now specify multiple source paths, eg:
+
+  virt-builder --source http://example.com/foo \
+    --source http://example.com/bar
+
+to get templates from multiple places.
+
+There is still only one built-in path, but we can add more later.
+
+(cherry picked from commit bb4e882d61b49045aabd35912ae7e3a18cd6028b)
+---
+ builder/builder.ml                | 32 +++++++++++-------
+ builder/cmdline.ml                | 69 ++++++++++++++++++++++++++++++---------
+ builder/index_parser.ml           |  5 ++-
+ builder/index_parser.mli          |  2 ++
+ builder/list_entries.ml           | 10 ++++--
+ builder/list_entries.mli          |  2 +-
+ builder/sigchecker.ml             |  7 ++--
+ builder/sigchecker.mli            |  4 ++-
+ builder/test-virt-builder-list.sh |  1 +
+ builder/virt-builder.pod          | 57 ++++++++++++++++++++++++++------
+ 10 files changed, 143 insertions(+), 46 deletions(-)
+
+diff --git a/builder/builder.ml b/builder/builder.ml
+index c9fd291..fc6078c 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -35,22 +35,27 @@ 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, fingerprint,
++    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, source, sync, upload, writes =
++    scrub_logfile, size, smp, sources, sync, upload, writes =
+     parse_cmdline () in
+ 
+   (* Timestamped messages in ordinary, non-debug non-quiet mode. *)
+   let msg fs = make_message_function ~quiet fs in
+ 
+-  (* If debugging, echo the command line arguments. *)
++  (* If debugging, echo the command line arguments and the sources. *)
+   if debug then (
+     eprintf "command line:";
+     List.iter (eprintf " %s") (Array.to_list Sys.argv);
+-    prerr_newline ()
++    prerr_newline ();
++    List.iteri (
++      fun i (source, fingerprint) ->
++        eprintf "source[%d] = (%S, %S)\n" i source fingerprint
++    ) sources
+   );
+ 
++
+   (* Handle some modes here, some later on. *)
+   let mode =
+     match mode with
+@@ -125,19 +130,23 @@ let main () =
+       )
+   in
+ 
+-  (* Make the downloader and signature checker abstract data types. *)
++  (* Download the sources. *)
+   let downloader = Downloader.create ~debug ~curl ~cache in
+-  let sigchecker =
+-    Sigchecker.create ~debug ~gpg ?fingerprint ~check_signature in
+-
+-  (* Download the source (index) file. *)
+-  let index = Index_parser.get_index ~debug ~downloader ~sigchecker source in
++  let index : Index_parser.index =
++    List.concat (
++      List.map (
++        fun (source, fingerprint) ->
++          let sigchecker =
++            Sigchecker.create ~debug ~gpg ~fingerprint ~check_signature in
++          Index_parser.get_index ~debug ~downloader ~sigchecker source
++      ) sources
++    ) in
+ 
+   (* Now handle the remaining modes. *)
+   let mode =
+     match mode with
+     | `List ->                          (* --list *)
+-      List_entries.list_entries ~list_long ~source index;
++      List_entries.list_entries ~list_long ~sources index;
+       exit 0
+ 
+     | `Print_cache ->                   (* --print-cache *)
+@@ -184,6 +193,7 @@ let main () =
+       eprintf (f_"%s: cannot find os-version '%s'.\nUse --list to list available guest types.\n")
+         prog arg;
+       exit 1 in
++  let sigchecker = entry.Index_parser.sigchecker in
+ 
+   (match mode with
+   | `Notes ->                           (* --notes *)
+diff --git a/builder/cmdline.ml b/builder/cmdline.ml
+index f8e604e..5256390 100644
+--- a/builder/cmdline.ml
++++ b/builder/cmdline.ml
+@@ -37,6 +37,8 @@ let default_cachedir =
+     with Not_found ->
+       None (* no cache directory *)
+ 
++let default_source = "http://libguestfs.org/download/builder/index.asc"
++
+ let parse_cmdline () =
+   let display_version () =
+     printf "virt-builder %s\n" Config.package_version;
+@@ -83,11 +85,8 @@ let parse_cmdline () =
+     edit := (file, expr) :: !edit
+   in
+ 
+-  let fingerprint =
+-    try Some (Sys.getenv "VIRT_BUILDER_FINGERPRINT")
+-    with Not_found -> None in
+-  let fingerprint = ref fingerprint in
+-  let set_fingerprint fp = fingerprint := Some fp in
++  let fingerprints = ref [] in
++  let add_fingerprint arg = fingerprints := arg :: !fingerprints in
+ 
+   let firstboot = ref [] in
+   let add_firstboot s =
+@@ -166,10 +165,8 @@ let parse_cmdline () =
+   let smp = ref None in
+   let set_smp arg = smp := Some arg in
+ 
+-  let source =
+-    try Sys.getenv "VIRT_BUILDER_SOURCE"
+-    with Not_found -> "http://libguestfs.org/download/builder/index.asc" in
+-  let source = ref source in
++  let sources = ref [] in
++  let add_source arg = sources := arg :: !sources in
+ 
+   let sync = ref true in
+ 
+@@ -223,7 +220,7 @@ let parse_cmdline () =
+     "--delete-cache", Arg.Unit delete_cache_mode,
+                                             " " ^ s_"Delete the template cache";
+     "--edit",    Arg.String add_edit,       "file:expr" ^ " " ^ s_"Edit file with Perl expr";
+-    "--fingerprint", Arg.String set_fingerprint,
++    "--fingerprint", Arg.String add_fingerprint,
+                                             "AAAA.." ^ " " ^ s_"Fingerprint of valid signing key";
+     "--firstboot", Arg.String add_firstboot, "script" ^ " " ^ s_"Run script at first guest boot";
+     "--firstboot-command", Arg.String add_firstboot_cmd, "cmd+args" ^ " " ^ s_"Run command at first guest boot";
+@@ -260,7 +257,7 @@ let parse_cmdline () =
+     "--scrub",   Arg.String add_scrub,      "name" ^ " " ^ s_"Scrub a file";
+     "--size",    Arg.String set_size,       "size" ^ " " ^ s_"Set output disk size";
+     "--smp",     Arg.Int set_smp,           "vcpus" ^ " " ^ s_"Set number of vCPUs";
+-    "--source",  Arg.Set_string source,     "URL" ^ " " ^ s_"Set source URL";
++    "--source",  Arg.String add_source,     "URL" ^ " " ^ s_"Set source URL";
+     "--no-sync", Arg.Clear sync,            " " ^ s_"Do not fsync output file on exit";
+     "--upload",  Arg.String add_upload,     "file:dest" ^ " " ^ s_"Upload file to dest";
+     "-v",        Arg.Set debug,             " " ^ s_"Enable debugging messages";
+@@ -301,7 +298,7 @@ read the man page virt-builder(1).
+   let debug = !debug in
+   let delete = List.rev !delete in
+   let edit = List.rev !edit in
+-  let fingerprint = !fingerprint in
++  let fingerprints = List.rev !fingerprints in
+   let firstboot = List.rev !firstboot in
+   let run = List.rev !run in
+   let format = match !format with "" -> None | s -> Some s in
+@@ -320,7 +317,7 @@ read the man page virt-builder(1).
+   let scrub_logfile = !scrub_logfile in
+   let size = !size in
+   let smp = !smp in
+-  let source = !source in
++  let sources = List.rev !sources in
+   let sync = !sync in
+   let upload = List.rev !upload in
+   let writes = List.rev !writes in
+@@ -375,8 +372,50 @@ read the man page virt-builder(1).
+         exit 1
+       ) in
+ 
++  (* Check source(s) and fingerprint(s), or use environment or default. *)
++  let sources =
++    let list_split = function "" -> [] | str -> string_nsplit "," str in
++    let rec repeat x = function
++      | 0 -> [] | 1 -> [x]
++      | n -> x :: repeat x (n-1)
++    in
++
++    let sources =
++      if sources <> [] then sources
++      else (
++        try list_split (Sys.getenv "VIRT_BUILDER_SOURCE")
++        with Not_found -> [ default_source ]
++      ) in
++    let fingerprints =
++      if fingerprints <> [] then fingerprints
++      else (
++        try list_split (Sys.getenv "VIRT_BUILDER_FINGERPRINT")
++        with Not_found -> [ Sigchecker.default_fingerprint ]
++      ) in
++
++    let nr_sources = List.length sources in
++    let fingerprints =
++      match fingerprints with
++      | [fingerprint] ->
++        (* You're allowed to have multiple sources and one fingerprint: it
++         * means that the same fingerprint is used for all sources.
++         *)
++        repeat fingerprint nr_sources
++      | xs -> xs in
++
++    if List.length fingerprints <> nr_sources then (
++      eprintf (f_"%s: source and fingerprint lists are not the same length\n")
++        prog;
++      exit 1
++    );
++
++    assert (nr_sources > 0);
++
++    (* Combine the sources and fingerprints into a single list of pairs. *)
++    List.combine sources fingerprints in
++
+   mode, arg,
+-  attach, cache, check_signature, curl, debug, delete, edit, fingerprint,
++  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, source, sync, upload, writes
++  scrub_logfile, size, smp, sources, sync, upload, writes
+diff --git a/builder/index_parser.ml b/builder/index_parser.ml
+index b5a0cf0..dc039fe 100644
+--- a/builder/index_parser.ml
++++ b/builder/index_parser.ml
+@@ -37,6 +37,8 @@ and entry = {
+   lvexpand : string option;
+   notes : string option;
+   hidden : bool;
++
++  sigchecker : Sigchecker.t;
+ }
+ 
+ let print_entry chan (name, { printable_name = printable_name;
+@@ -348,7 +350,8 @@ let get_index ~debug ~downloader ~sigchecker source =
+                         expand = expand;
+                         lvexpand = lvexpand;
+                         notes = notes;
+-                        hidden = hidden } in
++                        hidden = hidden;
++                        sigchecker = sigchecker } in
+           n, entry
+       ) sections in
+ 
+diff --git a/builder/index_parser.mli b/builder/index_parser.mli
+index 79df5ef..0b6317d 100644
+--- a/builder/index_parser.mli
++++ b/builder/index_parser.mli
+@@ -31,6 +31,8 @@ and entry = {
+   lvexpand : string option;
+   notes : string option;
+   hidden : bool;
++
++  sigchecker : Sigchecker.t;
+ }
+ 
+ val get_index : debug:bool -> downloader:Downloader.t -> sigchecker:Sigchecker.t -> string -> index
+diff --git a/builder/list_entries.ml b/builder/list_entries.ml
+index b233f0e..04a65ca 100644
+--- a/builder/list_entries.ml
++++ b/builder/list_entries.ml
+@@ -21,10 +21,14 @@ open Common_utils
+ 
+ open Printf
+ 
+-let list_entries ?(list_long = false) ~source index =
++let list_entries ?(list_long = false) ~sources index =
+   if list_long then (
+-    printf (f_"Source URI: %s\n") source;
+-    printf "\n"
++    List.iter (
++      fun (source, fingerprint) ->
++        printf (f_"Source URI: %s\n") source;
++        printf (f_"Fingerprint: %s\n") fingerprint;
++        printf "\n"
++    ) sources
+   );
+ 
+   List.iter (
+diff --git a/builder/list_entries.mli b/builder/list_entries.mli
+index e1d5c06..d9486b0 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 -> source:string -> Index_parser.index -> unit
++val list_entries : ?list_long:bool -> sources:(string * string) list -> Index_parser.index -> unit
+diff --git a/builder/sigchecker.ml b/builder/sigchecker.ml
+index 2bd3c11..b20a186 100644
+--- a/builder/sigchecker.ml
++++ b/builder/sigchecker.ml
+@@ -104,7 +104,7 @@ type t = {
+   check_signature : bool;
+ }
+ 
+-let create ~debug ~gpg ?(fingerprint = default_fingerprint) ~check_signature =
++let create ~debug ~gpg ~fingerprint ~check_signature =
+   {
+     debug = debug;
+     gpg = gpg;
+@@ -188,10 +188,9 @@ and do_verify t args =
+     exit 1
+   )
+ 
+-(* Import the default public key, if it's the default fingerprint. *)
++(* Import the default public key. *)
+ and import_key t =
+-  if not !key_imported && equal_fingerprints t.fingerprint default_fingerprint
+-  then (
++  if not !key_imported then (
+     let filename, chan = Filename.open_temp_file "vbpubkey" ".asc" in
+     unlink_on_exit filename;
+     output_string chan default_pubkey;
+diff --git a/builder/sigchecker.mli b/builder/sigchecker.mli
+index 4d89129..cdd800e 100644
+--- a/builder/sigchecker.mli
++++ b/builder/sigchecker.mli
+@@ -16,9 +16,11 @@
+  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+  *)
+ 
++val default_fingerprint : string
++
+ type t
+ 
+-val create : debug:bool -> gpg:string -> ?fingerprint:string -> check_signature:bool -> t
++val create : debug:bool -> gpg:string -> fingerprint:string -> check_signature:bool -> t
+ 
+ val verify : t -> string -> unit
+ (** Verify the file is signed (if check_signature is true). *)
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 01e4d1b..823f774 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -39,6 +39,7 @@ fi
+ long_list=$(./virt-builder --no-check-signature --no-cache --list --long)
+ 
+ if [ "$long_list" != "Source URI: $VIRT_BUILDER_SOURCE
++Fingerprint: F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0
+ 
+ os-version:              phony-debian
+ Full name:               Phony Debian
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 70e19c3..4e33bc8 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
+ given fingerprint.  (The fingerprint is a long string, usually written
+ as 10 groups of 4 hexadecimal digits).
+ 
+-If signature checking is enabled and the I<--fingerprint> option is
+-not given, then this checks the download was signed by
+-S<F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0> (which is
+-S<Richard W.M. Jones's> key).
++You can give this option multiple times.  If you have multiple source
++URLs, then you can have either no fingerprint, one fingerprint or
++multiple fingerprints.  If you have multiple, then each must
++correspond 1-1 with a source URL.
++
++The default fingerprint (if none are supplied) is
++S<F777 4FB1 AD07 4A7E 8C87 67EA 9173 8F73 E1B7 68A0>
++(which is S<Richard W.M. Jones's> key).
+ 
+ You can also set the C<VIRT_BUILDER_FINGERPRINT> environment variable.
+ 
+@@ -559,8 +563,11 @@ Enable N E<ge> 2 virtual CPUs for I<--run> scripts to use.
+ 
+ =item B<--source> URL
+ 
+-Set the source URL to look for templates.  If not specified it
+-defaults to L<http://libguestfs.org/download/builder/index.asc>
++Set the source URL to look for indexes.
++
++You can give this option multiple times to specify multiple sources.
++If not specified it defaults to
++L<http://libguestfs.org/download/builder/index.asc>
+ 
+ See also L</CREATING YOUR OWN TEMPLATES> below.
+ 
+@@ -1202,6 +1209,36 @@ Now run virt-builder commands as normal, eg:
+ 
+ To debug problems, add the C<-v> option to these commands.
+ 
++=head3 Running virt-builder against multiple sources
++
++It is possible to use multiple sources with virt-builder.  Use either
++multiple I<--source> and/or I<--fingerprint> options, or a
++comma-separated list in the C<VIRT_BUILDER_SOURCE> /
++C<VIRT_BUILDER_FINGERPRINT> environment variables:
++
++ virt-builder \
++   --source http://example.com/s1/index.asc \
++   --source http://example.com/s2/index.asc
++
++or equivalently:
++
++ export VIRT_BUILDER_SOURCE=http://example.com/s1/index.asc,http://example.com/s2/index.asc
++ virt-builder [...]
++
++You can provide N, 1 or 0 fingerprints.  In the case where you
++provide N fingerprints, N = number of sources and there is a 1-1
++correspondence between each source and each fingerprint:
++
++ virt-builder \
++   --source http://example.com/s1/index.asc --fingerprint '0123 ...' \
++   --source http://example.com/s2/index.asc --fingerprint '9876 ...'
++
++In the case where you provide 1 fingerprint, the same fingerprint
++is used for all sources.
++
++In the case where you provide no fingerprints, the default fingerprint
++built into virt-builder is used for all sources.
++
+ =head3 Licensing of templates
+ 
+ You should be aware of the licensing of images that you distribute.
+@@ -1386,13 +1423,13 @@ Used to determine the location of the template cache.  See L</CACHING>.
+ 
+ =item C<VIRT_BUILDER_FINGERPRINT>
+ 
+-Set the default value for the GPG signature fingerprint (see
+-I<--fingerprint> option).
++Set the default value for the GPG signature fingerprint or
++comma-separated list of fingerprints (see I<--fingerprint> option).
+ 
+ =item C<VIRT_BUILDER_SOURCE>
+ 
+-Set the default value for the source URL for the template repository
+-(see I<--source> option).
++Set the default value for the source URL (or comma-separated list of
++URLs) for the template repository (see I<--source> option).
+ 
+ =item C<XDG_CACHE_HOME>
+ 
+-- 
+1.8.3.1
+
diff --git a/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch b/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
new file mode 100644
index 0000000..4ee60bd
--- /dev/null
+++ b/0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
@@ -0,0 +1,39 @@
+From f1a283dc21a295d31dfb7d37ed67b1359841070c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 21:35:48 +0000
+Subject: [PATCH] builder: Don't use git tree / libguestfs.git to refer to the
+ source.
+
+git is just a VCS.
+
+(cherry picked from commit 3ffdddbedf176fa5f12172fb2e3c6bd4b2690f9e)
+---
+ builder/virt-builder.pod | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 4e33bc8..5eba666 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -949,7 +949,7 @@ out the information in this index file.
+ 
+ The templates hosted on libguestfs.org were created using shell
+ scripts, kickstart files and preseed files which can be found in the
+-libguestfs source tree, in C<libguestfs.git/builder/website>.
++libguestfs source tree, in C<builder/website>.
+ 
+ =head3 Setting up the repository
+ 
+@@ -994,8 +994,7 @@ Also find the fingerprint of your key:
+ There are many ways to create the templates.  For example you could
+ clone existing guests (see L<virt-sysprep(1)>), or you could install a
+ guest by hand (L<virt-install(1)>).  To see how the templates were
+-created for virt-builder, look at the scripts in
+-C<libguestfs.git/builder/website>
++created for virt-builder, look at the scripts in C<builder/website>
+ 
+ For best results when compressing the templates, use the following xz
+ options (see L<nbdkit-xz-plugin(1)> for further explanation):
+-- 
+1.8.3.1
+
diff --git a/0014-builder-Add-a-real-scanner-parser-for-index-files.patch b/0014-builder-Add-a-real-scanner-parser-for-index-files.patch
new file mode 100644
index 0000000..74852a7
--- /dev/null
+++ b/0014-builder-Add-a-real-scanner-parser-for-index-files.patch
@@ -0,0 +1,1232 @@
+From 4785b527ce69d0aa1c7983f81a70f30d9837ee88 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 14:53:41 +0000
+Subject: [PATCH] builder: Add a real scanner/parser for index files.
+
+This adds a tool called virt-index-validate to validate index files.
+
+(cherry picked from commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633)
+---
+ .gitignore                        |   7 ++
+ README                            |   4 +
+ builder/Makefile.am               |  56 +++++++++----
+ builder/index-parse.y             | 123 +++++++++++++++++++++++++++++
+ builder/index-parser-c.c          | 105 +++++++++++++++++++++++++
+ builder/index-scan.l              | 103 ++++++++++++++++++++++++
+ builder/index-struct.c            |  58 ++++++++++++++
+ builder/index-struct.h            |  48 ++++++++++++
+ builder/index-validate.c          | 161 ++++++++++++++++++++++++++++++++++++++
+ builder/index_parser.ml           | 143 ++++-----------------------------
+ builder/list_entries.ml           |   2 +-
+ builder/test-virt-builder-list.sh |  12 ++-
+ builder/virt-builder.pod          |  17 ++++
+ builder/virt-index-validate.pod   |  92 ++++++++++++++++++++++
+ configure.ac                      |   4 +
+ po-docs/ja/Makefile.am            |   1 +
+ po-docs/podfiles                  |   1 +
+ po-docs/uk/Makefile.am            |   1 +
+ po/POTFILES                       |   5 ++
+ 19 files changed, 793 insertions(+), 150 deletions(-)
+ create mode 100644 builder/index-parse.y
+ create mode 100644 builder/index-parser-c.c
+ create mode 100644 builder/index-scan.l
+ create mode 100644 builder/index-struct.c
+ create mode 100644 builder/index-struct.h
+ create mode 100644 builder/index-validate.c
+ create mode 100644 builder/virt-index-validate.pod
+
+diff --git a/.gitignore b/.gitignore
+index 8a1ffef..e2ea9ce 100644
+--- a/.gitignore
++++ b/.gitignore
+@@ -58,10 +58,16 @@ Makefile.in
+ /bash/virt-sparsify
+ /build-aux
+ /builder/.depend
++/builder/index-parse.c
++/builder/index-parse.h
++/builder/index-scan.c
+ /builder/stamp-virt-builder.pod
++/builder/stamp-virt-index-validate.pod
+ /builder/test-index
+ /builder/virt-builder
+ /builder/virt-builder.1
++/builder/virt-index-validate
++/builder/virt-index-validate.1
+ /builder/*.xz
+ /cat/stamp-virt-*.pod
+ /cat/virt-cat
+@@ -224,6 +230,7 @@ Makefile.in
+ /html/virt-edit.1.html
+ /html/virt-filesystems.1.html
+ /html/virt-format.1.html
++/html/virt-index-validate.1.html
+ /html/virt-inspector.1.html
+ /html/virt-list-filesystems.1.html
+ /html/virt-list-partitions.1.html
+diff --git a/README b/README
+index cdf492e..461915d 100644
+--- a/README
++++ b/README
+@@ -94,6 +94,10 @@ The full requirements are described below.
+ +--------------+-------------+---+-----------------------------------------+
+ | gperf        |             | R |                                         |
+ +--------------+-------------+---+-----------------------------------------+
++| flex         |             | R | flex & bison are required for virt-     |
+++--------------+-------------+---| builder.  We could make these           |
++| bison        |             | R | optional but automakes makes it hard.   |
+++--------------+-------------+---+-----------------------------------------+
+ | PCRE         |             | R | Perl-compatible Regular Expression lib. |
+ +--------------+-------------+---+-----------------------------------------+
+ | genisoimage  |             | R | mkisofs may work.                       |
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index b995c90..cb490e1 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -17,6 +17,12 @@
+ 
+ include $(top_srcdir)/subdir-rules.mk
+ 
++AM_YFLAGS = -d
++AM_CFLAGS = \
++	-I$(shell $(OCAMLC) -where) \
++	-I$(top_srcdir)/src \
++	-I$(top_srcdir)/fish
++
+ EXTRA_DIST = \
+ 	$(SOURCES) \
+ 	virt-builder.pod \
+@@ -71,6 +77,9 @@ SOURCES = \
+ 	sigchecker.mli \
+ 	sigchecker.ml
+ 
++man_MANS =
++noinst_DATA =
++
+ if HAVE_OCAML
+ 
+ # Note this list must be in dependency order.
+@@ -87,6 +96,10 @@ OBJECTS = \
+ 	$(top_builddir)/mllib/fsync.cmx \
+ 	$(top_builddir)/mllib/password.cmx \
+ 	$(top_builddir)/mllib/config.cmx \
++	index-scan.o \
++	index-struct.o \
++	index-parse.o \
++	index-parser-c.o \
+ 	get_kernel.cmx \
+ 	downloader.cmx \
+ 	sigchecker.cmx \
+@@ -127,24 +140,10 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ 	$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+ 
+-# automake will decide we don't need C support in this file.  Really
+-# we do, so we have to provide it ourselves.
+-
+-DEFAULT_INCLUDES = \
+-	-I. \
+-	-I$(top_builddir) \
+-	-I$(shell $(OCAMLC) -where) \
+-	-I$(top_srcdir)/src \
+-	-I$(top_srcdir)/fish
+-
+-.c.o:
+-	$(CC) $(CFLAGS) $(PROF_CFLAGS) $(DEFAULT_INCLUDES) -c $< -o $@
+-
+ # Manual pages and HTML files for the website.
+ 
+-man_MANS = virt-builder.1
+-
+-noinst_DATA = $(top_builddir)/html/virt-builder.1.html
++man_MANS += virt-builder.1
++noinst_DATA += $(top_builddir)/html/virt-builder.1.html
+ 
+ virt-builder.1 $(top_builddir)/html/virt-builder.1.html: stamp-virt-builder.pod
+ 
+@@ -200,3 +199,28 @@ endif
+ DISTCLEANFILES = .depend
+ 
+ .PHONY: depend docs
++
++# Build a small C index validator program.
++bin_PROGRAMS = virt-index-validate
++
++virt_index_validate_SOURCES = \
++	index-parse.y \
++	index-scan.l \
++	index-struct.h \
++	index-struct.c \
++	index-validate.c
++
++man_MANS += virt-index-validate.1
++noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
++
++virt-index-validate.1 $(top_builddir)/html/virt-index-validate.1.html: stamp-virt-index-validate.pod
++
++stamp-virt-index-validate.pod: virt-index-validate.pod
++	$(PODWRAPPER) \
++	  --man virt-index-validate.1 \
++	  --html $(top_builddir)/html/virt-index-validate.1.html \
++	  --license GPLv2+ \
++	  $<
++	touch $@
++
++CLEANFILES += stamp-virt-index-validate.pod
+diff --git a/builder/index-parse.y b/builder/index-parse.y
+new file mode 100644
+index 0000000..f5e551b
+--- /dev/null
++++ b/builder/index-parse.y
+@@ -0,0 +1,123 @@
++/* libguestfs virt-builder tool -*- fundamental -*-
++ * 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.
++ */
++
++%{
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "index-struct.h"
++
++extern void yyerror (const char *);
++extern int yylex (void);
++
++/* Join two strings with \n */
++static char *
++concat_newline (const char *str1, const char *str2)
++{
++  size_t len1, len2, len;
++  char *ret;
++
++  if (str2 == NULL)
++    return strdup (str1);
++
++  len1 = strlen (str1);
++  len2 = strlen (str2);
++  len = len1 + 1 /* \n */ + len2 + 1 /* \0 */;
++  ret = malloc (len);
++  memcpy (ret, str1, len1);
++  ret[len1] = '\n';
++  memcpy (ret + len1 + 1, str2, len2);
++  ret[len-1] = '\0';
++
++  return ret;
++}
++
++%}
++
++%locations
++
++%union {
++  struct section *section;
++  struct field *field;
++  char *str;
++}
++
++%token <str>   SECTION_HEADER
++%token <field> FIELD
++%token <str>   VALUE_CONT
++%token         EMPTY_LINE
++%token         PGP_PROLOGUE
++%token         PGP_EPILOGUE
++
++%type <section> sections section
++%type <field>   fields field
++%type <str>     continuations
++
++%%
++
++index:
++      sections
++        { parsed_index = $1; }
++    | PGP_PROLOGUE sections PGP_EPILOGUE
++        { parsed_index = $2; }
++
++sections:
++      section
++        { $$ = $1; }
++    | section EMPTY_LINE sections
++        { $$ = $1; $$->next = $3; }
++
++section:
++      SECTION_HEADER fields
++        { $$ = malloc (sizeof (struct section));
++          $$->next = NULL;
++          $$->name = $1;
++          $$->fields = $2; }
++
++fields:
++      /* empty */
++        { $$ = NULL; }
++    | field fields
++        { $$ = $1; $$->next = $2; }
++
++field: FIELD continuations
++        { $$ = $1;
++          char *old_value = $$->value;
++          $$->value = concat_newline (old_value, $2);
++          free (old_value);
++          free ($2); }
++
++continuations:
++      /* empty */
++        { $$ = NULL; }
++    | VALUE_CONT continuations
++        { $$ = concat_newline ($1, $2);
++          free ($1);
++          free ($2); }
++
++%%
++
++void
++yyerror (const char *msg)
++{
++  fprintf (stderr, "syntax error at line %d: %s\n",
++           yylloc.first_line, msg);
++}
+diff --git a/builder/index-parser-c.c b/builder/index-parser-c.c
+new file mode 100644
+index 0000000..17e680b
+--- /dev/null
++++ b/builder/index-parser-c.c
+@@ -0,0 +1,105 @@
++/* virt-builder
++ * 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.
++ */
++
++/* This file handles the interface between the C/lex/yacc index file
++ * parser, and the OCaml world.  See index_parser.ml for the OCaml
++ * type definition.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <errno.h>
++#include <unistd.h>
++
++#include <caml/alloc.h>
++#include <caml/fail.h>
++#include <caml/memory.h>
++#include <caml/mlvalues.h>
++
++#ifdef HAVE_CAML_UNIXSUPPORT_H
++#include <caml/unixsupport.h>
++#else
++#define Nothing ((value) 0)
++extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
++#endif
++
++#include "index-struct.h"
++#include "index-parse.h"
++
++extern FILE *yyin;
++
++value
++virt_builder_parse_index (value filenamev)
++{
++  CAMLparam1 (filenamev);
++  CAMLlocal4 (rv, v, sv, fv);
++  struct section *sections;
++  size_t i, nr_sections;
++
++  yyin = fopen (String_val (filenamev), "r");
++  if (yyin == NULL)
++    unix_error (errno, (char *) "fopen", filenamev);
++
++  if (yyparse () != 0) {
++    fclose (yyin);
++    caml_invalid_argument ("parse error");
++  }
++
++  if (fclose (yyin) == EOF)
++    unix_error (errno, (char *) "fclose", filenamev);
++
++  /* Convert the parsed data to OCaml structures. */
++  nr_sections = 0;
++  for (sections = parsed_index; sections != NULL; sections = sections->next)
++    nr_sections++;
++  rv = caml_alloc (nr_sections, 0);
++
++  for (i = 0, sections = parsed_index; sections != NULL;
++       i++, sections = sections->next) {
++    struct field *fields;
++    size_t j, nr_fields;
++
++    nr_fields = 0;
++    for (fields = sections->fields; fields != NULL; fields = fields->next)
++      nr_fields++;
++    fv = caml_alloc (nr_fields, 0);
++
++    for (j = 0, fields = sections->fields; fields != NULL;
++         j++, fields = fields->next) {
++      v = caml_alloc_tuple (2);
++      sv = caml_copy_string (fields->key);
++      Store_field (v, 0, sv);   /* (key, value) */
++      sv = caml_copy_string (fields->value);
++      Store_field (v, 1, sv);
++      Store_field (fv, j, v);   /* assign to return array of fields */
++    }
++
++    v = caml_alloc_tuple (2);
++    sv = caml_copy_string (sections->name);
++    Store_field (v, 0, sv);     /* (name, fields) */
++    Store_field (v, 1, fv);
++    Store_field (rv, i, v);     /* assign to return array of sections */
++  }
++
++  /* Free parsed global data. */
++  free_index ();
++
++  CAMLreturn (rv);
++}
+diff --git a/builder/index-scan.l b/builder/index-scan.l
+new file mode 100644
+index 0000000..9a6a0e3
+--- /dev/null
++++ b/builder/index-scan.l
+@@ -0,0 +1,103 @@
++/* libguestfs virt-builder tool -*- fundamental -*-
++ * 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.
++ */
++
++%{
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include "index-parse.h"
++#include "index-struct.h"
++
++#define YY_USER_ACTION yylloc.first_line = yylloc.last_line = yylineno;
++
++extern void yyerror (const char *);
++
++%}
++
++%option noyywrap
++%option yylineno
++
++%%
++
++ /* Apart from the PGP prologue/epilogue which is a hack, the
++  * scanning strategy is to deal with the file strictly line by
++  * line, and pass those lines up to the parser which deals with
++  * whether they appear in the right order to be meaningful.
++  * Note that flex does longest-match.
++  */
++
++  /* Ignore comments - '#' MUST appear at the start of a line. */
++^"#".*\n                { seen_comments++; }
++
++  /* An empty line is significant. */
++^\n                                     { return EMPTY_LINE; }
++
++  /* [...] marks beginning of a section. */
++^"["[-A-Za-z0-9.]+"]"\n {
++                      yylval.str = strndup (yytext+1, yyleng-3);
++                      return SECTION_HEADER;
++                    }
++
++  /* field=value or field[subfield]=value */
++^[A-Za-z0-9_.]+("["[A-Za-z0-9_,.]+"]")?"=".*\n {
++                      size_t i = strcspn (yytext, "=");
++                      yylval.field = malloc (sizeof (struct field));
++                      yylval.field->next = NULL;
++                      yylval.field->key = strndup (yytext, i);
++                      /* Note we chop the final \n off here. */
++                      yylval.field->value = strndup (yytext+i+1, yyleng-(i+2));
++                      return FIELD;
++                    }
++
++  /* Continuation line for multi-line values. */
++^[[:blank:]].*\n        {
++                      yylval.str = strndup (yytext+1, yyleng-2);
++                      return VALUE_CONT;
++                    }
++
++ /* Hack to eat the PGP prologue. */
++^"-----BEGIN PGP SIGNED MESSAGE-----\n"  {
++  int c, prevnl = 0;
++
++  /* Eat everything to the first blank line. */
++  while ((c = input ()) != EOF) {
++    if (c == '\n' && prevnl)
++      break;
++    prevnl = c == '\n';
++  }
++
++  return PGP_PROLOGUE;
++}
++
++ /* Hack to eat the PGP epilogue. */
++^"-----BEGIN PGP SIGNATURE-----\n"  {
++  /* Eat everything to the end of the file. */
++  while (input () != EOF)
++    ;
++
++  return PGP_EPILOGUE;
++}
++
++ /* anything else is an error */
++. {
++  yyerror ("unexpected character in input");
++  exit (EXIT_FAILURE);
++}
+diff --git a/builder/index-struct.c b/builder/index-struct.c
+new file mode 100644
+index 0000000..26bed24
+--- /dev/null
++++ b/builder/index-struct.c
+@@ -0,0 +1,58 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++
++#include "index-struct.h"
++
++struct section *parsed_index = NULL;
++int seen_comments = 0;
++
++static void free_section (struct section *section);
++static void free_field (struct field *field);
++
++void
++free_index (void)
++{
++  free_section (parsed_index);
++}
++
++static void
++free_section (struct section *section)
++{
++  if (section) {
++    free_section (section->next);
++    free (section->name);
++    free_field (section->fields);
++    free (section);
++  }
++}
++
++static void
++free_field (struct field *field)
++{
++  if (field) {
++    free_field (field->next);
++    free (field->key);
++    free (field->value);
++    free (field);
++  }
++}
+diff --git a/builder/index-struct.h b/builder/index-struct.h
+new file mode 100644
+index 0000000..ac8a3dd
+--- /dev/null
++++ b/builder/index-struct.h
+@@ -0,0 +1,48 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++/* The data structures produced when parsing the index file. */
++
++#ifndef INDEX_STRUCT_H
++#define INDEX_STRUCT_H
++
++/* A section or list of sections. */
++struct section {
++  struct section *next;
++  char *name;
++  struct field *fields;
++};
++
++/* A field or list of fields. */
++struct field {
++  struct field *next;
++  char *key;
++  char *value;
++};
++
++/* The parser (yyparse) stores the result here. */
++extern struct section *parsed_index;
++
++/* yyparse sets this if any comments were seen.  Required for checking
++ * compatibility with virt-builder 1.24.
++ */
++extern int seen_comments;
++
++extern void free_index (void);
++
++#endif /* INDEX_STRUCT_H */
+diff --git a/builder/index-validate.c b/builder/index-validate.c
+new file mode 100644
+index 0000000..d156c43
+--- /dev/null
++++ b/builder/index-validate.c
+@@ -0,0 +1,161 @@
++/* libguestfs virt-builder tool
++ * 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.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <limits.h>
++#include <getopt.h>
++#include <errno.h>
++#include <libintl.h>
++
++#include <guestfs.h>
++
++#include "guestfs-internal-frontend.h"
++
++#include "index-struct.h"
++#include "index-parse.h"
++
++extern FILE *yyin;
++
++static void
++usage (int exit_status)
++{
++  printf ("%s index\n", program_name);
++  exit (exit_status);
++}
++
++int
++main (int argc, char *argv[])
++{
++  enum { HELP_OPTION = CHAR_MAX + 1 };
++  static const char *options = "V";
++  static const struct option long_options[] = {
++    { "help", 0, 0, HELP_OPTION },
++    { "compat-1.24.0", 0, 0, 0 },
++    { "compat-1.24.1", 0, 0, 0 },
++    { "version", 0, 0, 'V' },
++    { 0, 0, 0, 0 }
++  };
++  int c;
++  int option_index;
++  int compat_1_24_0 = 0;
++  int compat_1_24_1 = 0;
++  const char *input;
++  struct section *sections;
++
++  for (;;) {
++    c = getopt_long (argc, argv, options, long_options, &option_index);
++    if (c == -1) break;
++
++    switch (c) {
++    case 0:                     /* options which are long only */
++      if (STREQ (long_options[option_index].name, "compat-1.24.0"))
++        compat_1_24_0 = compat_1_24_1 = 1;
++      else if (STREQ (long_options[option_index].name, "compat-1.24.1"))
++        compat_1_24_1 = 1;
++      else {
++        fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
++                 program_name, long_options[option_index].name, option_index);
++        exit (EXIT_FAILURE);
++      }
++      break;
++
++    case 'V':
++      printf ("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
++      exit (EXIT_SUCCESS);
++
++    case HELP_OPTION:
++      usage (EXIT_SUCCESS);
++
++    default:
++      usage (EXIT_FAILURE);
++    }
++  }
++
++  if (optind != argc-1)
++    usage (EXIT_FAILURE);
++
++  input = argv[optind++];
++
++  yyin = fopen (input, "r");
++  if (yyin == NULL) {
++    perror (input);
++    exit (EXIT_FAILURE);
++  }
++
++  if (yyparse () != 0) {
++    fprintf (stderr, _("%s: '%s' could not be validated, see errors above\n"),
++             program_name, input);
++    exit (EXIT_FAILURE);
++  }
++
++  if (fclose (yyin) == EOF) {
++    fprintf (stderr, _("%s: %s: error reading input file: %m\n"),
++             program_name, input);
++    exit (EXIT_FAILURE);
++  }
++
++  if (compat_1_24_1 && seen_comments) {
++    fprintf (stderr, _("%s: %s contains comments which will not work with virt-builder 1.24.1\n"),
++             program_name, input);
++    exit (EXIT_FAILURE);
++  }
++
++  /* Iterate over the parsed sections, semantically validating it. */
++  for (sections = parsed_index; sections != NULL; sections = sections->next) {
++    int seen_sig = 0;
++    struct field *fields;
++
++    for (fields = sections->fields; fields != NULL; fields = fields->next) {
++      if (compat_1_24_0) {
++        if (strchr (fields->key, '[') ||
++            strchr (fields->key, ']')) {
++          fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.0\n"),
++                   program_name, input, sections->name, fields->key);
++          exit (EXIT_FAILURE);
++        }
++      }
++      if (compat_1_24_1) {
++        if (strchr (fields->key, '.') ||
++            strchr (fields->key, ',')) {
++          fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.1\n"),
++                   program_name, input, sections->name, fields->key);
++          exit (EXIT_FAILURE);
++        }
++      }
++      if (STREQ (fields->key, "sig"))
++        seen_sig = 1;
++    }
++
++    if (compat_1_24_0 && !seen_sig) {
++      fprintf (stderr, _("%s: %s: section [%s] is missing a 'sig' field which will not work with virt-builder 1.24.0\n"),
++               program_name, input, sections->name);
++      exit (EXIT_FAILURE);
++    }
++  }
++
++  /* Free the parsed data. */
++  free_index ();
++
++  printf ("%s validated OK\n", input);
++
++  exit (EXIT_SUCCESS);
++}
+diff --git a/builder/index_parser.ml b/builder/index_parser.ml
+index dc039fe..fb47e50 100644
+--- a/builder/index_parser.ml
++++ b/builder/index_parser.ml
+@@ -97,14 +97,17 @@ let print_entry chan (name, { printable_name = printable_name;
+   );
+   if hidden then fp "hidden=true\n"
+ 
+-let fieldname_rex = Str.regexp "^\\([][a-z0-9_]+\\)=\\(.*\\)$"
++(* Types returned by the C index parser. *)
++type sections = section array
++and section = string * fields           (* [name] + fields *)
++and fields = field array
++and field = string * string             (* key + value *)
++
++(* Calls yyparse in the C code. *)
++external parse_index : string -> sections = "virt_builder_parse_index"
+ 
+ let get_index ~debug ~downloader ~sigchecker source =
+-  let rec corrupt_line line =
+-    eprintf (f_"virt-builder: error parsing index near this line:\n\n%s\n")
+-      line;
+-    corrupt_file ()
+-  and corrupt_file () =
++  let corrupt_file () =
+     eprintf (f_"\nThe index file downloaded from '%s' is corrupt.\nYou need to ask the supplier of this file to fix it and upload a fixed version.\n")
+       source;
+     exit 1
+@@ -119,133 +122,15 @@ let get_index ~debug ~downloader ~sigchecker source =
+      *)
+     Sigchecker.verify sigchecker tmpfile;
+ 
+-    (* Check the index page is not too huge. *)
+-    let st = stat tmpfile in
+-    if st.st_size > 1_000_000 then (
+-      eprintf (f_"virt-builder: index page '%s' is too large (size %d bytes)\n")
+-        source st.st_size;
+-      exit 1
+-    );
+-
+-    (* Load the file into memory. *)
+-    let index = read_whole_file tmpfile in
++    (* Try parsing the file. *)
++    let sections = parse_index tmpfile in
+     if delete_tmpfile then
+       (try Unix.unlink tmpfile with _ -> ());
+ 
+-    (* Split file into lines. *)
+-    let index = string_nsplit "\n" index in
+-
+-    (* If there is a signature (checked above) then remove it. *)
+-    let index =
+-      match index with
+-      | "-----BEGIN PGP SIGNED MESSAGE-----" :: lines ->
+-        (* Ignore all lines until we get to first blank. *)
+-        let lines = dropwhile ((<>) "") lines in
+-        (* Ignore the blank line too. *)
+-        let lines = List.tl lines in
+-        (* Take lines until we get to the end signature. *)
+-        let lines = takewhile ((<>) "-----BEGIN PGP SIGNATURE-----") lines in
+-        lines
+-      | _ -> index in
+-
+-    (* Split into sections around each /^[/ *)
+-    let rec loop = function
+-      | [] -> []
+-      | x :: xs when String.length x >= 1 && x.[0] = '[' ->
+-        let lines = takewhile ((<>) "") xs in
+-        let rest = dropwhile ((<>) "") xs in
+-        if rest = [] then
+-          [x, lines]
+-        else (
+-          let rest = List.tl rest in
+-          let rest = loop rest in
+-          (x, lines) :: rest
+-        )
+-      | x :: _ -> corrupt_line x
+-    in
+-    let sections = loop index in
+-
+-    (* Parse the fields in each section. *)
+-    let isspace = function ' ' | '\t' -> true | _ -> false in
+-    let starts_space str = String.length str >= 1 && isspace str.[0] in
+-    let rec loop = function
+-      | [] -> []
+-      | x :: xs when not (starts_space x) && String.contains x '=' ->
+-        let xs' = takewhile starts_space xs in
+-        let ys = dropwhile starts_space xs in
+-        (x :: xs') :: loop ys
+-      | x :: _ -> corrupt_line x
+-    in
+-    let sections = List.map (fun (n, lines) -> n, loop lines) sections in
+-
+-    if debug then (
+-      eprintf "index file (%s) after splitting:\n" source;
+-      List.iter (
+-        fun (n, fields) ->
+-          eprintf "  os-version: %s\n" n;
+-          let i = ref 0 in
+-          List.iter (
+-            fun field ->
+-              eprintf "    %d: " !i;
+-              List.iter prerr_endline field;
+-              incr i
+-          ) fields
+-      ) sections
+-    );
+-
+-    (* Now we've parsed the file into the correct sections, we
+-     * interpret the meaning of the fields.
+-     *)
++    let sections = Array.to_list sections in
+     let sections = List.map (
+       fun (n, fields) ->
+-        let len = String.length n in
+-        if len < 3 || n.[0] <> '[' || n.[len-1] <> ']' then
+-          corrupt_line n;
+-        let n = String.sub n 1 (len-2) in
+-
+-        let fields = List.map (
+-          function
+-          | [] -> assert false (* can never happen, I think? *)
+-          | x :: xs when Str.string_match fieldname_rex x 0 ->
+-            let field = Str.matched_group 1 x in
+-            let rest_of_line = Str.matched_group 2 x in
+-            let allow_multiline =
+-              match field with
+-              | "name" -> false
+-              | "osinfo" -> false
+-              | "file" -> false
+-              | "sig" -> false
+-              | "checksum" | "checksum[sha512]" -> false
+-              | "revision" -> false
+-              | "format" -> false
+-              | "size" -> false
+-              | "compressed_size" -> false
+-              | "expand" -> false
+-              | "lvexpand" -> false
+-              | "notes" -> true
+-              | "hidden" -> false
+-              | _ ->
+-                if debug then
+-                  eprintf "warning: unknown field '%s' in index (ignored)\n%!"
+-                    field;
+-                true in
+-            let value =
+-              if not allow_multiline then (
+-                if xs <> [] then (
+-                  eprintf (f_"virt-builder: field '%s' cannot span multiple lines\n")
+-                    field;
+-                  corrupt_line (List.hd xs)
+-                );
+-                rest_of_line
+-              ) else (
+-                String.concat "\n" (rest_of_line :: xs)
+-              ) in
+-            field, value
+-          | x :: _ ->
+-            corrupt_line x
+-        ) fields in
+-
+-        (n, fields)
++        n, Array.to_list fields
+     ) sections in
+ 
+     (* Check for repeated os-version names. *)
+@@ -356,7 +241,7 @@ let get_index ~debug ~downloader ~sigchecker source =
+       ) sections in
+ 
+     if debug then (
+-      eprintf "index file (%s) after parsing:\n" source;
++      eprintf "index file (%s) after parsing (C parser):\n" source;
+       List.iter (print_entry Pervasives.stderr) entries
+     );
+ 
+diff --git a/builder/list_entries.ml b/builder/list_entries.ml
+index 04a65ca..8c24fe2 100644
+--- a/builder/list_entries.ml
++++ b/builder/list_entries.ml
+@@ -62,7 +62,7 @@ let list_entries ?(list_long = false) ~sources index =
+           | None -> ()
+           | Some notes ->
+             printf "\n";
+-            printf "Notes:\n %s\n" notes
++            printf "Notes:\n\n%s\n" notes
+           );
+           printf "\n"
+         )
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 823f774..0a7c0d4 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -46,28 +46,32 @@ Full name:               Phony Debian
+ Minimum/default size:    512.0M
+ 
+ Notes:
+- Phony Debian look-alike used for testing.
++
++Phony Debian look-alike used for testing.
+ 
+ os-version:              phony-fedora
+ Full name:               Phony Fedora
+ Minimum/default size:    1.0G
+ 
+ Notes:
+- Phony Fedora look-alike used for testing.
++
++Phony Fedora look-alike used for testing.
+ 
+ os-version:              phony-ubuntu
+ Full name:               Phony Ubuntu
+ Minimum/default size:    512.0M
+ 
+ Notes:
+- Phony Ubuntu look-alike used for testing.
++
++Phony Ubuntu look-alike used for testing.
+ 
+ os-version:              phony-windows
+ Full name:               Phony Windows
+ Minimum/default size:    512.0M
+ 
+ Notes:
+- Phony Windows look-alike used for testing." ]; then
++
++Phony Windows look-alike used for testing." ]; then
+     echo "$0: unexpected --list --long output:"
+     echo "$long_list"
+     exit 1
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 5eba666..6497c0a 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1245,6 +1245,23 @@ For open source guests, provide a link to the source code in the
+ C<notes> field and comply with other requirements (eg. around
+ trademarks).
+ 
++=head3 Formal specification of the index file
++
++The index file format has a formal specification defined by the flex
++scanner and bison parser used to parse the file.  This can be found in
++the following files in the libguestfs source tree:
++
++ builder/index-scan.l
++ builder/index-parse.y
++
++A tool called L<virt-index-validate(1)> is available to validate the
++index file to ensure it is correct.
++
++Note that the parser and tool can work on either the signed or
++unsigned index file (ie. C<index> or C<index.asc>).
++
++The index is always encoded in UTF-8.
++
+ =head2 CACHING
+ 
+ Since the templates are usually very large, downloaded templates are
+diff --git a/builder/virt-index-validate.pod b/builder/virt-index-validate.pod
+new file mode 100644
+index 0000000..6b03703
+--- /dev/null
++++ b/builder/virt-index-validate.pod
+@@ -0,0 +1,92 @@
++=encoding utf8
++
++=head1 NAME
++
++virt-index-validate - Validate virt-builder index file
++
++=head1 SYNOPSIS
++
++ virt-index-validate index
++
++=head1 DESCRIPTION
++
++L<virt-builder(1)> uses an index file to store metadata about templates
++that it knows how to use.  This index file has a specific format which
++virt-index-validate knows how to validate.
++
++Note that virt-index-validate can validate either the signed or
++unsigned index file (ie. either C<index> or C<index.asc>).  It can
++only validate a local file, not a URL.
++
++=head1 OPTIONS
++
++=over 4
++
++=item B<--compat-1.24.0>
++
++Check for compatibility with virt-builder 1.24.0.  (Using this option
++implies I<--compat-1.24.1>, so you don't need to use both.)
++
++In particular:
++
++=over 4
++
++=item *
++
++This version of virt-builder could not handle C<[...]>
++(square brackets) in field names (eg. C<checksum[sha512]=...>).
++
++=item *
++
++It required detached signatures (C<sig=...>).
++
++=back
++
++=item B<--compat-1.24.1>
++
++Check for compatibility with virt-builder E<ge> 1.24.1.
++
++In particular:
++
++=over 4
++
++=item *
++
++This version of virt-builder could not handle C<.> (period) in field
++names or C<,> (comma) in subfield names.
++
++=item *
++
++It could not handle comments appearing in the file.
++
++=back
++
++=item B<--help>
++
++Display help.
++
++=item B<-V>
++
++=item B<--version>
++
++Display version number and exit.
++
++=back
++
++=head1 EXIT STATUS
++
++This program returns 0 if the index file validates, or non-zero if
++there was an error.
++
++=head1 SEE ALSO
++
++L<virt-builder(1)>,
++L<http://libguestfs.org/>.
++
++=head1 AUTHOR
++
++Richard W.M. Jones L<http://people.redhat.com/~rjones/>
++
++=head1 COPYRIGHT
++
++Copyright (C) 2013 Red Hat Inc.
+diff --git a/configure.ac b/configure.ac
+index 00cb151..30040e0 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -705,6 +705,10 @@ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
+ dnl Check for pxzcat (optional).
+ AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
+ 
++dnl (f)lex and bison are required for virt-builder.
++AC_PROG_LEX
++AC_PROG_YACC
++
+ dnl Check for QEMU for running binaries on this $host_cpu, fall
+ dnl back to basic 'qemu'.  Allow the user to override it.
+ qemu_system="$(
+diff --git a/po-docs/ja/Makefile.am b/po-docs/ja/Makefile.am
+index b053be0..f74ee42 100644
+--- a/po-docs/ja/Makefile.am
++++ b/po-docs/ja/Makefile.am
+@@ -60,6 +60,7 @@ MANPAGES = \
+ 	virt-edit.1 \
+ 	virt-filesystems.1 \
+ 	virt-format.1 \
++	virt-index-validate.1 \
+ 	virt-inspector.1 \
+ 	virt-list-filesystems.1 \
+ 	virt-list-partitions.1 \
+diff --git a/po-docs/podfiles b/po-docs/podfiles
+index 5ff9447..dd2898c 100644
+--- a/po-docs/podfiles
++++ b/po-docs/podfiles
+@@ -1,6 +1,7 @@
+ ../align/virt-alignment-scan.pod
+ ../appliance/libguestfs-make-fixed-appliance.pod
+ ../builder/virt-builder.pod
++../builder/virt-index-validate.pod
+ ../cat/virt-cat.pod
+ ../cat/virt-filesystems.pod
+ ../cat/virt-ls.pod
+diff --git a/po-docs/uk/Makefile.am b/po-docs/uk/Makefile.am
+index b053be0..f74ee42 100644
+--- a/po-docs/uk/Makefile.am
++++ b/po-docs/uk/Makefile.am
+@@ -60,6 +60,7 @@ MANPAGES = \
+ 	virt-edit.1 \
+ 	virt-filesystems.1 \
+ 	virt-format.1 \
++	virt-index-validate.1 \
+ 	virt-inspector.1 \
+ 	virt-list-filesystems.1 \
+ 	virt-list-partitions.1 \
+diff --git a/po/POTFILES b/po/POTFILES
+index a766f64..aa52b75 100644
+--- a/po/POTFILES
++++ b/po/POTFILES
+@@ -1,4 +1,9 @@
+ align/scan.c
++builder/index-parse.c
++builder/index-parser-c.c
++builder/index-scan.c
++builder/index-struct.c
++builder/index-validate.c
+ cat/cat.c
+ cat/filesystems.c
+ cat/ls.c
+-- 
+1.8.3.1
+
diff --git a/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch b/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
new file mode 100644
index 0000000..78259cc
--- /dev/null
+++ b/0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
@@ -0,0 +1,41 @@
+From a6f859302b6d7781ccb698ee8592bd16a4a28857 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Mon, 4 Nov 2013 22:13:23 +0000
+Subject: [PATCH] builder: Fix 'check-valgrind' so it does something in this
+ directory.
+
+(cherry picked from commit 2dca9d719434f6783e11976699e45a98128ca913)
+---
+ builder/test-virt-builder-list.sh | 2 +-
+ builder/test-virt-builder.sh      | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/builder/test-virt-builder-list.sh b/builder/test-virt-builder-list.sh
+index 0a7c0d4..11305a9 100755
+--- a/builder/test-virt-builder-list.sh
++++ b/builder/test-virt-builder-list.sh
+@@ -25,7 +25,7 @@ abs_srcdir=$(cd $srcdir && pwd)
+ 
+ export VIRT_BUILDER_SOURCE=file://$abs_srcdir/test-index
+ 
+-short_list=$(./virt-builder --no-check-signature --no-cache --list)
++short_list=$($VG ./virt-builder --no-check-signature --no-cache --list)
+ 
+ if [ "$short_list" != "phony-debian             Phony Debian
+ phony-fedora             Phony Fedora
+diff --git a/builder/test-virt-builder.sh b/builder/test-virt-builder.sh
+index 159f013..6296d16 100755
+--- a/builder/test-virt-builder.sh
++++ b/builder/test-virt-builder.sh
+@@ -49,7 +49,7 @@ rm -f $output
+ # Note we cannot test --install, --run since the phony Fedora doesn't
+ # have a real OS inside just some configuration files.  Just about
+ # every other option is fair game.
+-./virt-builder phony-fedora \
++$VG ./virt-builder phony-fedora \
+     -v --no-cache --no-check-signature $no_network \
+     -o $output --size 2G --format $format \
+     --hostname test.example.com \
+-- 
+1.8.3.1
+
diff --git a/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch b/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
new file mode 100644
index 0000000..88cf641
--- /dev/null
+++ b/0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
@@ -0,0 +1,35 @@
+From 736e8d289efb5a1e749dc9961fcc4fd519fa8b4c Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:15:19 +0000
+Subject: [PATCH] builder: Fix missing files in EXTRA_DIST.
+
+This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit 2035a75d66676c5fb2cc047a36c174dd953cd1b9)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index cb490e1..9dbe51e 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -26,6 +26,7 @@ AM_CFLAGS = \
+ EXTRA_DIST = \
+ 	$(SOURCES) \
+ 	virt-builder.pod \
++	virt-index-validate.pod \
+ 	test-virt-builder.sh \
+ 	test-virt-builder-list.sh \
+ 	website/.gitignore \
+@@ -70,6 +71,7 @@ SOURCES = \
+ 	get_kernel.ml \
+ 	index_parser.mli \
+ 	index_parser.ml \
++	index-parser-c.c \
+ 	list_entries.mli \
+ 	list_entries.ml \
+ 	perl_edit.ml \
+-- 
+1.8.3.1
+
diff --git a/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch b/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
new file mode 100644
index 0000000..b238cf2
--- /dev/null
+++ b/0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
@@ -0,0 +1,141 @@
+From e02dc7c0e4f017b2e7b53b7f70e80deef1ba5377 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:20:37 +0000
+Subject: [PATCH] builder: Add an extra Makefile.am to builder/website.
+
+(cherry picked from commit cd10f6f4db32689b2552b52a4875795be8b35694)
+---
+ Makefile.am                 |  2 +-
+ builder/Makefile.am         | 31 +--------------------------
+ builder/website/Makefile.am | 51 +++++++++++++++++++++++++++++++++++++++++++++
+ configure.ac                |  1 +
+ 4 files changed, 54 insertions(+), 31 deletions(-)
+ create mode 100644 builder/website/Makefile.am
+
+diff --git a/Makefile.am b/Makefile.am
+index 3014f6d..8aab678 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -118,7 +118,7 @@ SUBDIRS += csharp
+ # OCaml tools.  Note 'mllib' contains random shared code used by
+ # all of the OCaml tools.
+ if HAVE_OCAML
+-SUBDIRS += mllib builder resize sparsify sysprep
++SUBDIRS += mllib builder builder/website resize sparsify sysprep
+ endif
+ 
+ # Perl tools.
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 9dbe51e..c3719d1 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -28,36 +28,7 @@ EXTRA_DIST = \
+ 	virt-builder.pod \
+ 	virt-index-validate.pod \
+ 	test-virt-builder.sh \
+-	test-virt-builder-list.sh \
+-	website/.gitignore \
+-	website/test-guest.sh \
+-	website/README \
+-	website/index \
+-	website/index.asc \
+-	website/centos-6.ks \
+-	website/centos-6.sh \
+-	website/centos-6.xz.sig \
+-	website/debian-6.preseed \
+-	website/debian-6.sh \
+-	website/debian-6.xz.sig \
+-	website/debian-7.preseed \
+-	website/debian-7.sh \
+-	website/debian-7.xz.sig \
+-	website/fedora-18.ks \
+-	website/fedora-18.sh \
+-	website/fedora-18.xz.sig \
+-	website/fedora-19.ks \
+-	website/fedora-19.sh \
+-	website/fedora-19.xz.sig \
+-	website/ubuntu-10.04.preseed \
+-	website/ubuntu-10.04.sh \
+-	website/ubuntu-10.04.xz.sig \
+-	website/ubuntu-12.04.preseed \
+-	website/ubuntu-12.04.sh \
+-	website/ubuntu-12.04.xz.sig \
+-	website/ubuntu-13.10.preseed \
+-	website/ubuntu-13.10.sh \
+-	website/ubuntu-13.10.xz.sig
++	test-virt-builder-list.sh
+ 
+ CLEANFILES = *~ *.cmi *.cmo *.cmx *.cmxa *.o virt-builder
+ 
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+new file mode 100644
+index 0000000..ba74485
+--- /dev/null
++++ b/builder/website/Makefile.am
+@@ -0,0 +1,51 @@
++# libguestfs virt-builder tool
++# 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.
++
++include $(top_srcdir)/subdir-rules.mk
++
++EXTRA_DIST = \
++	.gitignore \
++	test-guest.sh \
++	README \
++	index \
++	index.asc \
++	centos-6.ks \
++	centos-6.sh \
++	centos-6.xz.sig \
++	debian-6.preseed \
++	debian-6.sh \
++	debian-6.xz.sig \
++	debian-7.preseed \
++	debian-7.sh \
++	debian-7.xz.sig \
++	fedora-18.ks \
++	fedora-18.sh \
++	fedora-18.xz.sig \
++	fedora-19.ks \
++	fedora-19.sh \
++	fedora-19.xz.sig \
++	ubuntu-10.04.preseed \
++	ubuntu-10.04.sh \
++	ubuntu-10.04.xz.sig \
++	ubuntu-12.04.preseed \
++	ubuntu-12.04.sh \
++	ubuntu-12.04.xz.sig \
++	ubuntu-13.10.preseed \
++	ubuntu-13.10.sh \
++	ubuntu-13.10.xz.sig
++
++CLEANFILES = *~
+diff --git a/configure.ac b/configure.ac
+index 30040e0..d797187 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1658,6 +1658,7 @@ AC_CONFIG_FILES([Makefile
+                  bash/Makefile
+                  builder/Makefile
+                  builder/test-index
++                 builder/website/Makefile
+                  cat/Makefile
+                  csharp/Makefile
+                  daemon/Makefile
+-- 
+1.8.3.1
+
diff --git a/0018-builder-website-Add-index-validation-test-script.patch b/0018-builder-website-Add-index-validation-test-script.patch
new file mode 100644
index 0000000..8647d1b
--- /dev/null
+++ b/0018-builder-website-Add-index-validation-test-script.patch
@@ -0,0 +1,57 @@
+From 919c22ead98cce4368425259f882ba7ed47c98fa Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 07:25:46 +0000
+Subject: [PATCH] builder/website: Add index validation test script.
+
+(cherry picked from commit 154bfb7dd46e7998eed1d40ead95923590763739)
+---
+ builder/website/Makefile.am |  4 ++++
+ builder/website/validate.sh | 24 ++++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+ create mode 100755 builder/website/validate.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index ba74485..2a3bbe6 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -49,3 +49,7 @@ EXTRA_DIST = \
+ 	ubuntu-13.10.xz.sig
+ 
+ CLEANFILES = *~
++
++# Validates the index file.
++TESTS_ENVIRONMENT = $(top_builddir)/run --test
++TESTS = validate.sh
+diff --git a/builder/website/validate.sh b/builder/website/validate.sh
+new file mode 100755
+index 0000000..f09e30c
+--- /dev/null
++++ b/builder/website/validate.sh
+@@ -0,0 +1,24 @@
++#!/bin/bash -
++# libguestfs virt-builder validate index
++# 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
++
++../virt-index-validate index
++../virt-index-validate index.asc
++
+-- 
+1.8.3.1
+
diff --git a/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch b/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
new file mode 100644
index 0000000..35fbc48
--- /dev/null
+++ b/0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
@@ -0,0 +1,942 @@
+From e20aea882e564c537b7ce8f7db6c618e5b4ffaee Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 10:21:32 +0000
+Subject: [PATCH] builder: Internal implementation of parallel xzcat (pxzcat).
+
+Instead of calling out to the pxzcat program, use an internal
+implementation.  This requires liblzma to be available at build time.
+If it's not available, fall back to using regular xzcat.
+
+It is intended that eventually this code will go away when regular
+xzcat / unxz is able to use threads.
+
+(cherry picked from commit 681c88ef5d69b1dec4b929ff3451c45968023e5a)
+---
+ README                   |   2 +-
+ builder/Makefile.am      |  11 +-
+ builder/builder.ml       |  24 +-
+ builder/pxzcat-c.c       | 650 +++++++++++++++++++++++++++++++++++++++++++++++
+ builder/pxzcat.ml        |  19 ++
+ builder/pxzcat.mli       |  31 +++
+ builder/virt-builder.pod |   7 +-
+ configure.ac             |  10 +-
+ mllib/config.ml.in       |   6 -
+ po/POTFILES              |   1 +
+ po/POTFILES-ml           |   1 +
+ 11 files changed, 726 insertions(+), 36 deletions(-)
+ create mode 100644 builder/pxzcat-c.c
+ create mode 100644 builder/pxzcat.ml
+ create mode 100644 builder/pxzcat.mli
+
+diff --git a/README b/README
+index 461915d..baf4de4 100644
+--- a/README
++++ b/README
+@@ -174,7 +174,7 @@ The full requirements are described below.
+ | gpg          |             | O | Used by virt-builder for digital        |
+ |              |             |   | signatures                              |
+ +--------------+-------------+---+-----------------------------------------+
+-| pxzcat       |             | O | Can be used by virt-builder for fast    |
++| liblzma      |             | O | Can be used by virt-builder for fast    |
+ |              |             |   | uncompression of templates.             |
+ +--------------+-------------+---+-----------------------------------------+
+ | findlib      |             | O | For the OCaml bindings.                 |
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index c3719d1..2027203 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -21,7 +21,9 @@ AM_YFLAGS = -d
+ AM_CFLAGS = \
+ 	-I$(shell $(OCAMLC) -where) \
+ 	-I$(top_srcdir)/src \
+-	-I$(top_srcdir)/fish
++	-I$(top_srcdir)/fish \
++	-pthread \
++	$(LIBLZMA_CFLAGS)
+ 
+ EXTRA_DIST = \
+ 	$(SOURCES) \
+@@ -47,6 +49,9 @@ SOURCES = \
+ 	list_entries.ml \
+ 	perl_edit.ml \
+ 	perl_edit.mli \
++	pxzcat.ml \
++	pxzcat.mli \
++	pxzcat-c.c \
+ 	sigchecker.mli \
+ 	sigchecker.ml
+ 
+@@ -73,6 +78,8 @@ OBJECTS = \
+ 	index-struct.o \
+ 	index-parse.o \
+ 	index-parser-c.o \
++	pxzcat-c.o \
++	pxzcat.cmx \
+ 	get_kernel.cmx \
+ 	downloader.cmx \
+ 	sigchecker.cmx \
+@@ -102,7 +109,7 @@ OCAMLOPTFLAGS = $(OCAMLCFLAGS)
+ virt-builder: $(OBJECTS)
+ 	$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) \
+ 	  mlguestfs.cmxa -linkpkg $^ \
+-	  -cclib '-lncurses -lcrypt' \
++	  -cclib '-pthread $(LIBLZMA_LIBS) -lncurses -lcrypt -lpthread' \
+ 	  $(OCAML_GCOV_LDFLAGS) \
+ 	  -o $@
+ 
+diff --git a/builder/builder.ml b/builder/builder.ml
+index fc6078c..a5a4dfe 100644
+--- a/builder/builder.ml
++++ b/builder/builder.ml
+@@ -24,6 +24,7 @@ open Common_utils
+ open Password
+ 
+ open Cmdline
++open Pxzcat
+ 
+ open Unix
+ open Printf
+@@ -333,27 +334,14 @@ let main () =
+ 
+       output, Some size, format, delete_output_file, do_resize, true in
+ 
+-  (* Create xzcat/pxzcat command to uncompress from input to output. *)
+-  let xzcat_command input output =
+-    match Config.pxzcat with
+-    | None -> sprintf "%s %s > %s" Config.xzcat input output
+-    | Some pxzcat -> sprintf "%s %s -o %s" pxzcat input output
+-  in
+-
+   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
+-    let cmd = xzcat_command template output in
+-    if debug then eprintf "%s\n%!" cmd;
+     msg (f_"Uncompressing: %s") file_uri;
+-    let r = Sys.command cmd in
+-    if r <> 0 then (
+-      eprintf (f_"%s: error: failed to uncompress template\n") prog;
+-      exit 1
+-    )
++    pxzcat template output
+   ) 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 () =
+       (* Uncompress it to a temporary file. *)
+       let { Index_parser.file_uri = file_uri } = entry in
+       let tmpfile = Filename.temp_file "vbsrc" ".img" in
+-      let cmd = xzcat_command template tmpfile in
+-      if debug then eprintf "%s\n%!" cmd;
+       msg (f_"Uncompressing: %s") file_uri;
+-      let r = Sys.command cmd in
+-      if r <> 0 then (
+-        eprintf (f_"%s: error: failed to uncompress template\n") prog;
+-        exit 1
+-      );
++      pxzcat template tmpfile;
+       unlink_on_exit tmpfile;
+       tmpfile in
+ 
+diff --git a/builder/pxzcat-c.c b/builder/pxzcat-c.c
+new file mode 100644
+index 0000000..5ffc9d9
+--- /dev/null
++++ b/builder/pxzcat-c.c
+@@ -0,0 +1,650 @@
++/* virt-builder
++ * 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.
++ */
++
++#include <config.h>
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#include <pthread.h>
++
++#include <caml/alloc.h>
++#include <caml/fail.h>
++#include <caml/memory.h>
++#include <caml/mlvalues.h>
++
++#ifdef HAVE_CAML_UNIXSUPPORT_H
++#include <caml/unixsupport.h>
++#else
++#define Nothing ((value) 0)
++extern void unix_error (int errcode, char * cmdname, value arg) Noreturn;
++#endif
++
++#ifdef HAVE_LIBLZMA
++#include <lzma.h>
++
++static void pxzcat (value filenamev, value outputfilev, unsigned nr_threads);
++#endif
++
++value
++virt_builder_pxzcat (value inputfilev, value outputfilev)
++{
++  CAMLparam2 (inputfilev, outputfilev);
++
++#ifdef HAVE_LIBLZMA
++
++  /* Parallel implementation of xzcat (pxzcat). */
++  /* XXX Make number of threads configurable? */
++  long i;
++  unsigned nr_threads;
++
++  i = sysconf (_SC_NPROCESSORS_ONLN);
++  if (i <= 0) {
++    perror ("could not get number of cores");
++    i = 1;
++  }
++  nr_threads = (unsigned) i;
++
++  /* NB: This might throw an exception if something fails.  If it
++   * does, this function won't return as a regular C function.
++   */
++  pxzcat (inputfilev, outputfilev, nr_threads);
++
++#else
++
++  /* Fallback: use regular xzcat. */
++  int fd;
++  pid_t pid;
++  int status;
++
++  fd = open (String_val (outputfilev), O_WRONLY|O_CREAT|O_TRUNC|O_NOCTTY, 0666);
++  if (fd == -1)
++    unix_error (errno, "open", outputfilev);
++
++  pid = fork ();
++  if (pid == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "fork", Nothing);
++  }
++
++  if (pid == 0) {               /* child - run xzcat */
++    dup2 (fd, 1);
++    execlp (XZCAT, XZCAT, String_val (inputfilev), NULL);
++    perror (XZCAT);
++    _exit (EXIT_FAILURE);
++  }
++
++  close (fd);
++
++  if (waitpid (pid, &status, 0) == -1)
++    unix_error (errno, "waitpid", Nothing);
++  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
++    caml_failwith (XZCAT " program failed, see earlier error messages");
++
++#endif
++
++  CAMLreturn (Val_unit);
++}
++
++#ifdef HAVE_LIBLZMA
++
++#define DEBUG 0
++
++#if DEBUG
++#define debug(fs,...) fprintf (stderr, "pxzcat: debug: " fs "\n", ## __VA_ARGS__)
++#else
++#define debug(fs,...) /* nothing */
++#endif
++
++/* Size of buffers used in decompression loop. */
++#define BUFFER_SIZE (64*1024)
++
++#define XZ_HEADER_MAGIC     "\xfd" "7zXZ\0"
++#define XZ_HEADER_MAGIC_LEN 6
++#define XZ_FOOTER_MAGIC     "YZ"
++#define XZ_FOOTER_MAGIC_LEN 2
++
++static int check_header_magic (int fd);
++static lzma_index *parse_indexes (value filenamev, int fd);
++static void iter_blocks (lzma_index *idx, unsigned nr_threads, value filenamev, int fd, value outputfilev, int ofd);
++
++static void
++pxzcat (value filenamev, value outputfilev, unsigned nr_threads)
++{
++  int fd, ofd;
++  uint64_t size;
++  lzma_index *idx;
++
++  /* Open the file. */
++  fd = open (String_val (filenamev), O_RDONLY);
++  if (fd == -1)
++    unix_error (errno, "open", filenamev);
++
++  /* Check file magic. */
++  if (!check_header_magic (fd)) {
++    close (fd);
++    caml_invalid_argument ("input file is not an xz file");
++  }
++
++  /* Read and parse the indexes. */
++  idx = parse_indexes (filenamev, fd);
++
++  /* Get the file uncompressed size, create the output file. */
++  size = lzma_index_uncompressed_size (idx);
++  debug ("uncompressed size = %" PRIu64 " bytes", size);
++
++  /* Avoid annoying ext4 auto_da_alloc which causes a flush on close
++   * unless we are very careful about not truncating a regular file
++   * from non-zero size to zero size.  (Thanks Eric Sandeen)
++   */
++  ofd = open (String_val (outputfilev), O_WRONLY|O_CREAT|O_NOCTTY, 0644);
++  if (ofd == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "open", outputfilev);
++  }
++
++  if (ftruncate (ofd, 1) == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "ftruncate", outputfilev);
++  }
++
++  if (lseek (ofd, 0, SEEK_SET) == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "lseek", outputfilev);
++  }
++
++  if (write (ofd, "\0", 1) == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "write", outputfilev);
++  }
++
++  if (ftruncate (ofd, size) == -1) {
++    int err = errno;
++    close (fd);
++    unix_error (err, "ftruncate", outputfilev);
++  }
++
++  /* Tell the kernel we won't read the output file. */
++  posix_fadvise (fd, 0, 0, POSIX_FADV_RANDOM|POSIX_FADV_DONTNEED);
++
++  /* Iterate over blocks. */
++  iter_blocks (idx, nr_threads, filenamev, fd, outputfilev, ofd);
++
++  lzma_index_end (idx, NULL);
++
++  if (close (fd) == -1)
++    unix_error (errno, "close", filenamev);
++}
++
++static int
++check_header_magic (int fd)
++{
++  char buf[XZ_HEADER_MAGIC_LEN];
++
++  if (lseek (fd, 0, SEEK_SET) == -1)
++    return 0;
++  if (read (fd, buf, XZ_HEADER_MAGIC_LEN) != XZ_HEADER_MAGIC_LEN)
++    return 0;
++  if (memcmp (buf, XZ_HEADER_MAGIC, XZ_HEADER_MAGIC_LEN) != 0)
++    return 0;
++  return 1;
++}
++
++/* For explanation of this function, see src/xz/list.c:parse_indexes
++ * in the xz sources.
++ */
++static lzma_index *
++parse_indexes (value filenamev, int fd)
++{
++  lzma_ret r;
++  off_t pos, index_size;
++  uint8_t footer[LZMA_STREAM_HEADER_SIZE];
++  uint8_t header[LZMA_STREAM_HEADER_SIZE];
++  lzma_stream_flags footer_flags;
++  lzma_stream_flags header_flags;
++  lzma_stream strm = LZMA_STREAM_INIT;
++  ssize_t n;
++  lzma_index *combined_index = NULL;
++  lzma_index *this_index = NULL;
++  lzma_vli stream_padding = 0;
++  size_t nr_streams = 0;
++
++  /* Check file size is a multiple of 4 bytes. */
++  pos = lseek (fd, 0, SEEK_END);
++  if (pos == (off_t) -1)
++    unix_error (errno, "lseek", filenamev);
++
++  if ((pos & 3) != 0)
++    caml_invalid_argument ("input not an xz file: size is not a multiple of 4 bytes");
++
++  /* Jump backwards through the file identifying each stream. */
++  while (pos > 0) {
++    debug ("looping through streams: pos = %" PRIu64, (uint64_t) pos);
++
++    if (pos < LZMA_STREAM_HEADER_SIZE)
++      caml_invalid_argument ("corrupted xz file");
++
++    if (lseek (fd, -LZMA_STREAM_HEADER_SIZE, SEEK_CUR) == -1)
++      unix_error (errno, "lseek", filenamev);
++
++    if (read (fd, footer, LZMA_STREAM_HEADER_SIZE) != LZMA_STREAM_HEADER_SIZE)
++      unix_error (errno, "read", filenamev);
++
++    /* Skip stream padding. */
++    if (footer[8] == 0 && footer[9] == 0 &&
++        footer[10] == 0 && footer[11] == 0) {
++      stream_padding += 4;
++      pos -= 4;
++      continue;
++    }
++
++    pos -= LZMA_STREAM_HEADER_SIZE;
++    nr_streams++;
++
++    debug ("decode stream footer at pos = %" PRIu64, (uint64_t) pos);
++
++    /* Does the stream footer look reasonable? */
++    r = lzma_stream_footer_decode (&footer_flags, footer);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "invalid stream footer - error %d\n", r);
++      caml_invalid_argument ("invalid stream footer");
++    }
++
++    debug ("backward_size = %" PRIu64, (uint64_t) footer_flags.backward_size);
++    index_size = footer_flags.backward_size;
++    if (pos < index_size + LZMA_STREAM_HEADER_SIZE)
++      caml_invalid_argument ("invalid stream footer");
++
++    pos -= index_size;
++    debug ("decode index at pos = %" PRIu64, (uint64_t) pos);
++
++    /* Seek backwards to the index of this stream. */
++    if (lseek (fd, pos, SEEK_SET) == -1)
++      unix_error (errno, "lseek", filenamev);
++
++    /* Decode the index. */
++    r = lzma_index_decoder (&strm, &this_index, UINT64_MAX);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "invalid stream index - error %d\n", r);
++      caml_invalid_argument ("invalid stream index");
++    }
++
++    do {
++      uint8_t buf[BUFSIZ];
++
++      strm.avail_in = index_size;
++      if (strm.avail_in > BUFSIZ)
++        strm.avail_in = BUFSIZ;
++
++      n = read (fd, &buf, strm.avail_in);
++      if (n == -1)
++        unix_error (errno, "read", filenamev);
++
++      index_size -= strm.avail_in;
++
++      strm.next_in = buf;
++      r = lzma_code (&strm, LZMA_RUN);
++    } while (r == LZMA_OK);
++
++    if (r != LZMA_STREAM_END) {
++      fprintf (stderr, "could not parse index - error %d\n", r);
++      caml_invalid_argument ("could not parse index");
++    }
++
++    pos -= lzma_index_total_size (this_index) + LZMA_STREAM_HEADER_SIZE;
++
++    debug ("decode stream header at pos = %" PRIu64, (uint64_t) pos);
++
++    /* Read and decode the stream header. */
++    if (lseek (fd, pos, SEEK_SET) == -1)
++      unix_error (errno, "lseek", filenamev);
++
++    if (read (fd, header, LZMA_STREAM_HEADER_SIZE) != LZMA_STREAM_HEADER_SIZE)
++      unix_error (errno, "read stream header", filenamev);
++
++    r = lzma_stream_header_decode (&header_flags, header);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "invalid stream header - error %d\n", r);
++      caml_invalid_argument ("invalid stream header");
++    }
++
++    /* Header and footer of the stream should be equal. */
++    r = lzma_stream_flags_compare (&header_flags, &footer_flags);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "header and footer of stream are not equal - error %d\n",
++               r);
++      caml_invalid_argument ("header and footer of stream are not equal");
++    }
++
++    /* Store the decoded stream flags in this_index. */
++    r = lzma_index_stream_flags (this_index, &footer_flags);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "cannot read stream_flags from index - error %d\n", r);
++      caml_invalid_argument ("cannot read stream_flags from index");
++    }
++
++    /* Store the amount of stream padding so far.  Needed to calculate
++     * compressed offsets correctly in multi-stream files.
++     */
++    r = lzma_index_stream_padding (this_index, stream_padding);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "cannot set stream_padding in index - error %d\n", r);
++      caml_invalid_argument ("cannot set stream_padding in index");
++    }
++
++    if (combined_index != NULL) {
++      r = lzma_index_cat (this_index, combined_index, NULL);
++      if (r != LZMA_OK) {
++        fprintf (stderr, "cannot combine indexes - error %d\n", r);
++        caml_invalid_argument ("cannot combine indexes");
++      }
++    }
++
++    combined_index = this_index;
++    this_index = NULL;
++  }
++
++  lzma_end (&strm);
++
++  return combined_index;
++}
++
++/* Return true iff the buffer is all zero bytes.
++ *
++ * Note that gcc is smart enough to optimize this properly:
++ * http://stackoverflow.com/questions/1493936/faster-means-of-checking-for-an-empty-buffer-in-c/1493989#1493989
++ */
++static inline int
++is_zero (const char *buffer, size_t size)
++{
++  size_t i;
++
++  for (i = 0; i < size; ++i) {
++    if (buffer[i] != 0)
++      return 0;
++  }
++
++  return 1;
++}
++
++struct global_state {
++  /* Current iterator.  Threads update this, but it is protected by a
++   * mutex, and each thread takes a copy of it when working on it.
++   */
++  lzma_index_iter iter;
++  lzma_bool iter_finished;
++  pthread_mutex_t iter_mutex;
++
++  /* Note that all threads are accessing these fds, so you have
++   * to use pread/pwrite instead of lseek!
++   */
++
++  /* Input file. */
++  const char *filename;
++  int fd;
++
++  /* Output file. */
++  const char *outputfile;
++  int ofd;
++};
++
++struct per_thread_state {
++  unsigned thread_num;
++  struct global_state *global;
++  int status;
++};
++
++/* Create threads to iterate over the blocks and uncompress. */
++static void *worker_thread (void *vp);
++
++static void
++iter_blocks (lzma_index *idx, unsigned nr_threads,
++             value filenamev, int fd, value outputfilev, int ofd)
++{
++  struct global_state global;
++  struct per_thread_state per_thread[nr_threads];
++  pthread_t thread[nr_threads];
++  unsigned u, nr_errors;
++  int err;
++  void *status;
++
++  lzma_index_iter_init (&global.iter, idx);
++  global.iter_finished = 0;
++  err = pthread_mutex_init (&global.iter_mutex, NULL);
++  if (err != 0)
++    unix_error (err, "pthread_mutex_init", Nothing);
++
++  global.filename = String_val (filenamev);
++  global.fd = fd;
++  global.outputfile = String_val (outputfilev);
++  global.ofd = ofd;
++
++  for (u = 0; u < nr_threads; ++u) {
++    per_thread[u].thread_num = u;
++    per_thread[u].global = &global;
++  }
++
++  /* Start the threads. */
++  for (u = 0; u < nr_threads; ++u) {
++    err = pthread_create (&thread[u], NULL, worker_thread, &per_thread[u]);
++    if (err != 0)
++      unix_error (err, "pthread_create", Nothing);
++  }
++
++  /* Wait for the threads to exit. */
++  nr_errors = 0;
++  for (u = 0; u < nr_threads; ++u) {
++    err = pthread_join (thread[u], &status);
++    if (err != 0) {
++      fprintf (stderr, "pthread_join (%u): %s\n", u, strerror (err));
++      nr_errors++;
++    }
++    if (*(int *)status == -1)
++      nr_errors++;
++  }
++
++  if (nr_errors > 0)
++    caml_invalid_argument ("some threads failed, see earlier errors");
++}
++
++/* Iterate over the blocks and uncompress. */
++static void *
++worker_thread (void *vp)
++{
++  struct per_thread_state *state = vp;
++  struct global_state *global = state->global;
++  lzma_index_iter iter;
++  int err;
++  off_t position, oposition;
++  uint8_t header[LZMA_BLOCK_HEADER_SIZE_MAX];
++  ssize_t n;
++  lzma_block block;
++  lzma_filter filters[LZMA_FILTERS_MAX + 1];
++  lzma_ret r;
++  lzma_stream strm = LZMA_STREAM_INIT;
++  uint8_t buf[BUFFER_SIZE];
++  char outbuf[BUFFER_SIZE];
++  size_t i;
++  lzma_bool iter_finished;
++
++  state->status = -1;
++
++  for (;;) {
++    /* Get the next block. */
++    err = pthread_mutex_lock (&global->iter_mutex);
++    if (err != 0) abort ();
++    iter_finished = global->iter_finished;
++    if (!iter_finished) {
++      iter_finished = global->iter_finished =
++        lzma_index_iter_next (&global->iter, LZMA_INDEX_ITER_NONEMPTY_BLOCK);
++      if (!iter_finished)
++        /* Take a local copy of this iterator since another thread will
++         * update the global version.
++         */
++        iter = global->iter;
++    }
++    err = pthread_mutex_unlock (&global->iter_mutex);
++    if (err != 0) abort ();
++    if (iter_finished)
++      break;
++
++    /* Read the block header.  Start by reading a single byte which
++     * tell us how big the block header is.
++     */
++    position = iter.block.compressed_file_offset;
++    n = pread (global->fd, header, 1, position);
++    if (n == 0) {
++      fprintf (stderr,
++               "%s: read: unexpected end of file reading block header byte\n",
++               global->filename);
++      return &state->status;
++    }
++    if (n == -1) {
++      perror (String_val (global->filename));
++      return &state->status;
++    }
++    position++;
++
++    if (header[0] == '\0') {
++      fprintf (stderr,
++               "%s: read: unexpected invalid block in file, header[0] = 0\n",
++               global->filename);
++      return &state->status;
++    }
++
++    block.version = 0;
++    block.check = iter.stream.flags->check;
++    block.filters = filters;
++    block.header_size = lzma_block_header_size_decode (header[0]);
++
++    /* Now read and decode the block header. */
++    n = pread (global->fd, &header[1], block.header_size-1, position);
++    if (n >= 0 && n != block.header_size-1) {
++      fprintf (stderr,
++               "%s: read: unexpected end of file reading block header\n",
++               global->filename);
++      return &state->status;
++    }
++    if (n == -1) {
++      perror (global->filename);
++      return &state->status;
++    }
++    position += n;
++
++    r = lzma_block_header_decode (&block, NULL, header);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "%s: invalid block header (error %d)\n",
++               global->filename, r);
++      return &state->status;
++    }
++
++    /* What this actually does is it checks that the block header
++     * matches the index.
++     */
++    r = lzma_block_compressed_size (&block, iter.block.unpadded_size);
++    if (r != LZMA_OK) {
++      fprintf (stderr,
++               "%s: cannot calculate compressed size (error %d)\n",
++               global->filename, r);
++      return &state->status;
++    }
++
++    /* Where we will start writing to. */
++    oposition = iter.block.uncompressed_file_offset;
++
++    /* Read the block data and uncompress it. */
++    r = lzma_block_decoder (&strm, &block);
++    if (r != LZMA_OK) {
++      fprintf (stderr, "%s: invalid block (error %d)\n", global->filename, r);
++      return &state->status;
++    }
++
++    strm.next_in = NULL;
++    strm.avail_in = 0;
++    strm.next_out = outbuf;
++    strm.avail_out = sizeof outbuf;
++
++    for (;;) {
++      lzma_action action = LZMA_RUN;
++
++      if (strm.avail_in == 0) {
++        strm.next_in = buf;
++        n = pread (global->fd, buf, sizeof buf, position);
++        if (n == -1) {
++          perror (global->filename);
++          return &state->status;
++        }
++        position += n;
++        strm.avail_in = n;
++        if (n == 0)
++          action = LZMA_FINISH;
++      }
++
++      r = lzma_code (&strm, action);
++
++      if (strm.avail_out == 0 || r == LZMA_STREAM_END) {
++        size_t wsz = sizeof outbuf - strm.avail_out;
++
++        /* Don't write if the block is all zero, to preserve output file
++         * sparseness.  However we have to update oposition.
++         */
++        if (!is_zero (outbuf, wsz)) {
++          if (pwrite (global->ofd, outbuf, wsz, oposition) != wsz) {
++            /* XXX Handle short writes. */
++            perror (global->filename);
++            return &state->status;
++          }
++        }
++        oposition += wsz;
++
++        strm.next_out = outbuf;
++        strm.avail_out = sizeof outbuf;
++      }
++
++      if (r == LZMA_STREAM_END)
++        break;
++      if (r != LZMA_OK) {
++        fprintf (stderr,
++                 "%s: could not parse block data (error %d)\n",
++                 global->filename, r);
++        return &state->status;
++      }
++    }
++
++    lzma_end (&strm);
++
++    for (i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
++      free (filters[i].options);
++  }
++
++  state->status = 0;
++  return &state->status;
++}
++
++#endif /* HAVE_LIBLZMA */
+diff --git a/builder/pxzcat.ml b/builder/pxzcat.ml
+new file mode 100644
+index 0000000..5645370
+--- /dev/null
++++ b/builder/pxzcat.ml
+@@ -0,0 +1,19 @@
++(* virt-builder
++ * 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.
++ *)
++
++external pxzcat : string -> string -> unit = "virt_builder_pxzcat"
+diff --git a/builder/pxzcat.mli b/builder/pxzcat.mli
+new file mode 100644
+index 0000000..a2830f0
+--- /dev/null
++++ b/builder/pxzcat.mli
+@@ -0,0 +1,31 @@
++(* virt-builder
++ * 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.
++ *)
++
++(** {1 Parallel xzcat (or fall back to regular xzcat).}
++
++    Eventually regular xzcat will be able to work in parallel and this
++    code can go away.
++*)
++
++val pxzcat : string -> string -> unit
++    (** [pxzcat input output] uncompresses the file [input] to the file
++        [output].  The input and output must both be seekable.
++
++        If liblzma was found at compile time, this uses an internal
++        implementation of parallel xzcat.  Otherwise regular xzcat is
++        used. *)
+diff --git a/builder/virt-builder.pod b/builder/virt-builder.pod
+index 6497c0a..bad59c1 100644
+--- a/builder/virt-builder.pod
++++ b/builder/virt-builder.pod
+@@ -1397,10 +1397,9 @@ the output format is the same as the template format (usually raw).
+ 
+ =head3 pxzcat
+ 
+-Virt-builder can use C<pxzcat> (parallel xzcat) if available to
+-uncompress the templates.  The default is to use regular C<xzcat>
+-which is single-threaded.  Currently this has to be compiled in,
+-ie. virt-builder will probably need to be recompiled to use pxzcat.
++Virt-builder uses an internal implementation of pxzcat (parallel
++xzcat) if liblzma was found at build time.  If liblzma was not found
++at build time, regular C<xzcat> is used which is single-threaded.
+ 
+ =head3 User-Mode Linux
+ 
+diff --git a/configure.ac b/configure.ac
+index d797187..7a18b8e 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -701,9 +701,15 @@ fi
+ dnl Check for xzcat (required).
+ AC_PATH_PROGS([XZCAT],[xzcat],[no])
+ test "x$XZCAT" = "xno" && AC_MSG_ERROR([xzcat must be installed])
++AC_DEFINE_UNQUOTED([XZCAT],["$XZCAT"],[Name of xzcat program.])
+ 
+-dnl Check for pxzcat (optional).
+-AC_PATH_PROGS([PXZCAT],[pxzcat],[no])
++dnl liblzma can be used by virt-builder (optional).
++PKG_CHECK_MODULES([LIBLZMA], [liblzma],[
++    AC_SUBST([LIBLZMA_CFLAGS])
++    AC_SUBST([LIBLZMA_LIBS])
++    AC_DEFINE([HAVE_LIBLZMA],[1],[liblzma found at compile time.])
++],
++[AC_MSG_WARN([liblzma not found, virt-builder will be slower])])
+ 
+ dnl (f)lex and bison are required for virt-builder.
+ AC_PROG_LEX
+diff --git a/mllib/config.ml.in b/mllib/config.ml.in
+index 5586c5c..d18bf7b 100644
+--- a/mllib/config.ml.in
++++ b/mllib/config.ml.in
+@@ -18,9 +18,3 @@
+ 
+ let package_name = "@PACKAGE_NAME@"
+ let package_version = "@PACKAGE_VERSION@"
+-
+-let xzcat = "@XZCAT@"
+-let pxzcat =
+-  match "@PXZCAT@" with
+-  | "no" -> None
+-  | path -> Some path
+diff --git a/po/POTFILES b/po/POTFILES
+index aa52b75..4bf805f 100644
+--- a/po/POTFILES
++++ b/po/POTFILES
+@@ -4,6 +4,7 @@ builder/index-parser-c.c
+ builder/index-scan.c
+ builder/index-struct.c
+ builder/index-validate.c
++builder/pxzcat-c.c
+ cat/cat.c
+ cat/filesystems.c
+ cat/ls.c
+diff --git a/po/POTFILES-ml b/po/POTFILES-ml
+index 185f87b..39ca2a0 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/perl_edit.ml
++builder/pxzcat.ml
+ builder/sigchecker.ml
+ mllib/common_gettext.ml
+ mllib/common_utils.ml
+-- 
+1.8.3.1
+
diff --git a/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch b/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
new file mode 100644
index 0000000..ef5ce5c
--- /dev/null
+++ b/0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
@@ -0,0 +1,493 @@
+From 7d81c64a1f96ef72c3ad84ce05d182bda3b30faa Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 13:59:55 +0000
+Subject: [PATCH] builder: Replace fedora-<NN> shell & kickstart with a single
+ script.
+
+Just use:
+
+  ./fedora.sh 18
+
+Note that you don't need to be root.
+
+(cherry picked from commit ade0f1a97d6371f5d5a538da9d41263146cc58d6)
+---
+ builder/website/Makefile.am  |  5 +--
+ builder/website/fedora-18.ks | 38 -----------------
+ builder/website/fedora-18.sh | 75 ---------------------------------
+ builder/website/fedora-19.ks | 38 -----------------
+ builder/website/fedora-19.sh | 75 ---------------------------------
+ builder/website/fedora.sh    | 99 ++++++++++++++++++++++++++++++++++++++++++++
+ builder/website/index        | 12 +++---
+ builder/website/index.asc    | 36 ++++++++--------
+ 8 files changed, 124 insertions(+), 254 deletions(-)
+ delete mode 100644 builder/website/fedora-18.ks
+ delete mode 100755 builder/website/fedora-18.sh
+ delete mode 100644 builder/website/fedora-19.ks
+ delete mode 100755 builder/website/fedora-19.sh
+ create mode 100755 builder/website/fedora.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index 2a3bbe6..4188439 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -32,11 +32,8 @@ EXTRA_DIST = \
+ 	debian-7.preseed \
+ 	debian-7.sh \
+ 	debian-7.xz.sig \
+-	fedora-18.ks \
+-	fedora-18.sh \
++	fedora.sh \
+ 	fedora-18.xz.sig \
+-	fedora-19.ks \
+-	fedora-19.sh \
+ 	fedora-19.xz.sig \
+ 	ubuntu-10.04.preseed \
+ 	ubuntu-10.04.sh \
+diff --git a/builder/website/fedora-18.ks b/builder/website/fedora-18.ks
+deleted file mode 100644
+index 5e6fe24..0000000
+--- a/builder/website/fedora-18.ks
++++ /dev/null
+@@ -1,38 +0,0 @@
+-# virt-builder
+-# 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.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-autopart --type=plain
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/fedora-18.sh b/builder/website/fedora-18.sh
+deleted file mode 100755
+index 6fd6214..0000000
+--- a/builder/website/fedora-18.sh
++++ /dev/null
+@@ -1,75 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# 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.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-tree=http://mirror.bytemark.co.uk/fedora/linux/releases/18/Fedora/x86_64/os/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f fedora-18.ks ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpf18 ||:
+-rm -f fedora-18 fedora-18.old
+-
+-virt-install \
+-    --name=tmpf18 \
+-    --ram 2048 \
+-    --cpu=host --vcpus=2 \
+-    --os-type=linux --os-variant=fedora18 \
+-    --initrd-inject=$pwd/fedora-18.ks \
+-    --extra-args="ks=file:/fedora-18.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+-    --disk $pwd/fedora-18,size=6 \
+-    --location=$tree \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpf18
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a fedora-18
+-
+-# Sparsify.
+-mv fedora-18 fedora-18.old
+-virt-sparsify fedora-18.old fedora-18
+-rm fedora-18.old
+-
+-# Compress.
+-rm -f fedora-18.xz
+-xz --best --block-size=16777216 fedora-18
+-
+-# Result:
+-ls -lh fedora-18.xz
+diff --git a/builder/website/fedora-19.ks b/builder/website/fedora-19.ks
+deleted file mode 100644
+index 5e6fe24..0000000
+--- a/builder/website/fedora-19.ks
++++ /dev/null
+@@ -1,38 +0,0 @@
+-# virt-builder
+-# 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.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-autopart --type=plain
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/fedora-19.sh b/builder/website/fedora-19.sh
+deleted file mode 100755
+index d175cdf..0000000
+--- a/builder/website/fedora-19.sh
++++ /dev/null
+@@ -1,75 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# 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.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-tree=http://mirror.bytemark.co.uk/fedora/linux/releases/19/Fedora/x86_64/os/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f fedora-19.ks ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpf19 ||:
+-rm -f fedora-19 fedora-19.old
+-
+-virt-install \
+-    --name=tmpf19 \
+-    --ram 2048 \
+-    --cpu=host --vcpus=2 \
+-    --os-type=linux --os-variant=fedora19 \
+-    --initrd-inject=$pwd/fedora-19.ks \
+-    --extra-args="ks=file:/fedora-19.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+-    --disk $pwd/fedora-19,size=4 \
+-    --location=$tree \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpf19
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a fedora-19
+-
+-# Sparsify.
+-mv fedora-19 fedora-19.old
+-virt-sparsify fedora-19.old fedora-19
+-rm fedora-19.old
+-
+-# Compress.
+-rm -f fedora-19.xz
+-xz --best --block-size=16777216 fedora-19
+-
+-# Result:
+-ls -lh fedora-19.xz
+diff --git a/builder/website/fedora.sh b/builder/website/fedora.sh
+new file mode 100755
+index 0000000..bb164d8
+--- /dev/null
++++ b/builder/website/fedora.sh
+@@ -0,0 +1,99 @@
++#!/bin/bash -
++# virt-builder
++# 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.
++
++# This script was used to create the Fedora templates used by
++# virt-builder.
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 1 ]; then
++    echo "$0 VERSION"
++    exit 1
++fi
++
++version=$1
++tree=http://mirror.bytemark.co.uk/fedora/linux/releases/$version/Fedora/x86_64/os/
++output=fedora-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Generate the kickstart to a temporary file.
++ks=$(mktemp)
++cat > $ks <<'EOF'
++install
++text
++reboot
++lang en_US.UTF-8
++keyboard us
++network --bootproto dhcp
++rootpw builder
++firewall --enabled --ssh
++selinux --enforcing
++timezone --utc America/New_York
++bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
++zerombr
++clearpart --all --initlabel
++autopart --type=plain
++
++# Halt the system once configuration has finished.
++poweroff
++
++%packages
++ at core
++%end
++EOF
++
++# Clean up function.
++cleanup ()
++{
++    rm -f $ks
++    virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++    --name=$tmpname \
++    --ram=2048 \
++    --cpu=host --vcpus=2 \
++    --os-type=linux --os-variant=fedora18 \
++    --initrd-inject=$ks \
++    --extra-args="ks=file:/`basename $ks` console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
++    --disk $(pwd)/$output,size=6 \
++    --location=$tree \
++    --nographics \
++    --noreboot
++
++# Sysprep (removes logfiles and so on).
++# Note this also touches /.autorelabel so the further installation
++# changes that we make will be labelled properly at first boot.
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 6165f28..bea11ce 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -96,9 +96,9 @@ notes=Fedora 18.
+  This Fedora image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-18.ks
+- libguestfs.git/builder/website/fedora-18.sh
++ found in the libguestfs source tree:
++ 
++ builder/website/fedora.sh
+  
+  Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+  Source and further information is available from http://fedoraproject.org/
+@@ -118,9 +118,9 @@ notes=Fedora 19.
+  This Fedora image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-19.ks
+- libguestfs.git/builder/website/fedora-19.sh
++ found in the libguestfs source tree:
++ 
++ builder/website/fedora.sh
+  
+  Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+  Source and further information is available from http://fedoraproject.org/
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 087ebeb..c04cf1d 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -99,9 +99,9 @@ notes=Fedora 18.
+  This Fedora image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-18.ks
+- libguestfs.git/builder/website/fedora-18.sh
++ found in the libguestfs source tree:
++ 
++ builder/website/fedora.sh
+  
+  Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+  Source and further information is available from http://fedoraproject.org/
+@@ -122,8 +122,8 @@ notes=Fedora 19.
+  
+  It is thus very minimal.  The kickstart and install script can be
+  found in the libguestfs git tree:
+- libguestfs.git/builder/website/fedora-19.ks
+- libguestfs.git/builder/website/fedora-19.sh
++ 
++ builder/website/fedora.sh
+  
+  Fedora and the Infinity design logo are trademarks of Red Hat, Inc.
+  Source and further information is available from http://fedoraproject.org/
+@@ -202,17 +202,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+ 
+-iQIcBAEBAgAGBQJSc9qSAAoJEJFzj3Pht2igkYkQAKoYhPycj0ydM5Gk3nbaSOuU
+-Rsz1LsujBsYTM+E51UjBm4bcCJw4HwHYRUMT/t5cdMSX/NjSNGHjeLRBQvOGJMHx
+-DV6quFv/mwSCjvncWPuT3iCRNIIAq0ECr5YvfKhJ6HtoD/cQM7WUivYdZUJERC89
+-H1d5bjDiU25qLrhl68fEMyQzzpKIq3CbsIsczlCxxuHefXNhhp7XmqGtrNwpd7im
+-FtbKaIPeUDreoDCNNZzeUwdJ3TR6ybPB1Iy5Pl3kaBcM3VKqV5qXdQdmCbLyVtzg
+-rg4cSxTRiMJGstMVIiDJzsS+DGfUngpXZnxndDpzaX6BVgMqFjSPcjjif2f+wWsK
+-t1eXAhyoUYK+mepsNmYsOzBLFgnQKnmRO4cy6DgKq+twrx4v7snDpQ8J+HZkGHM6
+-sdliAQ7QEBmcLVArlzsq61RP3XlWrSIwmRG7BBGFptom4p+m7JeIPCH9EKZ9QIDK
+-tWOq8LqEAsNvaJrw+HTcGaryEYOf6YmJFd0iHgqDOnrsvsPK9Ex8hhC05jYe/Lkp
+-HzZiRjHFpHbm8lBVFcrajyGumdIieg2EUh7iygxaRFQa+7UA7fkYuGhYXKcsbgyT
+-Q3/c5TUAAM9qpj70rtTHV0LCmXL21aPqsMRPD/Oawe9N2iYe0HfNuZ1bBauPJEGy
+-pixuD1Mt3Xl/2Hl0GVcY
+-=x34e
++iQIcBAEBAgAGBQJSePm7AAoJEJFzj3Pht2ig+fYP/RODYX3Y6Rfqgn5YcgOVbkEN
++5RNxNvE/cFba5w6eZzI2q/kdjH9JzHMqmevHwANNq8i37tmgrkFkGgZK7QD92xWS
++GF9QeaNh9usLi3gB9WRxsT5p017IUsns4lFhlPs6nXnuIqb3+7B/qYPQFqgW9QbO
++c3WYWhnHvxAAGvARnVirGs7ucyajjoqJA+P5yfnnxl8BPEk+1nuXowEH423czYq3
++E3dX5AUFy3mjfzK2DH12ladUYvxbur1p7eGKx7VkD1ZaqWtt+pss0+M7WO+tAt+w
++JkggdkBqY30T2zxchF8bRiObAFCXEpC7UmA50UPxXiVK94rXSr1jvAVHsh8nSjXA
++QfRcFA4JjnYRBqCiCu4Tp08MmfMKHFkCn/VtjUhugJHClkeR1GYkhUJ9pnu1goK/
++N3yNyW/kORgSgZFfmLvUcdAQIIyWTqvgXFkEe16FnWNmH1Aq8JbAH5l/Iw8Nk+bU
++gB9+kKdVyAH7j5+fasIuiw4N0dgiq4k3xktOgUMIt4I1mqpWEVJBGUWgcH/qx+FP
++nUoHXTDBLY6MZXAmtuV4TpvRPX85O5nSe6NnGsivaYVa7Dsqk5TUZhUpU46F2Sqv
++HsvhXO295LT7hPj2Cd++NAy1R+WV+eeldPwP+Ff9adOvB8uShHW+hVpSUVmeeIku
++LLd8N3ZnefviQj+p61It
++=qKVc
+ -----END PGP SIGNATURE-----
+-- 
+1.8.3.1
+
diff --git a/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch b/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
new file mode 100644
index 0000000..7988148
--- /dev/null
+++ b/0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
@@ -0,0 +1,2081 @@
+From da7e551daadfe32b0f386ffed41efc18a2150e3d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace ubuntu-<NN>.sh with a single script.
+
+Just use:
+
+  ./ubuntu.sh 10.04 lucid
+
+Note that you don't need to be root.
+
+(cherry picked from commit 91b5e7fb37751719304573882c521071aa811e36)
+---
+ builder/website/Makefile.am          |   8 +-
+ builder/website/index                |  21 +-
+ builder/website/index.asc            |  49 ++---
+ builder/website/ubuntu-10.04.preseed | 376 -----------------------------------
+ builder/website/ubuntu-10.04.sh      |  85 --------
+ builder/website/ubuntu-12.04.preseed | 376 -----------------------------------
+ builder/website/ubuntu-12.04.sh      |  85 --------
+ builder/website/ubuntu-13.10.preseed | 376 -----------------------------------
+ builder/website/ubuntu-13.10.sh      |  85 --------
+ builder/website/ubuntu.preseed       | 376 +++++++++++++++++++++++++++++++++++
+ builder/website/ubuntu.sh            |  84 ++++++++
+ 11 files changed, 500 insertions(+), 1421 deletions(-)
+ delete mode 100644 builder/website/ubuntu-10.04.preseed
+ delete mode 100755 builder/website/ubuntu-10.04.sh
+ delete mode 100644 builder/website/ubuntu-12.04.preseed
+ delete mode 100755 builder/website/ubuntu-12.04.sh
+ delete mode 100644 builder/website/ubuntu-13.10.preseed
+ delete mode 100755 builder/website/ubuntu-13.10.sh
+ create mode 100644 builder/website/ubuntu.preseed
+ create mode 100755 builder/website/ubuntu.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index 4188439..dfcb494 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -35,14 +35,10 @@ EXTRA_DIST = \
+ 	fedora.sh \
+ 	fedora-18.xz.sig \
+ 	fedora-19.xz.sig \
+-	ubuntu-10.04.preseed \
+-	ubuntu-10.04.sh \
++	ubuntu.preseed \
++	ubuntu.sh \
+ 	ubuntu-10.04.xz.sig \
+-	ubuntu-12.04.preseed \
+-	ubuntu-12.04.sh \
+ 	ubuntu-12.04.xz.sig \
+-	ubuntu-13.10.preseed \
+-	ubuntu-13.10.sh \
+ 	ubuntu-13.10.xz.sig
+ 
+ CLEANFILES = *~
+diff --git a/builder/website/index b/builder/website/index
+index bea11ce..4e6a867 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -141,9 +141,10 @@ notes=Ubuntu 10.04 (Lucid).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-10.04.preseed
+- libguestfs.git/builder/website/ubuntu-10.04.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+@@ -165,9 +166,10 @@ notes=Ubuntu 12.04 (Precise).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-12.04.preseed
+- libguestfs.git/builder/website/ubuntu-12.04.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+@@ -189,9 +191,10 @@ notes=Ubuntu 13.10 (Saucy).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-13.10.preseed
+- libguestfs.git/builder/website/ubuntu-13.10.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index c04cf1d..35e103c 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -121,7 +121,7 @@ notes=Fedora 19.
+  This Fedora image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
++ found in the libguestfs source tree:
+  
+  builder/website/fedora.sh
+  
+@@ -144,9 +144,10 @@ notes=Ubuntu 10.04 (Lucid).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-10.04.preseed
+- libguestfs.git/builder/website/ubuntu-10.04.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+@@ -168,9 +169,10 @@ notes=Ubuntu 12.04 (Precise).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-12.04.preseed
+- libguestfs.git/builder/website/ubuntu-12.04.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+@@ -192,9 +194,10 @@ notes=Ubuntu 13.10 (Saucy).
+  
+  Only the openssh-server package is selected in tasksel.
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/ubuntu-13.10.preseed
+- libguestfs.git/builder/website/ubuntu-13.10.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/ubuntu.preseed
++ builder/website/ubuntu.sh
+  
+  This image does not contain SSH host keys.  To regenerate them use:
+  
+@@ -202,17 +205,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+ 
+-iQIcBAEBAgAGBQJSePm7AAoJEJFzj3Pht2ig+fYP/RODYX3Y6Rfqgn5YcgOVbkEN
+-5RNxNvE/cFba5w6eZzI2q/kdjH9JzHMqmevHwANNq8i37tmgrkFkGgZK7QD92xWS
+-GF9QeaNh9usLi3gB9WRxsT5p017IUsns4lFhlPs6nXnuIqb3+7B/qYPQFqgW9QbO
+-c3WYWhnHvxAAGvARnVirGs7ucyajjoqJA+P5yfnnxl8BPEk+1nuXowEH423czYq3
+-E3dX5AUFy3mjfzK2DH12ladUYvxbur1p7eGKx7VkD1ZaqWtt+pss0+M7WO+tAt+w
+-JkggdkBqY30T2zxchF8bRiObAFCXEpC7UmA50UPxXiVK94rXSr1jvAVHsh8nSjXA
+-QfRcFA4JjnYRBqCiCu4Tp08MmfMKHFkCn/VtjUhugJHClkeR1GYkhUJ9pnu1goK/
+-N3yNyW/kORgSgZFfmLvUcdAQIIyWTqvgXFkEe16FnWNmH1Aq8JbAH5l/Iw8Nk+bU
+-gB9+kKdVyAH7j5+fasIuiw4N0dgiq4k3xktOgUMIt4I1mqpWEVJBGUWgcH/qx+FP
+-nUoHXTDBLY6MZXAmtuV4TpvRPX85O5nSe6NnGsivaYVa7Dsqk5TUZhUpU46F2Sqv
+-HsvhXO295LT7hPj2Cd++NAy1R+WV+eeldPwP+Ff9adOvB8uShHW+hVpSUVmeeIku
+-LLd8N3ZnefviQj+p61It
+-=qKVc
++iQIcBAEBAgAGBQJSePzzAAoJEJFzj3Pht2igrqQP/j/P4lsPU5HjBKNcNLNxKtHV
++9VJkn5/pfJGp0ovVoZqVJMknTwMQV850TDkbzMteWGgJEYFf5a6g8VHjmAkCunkl
++f1Das08tUjJcOow/pR8Dkwd2mGU4EDzwzun3BXnGgpnLcOURhLD28xp2SlLTmzfh
++tP5EWqgEBTT6Z8h6Rtth27lKveEk14w+QzJfwTgecySN+hTQY12NUIayNKmPrBE1
++SrbAGnw1KkpXAI7JQ1ofORsPKKSwZuHvhJY094315UwmB76EDwGzkMrRzZsYgMwN
++fESGh0YzyDdpl68G7QSOLUsDdZLXSB/dHi9FK4f6FsoUVf3kxelkZM4EXChL1ZMm
++NCMWhiYlmX5Z7KgPZqmKVToDXwQ0AAo0a+wNvJo4frtvDHMIGjBe/f+h4k67yOoc
++WGXqYGQG3cRrqVLanA5dFFmX+GGL/TG2cinvi+x5kJ902KeM17uyzk1uuMAUh/Rl
++RVSsLg9QH4sLE8wEPpaUzz2ei1Bf4P26hHtVOdK7YAueDUhfSfn9KIV/n5Fz4pRg
++G8FlpPnL1sfzbj8qpLqXHDnJ3rXGnYkSBalNJ7WVBBNlqaewuK/bcmLp9ffVeaN9
++CcDsWbv2UaeXXu8N9pcW2kEo1cBjKTR9NPT8ueZY0g0InNrPaz/cFMOf5K9MBfuC
++lRwdaDejqzKc5gYRKFnH
++=tYWz
+ -----END PGP SIGNATURE-----
+diff --git a/builder/website/ubuntu-10.04.preseed b/builder/website/ubuntu-10.04.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-10.04.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home:   separate /home partition
+-# - multi:  separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string                         \
+-#      boot-root ::                                            \
+-#              40 50 100 ext3                                  \
+-#                      $primary{ } $bootable{ }                \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ /boot }                     \
+-#              .                                               \
+-#              500 10000 1000000000 ext3                       \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ / }                         \
+-#              .                                               \
+-#              64 512 300% linux-swap                          \
+-#                      method{ swap } format{ }                \
+-#              .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-#       http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev  string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev  string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+-       select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+-       select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-#   debconf-get-selections --installer > file
+-#   debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-10.04.sh b/builder/website/ubuntu-10.04.sh
+deleted file mode 100755
+index 943a96a..0000000
+--- a/builder/website/ubuntu-10.04.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/lucid/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-10.04.preseed ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-10.04.preseed > preseed.cfg
+-
+-name=tmplucid
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-10.04 ubuntu-10.04.old
+-
+-virt-install \
+-    --name $name \
+-    --ram=1024 \
+-    --os-type=linux --os-variant=ubuntulucid \
+-    --initrd-inject=$pwd/preseed.cfg \
+-    --extra-args="auto console=tty0 console=ttyS0,115200" \
+-    --disk=$pwd/ubuntu-10.04,size=4 \
+-    --location=$location \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-10.04
+-
+-# Sparsify.
+-mv ubuntu-10.04 ubuntu-10.04.old
+-virt-sparsify ubuntu-10.04.old ubuntu-10.04
+-rm ubuntu-10.04.old
+-
+-# Compress.
+-rm -f ubuntu-10.04.xz
+-xz --best --block-size=16777216 ubuntu-10.04
+-
+-# Result:
+-ls -lh ubuntu-10.04.xz
+diff --git a/builder/website/ubuntu-12.04.preseed b/builder/website/ubuntu-12.04.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-12.04.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home:   separate /home partition
+-# - multi:  separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string                         \
+-#      boot-root ::                                            \
+-#              40 50 100 ext3                                  \
+-#                      $primary{ } $bootable{ }                \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ /boot }                     \
+-#              .                                               \
+-#              500 10000 1000000000 ext3                       \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ / }                         \
+-#              .                                               \
+-#              64 512 300% linux-swap                          \
+-#                      method{ swap } format{ }                \
+-#              .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-#       http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev  string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev  string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+-       select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+-       select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-#   debconf-get-selections --installer > file
+-#   debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-12.04.sh b/builder/website/ubuntu-12.04.sh
+deleted file mode 100755
+index 6134b1d..0000000
+--- a/builder/website/ubuntu-12.04.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/precise/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-12.04.preseed ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-12.04.preseed > preseed.cfg
+-
+-name=tmpprecise
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-12.04 ubuntu-12.04.old
+-
+-virt-install \
+-    --name $name \
+-    --ram=1024 \
+-    --os-type=linux --os-variant=ubuntuprecise \
+-    --initrd-inject=$pwd/preseed.cfg \
+-    --extra-args="auto console=tty0 console=ttyS0,115200" \
+-    --disk=$pwd/ubuntu-12.04,size=4 \
+-    --location=$location \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-12.04
+-
+-# Sparsify.
+-mv ubuntu-12.04 ubuntu-12.04.old
+-virt-sparsify ubuntu-12.04.old ubuntu-12.04
+-rm ubuntu-12.04.old
+-
+-# Compress.
+-rm -f ubuntu-12.04.xz
+-xz --best --block-size=16777216 ubuntu-12.04
+-
+-# Result:
+-ls -lh ubuntu-12.04.xz
+diff --git a/builder/website/ubuntu-13.10.preseed b/builder/website/ubuntu-13.10.preseed
+deleted file mode 100644
+index 236e174..0000000
+--- a/builder/website/ubuntu-13.10.preseed
++++ /dev/null
+@@ -1,376 +0,0 @@
+-#### Contents of the preconfiguration file (for &releasename;)
+-### Localization
+-# Locale sets language and country.
+-d-i debian-installer/locale string en_US
+-
+-# Keyboard selection.
+-# Disable automatic (interactive) keymap detection.
+-d-i console-setup/ask_detect boolean false
+-#d-i console-setup/modelcode string pc105
+-d-i console-setup/layoutcode string us
+-# To select a variant of the selected layout (if you leave this out, the
+-# basic form of the layout will be used):
+-#d-i console-setup/variantcode string dvorak
+-
+-### Network configuration
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_dhcp boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-#d-i mirror/country string manual
+-#d-i mirror/http/hostname string http.us.debian.org
+-#d-i mirror/http/directory string /ubuntu
+-#d-i mirror/http/proxy string
+-
+-# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
+-# CC is the ISO-3166-2 code for the selected country. You can preseed this
+-# so that it does so without asking.
+-d-i mirror/http/mirror select uk.archive.ubuntu.com
+-
+-# Suite to install.
+-#d-i mirror/suite string &releasename;
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string &releasename;
+-# Components to use for loading installer components (optional).
+-#d-i mirror/udeb/components multiselect main, restricted
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-# If the system has free space you can choose to only partition that space.
+-# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you can specify a disk to partition. The device name must
+-# be given in traditional non-devfs format.
+-# Note: A disk must be specified, unless the system has only one disk.
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are: "regular", "lvm" and "crypto"
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-
+-# For LVM partitioning, you can select how much of the volume group to use
+-# for logical volumes.
+-#d-i partman-auto-lvm/guided_size string max
+-#d-i partman-auto-lvm/guided_size string 10GB
+-#d-i partman-auto-lvm/guided_size string 50%
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home:   separate /home partition
+-# - multi:  separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# The recipe format is documented in the file devel/partman-auto-recipe.txt.
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string                         \
+-#      boot-root ::                                            \
+-#              40 50 100 ext3                                  \
+-#                      $primary{ } $bootable{ }                \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ /boot }                     \
+-#              .                                               \
+-#              500 10000 1000000000 ext3                       \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ / }                         \
+-#              .                                               \
+-#              64 512 300% linux-swap                          \
+-#                      method{ swap } format{ }                \
+-#              .
+-
+-# If you just want to change the default filesystem from ext3 to something
+-# else, you can do that without providing a full recipe.
+-#d-i partman/default_filesystem string ext4
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-### Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-generic
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo). The default is false; preseed this to true if you want to set
+-# a root password.
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Ubuntu User
+-#d-i passwd/username string ubuntu
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-# The installer will warn about weak passwords. If you are sure you know
+-# what you're doing and want to override it, uncomment this.
+-#d-i user-setup/allow-password-weak boolean true
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-# Set to true if you want to encrypt the first user's home directory.
+-d-i user-setup/encrypt-home boolean false
+-
+-### Apt setup
+-# You can choose to install restricted and universe software, or to install
+-# software from the backports repository.
+-#d-i apt-setup/restricted boolean true
+-#d-i apt-setup/universe boolean true
+-#d-i apt-setup/backports boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security
+-#d-i apt-setup/security_host string security.ubuntu.com
+-#d-i apt-setup/security_path string /ubuntu
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-#       http://local.server/ubuntu &releasename; main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated string true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect ubuntu-desktop
+-#tasksel tasksel/first multiselect lamp-server, print-server
+-#tasksel tasksel/first multiselect kubuntu-desktop
+-tasksel tasksel/first multiselect openssh-server
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Language pack selection
+-#d-i pkgsel/language-packs multiselect de, en, zh
+-
+-# Policy for applying updates. May be "none" (no automatic updates),
+-# "unattended-upgrades" (install security updates automatically), or
+-# "landscape" (manage system with Landscape).
+-#d-i pkgsel/update-policy select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-#popularity-contest popularity-contest/participate boolean false
+-
+-# By default, the system's locate database will be updated after the
+-# installer has finished installing most packages. This may take a while, so
+-# if you don't want it, you can set this to "false" to turn it off.
+-#d-i pkgsel/updatedb boolean true
+-
+-### Boot loader installation
+-# Grub is the default boot loader (for x86). If you want lilo installed
+-# instead, uncomment this:
+-#d-i grub-installer/skip boolean true
+-# To also skip installing lilo, and install no bootloader, uncomment this
+-# too:
+-#d-i lilo-installer/skip boolean true
+-
+-# This is fairly safe to set, it makes grub install automatically to the MBR
+-# if no other operating system is detected on the machine.
+-d-i grub-installer/only_debian boolean true
+-
+-# This one makes grub-installer install to the MBR if it also finds some other
+-# OS, which is less safe as it might not be able to boot that other OS.
+-d-i grub-installer/with_other_os boolean true
+-
+-# Alternatively, if you want to install to a location other than the mbr,
+-# uncomment and edit these lines:
+-#d-i grub-installer/only_debian boolean false
+-#d-i grub-installer/with_other_os boolean false
+-#d-i grub-installer/bootdev  string (hd0,0)
+-# To install grub to multiple disks:
+-#d-i grub-installer/bootdev  string (hd0,0) (hd1,0) (hd2,0)
+-
+-# Optional password for grub, either in clear text
+-#d-i grub-installer/password password r00tme
+-#d-i grub-installer/password-again password r00tme
+-# or encrypted using an MD5 hash, see grub-md5-crypt(8).
+-#d-i grub-installer/password-crypted password [MD5 hash]
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### X configuration
+-# X can detect the right driver for some cards, but if you're preseeding,
+-# you override whatever it chooses. Still, vesa will work most places.
+-#xserver-xorg xserver-xorg/config/device/driver select vesa
+-
+-# A caveat with mouse autodetection is that if it fails, X will retry it
+-# over and over. So if it's preseeded to be done, there is a possibility of
+-# an infinite loop if the mouse is not autodetected.
+-#xserver-xorg xserver-xorg/autodetect_mouse boolean true
+-
+-# Monitor autodetection is recommended.
+-xserver-xorg xserver-xorg/autodetect_monitor boolean true
+-# Uncomment if you have an LCD display.
+-#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
+-# X has three configuration paths for the monitor. Here's how to preseed
+-# the "medium" path, which is always available. The "simple" path may not
+-# be available, and the "advanced" path asks too many questions.
+-xserver-xorg xserver-xorg/config/monitor/selection-method \
+-       select medium
+-xserver-xorg xserver-xorg/config/monitor/mode-list \
+-       select 1024x768 @ 60 Hz
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-#   debconf-get-selections --installer > file
+-#   debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+-
+diff --git a/builder/website/ubuntu-13.10.sh b/builder/website/ubuntu-13.10.sh
+deleted file mode 100755
+index 7373176..0000000
+--- a/builder/website/ubuntu-13.10.sh
++++ /dev/null
+@@ -1,85 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-#export http_proxy=http://squid.corp.redhat.com:3128
+-#export https_proxy=$http_proxy
+-#export ftp_proxy=$http_proxy
+-location=http://archive.ubuntu.net/ubuntu/dists/saucy/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f ubuntu-13.10.preseed ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < ubuntu-13.10.preseed > preseed.cfg
+-
+-name=tmpsaucy
+-
+-virsh undefine $name ||:
+-rm -f ubuntu-13.10 ubuntu-13.10.old
+-
+-virt-install \
+-    --name $name \
+-    --ram=1024 \
+-    --os-type=linux --os-variant=ubuntusaucy \
+-    --initrd-inject=$pwd/preseed.cfg \
+-    --extra-args="auto console=tty0 console=ttyS0,115200" \
+-    --disk=$pwd/ubuntu-13.10,size=4 \
+-    --location=$location \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine $name
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a ubuntu-13.10
+-
+-# Sparsify.
+-mv ubuntu-13.10 ubuntu-13.10.old
+-virt-sparsify ubuntu-13.10.old ubuntu-13.10
+-rm ubuntu-13.10.old
+-
+-# Compress.
+-rm -f ubuntu-13.10.xz
+-xz --best --block-size=16777216 ubuntu-13.10
+-
+-# Result:
+-ls -lh ubuntu-13.10.xz
+diff --git a/builder/website/ubuntu.preseed b/builder/website/ubuntu.preseed
+new file mode 100644
+index 0000000..236e174
+--- /dev/null
++++ b/builder/website/ubuntu.preseed
+@@ -0,0 +1,376 @@
++#### Contents of the preconfiguration file (for &releasename;)
++### Localization
++# Locale sets language and country.
++d-i debian-installer/locale string en_US
++
++# Keyboard selection.
++# Disable automatic (interactive) keymap detection.
++d-i console-setup/ask_detect boolean false
++#d-i console-setup/modelcode string pc105
++d-i console-setup/layoutcode string us
++# To select a variant of the selected layout (if you leave this out, the
++# basic form of the layout will be used):
++#d-i console-setup/variantcode string dvorak
++
++### Network configuration
++# netcfg will choose an interface that has link if possible. This makes it
++# skip displaying a list if there is more than one interface.
++d-i netcfg/choose_interface select auto
++
++# To pick a particular interface instead:
++#d-i netcfg/choose_interface select eth1
++
++# If you have a slow dhcp server and the installer times out waiting for
++# it, this might be useful.
++#d-i netcfg/dhcp_timeout string 60
++
++# If you prefer to configure the network manually, uncomment this line and
++# the static network configuration below.
++#d-i netcfg/disable_dhcp boolean true
++
++# If you want the preconfiguration file to work on systems both with and
++# without a dhcp server, uncomment these lines and the static network
++# configuration below.
++#d-i netcfg/dhcp_failed note
++#d-i netcfg/dhcp_options select Configure network manually
++
++# Static network configuration.
++#d-i netcfg/get_nameservers string 192.168.1.1
++#d-i netcfg/get_ipaddress string 192.168.1.42
++#d-i netcfg/get_netmask string 255.255.255.0
++#d-i netcfg/get_gateway string 192.168.1.1
++#d-i netcfg/confirm_static boolean true
++
++# Any hostname and domain names assigned from dhcp take precedence over
++# values set here. However, setting the values still prevents the questions
++# from being shown, even if values come from dhcp.
++d-i netcfg/get_hostname string unassigned-hostname
++d-i netcfg/get_domain string unassigned-domain
++
++# Disable that annoying WEP key dialog.
++d-i netcfg/wireless_wep string
++# The wacky dhcp hostname that some ISPs use as a password of sorts.
++#d-i netcfg/dhcp_hostname string radish
++
++# If non-free firmware is needed for the network or other hardware, you can
++# configure the installer to always try to load it, without prompting. Or
++# change to false to disable asking.
++#d-i hw-detect/load_firmware boolean true
++
++### Mirror settings
++# If you select ftp, the mirror/country string does not need to be set.
++#d-i mirror/protocol string ftp
++#d-i mirror/country string manual
++#d-i mirror/http/hostname string http.us.debian.org
++#d-i mirror/http/directory string /ubuntu
++#d-i mirror/http/proxy string
++
++# Alternatively: by default, the installer uses CC.archive.ubuntu.com where
++# CC is the ISO-3166-2 code for the selected country. You can preseed this
++# so that it does so without asking.
++d-i mirror/http/mirror select uk.archive.ubuntu.com
++
++# Suite to install.
++#d-i mirror/suite string &releasename;
++# Suite to use for loading installer components (optional).
++#d-i mirror/udeb/suite string &releasename;
++# Components to use for loading installer components (optional).
++#d-i mirror/udeb/components multiselect main, restricted
++
++### Clock and time zone setup
++# Controls whether or not the hardware clock is set to UTC.
++d-i clock-setup/utc boolean true
++
++# You may set this to any valid setting for $TZ; see the contents of
++# /usr/share/zoneinfo/ for valid values.
++d-i time/zone string US/Eastern
++
++# Controls whether to use NTP to set the clock during the install
++d-i clock-setup/ntp boolean true
++# NTP server to use. The default is almost always fine here.
++#d-i clock-setup/ntp-server string ntp.example.com
++
++### Partitioning
++# If the system has free space you can choose to only partition that space.
++# Alternatives: custom, some_device, some_device_crypto, some_device_lvm.
++#d-i partman-auto/init_automatically_partition select biggest_free
++
++# Alternatively, you can specify a disk to partition. The device name must
++# be given in traditional non-devfs format.
++# Note: A disk must be specified, unless the system has only one disk.
++# For example, to use the first SCSI/SATA hard disk:
++#d-i partman-auto/disk string /dev/sda
++# In addition, you'll need to specify the method to use.
++# The presently available methods are: "regular", "lvm" and "crypto"
++d-i partman-auto/method string regular
++
++# If one of the disks that are going to be automatically partitioned
++# contains an old LVM configuration, the user will normally receive a
++# warning. This can be preseeded away...
++d-i partman-lvm/device_remove_lvm boolean true
++# The same applies to pre-existing software RAID array:
++d-i partman-md/device_remove_md boolean true
++# And the same goes for the confirmation to write the lvm partitions.
++d-i partman-lvm/confirm boolean true
++
++# For LVM partitioning, you can select how much of the volume group to use
++# for logical volumes.
++#d-i partman-auto-lvm/guided_size string max
++#d-i partman-auto-lvm/guided_size string 10GB
++#d-i partman-auto-lvm/guided_size string 50%
++
++# You can choose one of the three predefined partitioning recipes:
++# - atomic: all files in one partition
++# - home:   separate /home partition
++# - multi:  separate /home, /usr, /var, and /tmp partitions
++d-i partman-auto/choose_recipe select atomic
++
++# Or provide a recipe of your own...
++# The recipe format is documented in the file devel/partman-auto-recipe.txt.
++# If you have a way to get a recipe file into the d-i environment, you can
++# just point at it.
++#d-i partman-auto/expert_recipe_file string /hd-media/recipe
++
++# If not, you can put an entire recipe into the preconfiguration file in one
++# (logical) line. This example creates a small /boot partition, suitable
++# swap, and uses the rest of the space for the root partition:
++#d-i partman-auto/expert_recipe string                         \
++#      boot-root ::                                            \
++#              40 50 100 ext3                                  \
++#                      $primary{ } $bootable{ }                \
++#                      method{ format } format{ }              \
++#                      use_filesystem{ } filesystem{ ext3 }    \
++#                      mountpoint{ /boot }                     \
++#              .                                               \
++#              500 10000 1000000000 ext3                       \
++#                      method{ format } format{ }              \
++#                      use_filesystem{ } filesystem{ ext3 }    \
++#                      mountpoint{ / }                         \
++#              .                                               \
++#              64 512 300% linux-swap                          \
++#                      method{ swap } format{ }                \
++#              .
++
++# If you just want to change the default filesystem from ext3 to something
++# else, you can do that without providing a full recipe.
++#d-i partman/default_filesystem string ext4
++
++# This makes partman automatically partition without confirmation, provided
++# that you told it what to do using one of the methods above.
++d-i partman/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++### Controlling how partitions are mounted
++# The default is to mount by UUID, but you can also choose "traditional" to
++# use traditional device names, or "label" to try filesystem labels before
++# falling back to UUIDs.
++#d-i partman/mount_style select uuid
++
++### Base system installation
++# The kernel image (meta) package to be installed; "none" can be used if no
++# kernel is to be installed.
++#d-i base-installer/kernel/image string linux-generic
++
++### Account setup
++# Skip creation of a root account (normal user account will be able to
++# use sudo). The default is false; preseed this to true if you want to set
++# a root password.
++#d-i passwd/root-login boolean false
++# Alternatively, to skip creation of a normal user account.
++d-i passwd/make-user boolean false
++
++# Root password, either in clear text
++d-i passwd/root-password password builder
++d-i passwd/root-password-again password builder
++# or encrypted using an MD5 hash.
++#d-i passwd/root-password-crypted password [MD5 hash]
++
++# To create a normal user account.
++#d-i passwd/user-fullname string Ubuntu User
++#d-i passwd/username string ubuntu
++# Normal user's password, either in clear text
++#d-i passwd/user-password password insecure
++#d-i passwd/user-password-again password insecure
++# or encrypted using an MD5 hash.
++#d-i passwd/user-password-crypted password [MD5 hash]
++# Create the first user with the specified UID instead of the default.
++#d-i passwd/user-uid string 1010
++# The installer will warn about weak passwords. If you are sure you know
++# what you're doing and want to override it, uncomment this.
++#d-i user-setup/allow-password-weak boolean true
++
++# The user account will be added to some standard initial groups. To
++# override that, use this.
++#d-i passwd/user-default-groups string audio cdrom video
++
++# Set to true if you want to encrypt the first user's home directory.
++d-i user-setup/encrypt-home boolean false
++
++### Apt setup
++# You can choose to install restricted and universe software, or to install
++# software from the backports repository.
++#d-i apt-setup/restricted boolean true
++#d-i apt-setup/universe boolean true
++#d-i apt-setup/backports boolean true
++# Uncomment this if you don't want to use a network mirror.
++#d-i apt-setup/use_mirror boolean false
++# Select which update services to use; define the mirrors to be used.
++# Values shown below are the normal defaults.
++#d-i apt-setup/services-select multiselect security
++#d-i apt-setup/security_host string security.ubuntu.com
++#d-i apt-setup/security_path string /ubuntu
++
++# Additional repositories, local[0-9] available
++#d-i apt-setup/local0/repository string \
++#       http://local.server/ubuntu &releasename; main
++#d-i apt-setup/local0/comment string local server
++# Enable deb-src lines
++#d-i apt-setup/local0/source boolean true
++# URL to the public key of the local repository; you must provide a key or
++# apt will complain about the unauthenticated repository and so the
++# sources.list line will be left commented out
++#d-i apt-setup/local0/key string http://local.server/key
++
++# By default the installer requires that repositories be authenticated
++# using a known gpg key. This setting can be used to disable that
++# authentication. Warning: Insecure, not recommended.
++#d-i debian-installer/allow_unauthenticated string true
++
++### Package selection
++#tasksel tasksel/first multiselect ubuntu-desktop
++#tasksel tasksel/first multiselect lamp-server, print-server
++#tasksel tasksel/first multiselect kubuntu-desktop
++tasksel tasksel/first multiselect openssh-server
++
++# Individual additional packages to install
++#d-i pkgsel/include string openssh-server build-essential
++# Whether to upgrade packages after debootstrap.
++# Allowed values: none, safe-upgrade, full-upgrade
++#d-i pkgsel/upgrade select none
++
++# Language pack selection
++#d-i pkgsel/language-packs multiselect de, en, zh
++
++# Policy for applying updates. May be "none" (no automatic updates),
++# "unattended-upgrades" (install security updates automatically), or
++# "landscape" (manage system with Landscape).
++#d-i pkgsel/update-policy select none
++
++# Some versions of the installer can report back on what software you have
++# installed, and what software you use. The default is not to report back,
++# but sending reports helps the project determine what software is most
++# popular and include it on CDs.
++#popularity-contest popularity-contest/participate boolean false
++
++# By default, the system's locate database will be updated after the
++# installer has finished installing most packages. This may take a while, so
++# if you don't want it, you can set this to "false" to turn it off.
++#d-i pkgsel/updatedb boolean true
++
++### Boot loader installation
++# Grub is the default boot loader (for x86). If you want lilo installed
++# instead, uncomment this:
++#d-i grub-installer/skip boolean true
++# To also skip installing lilo, and install no bootloader, uncomment this
++# too:
++#d-i lilo-installer/skip boolean true
++
++# This is fairly safe to set, it makes grub install automatically to the MBR
++# if no other operating system is detected on the machine.
++d-i grub-installer/only_debian boolean true
++
++# This one makes grub-installer install to the MBR if it also finds some other
++# OS, which is less safe as it might not be able to boot that other OS.
++d-i grub-installer/with_other_os boolean true
++
++# Alternatively, if you want to install to a location other than the mbr,
++# uncomment and edit these lines:
++#d-i grub-installer/only_debian boolean false
++#d-i grub-installer/with_other_os boolean false
++#d-i grub-installer/bootdev  string (hd0,0)
++# To install grub to multiple disks:
++#d-i grub-installer/bootdev  string (hd0,0) (hd1,0) (hd2,0)
++
++# Optional password for grub, either in clear text
++#d-i grub-installer/password password r00tme
++#d-i grub-installer/password-again password r00tme
++# or encrypted using an MD5 hash, see grub-md5-crypt(8).
++#d-i grub-installer/password-crypted password [MD5 hash]
++
++### Finishing up the installation
++# During installations from serial console, the regular virtual consoles
++# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
++# line to prevent this.
++#d-i finish-install/keep-consoles boolean true
++
++# Avoid that last message about the install being complete.
++d-i finish-install/reboot_in_progress note
++
++# This will prevent the installer from ejecting the CD during the reboot,
++# which is useful in some situations.
++#d-i cdrom-detect/eject boolean false
++
++# This is how to make the installer shutdown when finished, but not
++# reboot into the installed system.
++#d-i debian-installer/exit/halt boolean true
++# This will power off the machine instead of just halting it.
++#d-i debian-installer/exit/poweroff boolean true
++
++### X configuration
++# X can detect the right driver for some cards, but if you're preseeding,
++# you override whatever it chooses. Still, vesa will work most places.
++#xserver-xorg xserver-xorg/config/device/driver select vesa
++
++# A caveat with mouse autodetection is that if it fails, X will retry it
++# over and over. So if it's preseeded to be done, there is a possibility of
++# an infinite loop if the mouse is not autodetected.
++#xserver-xorg xserver-xorg/autodetect_mouse boolean true
++
++# Monitor autodetection is recommended.
++xserver-xorg xserver-xorg/autodetect_monitor boolean true
++# Uncomment if you have an LCD display.
++#xserver-xorg xserver-xorg/config/monitor/lcd boolean true
++# X has three configuration paths for the monitor. Here's how to preseed
++# the "medium" path, which is always available. The "simple" path may not
++# be available, and the "advanced" path asks too many questions.
++xserver-xorg xserver-xorg/config/monitor/selection-method \
++       select medium
++xserver-xorg xserver-xorg/config/monitor/mode-list \
++       select 1024x768 @ 60 Hz
++
++### Preseeding other packages
++# Depending on what software you choose to install, or if things go wrong
++# during the installation process, it's possible that other questions may
++# be asked. You can preseed those too, of course. To get a list of every
++# possible question that could be asked during an install, do an
++# installation, and then run these commands:
++#   debconf-get-selections --installer > file
++#   debconf-get-selections >> file
++
++
++#### Advanced options
++### Running custom commands during the installation
++# d-i preseeding is inherently not secure. Nothing in the installer checks
++# for attempts at buffer overflows or other exploits of the values of a
++# preconfiguration file like this one. Only use preconfiguration files from
++# trusted locations! To drive that home, and because it's generally useful,
++# here's a way to run any shell command you'd like inside the installer,
++# automatically.
++
++# This first command is run as early as possible, just after
++# preseeding is read.
++#d-i preseed/early_command string anna-install some-udeb
++
++# This command is run immediately before the partitioner starts. It may be
++# useful to apply dynamic partitioner preseeding that depends on the state
++# of the disks (which may not be visible when preseed/early_command runs).
++#d-i partman/early_command string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
++
++# This command is run just before the install finishes, but when there is
++# still a usable /target directory. You can chroot to /target and use it
++# directly, or use the apt-install and in-target commands to easily install
++# packages and run commands in the target system.
++#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
++
+diff --git a/builder/website/ubuntu.sh b/builder/website/ubuntu.sh
+new file mode 100755
+index 0000000..edafd69
+--- /dev/null
++++ b/builder/website/ubuntu.sh
+@@ -0,0 +1,84 @@
++#!/bin/bash -
++# libguestfs
++# 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.
++
++# The basic plan comes from:
++# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
++# https://wiki.debian.org/DebianInstaller/Preseed
++# https://help.ubuntu.com/10.04/installation-guide/i386/preseed-using.html
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 2 ]; then
++    echo "$0 VERSION DIST"
++    exit 1
++fi
++
++# Some configuration.
++version=$1
++dist=$2
++location=http://archive.ubuntu.net/ubuntu/dists/$dist/main/installer-amd64
++output=ubuntu-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Make sure it's being run from the correct directory.
++if [ ! -f ubuntu.preseed ]; then
++    echo "You are running this script from the wrong directory."
++    exit 1
++fi
++
++# Note that the injected file must be called "/preseed.cfg" in order
++# for d-i to pick it up.
++sed -e "s, at CACHE@,$http_proxy,g" < ubuntu.preseed > preseed.cfg
++
++# Clean up function.
++cleanup ()
++{
++    rm -f preseed.cfg
++    virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++    --name=$tmpname \
++    --ram=1024 \
++    --os-type=linux --os-variant=ubuntu$dist \
++    --initrd-inject=$(pwd)/preseed.cfg \
++    --extra-args="auto console=tty0 console=ttyS0,115200" \
++    --disk=$(pwd)/$output,size=4 \
++    --location=$location \
++    --nographics \
++    --noreboot
++
++# Sysprep (removes logfiles and so on).
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+-- 
+1.8.3.1
+
diff --git a/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch b/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
new file mode 100644
index 0000000..aeaf7bf
--- /dev/null
+++ b/0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
@@ -0,0 +1,1578 @@
+From 181b928c9e821fd8888966ba422120474b938f2e Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace debian-<NN>.sh with a single script.
+
+Just use:
+
+  ./debian.sh 6 squeeze
+
+Note that you don't need to be root.
+
+(cherry picked from commit af9e9299bf0f422d7e07ccfe9a59e664b49c2dfe)
+---
+ builder/website/Makefile.am      |   6 +-
+ builder/website/debian-6.preseed | 385 ---------------------------------------
+ builder/website/debian-6.sh      |  76 --------
+ builder/website/debian-7.preseed | 385 ---------------------------------------
+ builder/website/debian-7.sh      |  82 ---------
+ builder/website/debian.preseed   | 385 +++++++++++++++++++++++++++++++++++++++
+ builder/website/debian.sh        |  83 +++++++++
+ builder/website/index            |  14 +-
+ builder/website/index.asc        |  40 ++--
+ 9 files changed, 499 insertions(+), 957 deletions(-)
+ delete mode 100644 builder/website/debian-6.preseed
+ delete mode 100755 builder/website/debian-6.sh
+ delete mode 100644 builder/website/debian-7.preseed
+ delete mode 100755 builder/website/debian-7.sh
+ create mode 100644 builder/website/debian.preseed
+ create mode 100755 builder/website/debian.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index dfcb494..a662176 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -26,11 +26,9 @@ EXTRA_DIST = \
+ 	centos-6.ks \
+ 	centos-6.sh \
+ 	centos-6.xz.sig \
+-	debian-6.preseed \
+-	debian-6.sh \
++	debian.preseed \
++	debian.sh \
+ 	debian-6.xz.sig \
+-	debian-7.preseed \
+-	debian-7.sh \
+ 	debian-7.xz.sig \
+ 	fedora.sh \
+ 	fedora-18.xz.sig \
+diff --git a/builder/website/debian-6.preseed b/builder/website/debian-6.preseed
+deleted file mode 100644
+index faa4430..0000000
+--- a/builder/website/debian-6.preseed
++++ /dev/null
+@@ -1,385 +0,0 @@
+-#### Contents of the preconfiguration file (for wheezy)
+-### Localization
+-# Preseeding only locale sets language, country and locale.
+-d-i debian-installer/locale string en_US
+-
+-# The values can also be preseeded individually for greater flexibility.
+-#d-i debian-installer/language string en
+-#d-i debian-installer/country string NL
+-#d-i debian-installer/locale string en_GB.UTF-8
+-# Optionally specify additional locales to be generated.
+-#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
+-
+-# Keyboard selection.
+-# keymap is an alias for keyboard-configuration/xkb-keymap
+-d-i keymap select us
+-# d-i keyboard-configuration/toggle select No toggling
+-
+-### Network configuration
+-# Disable network configuration entirely. This is useful for cdrom
+-# installations on non-networked devices where the network questions,
+-# warning and long timeouts are a nuisance.
+-d-i netcfg/enable boolean true
+-
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# To set a different link detection timeout (default is 3 seconds).
+-# Values are interpreted as seconds.
+-#d-i netcfg/link_detection_timeout string 10
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-#d-i netcfg/dhcpv6_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_autoconfig boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#
+-# IPv4 example
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-#
+-# IPv6 example
+-#d-i netcfg/get_ipaddress string fc00::2
+-#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
+-#d-i netcfg/get_gateway string fc00::1
+-#d-i netcfg/get_nameservers string fc00::1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# If you want to force a hostname, regardless of what either the DHCP
+-# server returns or what the reverse DNS entry for the IP is, uncomment
+-# and adjust the following line.
+-#d-i netcfg/hostname string somehost
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Network console
+-# Use the following settings if you wish to make use of the network-console
+-# component for remote installation over SSH. This only makes sense if you
+-# intend to perform the remainder of the installation manually.
+-#d-i anna/choose_modules string network-console
+-#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
+-#d-i network-console/password password r00tme
+-#d-i network-console/password-again password r00tme
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-d-i mirror/country string manual
+-d-i mirror/http/hostname string ftp.uk.debian.org
+-d-i mirror/http/directory string /debian
+-d-i mirror/http/proxy string @CACHE@
+-
+-# Suite to install.
+-#d-i mirror/suite string testing
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string testing
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo).
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Debian User
+-#d-i passwd/username string debian
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-## Partitioning example
+-# If the system has free space you can choose to only partition that space.
+-# This is only honoured if partman-auto/method (below) is not set.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you may specify a disk to partition. If the system has only
+-# one disk the installer will default to using that, but otherwise the device
+-# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
+-# /dev/sda, and not e.g. /dev/discs/disc0/disc).
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are:
+-# - regular: use the usual partition types for your architecture
+-# - lvm:     use LVM to partition the disk
+-# - crypto:  use LVM within an encrypted partition
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-d-i partman-lvm/confirm_nooverwrite boolean true
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home:   separate /home partition
+-# - multi:  separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string                         \
+-#      boot-root ::                                            \
+-#              40 50 100 ext3                                  \
+-#                      $primary{ } $bootable{ }                \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ /boot }                     \
+-#              .                                               \
+-#              500 10000 1000000000 ext3                       \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ / }                         \
+-#              .                                               \
+-#              64 512 300% linux-swap                          \
+-#                      method{ swap } format{ }                \
+-#              .
+-
+-# The full recipe format is documented in the file partman-auto-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository. This also documents how to specify settings such as file
+-# system labels, volume group names and which physical devices to include
+-# in a volume group.
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Partitioning using RAID
+-# The method should be set to "raid".
+-#d-i partman-auto/method string raid
+-# Specify the disks to be partitioned. They will all get the same layout,
+-# so this will only work if the disks are the same size.
+-#d-i partman-auto/disk string /dev/sda /dev/sdb
+-
+-# Next you need to specify the physical partitions that will be used. 
+-#d-i partman-auto/expert_recipe string \
+-#      multiraid ::                                         \
+-#              1000 5000 4000 raid                          \
+-#                      $primary{ } method{ raid }           \
+-#              .                                            \
+-#              64 512 300% raid                             \
+-#                      method{ raid }                       \
+-#              .                                            \
+-#              500 10000 1000000000 raid                    \
+-#                      method{ raid }                       \
+-#              .
+-
+-# Last you need to specify how the previously defined partitions will be
+-# used in the RAID setup. Remember to use the correct partition numbers
+-# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
+-# devices are separated using "#".
+-# Parameters are:
+-# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
+-#          <devices> <sparedevices>
+-
+-#d-i partman-auto-raid/recipe string \
+-#    1 2 0 ext3 /                    \
+-#          /dev/sda1#/dev/sdb1       \
+-#    .                               \
+-#    1 2 0 swap -                    \
+-#          /dev/sda5#/dev/sdb5       \
+-#    .                               \
+-#    0 2 0 ext3 /home                \
+-#          /dev/sda6#/dev/sdb6       \
+-#    .
+-
+-# For additional information see the file partman-auto-raid-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository.
+-
+-# This makes partman automatically partition without confirmation.
+-d-i partman-md/confirm boolean true
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# Configure APT to not install recommended packages by default. Use of this
+-# option can result in an incomplete system and should only be used by very
+-# experienced users.
+-#d-i base-installer/install-recommends boolean false
+-
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-image-486
+-
+-### Apt setup
+-# You can choose to install non-free and contrib software.
+-#d-i apt-setup/non-free boolean true
+-#d-i apt-setup/contrib boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security, volatile
+-#d-i apt-setup/security_host string security.debian.org
+-#d-i apt-setup/volatile_host string volatile.debian.org
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-#       http://local.server/debian stable main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated boolean true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect standard, web-server
+-# If the desktop task is selected, install the kde and xfce desktops
+-# instead of the default gnome desktop.
+-#tasksel tasksel/desktop multiselect kde, xfce
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-popularity-contest popularity-contest/participate boolean false
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-#   debconf-get-selections --installer > file
+-#   debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command \
+-#       string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian-6.sh b/builder/website/debian-6.sh
+deleted file mode 100755
+index 7976c9c..0000000
+--- a/builder/website/debian-6.sh
++++ /dev/null
+@@ -1,76 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-location=http://ftp.uk.debian.org/debian/dists/squeeze/main/installer-amd64
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f debian-6.preseed ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < debian-6.preseed > preseed.cfg
+-
+-virsh undefine tmpd6 ||:
+-rm -f debian-6 debian-6.old
+-
+-virt-install \
+-    --name tmpd6 \
+-    --ram=1024 \
+-    --os-type=linux --os-variant=debiansqueeze \
+-    --initrd-inject=$pwd/preseed.cfg \
+-    --extra-args="auto console=tty0 console=ttyS0,115200" \
+-    --disk=$pwd/debian-6,size=4 \
+-    --location=$location \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpd6
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a debian-6
+-
+-# Sparsify.
+-mv debian-6 debian-6.old
+-virt-sparsify debian-6.old debian-6
+-rm debian-6.old
+-
+-# Compress.
+-rm -f debian-6.xz
+-xz --best --block-size=$((16*1024*1024)) debian-6
+-
+-# Result:
+-ls -lh debian-6.xz
+diff --git a/builder/website/debian-7.preseed b/builder/website/debian-7.preseed
+deleted file mode 100644
+index faa4430..0000000
+--- a/builder/website/debian-7.preseed
++++ /dev/null
+@@ -1,385 +0,0 @@
+-#### Contents of the preconfiguration file (for wheezy)
+-### Localization
+-# Preseeding only locale sets language, country and locale.
+-d-i debian-installer/locale string en_US
+-
+-# The values can also be preseeded individually for greater flexibility.
+-#d-i debian-installer/language string en
+-#d-i debian-installer/country string NL
+-#d-i debian-installer/locale string en_GB.UTF-8
+-# Optionally specify additional locales to be generated.
+-#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
+-
+-# Keyboard selection.
+-# keymap is an alias for keyboard-configuration/xkb-keymap
+-d-i keymap select us
+-# d-i keyboard-configuration/toggle select No toggling
+-
+-### Network configuration
+-# Disable network configuration entirely. This is useful for cdrom
+-# installations on non-networked devices where the network questions,
+-# warning and long timeouts are a nuisance.
+-d-i netcfg/enable boolean true
+-
+-# netcfg will choose an interface that has link if possible. This makes it
+-# skip displaying a list if there is more than one interface.
+-d-i netcfg/choose_interface select auto
+-
+-# To pick a particular interface instead:
+-#d-i netcfg/choose_interface select eth1
+-
+-# To set a different link detection timeout (default is 3 seconds).
+-# Values are interpreted as seconds.
+-#d-i netcfg/link_detection_timeout string 10
+-
+-# If you have a slow dhcp server and the installer times out waiting for
+-# it, this might be useful.
+-#d-i netcfg/dhcp_timeout string 60
+-#d-i netcfg/dhcpv6_timeout string 60
+-
+-# If you prefer to configure the network manually, uncomment this line and
+-# the static network configuration below.
+-#d-i netcfg/disable_autoconfig boolean true
+-
+-# If you want the preconfiguration file to work on systems both with and
+-# without a dhcp server, uncomment these lines and the static network
+-# configuration below.
+-#d-i netcfg/dhcp_failed note
+-#d-i netcfg/dhcp_options select Configure network manually
+-
+-# Static network configuration.
+-#
+-# IPv4 example
+-#d-i netcfg/get_ipaddress string 192.168.1.42
+-#d-i netcfg/get_netmask string 255.255.255.0
+-#d-i netcfg/get_gateway string 192.168.1.1
+-#d-i netcfg/get_nameservers string 192.168.1.1
+-#d-i netcfg/confirm_static boolean true
+-#
+-# IPv6 example
+-#d-i netcfg/get_ipaddress string fc00::2
+-#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
+-#d-i netcfg/get_gateway string fc00::1
+-#d-i netcfg/get_nameservers string fc00::1
+-#d-i netcfg/confirm_static boolean true
+-
+-# Any hostname and domain names assigned from dhcp take precedence over
+-# values set here. However, setting the values still prevents the questions
+-# from being shown, even if values come from dhcp.
+-d-i netcfg/get_hostname string unassigned-hostname
+-d-i netcfg/get_domain string unassigned-domain
+-
+-# If you want to force a hostname, regardless of what either the DHCP
+-# server returns or what the reverse DNS entry for the IP is, uncomment
+-# and adjust the following line.
+-#d-i netcfg/hostname string somehost
+-
+-# Disable that annoying WEP key dialog.
+-d-i netcfg/wireless_wep string
+-# The wacky dhcp hostname that some ISPs use as a password of sorts.
+-#d-i netcfg/dhcp_hostname string radish
+-
+-# If non-free firmware is needed for the network or other hardware, you can
+-# configure the installer to always try to load it, without prompting. Or
+-# change to false to disable asking.
+-#d-i hw-detect/load_firmware boolean true
+-
+-### Network console
+-# Use the following settings if you wish to make use of the network-console
+-# component for remote installation over SSH. This only makes sense if you
+-# intend to perform the remainder of the installation manually.
+-#d-i anna/choose_modules string network-console
+-#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
+-#d-i network-console/password password r00tme
+-#d-i network-console/password-again password r00tme
+-
+-### Mirror settings
+-# If you select ftp, the mirror/country string does not need to be set.
+-#d-i mirror/protocol string ftp
+-d-i mirror/country string manual
+-d-i mirror/http/hostname string ftp.uk.debian.org
+-d-i mirror/http/directory string /debian
+-d-i mirror/http/proxy string @CACHE@
+-
+-# Suite to install.
+-#d-i mirror/suite string testing
+-# Suite to use for loading installer components (optional).
+-#d-i mirror/udeb/suite string testing
+-
+-### Account setup
+-# Skip creation of a root account (normal user account will be able to
+-# use sudo).
+-#d-i passwd/root-login boolean false
+-# Alternatively, to skip creation of a normal user account.
+-d-i passwd/make-user boolean false
+-
+-# Root password, either in clear text
+-d-i passwd/root-password password builder
+-d-i passwd/root-password-again password builder
+-# or encrypted using an MD5 hash.
+-#d-i passwd/root-password-crypted password [MD5 hash]
+-
+-# To create a normal user account.
+-#d-i passwd/user-fullname string Debian User
+-#d-i passwd/username string debian
+-# Normal user's password, either in clear text
+-#d-i passwd/user-password password insecure
+-#d-i passwd/user-password-again password insecure
+-# or encrypted using an MD5 hash.
+-#d-i passwd/user-password-crypted password [MD5 hash]
+-# Create the first user with the specified UID instead of the default.
+-#d-i passwd/user-uid string 1010
+-
+-# The user account will be added to some standard initial groups. To
+-# override that, use this.
+-#d-i passwd/user-default-groups string audio cdrom video
+-
+-### Clock and time zone setup
+-# Controls whether or not the hardware clock is set to UTC.
+-d-i clock-setup/utc boolean true
+-
+-# You may set this to any valid setting for $TZ; see the contents of
+-# /usr/share/zoneinfo/ for valid values.
+-d-i time/zone string US/Eastern
+-
+-# Controls whether to use NTP to set the clock during the install
+-d-i clock-setup/ntp boolean true
+-# NTP server to use. The default is almost always fine here.
+-#d-i clock-setup/ntp-server string ntp.example.com
+-
+-### Partitioning
+-## Partitioning example
+-# If the system has free space you can choose to only partition that space.
+-# This is only honoured if partman-auto/method (below) is not set.
+-#d-i partman-auto/init_automatically_partition select biggest_free
+-
+-# Alternatively, you may specify a disk to partition. If the system has only
+-# one disk the installer will default to using that, but otherwise the device
+-# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
+-# /dev/sda, and not e.g. /dev/discs/disc0/disc).
+-# For example, to use the first SCSI/SATA hard disk:
+-#d-i partman-auto/disk string /dev/sda
+-# In addition, you'll need to specify the method to use.
+-# The presently available methods are:
+-# - regular: use the usual partition types for your architecture
+-# - lvm:     use LVM to partition the disk
+-# - crypto:  use LVM within an encrypted partition
+-d-i partman-auto/method string regular
+-
+-# If one of the disks that are going to be automatically partitioned
+-# contains an old LVM configuration, the user will normally receive a
+-# warning. This can be preseeded away...
+-d-i partman-lvm/device_remove_lvm boolean true
+-# The same applies to pre-existing software RAID array:
+-d-i partman-md/device_remove_md boolean true
+-# And the same goes for the confirmation to write the lvm partitions.
+-d-i partman-lvm/confirm boolean true
+-d-i partman-lvm/confirm_nooverwrite boolean true
+-
+-# You can choose one of the three predefined partitioning recipes:
+-# - atomic: all files in one partition
+-# - home:   separate /home partition
+-# - multi:  separate /home, /usr, /var, and /tmp partitions
+-d-i partman-auto/choose_recipe select atomic
+-
+-# Or provide a recipe of your own...
+-# If you have a way to get a recipe file into the d-i environment, you can
+-# just point at it.
+-#d-i partman-auto/expert_recipe_file string /hd-media/recipe
+-
+-# If not, you can put an entire recipe into the preconfiguration file in one
+-# (logical) line. This example creates a small /boot partition, suitable
+-# swap, and uses the rest of the space for the root partition:
+-#d-i partman-auto/expert_recipe string                         \
+-#      boot-root ::                                            \
+-#              40 50 100 ext3                                  \
+-#                      $primary{ } $bootable{ }                \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ /boot }                     \
+-#              .                                               \
+-#              500 10000 1000000000 ext3                       \
+-#                      method{ format } format{ }              \
+-#                      use_filesystem{ } filesystem{ ext3 }    \
+-#                      mountpoint{ / }                         \
+-#              .                                               \
+-#              64 512 300% linux-swap                          \
+-#                      method{ swap } format{ }                \
+-#              .
+-
+-# The full recipe format is documented in the file partman-auto-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository. This also documents how to specify settings such as file
+-# system labels, volume group names and which physical devices to include
+-# in a volume group.
+-
+-# This makes partman automatically partition without confirmation, provided
+-# that you told it what to do using one of the methods above.
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Partitioning using RAID
+-# The method should be set to "raid".
+-#d-i partman-auto/method string raid
+-# Specify the disks to be partitioned. They will all get the same layout,
+-# so this will only work if the disks are the same size.
+-#d-i partman-auto/disk string /dev/sda /dev/sdb
+-
+-# Next you need to specify the physical partitions that will be used. 
+-#d-i partman-auto/expert_recipe string \
+-#      multiraid ::                                         \
+-#              1000 5000 4000 raid                          \
+-#                      $primary{ } method{ raid }           \
+-#              .                                            \
+-#              64 512 300% raid                             \
+-#                      method{ raid }                       \
+-#              .                                            \
+-#              500 10000 1000000000 raid                    \
+-#                      method{ raid }                       \
+-#              .
+-
+-# Last you need to specify how the previously defined partitions will be
+-# used in the RAID setup. Remember to use the correct partition numbers
+-# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
+-# devices are separated using "#".
+-# Parameters are:
+-# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
+-#          <devices> <sparedevices>
+-
+-#d-i partman-auto-raid/recipe string \
+-#    1 2 0 ext3 /                    \
+-#          /dev/sda1#/dev/sdb1       \
+-#    .                               \
+-#    1 2 0 swap -                    \
+-#          /dev/sda5#/dev/sdb5       \
+-#    .                               \
+-#    0 2 0 ext3 /home                \
+-#          /dev/sda6#/dev/sdb6       \
+-#    .
+-
+-# For additional information see the file partman-auto-raid-recipe.txt
+-# included in the 'debian-installer' package or available from D-I source
+-# repository.
+-
+-# This makes partman automatically partition without confirmation.
+-d-i partman-md/confirm boolean true
+-d-i partman-partitioning/confirm_write_new_label boolean true
+-d-i partman/choose_partition select finish
+-d-i partman/confirm boolean true
+-d-i partman/confirm_nooverwrite boolean true
+-
+-## Controlling how partitions are mounted
+-# The default is to mount by UUID, but you can also choose "traditional" to
+-# use traditional device names, or "label" to try filesystem labels before
+-# falling back to UUIDs.
+-#d-i partman/mount_style select uuid
+-
+-### Base system installation
+-# Configure APT to not install recommended packages by default. Use of this
+-# option can result in an incomplete system and should only be used by very
+-# experienced users.
+-#d-i base-installer/install-recommends boolean false
+-
+-# The kernel image (meta) package to be installed; "none" can be used if no
+-# kernel is to be installed.
+-#d-i base-installer/kernel/image string linux-image-486
+-
+-### Apt setup
+-# You can choose to install non-free and contrib software.
+-#d-i apt-setup/non-free boolean true
+-#d-i apt-setup/contrib boolean true
+-# Uncomment this if you don't want to use a network mirror.
+-#d-i apt-setup/use_mirror boolean false
+-# Select which update services to use; define the mirrors to be used.
+-# Values shown below are the normal defaults.
+-#d-i apt-setup/services-select multiselect security, volatile
+-#d-i apt-setup/security_host string security.debian.org
+-#d-i apt-setup/volatile_host string volatile.debian.org
+-
+-# Additional repositories, local[0-9] available
+-#d-i apt-setup/local0/repository string \
+-#       http://local.server/debian stable main
+-#d-i apt-setup/local0/comment string local server
+-# Enable deb-src lines
+-#d-i apt-setup/local0/source boolean true
+-# URL to the public key of the local repository; you must provide a key or
+-# apt will complain about the unauthenticated repository and so the
+-# sources.list line will be left commented out
+-#d-i apt-setup/local0/key string http://local.server/key
+-
+-# By default the installer requires that repositories be authenticated
+-# using a known gpg key. This setting can be used to disable that
+-# authentication. Warning: Insecure, not recommended.
+-#d-i debian-installer/allow_unauthenticated boolean true
+-
+-### Package selection
+-#tasksel tasksel/first multiselect standard, web-server
+-# If the desktop task is selected, install the kde and xfce desktops
+-# instead of the default gnome desktop.
+-#tasksel tasksel/desktop multiselect kde, xfce
+-
+-# Individual additional packages to install
+-#d-i pkgsel/include string openssh-server build-essential
+-# Whether to upgrade packages after debootstrap.
+-# Allowed values: none, safe-upgrade, full-upgrade
+-#d-i pkgsel/upgrade select none
+-
+-# Some versions of the installer can report back on what software you have
+-# installed, and what software you use. The default is not to report back,
+-# but sending reports helps the project determine what software is most
+-# popular and include it on CDs.
+-popularity-contest popularity-contest/participate boolean false
+-
+-### Finishing up the installation
+-# During installations from serial console, the regular virtual consoles
+-# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
+-# line to prevent this.
+-#d-i finish-install/keep-consoles boolean true
+-
+-# Avoid that last message about the install being complete.
+-d-i finish-install/reboot_in_progress note
+-
+-# This will prevent the installer from ejecting the CD during the reboot,
+-# which is useful in some situations.
+-#d-i cdrom-detect/eject boolean false
+-
+-# This is how to make the installer shutdown when finished, but not
+-# reboot into the installed system.
+-#d-i debian-installer/exit/halt boolean true
+-# This will power off the machine instead of just halting it.
+-#d-i debian-installer/exit/poweroff boolean true
+-
+-### Preseeding other packages
+-# Depending on what software you choose to install, or if things go wrong
+-# during the installation process, it's possible that other questions may
+-# be asked. You can preseed those too, of course. To get a list of every
+-# possible question that could be asked during an install, do an
+-# installation, and then run these commands:
+-#   debconf-get-selections --installer > file
+-#   debconf-get-selections >> file
+-
+-
+-#### Advanced options
+-### Running custom commands during the installation
+-# d-i preseeding is inherently not secure. Nothing in the installer checks
+-# for attempts at buffer overflows or other exploits of the values of a
+-# preconfiguration file like this one. Only use preconfiguration files from
+-# trusted locations! To drive that home, and because it's generally useful,
+-# here's a way to run any shell command you'd like inside the installer,
+-# automatically.
+-
+-# This first command is run as early as possible, just after
+-# preseeding is read.
+-#d-i preseed/early_command string anna-install some-udeb
+-# This command is run immediately before the partitioner starts. It may be
+-# useful to apply dynamic partitioner preseeding that depends on the state
+-# of the disks (which may not be visible when preseed/early_command runs).
+-#d-i partman/early_command \
+-#       string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
+-# This command is run just before the install finishes, but when there is
+-# still a usable /target directory. You can chroot to /target and use it
+-# directly, or use the apt-install and in-target commands to easily install
+-# packages and run commands in the target system.
+-#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian-7.sh b/builder/website/debian-7.sh
+deleted file mode 100755
+index b294b65..0000000
+--- a/builder/website/debian-7.sh
++++ /dev/null
+@@ -1,82 +0,0 @@
+-#!/bin/bash -
+-# libguestfs
+-# 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.
+-
+-# The basic plan comes from:
+-# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
+-# https://wiki.debian.org/DebianInstaller/Preseed
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-location=http://ftp.uk.debian.org/debian/dists/stable/main/installer-amd64
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f debian-7.preseed ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-# Note that the injected file must be called "/preseed.cfg" in order
+-# for d-i to pick it up.
+-sed -e "s, at CACHE@,$http_proxy,g" < debian-7.preseed > preseed.cfg
+-
+-virsh undefine tmpd7 ||:
+-rm -f debian-7 debian-7.old
+-
+-virt-install \
+-    --name tmpd7 \
+-    --ram=1024 \
+-    --os-type=linux --os-variant=debianwheezy \
+-    --initrd-inject=$pwd/preseed.cfg \
+-    --extra-args="auto console=tty0 console=ttyS0,115200" \
+-    --disk=$pwd/debian-7,size=4 \
+-    --location=$location \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpd7
+-
+-rm preseed.cfg
+-
+-# Sysprep (removes logfiles and so on).
+-virt-sysprep -a debian-7
+-
+-# Sparsify.
+-mv debian-7 debian-7.old
+-virt-sparsify debian-7.old debian-7
+-rm debian-7.old
+-
+-# Compress.
+-rm -f debian-7.xz
+-xz --best --block-size=16777216 debian-7
+-
+-# Result:
+-ls -lh debian-7.xz
+diff --git a/builder/website/debian.preseed b/builder/website/debian.preseed
+new file mode 100644
+index 0000000..faa4430
+--- /dev/null
++++ b/builder/website/debian.preseed
+@@ -0,0 +1,385 @@
++#### Contents of the preconfiguration file (for wheezy)
++### Localization
++# Preseeding only locale sets language, country and locale.
++d-i debian-installer/locale string en_US
++
++# The values can also be preseeded individually for greater flexibility.
++#d-i debian-installer/language string en
++#d-i debian-installer/country string NL
++#d-i debian-installer/locale string en_GB.UTF-8
++# Optionally specify additional locales to be generated.
++#d-i localechooser/supported-locales multiselect en_US.UTF-8, nl_NL.UTF-8
++
++# Keyboard selection.
++# keymap is an alias for keyboard-configuration/xkb-keymap
++d-i keymap select us
++# d-i keyboard-configuration/toggle select No toggling
++
++### Network configuration
++# Disable network configuration entirely. This is useful for cdrom
++# installations on non-networked devices where the network questions,
++# warning and long timeouts are a nuisance.
++d-i netcfg/enable boolean true
++
++# netcfg will choose an interface that has link if possible. This makes it
++# skip displaying a list if there is more than one interface.
++d-i netcfg/choose_interface select auto
++
++# To pick a particular interface instead:
++#d-i netcfg/choose_interface select eth1
++
++# To set a different link detection timeout (default is 3 seconds).
++# Values are interpreted as seconds.
++#d-i netcfg/link_detection_timeout string 10
++
++# If you have a slow dhcp server and the installer times out waiting for
++# it, this might be useful.
++#d-i netcfg/dhcp_timeout string 60
++#d-i netcfg/dhcpv6_timeout string 60
++
++# If you prefer to configure the network manually, uncomment this line and
++# the static network configuration below.
++#d-i netcfg/disable_autoconfig boolean true
++
++# If you want the preconfiguration file to work on systems both with and
++# without a dhcp server, uncomment these lines and the static network
++# configuration below.
++#d-i netcfg/dhcp_failed note
++#d-i netcfg/dhcp_options select Configure network manually
++
++# Static network configuration.
++#
++# IPv4 example
++#d-i netcfg/get_ipaddress string 192.168.1.42
++#d-i netcfg/get_netmask string 255.255.255.0
++#d-i netcfg/get_gateway string 192.168.1.1
++#d-i netcfg/get_nameservers string 192.168.1.1
++#d-i netcfg/confirm_static boolean true
++#
++# IPv6 example
++#d-i netcfg/get_ipaddress string fc00::2
++#d-i netcfg/get_netmask string ffff:ffff:ffff:ffff::
++#d-i netcfg/get_gateway string fc00::1
++#d-i netcfg/get_nameservers string fc00::1
++#d-i netcfg/confirm_static boolean true
++
++# Any hostname and domain names assigned from dhcp take precedence over
++# values set here. However, setting the values still prevents the questions
++# from being shown, even if values come from dhcp.
++d-i netcfg/get_hostname string unassigned-hostname
++d-i netcfg/get_domain string unassigned-domain
++
++# If you want to force a hostname, regardless of what either the DHCP
++# server returns or what the reverse DNS entry for the IP is, uncomment
++# and adjust the following line.
++#d-i netcfg/hostname string somehost
++
++# Disable that annoying WEP key dialog.
++d-i netcfg/wireless_wep string
++# The wacky dhcp hostname that some ISPs use as a password of sorts.
++#d-i netcfg/dhcp_hostname string radish
++
++# If non-free firmware is needed for the network or other hardware, you can
++# configure the installer to always try to load it, without prompting. Or
++# change to false to disable asking.
++#d-i hw-detect/load_firmware boolean true
++
++### Network console
++# Use the following settings if you wish to make use of the network-console
++# component for remote installation over SSH. This only makes sense if you
++# intend to perform the remainder of the installation manually.
++#d-i anna/choose_modules string network-console
++#d-i network-console/authorized_keys_url string http://10.0.0.1/openssh-key
++#d-i network-console/password password r00tme
++#d-i network-console/password-again password r00tme
++
++### Mirror settings
++# If you select ftp, the mirror/country string does not need to be set.
++#d-i mirror/protocol string ftp
++d-i mirror/country string manual
++d-i mirror/http/hostname string ftp.uk.debian.org
++d-i mirror/http/directory string /debian
++d-i mirror/http/proxy string @CACHE@
++
++# Suite to install.
++#d-i mirror/suite string testing
++# Suite to use for loading installer components (optional).
++#d-i mirror/udeb/suite string testing
++
++### Account setup
++# Skip creation of a root account (normal user account will be able to
++# use sudo).
++#d-i passwd/root-login boolean false
++# Alternatively, to skip creation of a normal user account.
++d-i passwd/make-user boolean false
++
++# Root password, either in clear text
++d-i passwd/root-password password builder
++d-i passwd/root-password-again password builder
++# or encrypted using an MD5 hash.
++#d-i passwd/root-password-crypted password [MD5 hash]
++
++# To create a normal user account.
++#d-i passwd/user-fullname string Debian User
++#d-i passwd/username string debian
++# Normal user's password, either in clear text
++#d-i passwd/user-password password insecure
++#d-i passwd/user-password-again password insecure
++# or encrypted using an MD5 hash.
++#d-i passwd/user-password-crypted password [MD5 hash]
++# Create the first user with the specified UID instead of the default.
++#d-i passwd/user-uid string 1010
++
++# The user account will be added to some standard initial groups. To
++# override that, use this.
++#d-i passwd/user-default-groups string audio cdrom video
++
++### Clock and time zone setup
++# Controls whether or not the hardware clock is set to UTC.
++d-i clock-setup/utc boolean true
++
++# You may set this to any valid setting for $TZ; see the contents of
++# /usr/share/zoneinfo/ for valid values.
++d-i time/zone string US/Eastern
++
++# Controls whether to use NTP to set the clock during the install
++d-i clock-setup/ntp boolean true
++# NTP server to use. The default is almost always fine here.
++#d-i clock-setup/ntp-server string ntp.example.com
++
++### Partitioning
++## Partitioning example
++# If the system has free space you can choose to only partition that space.
++# This is only honoured if partman-auto/method (below) is not set.
++#d-i partman-auto/init_automatically_partition select biggest_free
++
++# Alternatively, you may specify a disk to partition. If the system has only
++# one disk the installer will default to using that, but otherwise the device
++# name must be given in traditional, non-devfs format (so e.g. /dev/hda or
++# /dev/sda, and not e.g. /dev/discs/disc0/disc).
++# For example, to use the first SCSI/SATA hard disk:
++#d-i partman-auto/disk string /dev/sda
++# In addition, you'll need to specify the method to use.
++# The presently available methods are:
++# - regular: use the usual partition types for your architecture
++# - lvm:     use LVM to partition the disk
++# - crypto:  use LVM within an encrypted partition
++d-i partman-auto/method string regular
++
++# If one of the disks that are going to be automatically partitioned
++# contains an old LVM configuration, the user will normally receive a
++# warning. This can be preseeded away...
++d-i partman-lvm/device_remove_lvm boolean true
++# The same applies to pre-existing software RAID array:
++d-i partman-md/device_remove_md boolean true
++# And the same goes for the confirmation to write the lvm partitions.
++d-i partman-lvm/confirm boolean true
++d-i partman-lvm/confirm_nooverwrite boolean true
++
++# You can choose one of the three predefined partitioning recipes:
++# - atomic: all files in one partition
++# - home:   separate /home partition
++# - multi:  separate /home, /usr, /var, and /tmp partitions
++d-i partman-auto/choose_recipe select atomic
++
++# Or provide a recipe of your own...
++# If you have a way to get a recipe file into the d-i environment, you can
++# just point at it.
++#d-i partman-auto/expert_recipe_file string /hd-media/recipe
++
++# If not, you can put an entire recipe into the preconfiguration file in one
++# (logical) line. This example creates a small /boot partition, suitable
++# swap, and uses the rest of the space for the root partition:
++#d-i partman-auto/expert_recipe string                         \
++#      boot-root ::                                            \
++#              40 50 100 ext3                                  \
++#                      $primary{ } $bootable{ }                \
++#                      method{ format } format{ }              \
++#                      use_filesystem{ } filesystem{ ext3 }    \
++#                      mountpoint{ /boot }                     \
++#              .                                               \
++#              500 10000 1000000000 ext3                       \
++#                      method{ format } format{ }              \
++#                      use_filesystem{ } filesystem{ ext3 }    \
++#                      mountpoint{ / }                         \
++#              .                                               \
++#              64 512 300% linux-swap                          \
++#                      method{ swap } format{ }                \
++#              .
++
++# The full recipe format is documented in the file partman-auto-recipe.txt
++# included in the 'debian-installer' package or available from D-I source
++# repository. This also documents how to specify settings such as file
++# system labels, volume group names and which physical devices to include
++# in a volume group.
++
++# This makes partman automatically partition without confirmation, provided
++# that you told it what to do using one of the methods above.
++d-i partman-partitioning/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++## Partitioning using RAID
++# The method should be set to "raid".
++#d-i partman-auto/method string raid
++# Specify the disks to be partitioned. They will all get the same layout,
++# so this will only work if the disks are the same size.
++#d-i partman-auto/disk string /dev/sda /dev/sdb
++
++# Next you need to specify the physical partitions that will be used. 
++#d-i partman-auto/expert_recipe string \
++#      multiraid ::                                         \
++#              1000 5000 4000 raid                          \
++#                      $primary{ } method{ raid }           \
++#              .                                            \
++#              64 512 300% raid                             \
++#                      method{ raid }                       \
++#              .                                            \
++#              500 10000 1000000000 raid                    \
++#                      method{ raid }                       \
++#              .
++
++# Last you need to specify how the previously defined partitions will be
++# used in the RAID setup. Remember to use the correct partition numbers
++# for logical partitions. RAID levels 0, 1, 5, 6 and 10 are supported;
++# devices are separated using "#".
++# Parameters are:
++# <raidtype> <devcount> <sparecount> <fstype> <mountpoint> \
++#          <devices> <sparedevices>
++
++#d-i partman-auto-raid/recipe string \
++#    1 2 0 ext3 /                    \
++#          /dev/sda1#/dev/sdb1       \
++#    .                               \
++#    1 2 0 swap -                    \
++#          /dev/sda5#/dev/sdb5       \
++#    .                               \
++#    0 2 0 ext3 /home                \
++#          /dev/sda6#/dev/sdb6       \
++#    .
++
++# For additional information see the file partman-auto-raid-recipe.txt
++# included in the 'debian-installer' package or available from D-I source
++# repository.
++
++# This makes partman automatically partition without confirmation.
++d-i partman-md/confirm boolean true
++d-i partman-partitioning/confirm_write_new_label boolean true
++d-i partman/choose_partition select finish
++d-i partman/confirm boolean true
++d-i partman/confirm_nooverwrite boolean true
++
++## Controlling how partitions are mounted
++# The default is to mount by UUID, but you can also choose "traditional" to
++# use traditional device names, or "label" to try filesystem labels before
++# falling back to UUIDs.
++#d-i partman/mount_style select uuid
++
++### Base system installation
++# Configure APT to not install recommended packages by default. Use of this
++# option can result in an incomplete system and should only be used by very
++# experienced users.
++#d-i base-installer/install-recommends boolean false
++
++# The kernel image (meta) package to be installed; "none" can be used if no
++# kernel is to be installed.
++#d-i base-installer/kernel/image string linux-image-486
++
++### Apt setup
++# You can choose to install non-free and contrib software.
++#d-i apt-setup/non-free boolean true
++#d-i apt-setup/contrib boolean true
++# Uncomment this if you don't want to use a network mirror.
++#d-i apt-setup/use_mirror boolean false
++# Select which update services to use; define the mirrors to be used.
++# Values shown below are the normal defaults.
++#d-i apt-setup/services-select multiselect security, volatile
++#d-i apt-setup/security_host string security.debian.org
++#d-i apt-setup/volatile_host string volatile.debian.org
++
++# Additional repositories, local[0-9] available
++#d-i apt-setup/local0/repository string \
++#       http://local.server/debian stable main
++#d-i apt-setup/local0/comment string local server
++# Enable deb-src lines
++#d-i apt-setup/local0/source boolean true
++# URL to the public key of the local repository; you must provide a key or
++# apt will complain about the unauthenticated repository and so the
++# sources.list line will be left commented out
++#d-i apt-setup/local0/key string http://local.server/key
++
++# By default the installer requires that repositories be authenticated
++# using a known gpg key. This setting can be used to disable that
++# authentication. Warning: Insecure, not recommended.
++#d-i debian-installer/allow_unauthenticated boolean true
++
++### Package selection
++#tasksel tasksel/first multiselect standard, web-server
++# If the desktop task is selected, install the kde and xfce desktops
++# instead of the default gnome desktop.
++#tasksel tasksel/desktop multiselect kde, xfce
++
++# Individual additional packages to install
++#d-i pkgsel/include string openssh-server build-essential
++# Whether to upgrade packages after debootstrap.
++# Allowed values: none, safe-upgrade, full-upgrade
++#d-i pkgsel/upgrade select none
++
++# Some versions of the installer can report back on what software you have
++# installed, and what software you use. The default is not to report back,
++# but sending reports helps the project determine what software is most
++# popular and include it on CDs.
++popularity-contest popularity-contest/participate boolean false
++
++### Finishing up the installation
++# During installations from serial console, the regular virtual consoles
++# (VT1-VT6) are normally disabled in /etc/inittab. Uncomment the next
++# line to prevent this.
++#d-i finish-install/keep-consoles boolean true
++
++# Avoid that last message about the install being complete.
++d-i finish-install/reboot_in_progress note
++
++# This will prevent the installer from ejecting the CD during the reboot,
++# which is useful in some situations.
++#d-i cdrom-detect/eject boolean false
++
++# This is how to make the installer shutdown when finished, but not
++# reboot into the installed system.
++#d-i debian-installer/exit/halt boolean true
++# This will power off the machine instead of just halting it.
++#d-i debian-installer/exit/poweroff boolean true
++
++### Preseeding other packages
++# Depending on what software you choose to install, or if things go wrong
++# during the installation process, it's possible that other questions may
++# be asked. You can preseed those too, of course. To get a list of every
++# possible question that could be asked during an install, do an
++# installation, and then run these commands:
++#   debconf-get-selections --installer > file
++#   debconf-get-selections >> file
++
++
++#### Advanced options
++### Running custom commands during the installation
++# d-i preseeding is inherently not secure. Nothing in the installer checks
++# for attempts at buffer overflows or other exploits of the values of a
++# preconfiguration file like this one. Only use preconfiguration files from
++# trusted locations! To drive that home, and because it's generally useful,
++# here's a way to run any shell command you'd like inside the installer,
++# automatically.
++
++# This first command is run as early as possible, just after
++# preseeding is read.
++#d-i preseed/early_command string anna-install some-udeb
++# This command is run immediately before the partitioner starts. It may be
++# useful to apply dynamic partitioner preseeding that depends on the state
++# of the disks (which may not be visible when preseed/early_command runs).
++#d-i partman/early_command \
++#       string debconf-set partman-auto/disk "$(list-devices disk | head -n1)"
++# This command is run just before the install finishes, but when there is
++# still a usable /target directory. You can chroot to /target and use it
++# directly, or use the apt-install and in-target commands to easily install
++# packages and run commands in the target system.
++#d-i preseed/late_command string apt-install zsh; in-target chsh -s /bin/zsh
+diff --git a/builder/website/debian.sh b/builder/website/debian.sh
+new file mode 100755
+index 0000000..ae0ff75
+--- /dev/null
++++ b/builder/website/debian.sh
+@@ -0,0 +1,83 @@
++#!/bin/bash -
++# libguestfs
++# 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.
++
++# The basic plan comes from:
++# http://honk.sigxcpu.org/con/Preseeding_Debian_virtual_machines_with_virt_install.html
++# https://wiki.debian.org/DebianInstaller/Preseed
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 2 ]; then
++    echo "$0 VERSION DIST"
++    exit 1
++fi
++
++# Some configuration.
++version=$1
++dist=$2
++location=http://ftp.uk.debian.org/debian/dists/$dist/main/installer-amd64
++output=debian-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++rm -f $output $output.old $output.xz
++
++# Make sure it's being run from the correct directory.
++if [ ! -f debian.preseed ]; then
++    echo "You are running this script from the wrong directory."
++    exit 1
++fi
++
++# Note that the injected file must be called "/preseed.cfg" in order
++# for d-i to pick it up.
++sed -e "s, at CACHE@,$http_proxy,g" < debian.preseed > preseed.cfg
++
++# Clean up function.
++cleanup ()
++{
++    rm -f preseed.cfg
++    virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++    --name=$tmpname \
++    --ram=1024 \
++    --os-type=linux --os-variant=debian$dist \
++    --initrd-inject=$(pwd)/preseed.cfg \
++    --extra-args="auto console=tty0 console=ttyS0,115200" \
++    --disk=$(pwd)/$output,size=4 \
++    --location=$location \
++    --nographics \
++    --noreboot
++
++# Sysprep (removes logfiles and so on).
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 4e6a867..494c177 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -36,9 +36,10 @@ notes=Debian 6 (Squeeze).
+  This is a default Debian install.
+  
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-6.preseed
+- libguestfs.git/builder/website/debian-6.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/debian.preseed
++ builder/website/debian.sh
+  
+  This image is so very minimal that it only includes an ssh
+  server and no virtual consoles.  To enable virtual consoles
+@@ -66,9 +67,10 @@ notes=Debian 7 (Wheezy).
+  This is a default Debian install.
+  
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-7.preseed
+- libguestfs.git/builder/website/debian-7.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/debian.preseed
++ builder/website/debian.sh
+  
+  This image is so very minimal that it only includes an ssh
+  server and no virtual consoles.  To enable virtual consoles
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 35e103c..35f6281 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -39,9 +39,10 @@ notes=Debian 6 (Squeeze).
+  This is a default Debian install.
+  
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-6.preseed
+- libguestfs.git/builder/website/debian-6.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/debian.preseed
++ builder/website/debian.sh
+  
+  This image is so very minimal that it only includes an ssh
+  server and no virtual consoles.  To enable virtual consoles
+@@ -69,9 +70,10 @@ notes=Debian 7 (Wheezy).
+  This is a default Debian install.
+  
+  The preseed and virt-install scripts that produced this image
+- can be found in the libguestfs git tree:
+- libguestfs.git/builder/website/debian-7.preseed
+- libguestfs.git/builder/website/debian-7.sh
++ can be found in the libguestfs source tree:
++ 
++ builder/website/debian.preseed
++ builder/website/debian.sh
+  
+  This image is so very minimal that it only includes an ssh
+  server and no virtual consoles.  To enable virtual consoles
+@@ -205,17 +207,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+ 
+-iQIcBAEBAgAGBQJSePzzAAoJEJFzj3Pht2igrqQP/j/P4lsPU5HjBKNcNLNxKtHV
+-9VJkn5/pfJGp0ovVoZqVJMknTwMQV850TDkbzMteWGgJEYFf5a6g8VHjmAkCunkl
+-f1Das08tUjJcOow/pR8Dkwd2mGU4EDzwzun3BXnGgpnLcOURhLD28xp2SlLTmzfh
+-tP5EWqgEBTT6Z8h6Rtth27lKveEk14w+QzJfwTgecySN+hTQY12NUIayNKmPrBE1
+-SrbAGnw1KkpXAI7JQ1ofORsPKKSwZuHvhJY094315UwmB76EDwGzkMrRzZsYgMwN
+-fESGh0YzyDdpl68G7QSOLUsDdZLXSB/dHi9FK4f6FsoUVf3kxelkZM4EXChL1ZMm
+-NCMWhiYlmX5Z7KgPZqmKVToDXwQ0AAo0a+wNvJo4frtvDHMIGjBe/f+h4k67yOoc
+-WGXqYGQG3cRrqVLanA5dFFmX+GGL/TG2cinvi+x5kJ902KeM17uyzk1uuMAUh/Rl
+-RVSsLg9QH4sLE8wEPpaUzz2ei1Bf4P26hHtVOdK7YAueDUhfSfn9KIV/n5Fz4pRg
+-G8FlpPnL1sfzbj8qpLqXHDnJ3rXGnYkSBalNJ7WVBBNlqaewuK/bcmLp9ffVeaN9
+-CcDsWbv2UaeXXu8N9pcW2kEo1cBjKTR9NPT8ueZY0g0InNrPaz/cFMOf5K9MBfuC
+-lRwdaDejqzKc5gYRKFnH
+-=tYWz
++iQIcBAEBAgAGBQJSeP5LAAoJEJFzj3Pht2igO5QP/2jjVb8W15AWxvuATDc/kOXE
++8Dvg4hFbvvBnv/U9QQ1/2BNQDykATcVIE/lWg7VzpF2HLuEwbVdwAgEO73xKpeRT
++U6zGNxkTi0mfr3aKT4rfQtqNlMkc1IMVCQSBJEIHLd1hjh2gozBCM9KM4f5YHK2P
++i/6GX8j7AeWzVkOb60PKKQrGk1ycXm0UbZuS0MPBqnc9v56fzEyaWVvvrCQEOq7a
++zTJULgOcfCBHQLF8re2upQV5NbYwruplaCYpsTcvNHvQ/vsoUIf0dNbqvarpwFUQ
++FHDesMZQBW6OWzsIBkeMYfIJ4GXO0A0ZlVuzBW07eHbmr0ev1b4c37npHrsuytbI
++TF6SUF7wyIxZlKbyf4W+RaX1hAsMOKXU8ptsMBmBPn7UnWrLbCDAPpS27ruZOA4q
++oPGeuKLUGPnimjNEatkJH8rmWlg71hsCy1hMGAOTXAUpCgPXHv/WHa0n4GTbtJ1y
++VzUElr0wAGPOqrClJse6po1h7f6XEdB4mLZ8OYHKNDjJl57QirUcmnmYmRMsctN4
++tKYgnEcv+PhNMEV/GIQXLrtCYX/Ty81AV4hwlfzL3fjqdxX9f+Fem5PcxeMaS0ik
++xfnpMsRuprkoNyTAhDr6AX9AcY4fEW8NSfG5YUjt+s27IFLIjl7HfWCbRqcqGwv9
++VvLm+Omd+GUA6rd4fuee
++=Gv5k
+ -----END PGP SIGNATURE-----
+-- 
+1.8.3.1
+
diff --git a/0023-builder-Replace-centos-6.sh-with-a-single-script.patch b/0023-builder-Replace-centos-6.sh-with-a-single-script.patch
new file mode 100644
index 0000000..e70794c
--- /dev/null
+++ b/0023-builder-Replace-centos-6.sh-with-a-single-script.patch
@@ -0,0 +1,343 @@
+From 401de624d1bbd3a2b5bd0a7bad17f6f17c986a5d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 14:08:01 +0000
+Subject: [PATCH] builder: Replace centos-6.sh with a single script.
+
+Just use:
+
+  ./centos.sh 6
+
+Note that you don't need to be root.
+
+(cherry picked from commit 2f3fb2420e7f2ccc19fdc863ecc7b7ce29dd6aa1)
+---
+ builder/website/Makefile.am |   3 +-
+ builder/website/centos-6.ks |  40 ------------------
+ builder/website/centos-6.sh |  78 ----------------------------------
+ builder/website/centos.sh   | 101 ++++++++++++++++++++++++++++++++++++++++++++
+ builder/website/index       |   6 +--
+ builder/website/index.asc   |  32 +++++++-------
+ 6 files changed, 121 insertions(+), 139 deletions(-)
+ delete mode 100644 builder/website/centos-6.ks
+ delete mode 100755 builder/website/centos-6.sh
+ create mode 100755 builder/website/centos.sh
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index a662176..cdf263a 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -23,8 +23,7 @@ EXTRA_DIST = \
+ 	README \
+ 	index \
+ 	index.asc \
+-	centos-6.ks \
+-	centos-6.sh \
++	centos.sh \
+ 	centos-6.xz.sig \
+ 	debian.preseed \
+ 	debian.sh \
+diff --git a/builder/website/centos-6.ks b/builder/website/centos-6.ks
+deleted file mode 100644
+index 55e2e86..0000000
+--- a/builder/website/centos-6.ks
++++ /dev/null
+@@ -1,40 +0,0 @@
+-# virt-builder
+-# 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.
+-
+-install
+-text
+-reboot
+-lang en_US.UTF-8
+-keyboard us
+-network --bootproto dhcp
+-rootpw builder
+-firewall --enabled --ssh
+-selinux --enforcing
+-timezone --utc America/New_York
+-bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
+-zerombr
+-clearpart --all --initlabel
+-part /boot --fstype=ext4 --size=512         --asprimary
+-part swap                --size=1024        --asprimary
+-part /     --fstype=ext4 --size=1024 --grow --asprimary
+-
+-# Halt the system once configuration has finished.
+-poweroff
+-
+-%packages
+- at core
+-%end
+diff --git a/builder/website/centos-6.sh b/builder/website/centos-6.sh
+deleted file mode 100755
+index 611ba90..0000000
+--- a/builder/website/centos-6.sh
++++ /dev/null
+@@ -1,78 +0,0 @@
+-#!/bin/bash -
+-# virt-builder
+-# 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.
+-
+-set -e
+-set -x
+-
+-# Some configuration.
+-export http_proxy=http://cache.home.annexia.org:3128
+-export https_proxy=$http_proxy
+-export ftp_proxy=$http_proxy
+-
+-# We rebuild this every time there is a new 6.x release, and bump
+-# the revision in the index.
+-tree=http://mirror.bytemark.co.uk/centos/6.4/os/x86_64/
+-
+-# Currently you have to run this script as root.
+-if [ `id -u` -ne 0 ]; then
+-    echo "You have to run this script as root."
+-    exit 1
+-fi
+-
+-# Make sure it's being run from the correct directory.
+-if [ ! -f centos-6.ks ]; then
+-    echo "You are running this script from the wrong directory."
+-    exit 1
+-fi
+-
+-pwd=`pwd`
+-
+-virsh undefine tmpc6 ||:
+-rm -f centos-6 centos-6.old
+-
+-virt-install \
+-    --name=tmpc6 \
+-    --ram 2048 \
+-    --cpu=host --vcpus=2 \
+-    --os-type=linux --os-variant=fedora18 \
+-    --initrd-inject=$pwd/centos-6.ks \
+-    --extra-args="ks=file:/centos-6.ks console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
+-    --disk $pwd/centos-6,size=6 \
+-    --location=$tree \
+-    --nographics \
+-    --noreboot
+-# The virt-install command should exit after complete installation.
+-# Remove the guest, we don't want it to be defined in libvirt.
+-virsh undefine tmpc6
+-
+-# Sysprep (removes logfiles and so on).
+-# Note this also touches /.autorelabel so the further installation
+-# changes that we make will be labelled properly at first boot.
+-virt-sysprep -a centos-6
+-
+-# Sparsify.
+-mv centos-6 centos-6.old
+-virt-sparsify centos-6.old centos-6
+-rm centos-6.old
+-
+-# Compress.
+-rm -f centos-6.xz
+-xz --best --block-size=16777216 centos-6
+-
+-# Result:
+-ls -lh centos-6.xz
+diff --git a/builder/website/centos.sh b/builder/website/centos.sh
+new file mode 100755
+index 0000000..ce7abb6
+--- /dev/null
++++ b/builder/website/centos.sh
+@@ -0,0 +1,101 @@
++#!/bin/bash -
++# virt-builder
++# 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.
++
++unset CDPATH
++export LANG=C
++set -e
++set -x
++
++if [ $# -ne 1 ]; then
++    echo "$0 VERSION"
++    exit 1
++fi
++
++version=$1
++output=fedora-$version
++tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
++
++# We rebuild this every time there is a new 6.x release, and bump
++# the revision in the index.
++tree=http://mirror.bytemark.co.uk/centos/$version/os/x86_64/
++
++rm -f $output $output.old $output.xz
++
++# Generate the kickstart to a temporary file.
++ks=$(mktemp)
++cat > $ks <<'EOF'
++install
++text
++reboot
++lang en_US.UTF-8
++keyboard us
++network --bootproto dhcp
++rootpw builder
++firewall --enabled --ssh
++selinux --enforcing
++timezone --utc America/New_York
++bootloader --location=mbr --append="console=tty0 console=ttyS0,115200 rd_NO_PLYMOUTH"
++zerombr
++clearpart --all --initlabel
++part /boot --fstype=ext4 --size=512         --asprimary
++part swap                --size=1024        --asprimary
++part /     --fstype=ext4 --size=1024 --grow --asprimary
++
++# Halt the system once configuration has finished.
++poweroff
++
++%packages
++ at core
++%end
++EOF
++
++# Clean up function.
++cleanup ()
++{
++    rm -f $ks
++    virsh undefine $tmpname ||:
++}
++trap cleanup INT QUIT TERM EXIT ERR
++
++virt-install \
++    --name=$tmpname \
++    --ram=2048 \
++    --cpu=host --vcpus=2 \
++    --os-type=linux --os-variant=rhel$version \
++    --initrd-inject=$ks \
++    --extra-args="ks=file:/`basename $ks` console=tty0 console=ttyS0,115200 proxy=$http_proxy" \
++    --disk $(pwd)/$output,size=6 \
++    --location=$tree \
++    --nographics \
++    --noreboot
++
++# Sysprep (removes logfiles and so on).
++# Note this also touches /.autorelabel so the further installation
++# changes that we make will be labelled properly at first boot.
++virt-sysprep -a $output
++
++# Sparsify.
++mv $output $output.old
++virt-sparsify $output.old $output
++rm $output.old
++
++# Compress.
++xz --best --block-size=16777216 $output
++
++# Result:
++ls -lh $output.xz
+diff --git a/builder/website/index b/builder/website/index
+index 494c177..49b964c 100644
+--- a/builder/website/index
++++ b/builder/website/index
+@@ -14,9 +14,9 @@ notes=CentOS 6.4
+  This CentOS image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/centos-6.ks
+- libguestfs.git/builder/website/centos-6.sh
++ found in the libguestfs source tree:
++ 
++ builder/website/centos.sh
+  
+  Note that `virt-builder centos-6' will always install the latest
+  6.x release.
+diff --git a/builder/website/index.asc b/builder/website/index.asc
+index 35f6281..6711df7 100644
+--- a/builder/website/index.asc
++++ b/builder/website/index.asc
+@@ -17,9 +17,9 @@ notes=CentOS 6.4
+  This CentOS image contains only unmodified @Core group packages.
+  
+  It is thus very minimal.  The kickstart and install script can be
+- found in the libguestfs git tree:
+- libguestfs.git/builder/website/centos-6.ks
+- libguestfs.git/builder/website/centos-6.sh
++ found in the libguestfs source tree:
++ 
++ builder/website/centos.sh
+  
+  Note that `virt-builder centos-6' will always install the latest
+  6.x release.
+@@ -207,17 +207,17 @@ notes=Ubuntu 13.10 (Saucy).
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.14 (GNU/Linux)
+ 
+-iQIcBAEBAgAGBQJSeP5LAAoJEJFzj3Pht2igO5QP/2jjVb8W15AWxvuATDc/kOXE
+-8Dvg4hFbvvBnv/U9QQ1/2BNQDykATcVIE/lWg7VzpF2HLuEwbVdwAgEO73xKpeRT
+-U6zGNxkTi0mfr3aKT4rfQtqNlMkc1IMVCQSBJEIHLd1hjh2gozBCM9KM4f5YHK2P
+-i/6GX8j7AeWzVkOb60PKKQrGk1ycXm0UbZuS0MPBqnc9v56fzEyaWVvvrCQEOq7a
+-zTJULgOcfCBHQLF8re2upQV5NbYwruplaCYpsTcvNHvQ/vsoUIf0dNbqvarpwFUQ
+-FHDesMZQBW6OWzsIBkeMYfIJ4GXO0A0ZlVuzBW07eHbmr0ev1b4c37npHrsuytbI
+-TF6SUF7wyIxZlKbyf4W+RaX1hAsMOKXU8ptsMBmBPn7UnWrLbCDAPpS27ruZOA4q
+-oPGeuKLUGPnimjNEatkJH8rmWlg71hsCy1hMGAOTXAUpCgPXHv/WHa0n4GTbtJ1y
+-VzUElr0wAGPOqrClJse6po1h7f6XEdB4mLZ8OYHKNDjJl57QirUcmnmYmRMsctN4
+-tKYgnEcv+PhNMEV/GIQXLrtCYX/Ty81AV4hwlfzL3fjqdxX9f+Fem5PcxeMaS0ik
+-xfnpMsRuprkoNyTAhDr6AX9AcY4fEW8NSfG5YUjt+s27IFLIjl7HfWCbRqcqGwv9
+-VvLm+Omd+GUA6rd4fuee
+-=Gv5k
++iQIcBAEBAgAGBQJSeP+vAAoJEJFzj3Pht2igQIEQALPlH98SZFjg0JAWWMQyLlfb
++A9CF8z2Y/3E8D1+kAqNIJZwXuaJ2f4KnTh1gU1VYHj97hEI6+GolrfISGF+NZOdG
++cI39bQYPWXPbO78Ftv/Ox92JjzbK6XFgErRhbL9ldqmQJ6e51Kpqc5ItULx6rmHD
++uBrOCiUAP49GjxA/LZWzEVHYNidQz/c3kpMFOVIyavWffVzpeFM8+R7zyYWOxP9K
++HZvNM/8TIRCsIyvKETTxMvq+fqGLZBck0e6jT9GugQ5cH0QrdQQIYZd6K3PkvMH6
++Lao9KFfQcdWa7RNa3JNOKIf8Y19VyhAzybLunbjEBJqeq1Sn/3DNtAto3IV7JuOD
++1ySBFDh4I5xEGLBfwhbNOmgV9ccDaffCIju+vz9P9War04cnAFXP9WrUlzvDz5Jl
++zp8CoasP8TdZE9A1zc57UPsdB946/yU6c5zmVOj1uyNxlW3ED/ZD98c45OKuYlpb
++gXhP6am/6QGJFO7mAGihltjAqUayhTsE3s3O26pxQ5AiysuzppjvoNDc8XAlHkWd
++NbLiS4mXY7BbRvdmIg2g9Q7ohnOqQ13L/7CDgu622BPqj1vfrw2KjNJ+w6DzfXN7
++bDevIRlB/hqHaeRAQobUm4ecnVwtIOjDLIjKtHQWkNFiNpaIVIRHgE35F0GVij/R
++wCAfC7j5yJwXxDx8jMZf
++=EoPi
+ -----END PGP SIGNATURE-----
+-- 
+1.8.3.1
+
diff --git a/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch b/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
new file mode 100644
index 0000000..5f0404c
--- /dev/null
+++ b/0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
@@ -0,0 +1,27 @@
+From 6f548264f40339e829c3bb2023f3352b4e69b490 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:15:17 +0000
+Subject: [PATCH] builder/website: Add validate.sh test script to EXTRA_DIST.
+
+This fixes commit 154bfb7dd46e7998eed1d40ead95923590763739.
+
+(cherry picked from commit 92206e8d09455b3ec63d44e4b55d5eef415681af)
+---
+ builder/website/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/builder/website/Makefile.am b/builder/website/Makefile.am
+index cdf263a..ec1ca65 100644
+--- a/builder/website/Makefile.am
++++ b/builder/website/Makefile.am
+@@ -20,6 +20,7 @@ include $(top_srcdir)/subdir-rules.mk
+ EXTRA_DIST = \
+ 	.gitignore \
+ 	test-guest.sh \
++	validate.sh \
+ 	README \
+ 	index \
+ 	index.asc \
+-- 
+1.8.3.1
+
diff --git a/0025-builder-Add-missing-dependency.patch b/0025-builder-Add-missing-dependency.patch
new file mode 100644
index 0000000..edd4420
--- /dev/null
+++ b/0025-builder-Add-missing-dependency.patch
@@ -0,0 +1,33 @@
+From 7ae728b1a5db0290ca2ed488ae3e67c968d2f477 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:42:05 +0000
+Subject: [PATCH] builder: Add missing dependency.
+
+index-parser-c.c depends on index-parse.h being created first.
+However without an explicit dependency, this is not done (and implicit
+deps don't work because automake doesn't sufficiently understand OCaml
+programs).
+
+This fixes commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit dfe97b352d6b398c3cb3ddb1c9984767722e514b)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 2027203..a44f820 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -120,6 +120,8 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ 	$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+ 
++index-parser-c.o: index-parse.h
++
+ # Manual pages and HTML files for the website.
+ 
+ man_MANS += virt-builder.1
+-- 
+1.8.3.1
+
diff --git a/0026-builder-Add-some-generated-files-to-CLEANFILES.patch b/0026-builder-Add-some-generated-files-to-CLEANFILES.patch
new file mode 100644
index 0000000..956efff
--- /dev/null
+++ b/0026-builder-Add-some-generated-files-to-CLEANFILES.patch
@@ -0,0 +1,29 @@
+From 88ffe2a4e415e7502f6749938a621899d2de0251 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:43:24 +0000
+Subject: [PATCH] builder: Add some generated files to CLEANFILES.
+
+This updates commit a4800e2d4fc50f372a8b626333c4fbb9b8ca9633.
+
+(cherry picked from commit 01551e546293bbbd094d4d4acfdaf421f7758251)
+---
+ builder/Makefile.am | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index a44f820..44384d9 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -205,4 +205,8 @@ stamp-virt-index-validate.pod: virt-index-validate.pod
+ 	  $<
+ 	touch $@
+ 
+-CLEANFILES += stamp-virt-index-validate.pod
++CLEANFILES += \
++	index-parse.c \
++	index-parse.h \
++	index-scan.c \
++	stamp-virt-index-validate.pod
+-- 
+1.8.3.1
+
diff --git a/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch b/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
new file mode 100644
index 0000000..5da91eb
--- /dev/null
+++ b/0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
@@ -0,0 +1,30 @@
+From 5ab8da71343c6f8c0dd16111480893730db2cc84 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 15:56:34 +0000
+Subject: [PATCH] builder: Add dependency from index-parse.h to index-validate.
+
+For some reason automake doesn't get this dependency right,
+resulting in occasional build failures if yacc races the
+rest of the build.
+
+(cherry picked from commit e3ac293e869a4c69225e3d954b812e9bf21588a1)
+---
+ builder/Makefile.am | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 44384d9..593e3ef 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -192,6 +192,8 @@ virt_index_validate_SOURCES = \
+ 	index-struct.c \
+ 	index-validate.c
+ 
++index-validate.o: index-parse.h
++
+ man_MANS += virt-index-validate.1
+ noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
+ 
+-- 
+1.8.3.1
+
diff --git a/0028-builder-Fix-centos-script-output-filename-was-wrong.patch b/0028-builder-Fix-centos-script-output-filename-was-wrong.patch
new file mode 100644
index 0000000..c406961
--- /dev/null
+++ b/0028-builder-Fix-centos-script-output-filename-was-wrong.patch
@@ -0,0 +1,28 @@
+From 1f8d51695861b76edc23aca82f39ef816a20061d Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 16:51:08 +0000
+Subject: [PATCH] builder: Fix centos script - output filename was wrong.
+
+This fixes commit 2f3fb2420e7f2ccc19fdc863ecc7b7ce29dd6aa1.
+
+(cherry picked from commit 663012c5ffecc6f89ad164d292fc0f970338f824)
+---
+ builder/website/centos.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/builder/website/centos.sh b/builder/website/centos.sh
+index ce7abb6..d9f2645 100755
+--- a/builder/website/centos.sh
++++ b/builder/website/centos.sh
+@@ -27,7 +27,7 @@ if [ $# -ne 1 ]; then
+ fi
+ 
+ version=$1
+-output=fedora-$version
++output=centos-$version
+ tmpname=tmp-$(tr -cd 'a-f0-9' < /dev/urandom | head -c 8)
+ 
+ # We rebuild this every time there is a new 6.x release, and bump
+-- 
+1.8.3.1
+
diff --git a/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch b/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
new file mode 100644
index 0000000..64e64a9
--- /dev/null
+++ b/0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
@@ -0,0 +1,51 @@
+From 90b8f20a41798ba4a38e7681783a5a14a13ef541 Mon Sep 17 00:00:00 2001
+From: "Richard W.M. Jones" <rjones at redhat.com>
+Date: Tue, 5 Nov 2013 17:40:20 +0000
+Subject: [PATCH] builder: Add dependencies which automake doesn't generate
+ correctly.
+
+This is a further attempt, earlier commits:
+commit e3ac293e869a4c69225e3d954b812e9bf21588a1
+commit dfe97b352d6b398c3cb3ddb1c9984767722e514b
+
+(cherry picked from commit 4339b55d105eab6eba2756bffff42a1c34f9f656)
+---
+ builder/Makefile.am | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/builder/Makefile.am b/builder/Makefile.am
+index 593e3ef..a828ffd 100644
+--- a/builder/Makefile.am
++++ b/builder/Makefile.am
+@@ -120,8 +120,6 @@ virt-builder: $(OBJECTS)
+ .ml.cmx:
+ 	$(OCAMLFIND) ocamlopt $(OCAMLOPTFLAGS) -c $< -o $@
+ 
+-index-parser-c.o: index-parse.h
+-
+ # Manual pages and HTML files for the website.
+ 
+ man_MANS += virt-builder.1
+@@ -192,8 +190,6 @@ virt_index_validate_SOURCES = \
+ 	index-struct.c \
+ 	index-validate.c
+ 
+-index-validate.o: index-parse.h
+-
+ man_MANS += virt-index-validate.1
+ noinst_DATA += $(top_builddir)/html/virt-index-validate.1.html
+ 
+@@ -212,3 +208,10 @@ CLEANFILES += \
+ 	index-parse.h \
+ 	index-scan.c \
+ 	stamp-virt-index-validate.pod
++
++# Fix dependencies which automake doesn't generate correctly.
++if HAVE_OCAML
++index-parser-c.o: index-parse.h
++index-scan.o: index-parse.h
++endif
++index-validate.o: index-parse.h
+-- 
+1.8.3.1
+
diff --git a/copy-patches.sh b/copy-patches.sh
new file mode 100755
index 0000000..e242cd2
--- /dev/null
+++ b/copy-patches.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -
+
+set -e
+
+# Maintainer script to copy patches from the git repo to the current
+# directory.  Use it like this:
+#   ./copy-patches.sh
+
+# Check we're in the right directory.
+if [ ! -f libguestfs.spec ]; then
+    echo "$0: run this from the directory containing 'libguestfs.spec'"
+    exit 1
+fi
+
+git_checkout=$HOME/d/libguestfs-fedora-20
+if [ ! -d $git_checkout ]; then
+    echo "$0: $git_checkout does not exist"
+    echo "This script is only for use by the maintainer when preparing a"
+    echo "libguestfs release for Fedora 20."
+    exit 1
+fi
+
+# Get the base version of libguestfs.
+version=`grep '^Version:' libguestfs.spec | awk '{print $2}'`
+
+# Remove any existing patches.
+git rm -f [0-9]*.patch ||:
+rm -f [0-9]*.patch
+
+# Get the patches.
+(cd $git_checkout; rm -f [0-9]*.patch; git format-patch -N $version)
+mv $git_checkout/[0-9]*.patch .
+
+# Remove any not to be applied.
+rm -f *NOT-FOR-RPM*.patch
+
+# Add the patches.
+git add [0-9]*.patch
+
+# Print out the patch lines.
+echo
+echo "--- Copy the following text into libguestfs.spec file"
+echo
+
+echo "# Git-managed patches."
+for f in [0-9]*.patch; do
+    n=`echo $f | awk -F- '{print $1}'`
+    echo "Patch$n:     $f"
+done
+
+echo "# Add any non-git patches here."
+echo
+echo "--- End of text"
diff --git a/libguestfs.spec b/libguestfs.spec
index f446e06..65c3334 100644
--- a/libguestfs.spec
+++ b/libguestfs.spec
@@ -12,13 +12,56 @@ Summary:       Access and modify virtual machine disk images
 Name:          libguestfs
 Epoch:         1
 Version:       1.24.1
-Release:       1%{?dist}
+Release:       2%{?dist}
 License:       LGPLv2+
 
 # Source and patches.
 URL:           http://libguestfs.org/
 Source0:       http://libguestfs.org/download/1.23-development/%{name}-%{version}.tar.gz
 
+# Note we use the fedora-20 branch from the upstream repo which
+# contains only upstream, backported patches, but conveniently manages
+# them in git.  In order to update this list, run the
+# 'copy-patches.sh' script.
+
+# Git-managed patches.
+Patch0001:     0001-builder-Don-t-run-virt-resize-when-not-necessary.patch
+Patch0002:     0002-builder-Make-xzcat-binary-configurable-and-use-AC_PA.patch
+Patch0003:     0003-builder-Use-pxzcat-optionally-to-speed-up-xzcat-step.patch
+Patch0004:     0004-builder-Add-no-sync-option-to-avoid-sync-on-exit.patch
+Patch0005:     0005-builder-Add-mkdir-option-to-create-directories.patch
+Patch0006:     0006-builder-Allow-upload-to-a-directory.patch
+Patch0007:     0007-builder-Add-write-option-to-write-a-literal-file.patch
+Patch0008:     0008-builder-Document-how-to-boot-VMs-directly-in-qemu-or.patch
+Patch0009:     0009-firstboot-Send-the-output-to-the-console-as-well-as-.patch
+Patch0010:     0010-builder-Add-a-section-on-performance-to-the-manual.patch
+Patch0011:     0011-builder-Add-m-memsize-and-smp-command-line-options.patch
+Patch0012:     0012-builder-Allow-multiple-source-paths-to-be-specified.patch
+Patch0013:     0013-builder-Don-t-use-git-tree-libguestfs.git-to-refer-t.patch
+Patch0014:     0014-builder-Add-a-real-scanner-parser-for-index-files.patch
+Patch0015:     0015-builder-Fix-check-valgrind-so-it-does-something-in-t.patch
+Patch0016:     0016-builder-Fix-missing-files-in-EXTRA_DIST.patch
+Patch0017:     0017-builder-Add-an-extra-Makefile.am-to-builder-website.patch
+Patch0018:     0018-builder-website-Add-index-validation-test-script.patch
+Patch0019:     0019-builder-Internal-implementation-of-parallel-xzcat-px.patch
+Patch0020:     0020-builder-Replace-fedora-NN-shell-kickstart-with-a-sin.patch
+Patch0021:     0021-builder-Replace-ubuntu-NN-.sh-with-a-single-script.patch
+Patch0022:     0022-builder-Replace-debian-NN-.sh-with-a-single-script.patch
+Patch0023:     0023-builder-Replace-centos-6.sh-with-a-single-script.patch
+Patch0024:     0024-builder-website-Add-validate.sh-test-script-to-EXTRA.patch
+Patch0025:     0025-builder-Add-missing-dependency.patch
+Patch0026:     0026-builder-Add-some-generated-files-to-CLEANFILES.patch
+Patch0027:     0027-builder-Add-dependency-from-index-parse.h-to-index-v.patch
+Patch0028:     0028-builder-Fix-centos-script-output-filename-was-wrong.patch
+Patch0029:     0029-builder-Add-dependencies-which-automake-doesn-t-gene.patch
+# Add any non-git patches here.
+
+# Use git for patch management.
+BuildRequires: git
+
+# Run autotools after applying the patches.
+BuildRequires: autoconf, automake, libtool, gettext-devel
+
 # Basic build requirements:
 BuildRequires: perl(Pod::Simple)
 BuildRequires: perl(Pod::Man)
@@ -147,6 +190,8 @@ Source3:       99-guestfsd.rules
 # Replacement README file for Fedora users.
 Source4:       README-replacement.in
 
+Source5:       copy-patches.sh
+
 # https://fedoraproject.org/wiki/Packaging:No_Bundled_Libraries#Packages_granted_exceptions
 Provides:      bundled(gnulib)
 
@@ -573,6 +618,19 @@ for %{name}.
 %prep
 %setup -q
 
+# Use git to manage patches.
+# http://rwmj.wordpress.com/2011/08/09/nice-rpm-git-patch-management-trick/
+git init
+git config user.email "libguestfs at redhat.com"
+git config user.name "libguestfs"
+git add .
+git commit -a -q -m "%{version} baseline"
+git am %{patches}
+
+# Patches affect Makefile.am and configure.ac, so rerun autotools.
+autoreconf -i
+autoconf
+
 if [ "$(getenforce | tr '[A-Z]' '[a-z]')" != "disabled" ]; then
     # For sVirt to work, the local temporary directory we use in the
     # tests must be labelled the same way as /tmp.
@@ -630,6 +688,9 @@ fi
   --enable-install-daemon \
   $extra
 
+# Patches above add man pages, so this is needed.
+make -C po-docs update-po
+
 # 'INSTALLDIRS' ensures that Perl and Ruby libs are installed in the
 # vendor dir not the site dir.
 make V=1 INSTALLDIRS=vendor %{?_smp_mflags}
@@ -980,6 +1041,10 @@ mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/libguestfs
 
 
 %changelog
+* Tue Nov 05 2013 Richard W.M. Jones <rjones at redhat.com> - 1:1.24.1-2
+- Backport virt-builder features from upstream at users [multiple] requests.
+- Use git to manage patches, add copy-patches.sh script.
+
 * Fri Nov 01 2013 Richard W.M. Jones <rjones at redhat.com> - 1:1.24.1-1
 - New upstream version 1.24.1.
 


More information about the scm-commits mailing list