Hi, this is a prototype of something I've around for some time. Basically it is about adding new appliances in addition to the main one currently used and kept up-to-date automatically: this way it is possible to create new appliances with extra packages, to be used in specific contexts (like virt-rescue, with more network/recovery tools) without filling the main appliance. It's still WIP (the most notable lack is a proper base.tar.gz with config files of flavour packages), but I'd like to get some feedback about it. Pino Toscano (3): New API: appliance flavours appliance: add a "rescue" appliance for virt-rescue appliance: move openssh to the "rescue" appliance appliance/Makefile.am | 21 ++++++++++++++++++++- appliance/packagelist-rescue.in | 32 ++++++++++++++++++++++++++++++++ appliance/packagelist.in | 4 ---- generator/actions.ml | 28 ++++++++++++++++++++++++++++ rescue/rescue.c | 4 ++++ src/appliance.c | 22 +++++++++++++++++----- src/guestfs-internal.h | 1 + src/guestfs.pod | 18 ++++++++++++++++++ src/handle.c | 24 ++++++++++++++++++++++++ 9 files changed, 144 insertions(+), 10 deletions(-) create mode 100644 appliance/packagelist-rescue.in -- 1.9.3
This introduces the concept of "appliance flavour", i.e. a different appliance whose configuration is based on the main appliance, with additional packages. The default appliance (and its configuration) is unchanged. --- generator/actions.ml | 28 ++++++++++++++++++++++++++++ src/appliance.c | 22 +++++++++++++++++----- src/guestfs-internal.h | 1 + src/guestfs.pod | 18 ++++++++++++++++++ src/handle.c | 24 ++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 5 deletions(-) diff --git a/generator/actions.ml b/generator/actions.ml index eec3b94..e2c7303 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -3279,6 +3279,34 @@ refers to. This is the same as the C<lstat(2)> system call." }; + { defaults with + name = "set_flavour"; + style = RErr, [String "flavour"], []; + fish_alias = ["flavour"]; config_only = true; + blocking = false; + shortdesc = "set the appliance flavour"; + longdesc = "\ +Sets a different flavour for the libguestfs appliance. + +A flavour is a different appliance than the main one, usually +with more packages to provide more features. + +See L<guestfs(3)/APPLIANCE FLAVOUR>." }; + + { defaults with + name = "get_flavour"; + style = RString "flavour", [], []; + blocking = false; + tests = [ + InitNone, Always, TestRun ( + [["get_flavour"]]), [] + ]; + shortdesc = "get the appliance flavour"; + longdesc = "\ +Returns the current flavour for the libguestfs appliance. + +See L<guestfs(3)/APPLIANCE FLAVOUR>." }; + ] (* daemon_functions are any functions which cause some action diff --git a/src/appliance.c b/src/appliance.c index d7aa6b1..956cd88 100644 --- a/src/appliance.c +++ b/src/appliance.c @@ -52,7 +52,7 @@ static int contains_old_style_appliance (guestfs_h *g, const char *path, void *d static int contains_fixed_appliance (guestfs_h *g, const char *path, void *data); static int contains_supermin_appliance (guestfs_h *g, const char *path, void *data); static int build_supermin_appliance (guestfs_h *g, const char *supermin_path, uid_t uid, char **kernel, char **dtb, char **initrd, char **appliance); -static int run_supermin_build (guestfs_h *g, const char *lockfile, const char *appliancedir, const char *supermin_path); +static int run_supermin_build (guestfs_h *g, const char *flavour, const char *lockfile, const char *appliancedir, const char *supermin_path); /* Locate or build the appliance. * @@ -221,19 +221,27 @@ build_supermin_appliance (guestfs_h *g, char **initrd, char **appliance) { CLEANUP_FREE char *tmpdir = guestfs_get_cachedir (g); + CLEANUP_FREE char *flavour = guestfs_get_flavour (g); struct stat statbuf; size_t len; + size_t flavourlen; /* len must be longer than the length of any pathname we can * generate in this function. */ - len = strlen (tmpdir) + 128; + flavourlen = strlen (flavour); + char flavoursuffix[1 + flavourlen + 1]; + if (flavourlen > 0) + snprintf (flavoursuffix, sizeof flavoursuffix, "-%s", flavour); + else + flavoursuffix[0] = '\0'; + len = strlen (tmpdir) + 128 + sizeof flavoursuffix; char cachedir[len]; snprintf (cachedir, len, "%s/.guestfs-%d", tmpdir, uid); char lockfile[len]; - snprintf (lockfile, len, "%s/lock", cachedir); + snprintf (lockfile, len, "%s/lock%s", cachedir, flavoursuffix); char appliancedir[len]; - snprintf (appliancedir, len, "%s/appliance.d", cachedir); + snprintf (appliancedir, len, "%s/appliance%s.d", cachedir, flavoursuffix); ignore_value (mkdir (cachedir, 0755)); ignore_value (chmod (cachedir, 0755)); /* RHBZ#921292 */ @@ -267,7 +275,8 @@ build_supermin_appliance (guestfs_h *g, if (g->verbose) guestfs___print_timestamped_message (g, "run supermin"); - if (run_supermin_build (g, lockfile, appliancedir, supermin_path) == -1) + if (run_supermin_build (g, flavour, lockfile, appliancedir, + supermin_path) == -1) return -1; if (g->verbose) @@ -319,6 +328,7 @@ build_supermin_appliance (guestfs_h *g, */ static int run_supermin_build (guestfs_h *g, + const char *flavour, const char *lockfile, const char *appliancedir, const char *supermin_path) @@ -358,6 +368,8 @@ run_supermin_build (guestfs_h *g, guestfs___cmd_add_arg (cmd, DTB_WILDCARD); #endif guestfs___cmd_add_arg_format (cmd, "%s/supermin.d", supermin_path); + if (strlen (flavour) > 0) + guestfs___cmd_add_arg_format (cmd, "%s/supermin-%s.d", supermin_path, flavour); guestfs___cmd_add_arg (cmd, "-o"); guestfs___cmd_add_arg (cmd, appliancedir); diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index fd0c4a1..9dd62b9 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -376,6 +376,7 @@ struct guestfs_h char *path; /* Path to the appliance. */ char *hv; /* Hypervisor (HV) binary. */ char *append; /* Append to kernel command line. */ + char *flavour; /* Appliance flavour. */ struct hv_param *hv_params; /* Extra hv parameters. */ diff --git a/src/guestfs.pod b/src/guestfs.pod index e4f9b54..363abd2 100644 --- a/src/guestfs.pod +++ b/src/guestfs.pod @@ -1655,6 +1655,18 @@ Linux kernel, then we might remove it from libguestfs too. =back +=head2 APPLIANCE FLAVOUR + +A flavour is a different appliance for libguestfs, created from the +main appliance with additional configuration files for extra packages +in it. A typical usage for them is to provide appliances with more +packages than the main one, so they can provide more functionalities +without filling the main appliance. + +By default there is no flavour set, which means the main appliance +is used. A different flavour can be set with L</guestfs_set_flavour>, +or setting using the C<LIBGUESTFS_FLAVOUR> environment variable. + =head2 ABI GUARANTEE We guarantee the libguestfs ABI (binary interface), for public, @@ -4682,6 +4694,12 @@ See also L</LIBGUESTFS_TMPDIR>, L</guestfs_set_cachedir>. Set C<LIBGUESTFS_DEBUG=1> to enable verbose messages. This has the same effect as calling C<guestfs_set_verbose (g, 1)>. +=item LIBGUESTFS_FLAVOUR + +Set the appliance flavour used as libguestfs appliance. + +See also L</APPLIANCE FLAVOUR> above. + =item LIBGUESTFS_HV Set the default hypervisor (usually qemu) binary that libguestfs uses. diff --git a/src/handle.c b/src/handle.c index 0200528..6c4c33e 100644 --- a/src/handle.c +++ b/src/handle.c @@ -262,6 +262,12 @@ parse_environment (guestfs_h *g, return -1; } + str = do_getenv (data, "LIBGUESTFS_FLAVOUR"); + if (str) { + if (guestfs_set_flavour (g, str) == -1) + return -1; + } + return 0; } @@ -866,3 +872,21 @@ guestfs__get_smp (guestfs_h *g) { return g->smp; } + +int +guestfs__set_flavour (guestfs_h *g, const char *flavour) +{ + free (g->flavour); + if (flavour && flavour[0] != '\0') + g->flavour = safe_strdup (g, flavour); + else + g->flavour = NULL; + + return 0; +} + +char * +guestfs__get_flavour (guestfs_h *g) +{ + return safe_strdup (g, g->flavour ? g->flavour : ""); +} -- 1.9.3
Pino Toscano
2014-Oct-02 15:36 UTC
[Libguestfs] [PATCH 2/3] appliance: add a "rescue" appliance for virt-rescue
Add a new appliance flavour for virt-rescue, so it can have extra packages. Currently it provides no extra packages. --- appliance/Makefile.am | 21 ++++++++++++++++++++- appliance/packagelist-rescue.in | 16 ++++++++++++++++ rescue/rescue.c | 4 ++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 appliance/packagelist-rescue.in diff --git a/appliance/Makefile.am b/appliance/Makefile.am index 7b30bbe..4e19708 100644 --- a/appliance/Makefile.am +++ b/appliance/Makefile.am @@ -32,6 +32,7 @@ EXTRA_DIST = \ fsdir = $(libdir)/guestfs superminfsdir = $(libdir)/guestfs/supermin.d +superminrescuefsdir = $(libdir)/guestfs/supermin-rescue.d fs_DATA superminfs_DATA = \ @@ -42,6 +43,8 @@ superminfs_DATA = \ supermin.d/init.tar.gz \ supermin.d/packages \ supermin.d/udev-rules.tar.gz +superminrescuefs_DATA = \ + supermin-rescue.d/packages supermin.d/base.tar.gz supermin.d/packages: stamp-supermin stamp-supermin: make.sh packagelist @@ -55,6 +58,14 @@ stamp-supermin: make.sh packagelist supermin.d/udev-rules.tar.gz touch $@ +supermin-rescue.d/packages: stamp-supermin-rescue +stamp-supermin-rescue: stamp-supermin make.sh packagelist-rescue + rm -f $@ supermin-rescue.d/packages + mkdir -p supermin-rescue.d + cat packagelist-rescue | awk '{for (i=1; i<=NF; i++) print $i}' \ + | sort > supermin-rescue.d/packages + touch $@ + # This used to be a configure-generated file. However config.status # always touches the destination file, which means the appliance got # rebuilt too often. @@ -76,6 +87,12 @@ packagelist: packagelist.in Makefile cmp -s $@ $@-t || mv $@-t $@ rm -f $@-t +packagelist-rescue: packagelist-rescue.in Makefile + m4 $(PACKAGELIST_CPP_FLAGS) $< | \ + grep -v '^[[:space:]]*$$' | grep -v '^#' > $@-t + cmp -s $@ $@-t || mv $@-t $@ + rm -f $@-t + supermin.d/daemon.tar.gz: ../daemon/guestfsd guestfsd.suppressions guestfs_lvm_conf.aug guestfs_shadow.aug rm -f $@ $@-t rm -rf tmp-d @@ -151,4 +168,6 @@ CLEANFILES = \ DISTCLEANFILES = \ stamp-supermin \ - supermin.d/* + stamp-supermin-rescue \ + supermin.d/* \ + supermin-rescue.d/* diff --git a/appliance/packagelist-rescue.in b/appliance/packagelist-rescue.in new file mode 100644 index 0000000..aec0201 --- /dev/null +++ b/appliance/packagelist-rescue.in @@ -0,0 +1,16 @@ +dnl This is the list of distro packages which are +dnl installed on the appliance. +dnl +dnl This file is processed by m4 with one of the +dnl following symbols defined (depending on the distro): +dnl +dnl REDHAT=1 For Fedora, RHEL, EPEL and workalikes. +dnl DEBIAN=1 For Debian. +dnl UBUNTU=1 For Ubuntu. +dnl ARCHLINUX=1 For Archlinux. +dnl SUSE=1 For OpenSUSE. +dnl FRUGALWARE=1 For Frugalware. +dnl MAGEIA=1 For Mageia. + +dnl Basically the same with a few minor tweaks. +ifelse(UBUNTU,1,`define(`DEBIAN',1)') diff --git a/rescue/rescue.c b/rescue/rescue.c index 00187a4..79c7d9a 100644 --- a/rescue/rescue.c +++ b/rescue/rescue.c @@ -323,6 +323,10 @@ main (int argc, char *argv[]) } } + /* Use the "rescue" appliance flavour. */ + if (guestfs_set_flavour (g, "rescue") == -1) + exit (EXIT_FAILURE); + /* Set other features. */ if (memsize > 0) if (guestfs_set_memsize (g, memsize) == -1) -- 1.9.3
Pino Toscano
2014-Oct-02 15:36 UTC
[Libguestfs] [PATCH 3/3] appliance: move openssh to the "rescue" appliance
--- appliance/packagelist-rescue.in | 16 ++++++++++++++++ appliance/packagelist.in | 4 ---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/appliance/packagelist-rescue.in b/appliance/packagelist-rescue.in index aec0201..4cc94c4 100644 --- a/appliance/packagelist-rescue.in +++ b/appliance/packagelist-rescue.in @@ -14,3 +14,19 @@ dnl MAGEIA=1 For Mageia. dnl Basically the same with a few minor tweaks. ifelse(UBUNTU,1,`define(`DEBIAN',1)') + +ifelse(REDHAT,1, + openssh-clients +) + +ifelse(DEBIAN,1, + openssh-client +) + +ifelse(FRUGALWARE,1, + openssh +) + +ifelse(MAGEIA,1, + openssh-clients +) diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 276b4c2..b91b2e2 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -43,7 +43,6 @@ ifelse(REDHAT,1, nilfs-utils ntfsprogs ntfs-3g - openssh-clients pcre reiserfs-utils libselinux @@ -87,7 +86,6 @@ dnl iproute has been renamed to iproute2 mtools nilfs-tools ntfs-3g - openssh-client reiserfsprogs sysvinit dnl for /sbin/reboot systemd dnl alternative for /sbin/reboot @@ -158,7 +156,6 @@ ifelse(FRUGALWARE,1, libcap ntfsprogs ntfs-3g - openssh pcre reiserfsprogs systemd @@ -190,7 +187,6 @@ ifelse(MAGEIA,1, nilfs-utils ntfsprogs ntfs-3g - openssh-clients pcre reiserfs-utils libselinux -- 1.9.3
Richard W.M. Jones
2014-Oct-02 17:05 UTC
Re: [Libguestfs] [PATCH 0/3] RFC: appliance flavours
On Thu, Oct 02, 2014 at 05:36:22PM +0200, Pino Toscano wrote:> Hi, > > this is a prototype of something I've around for some time. > Basically it is about adding new appliances in addition to the main > one currently used and kept up-to-date automatically: this way it is > possible to create new appliances with extra packages, to be used in > specific contexts (like virt-rescue, with more network/recovery tools) > without filling the main appliance. > > It's still WIP (the most notable lack is a proper base.tar.gz with > config files of flavour packages), but I'd like to get some feedback > about it.My problem with this is that we (Fedora & Debian) do something similar already: https://apps.fedoraproject.org/packages/libguestfs-rescue https://packages.debian.org/search?keywords=libguestfs-rescue A little bit different because the application (eg. virt-rescue) doesn't request the extra packages, and also because if the end user installs libguestfs-rescue then all appliances have the extra packages whether they need them or not. I'd say that the first is a packaging issue: virt-rescue might be packaged into libguestfs-rescue. The second isn't really a problem since the size of the appliance doesn't matter (it is loaded on demand). Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-p2v converts physical machines to virtual machines. Boot with a live CD or over the network (PXE) and turn machines into KVM guests. http://libguestfs.org/virt-v2v
Apparently Analagous Threads
- [PATCH] arm: appliance: Add support for device trees (dtb's).
- [PATCH 0/4] lib: qemu: Memoize qemu feature detection.
- [PATCH 0/10] Add a mini-library for running external commands.
- Remove temporary directories created during appliance building along error paths (RHBZ#769680)
- [PATCH 0/5] Use less stack.