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