[Libguestfs] [PATCH 1/3] New API: appliance flavours

Pino Toscano ptoscano at redhat.com
Thu Oct 2 15:36:23 UTC 2014


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




More information about the Libguestfs mailing list