On Wed, Nov 30, 2016 at 01:54:43PM +0100, Pino Toscano wrote:
On Monday, 28 November 2016 10:40:51 CET Richard W.M. Jones wrote:
> Create a new directory (builder/template). Integrate all of the
> scripts into a single program, so that templates are generated more
> consistently.
>
> This also changes how the index file is generated. The script now
> generates the index file fragment and saves it under version control,
> and then generates the final index file by concatenating these.
> (Previously the index was written by hand which was tedious and
> error-prone.)
>
> The new script also saves the generated kickstart under version
> control so it can be referenced later.
> ---
Note that the fragments for Ubuntu guests don't seem to match what the
new make-template.ml produces -- in particular, the ones in this patch
have osinfo=ubuntu$codename instead of osinfo=ubuntu$version as the
script should produce. Ah I see, the current index is wrong already...
This is generally true for most of the guests. However I didn't
want to change the existing fragments.
Also, this patch includes changes in the website index but not in
the
index.asc -- I'd just leave them unchanged in this patch (simple git
move), and then regenerate them in a followup commit.
The index.asc has to be signed so you wouldn't want to generate
it automatically.
> diff --git a/builder/website/Makefile.am
b/builder/templates/Makefile.am
> similarity index 66%
> rename from builder/website/Makefile.am
> rename to builder/templates/Makefile.am
> index d79b9a0..d1b89f9 100644
> --- a/builder/website/Makefile.am
> +++ b/builder/templates/Makefile.am
> @@ -1,5 +1,5 @@
> # libguestfs virt-builder tool
> -# Copyright (C) 2013 Red Hat Inc.
> +# Copyright (C) 2013-2016 Red Hat Inc.
> #
> # This program is free software; you can redistribute it and/or modify
> # it under the terms of the GNU General Public License as published by
> @@ -17,33 +17,25 @@
>
> include $(top_srcdir)/subdir-rules.mk
>
> +index_fragments = $(wildcard *.index-fragment)
> +
> EXTRA_DIST = \
> - .gitignore \
> - compress.sh \
> - test-guest.sh \
> - validate.sh \
> - README \
> - index \
> - index.asc \
> - centos.sh \
> - centos-aarch64.sh \
> + $(index_fragments) \
> + *.ks \
Considering $(wildcard) above is already a GNU extension, I'd use it
for *.ks as well.
> debian.preseed \
> - debian.sh \
> - fedora.sh \
> - fedora-aarch64.sh \
> - fedora-armv7l.sh \
> - fedora-i686.sh \
> - fedora-ppc64.sh \
> - fedora-ppc64le.sh \
> - fedora-s390x.sh \
> - rhel.sh \
> - rhel-aarch64.sh \
> - rhel-ppc64.sh \
> - rhel-ppc64le.sh \
> - scientificlinux.sh \
> + make-template.ml \
> ubuntu.preseed \
> - ubuntu.sh \
> - ubuntu-ppc64le.sh
> + validate.sh
> +
> +# Create the index file under the top level website/ directory.
> +noinst_DATA = $(top_builddir)/website/download/builder/index
> +
> +$(top_builddir)/website/download/builder/index: $(index_fragments)
> + rm -f $@ $@-t
> + cat *.index-fragment > $@-t
Should $^ be used instead of *index-fragment? Also, the order of the
files could be made stable with sorting, so the index does not change
just because of different results of the wildcard expansion.
I used *.index-fragment so that the order is stable. It turns out
that $(wildcard ..) doesn't sort.
> + (* Set the path to use locally built copies of the virt-*
tools. *)
> + let () =
> + let orig_path = Unix.getenv "PATH" in
> + let paths = ["builder"; "customize"; "sparsify";
"sysprep"] in
> + let prefix = Sys.getcwd () // ".." // ".." in
> + let paths = List.map ((//) prefix) paths in
> + let new_path = String.concat ":" (paths @ [orig_path]) in
> + Unix.putenv "PATH" new_path in
Wouldn't be better just rely on the libguestfs tools in $PATH, i.e.
using ./run for uninstalled versions? Just use a check similar to the
one below (inspired from virt-builder):
(* Check that we have libguestfs tools. *)
let cmd = "virt-sparsify --help >/dev/null 2>&1" in
if shell_command cmd <> 0 then (
eprintf "%s: libguestfs tools not available (use ./run for uninstalled
versions)\n" prog;
exit 1
);
Could do this. The problem is that I wanted to unconditionally use
the just-built tools, to avoid the case where (eg) I make a fix to
virt-sparsify, rebuild a template, but the template isn't sparsified
correctly because it used the wrong version of virt-sparsify.
> +and os_of_string os ver =
> + match os, ver with
> + | "centos", ver -> let maj, min = parse_major_minor ver in CentOS
(maj, min)
> + | "rhel", ver -> let maj, min = parse_major_minor ver in RHEL (maj,
min)
> + | "debian", "6" -> Debian (6, "squeeze")
> + | "debian", "7" -> Debian (7, "wheezy")
> + | "debian", "8" -> Debian (8, "jessie")
> + | "ubuntu", "10.04" -> Ubuntu (ver, "lucid")
> + | "ubuntu", "12.04" -> Ubuntu (ver, "precise")
> + | "ubuntu", "14.04" -> Ubuntu (ver, "trusty")
> + | "ubuntu", "16.04" -> Ubuntu (ver, "xenial")
> + | "fedora", ver -> Fedora (int_of_string ver)
> + | _ ->
> + eprintf "%s: unknown or unsupported OS\n" prog; exit 1
Can the error message also print the distro name and version?
Sure (and others too).
> +and make_kickstart_common ks_filename os arch =
> + let buf = Buffer.create 4096 in
> + let bpf fs = bprintf buf fs in
> +
> + bpf "\
> +# Kickstart file for %s
> +# Generated by libguestfs.git/builder/templates/make-template.ml
> +
> +install
> +text
> +reboot
> +lang en_US.UTF-8
> +keyboard us
> +network --bootproto dhcp
> +rootpw builder
> +firewall --enabled --ssh
> +timezone --utc America/New_York
> +" (string_of_os os arch);
> +
> + (match os with
> + | RHEL (3, _) ->
> + bpf "\
> +langsupport en_US
> +mouse generic
> +";
> + | _ -> ()
> + );
rhel.sh has:
if [ $major -le 4 ]; then
so I think the check should rather be:
| RHEL (ver, _) when ver <= 4 ->
OK
> +
> + (match os with
> + | RHEL (3, _) -> ()
> + | _ -> bpf "selinux --enforcing\n"
> + );
rhel.sh has:
if [ $major -ge 4 ]; then
so I think the check should rather be:
| RHEL (ver, _) when ver >= 4 ->
(OK, the current code does the same considering only RHEL >= 3 is
supported, but could be better to convert it straight from the script.)
OK
> +
> + (match os with
> + | RHEL (5, _) -> bpf "key --skip\n"
> + | _ -> ()
> + );
> + bpf "\n";
> +
> + bpf "bootloader --location=mbr --append=\"%s\"\n"
> + (kernel_cmdline_of_os os arch);
> + bpf "\n";
> +
> + (match os with
> + | CentOS _ ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +part /boot --fstype=ext4 --size=512 --asprimary
> +part swap --size=1024 --asprimary
> +part / --fstype=ext4 --size=1024 --grow --asprimary
> +";
> + | RHEL ((3|4), _) ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +part /boot --fstype=ext2 --size=512 --asprimary
> +part swap --size=1024 --asprimary
> +part / --fstype=ext3 --size=1024 --grow --asprimary
> +";
> + | RHEL (5, _) ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +part /boot --fstype=ext2 --size=512 --asprimary
> +part swap --size=1024 --asprimary
> +part / --fstype=ext4 --size=1024 --grow --asprimary
> +";
> + | RHEL (6, _) ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +part /boot --fstype=ext4 --size=512 --asprimary
> +part swap --size=1024 --asprimary
> +part / --fstype=ext4 --size=1024 --grow --asprimary
> +";
> + | RHEL (7, _) ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +part /boot --fstype=ext4 --size=512 --asprimary
> +part swap --size=1024 --asprimary
> +part / --fstype=xfs --size=1024 --grow --asprimary
> +";
IMHO the RHEL cases could be merged together, leaving the bootfs and
rootfs selection by version.
I had to change this in a later version because it turns out the above
doesn't work properly for RHEL 7.
> + | _ ->
> + bpf "\
> +zerombr
> +clearpart --all --initlabel
> +autopart --type=plain
> +";
> + );
> + bpf "\n";
> +
> + (match os with
> + | RHEL (3, _) -> ()
> + | _ ->
> + bpf "\
> +# Halt the system once configuration has finished.
> +poweroff
> +";
> + );
rhel.sh has:
if [ $major -ge 4 ]; then
so I think the check should rather be:
| RHEL (ver, _) when ver >= 4 ->
(Same note above.)
OK
> + bpf "\n";
> +
> + bpf "\
> +%%packages
> +@core
> +";
> +
> + (match os with
> + | RHEL ((3|4|5), _) -> ()
> + | _ ->
> + bpf "%%end\n"
> + );
rhel.sh has:
if [ $major -ge 6 ]; then
so I think the check should rather be:
| RHEL (ver, _) when ver >= 6 ->
(Same note above.)
OK
> +and copy_preseed_to_temporary source =
> + (* d-i only works if the file is literally called "/preseed.cfg" *)
> + let d = "/tmp" // random8 () ^ ".tmp" in
Filename.temp_dir_name instead of /tmp here.
Yup.
> +and make_location os arch =
> + match os, arch with
> + | CentOS (major, _), Aarch64 ->
> + (* XXX This always points to the latest CentOS, so
> + * effectively the minor number is always ignored.
> + *)
> + sprintf "http://mirror.centos.org/altarch/%d/os/aarch64/" major
> +
> + | CentOS (major, _), X86_64 ->
> + (* For 6.x we rebuild this every time there is a new 6.x release, and bump
> + * the revision in the index.
> + * For 7.x this always points to the latest CentOS, so
> + * effectively the minor number is always ignored.
> + *)
> + sprintf "http://mirror.centos.org/centos-7/%d/os/x86_64/" major
> +
> + | Debian (_, dist), X86_64 ->
> + sprintf
"http://ftp.uk.debian.org/debian/dists/%s/main/installer-amd64"
> + dist
While we are here, should we use either httpredir.debian.org (but IIRC
it's deprecated), or
deb.debian.org (works best with current testing,
but should still work also with current stable and older).
> + | _ ->
> + eprintf "%s: don't know how to calculate the --location for this OS
and architecture\n" prog;
> + exit 1
Ditto as above (i.e. print details of unknown distro/version).
OK.
> +and make_index_fragment os arch index_fragment output nvram
revision expandfs =
> + let chan = open_out (index_fragment ^ ".new") in
> + let fpf fs = fprintf chan fs in
> +
> + fpf "[%s]\n" (string_of_os_noarch os);
> + fpf "name=%s\n" (long_name_of_os os arch);
> + fpf "osinfo=%s\n" (true_os_variant_of_os os);
> + fpf "arch=%s\n" (string_of_arch arch);
> + fpf "file=%s\n" output;
> + (match revision with
> + | None -> ()
> + | Some i -> fpf "revision=%d\n" i
> + );
> + fpf "checksum[sha512]=%s\n" (sha512sum_of_file output);
> + fpf "format=raw\n";
> + fpf "size=%d\n" (virtual_size_gb * 1024 * 1024 * 1024);
Shouldn't this be Int64?
We actually assert that the word size is 64 bits (in main ()), but
using Int64 would be less lazy.
> +and open_guest filename =
> + let g = new Guestfs.guestfs () in
> + g#add_drive_opts ~format:"raw" filename;
> + g#launch ();
> +
> + let roots = g#inspect_os () in
> + if Array.length roots = 0 then (
> + eprintf "%s: cannot inspect this guest\n" prog;
> + exit 1
> + );
> + let root = roots.(0) in
> +
> + let mps = g#inspect_get_mountpoints root in
> + let cmp (a,_) (b,_) = compare (String.length a) (String.length b) in
> + let mps = List.sort cmp mps in
> + List.iter (
> + fun (mp, dev) ->
> + try g#mount_ro dev mp
> + with Guestfs.Error msg -> eprintf "%s (ignored)\n" msg
Should mount errors be ignored in this case?
No they shouldn't be ignored.
Thanks,
Rich.
--
Richard Jones, Virtualization Group, Red Hat
http://people.redhat.com/~rjones
Read my programming and virtualization blog:
http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html