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
Maybe Matching 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.