[Libguestfs] [PATCH] New APIs: inspect-get-package-format, inspect-get-package-management.

Richard W.M. Jones rjones at redhat.com
Fri Nov 12 14:15:33 UTC 2010


It's neat that you can now do:

 $ guestfish -a F14x64.img -i \
     inspect-get-package-management /dev/vg_f13x64/lv_root
 yum

But it would be better if we didn't have to "know" the root
filesystem there, something like:

 $ guestfish -a F14x64.img -i <<EOF
     set roots inspect-get-roots
     inspect-get-package-management %{roots[0]}
 EOF
 yum

I've not quite worked out what this would look like, or if it's really
a good idea to add such additional complexity to guestfish.  Though I
do wish I'd written a proper lex/yacc parser in the first place ...

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming blog: http://rwmj.wordpress.com
Fedora now supports 80 OCaml packages (the OPEN alternative to F#)
http://cocan.org/getting_started_with_ocaml_on_red_hat_and_fedora
-------------- next part --------------
>From 3fd2b9d0b6d2bac5e9267fbcf1556f459d7313fe Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at redhat.com>
Date: Fri, 12 Nov 2010 12:29:14 +0000
Subject: [PATCH] New APIs: inspect-get-package-format, inspect-get-package-management.

This APIs reimplement some parts of virt-inspector in C.
---
 generator/generator_actions.ml |   46 +++++++++++++
 inspector/virt-inspector       |   64 ++++-------------
 src/guestfs-internal.h         |   21 ++++++
 src/inspect.c                  |  146 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 228 insertions(+), 49 deletions(-)

diff --git a/generator/generator_actions.ml b/generator/generator_actions.ml
index 12fda29..8cb93aa 100644
--- a/generator/generator_actions.ml
+++ b/generator/generator_actions.ml
@@ -1119,6 +1119,52 @@ The optional parameters are passed directly through to
 C<guestfs_add_drive_opts>.");
 *)
 
+  ("inspect_get_package_format", (RString "packageformat", [Device "root"], []), -1, [],
+   [],
+   "get package format used by the operating system",
+   "\
+This function should only be called with a root device string
+as returned by C<guestfs_inspect_os>.
+
+This function and C<guestfs_inspect_get_package_management> return
+the package format and package management tool used by the
+inspected operating system.  For example for Fedora these
+functions would return C<rpm> (package format) and
+C<yum> (package management).
+
+This returns the string C<unknown> if we could not determine the
+package format I<or> if the operating system does not have
+a real packaging system (eg. Windows).
+
+Possible strings include: C<rpm>, C<deb>, C<ebuild>, C<pisi>, C<pacman>.
+Future versions of libguestfs may return other strings.
+
+Please read L<guestfs(3)/INSPECTION> for more details.");
+
+  ("inspect_get_package_management", (RString "packagemanagement", [Device "root"], []), -1, [],
+   [],
+   "get package management tool used by the operating system",
+   "\
+This function should only be called with a root device string
+as returned by C<guestfs_inspect_os>.
+
+C<guestfs_inspect_get_package_format> and this function return
+the package format and package management tool used by the
+inspected operating system.  For example for Fedora these
+functions would return C<rpm> (package format) and
+C<yum> (package management).
+
+This returns the string C<unknown> if we could not determine the
+package management tool I<or> if the operating system does not have
+a real packaging system (eg. Windows).
+
+Possible strings include: C<yum>, C<up2date>,
+C<apt> (for all Debian derivatives),
+C<portage>, C<pisi>, C<pacman>.
+Future versions of libguestfs may return other strings.
+
+Please read L<guestfs(3)/INSPECTION> for more details.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
diff --git a/inspector/virt-inspector b/inspector/virt-inspector
index 9e12dc8..ce9ac0e 100755
--- a/inspector/virt-inspector
+++ b/inspector/virt-inspector
@@ -200,17 +200,17 @@ foreach $root (@roots) {
     # Basic OS fields.
     $xml->dataElement (root => canonicalize ($root));
 
-    my ($s, $distro, $major_version);
+    my $s;
     $s = $g->inspect_get_type ($root);
     $xml->dataElement (name => $s) if $s ne "unknown";
     $s = $g->inspect_get_arch ($root);
     $xml->dataElement (arch => $s) if $s ne "unknown";
-    $distro = $g->inspect_get_distro ($root);
-    $xml->dataElement (distro => $distro) if $distro ne "unknown";
+    $s = $g->inspect_get_distro ($root);
+    $xml->dataElement (distro => $s) if $s ne "unknown";
     $s = $g->inspect_get_product_name ($root);
     $xml->dataElement (product_name => $s) if $s ne "unknown";
-    $major_version = $g->inspect_get_major_version ($root);
-    $xml->dataElement (major_version => $major_version);
+    $s = $g->inspect_get_major_version ($root);
+    $xml->dataElement (major_version => $s);
     $s = $g->inspect_get_minor_version ($root);
     $xml->dataElement (minor_version => $s);
 
@@ -226,7 +226,7 @@ foreach $root (@roots) {
     output_filesystems ($root);
 
     # Package format / management and applications.
-    output_applications ($root, $distro, $major_version);
+    output_applications ($root);
 
     $xml->endTag("operatingsystem");
 
@@ -370,58 +370,24 @@ sub output_applications
 {
     local $_;
     my $root = shift;
-    my $distro = shift;
-    my $major_version = shift;
 
     # Based on the distro, take a guess at the package format
     # and package management.
     my ($package_format, $package_management);
-    if (defined $distro) {
-        if ($distro eq "archlinux") {
-            $package_format = "pacman";
-            $package_management = "pacman";
-        }
-        elsif ($distro eq "debian" || $distro eq "ubuntu") {
-            $package_format = "deb";
-            $package_management = "apt";
-        }
-        elsif ($distro eq "fedora" || $distro eq "meego") {
-            $package_format = "rpm";
-            $package_management = "yum";
-        }
-        elsif ($distro eq "gentoo") {
-            $package_format = "ebuild";
-            $package_management = "portage";
-        }
-        elsif ($distro eq "pardus") {
-            $package_format = "pisi";
-            $package_management = "pisi";
-        }
-        elsif ($distro =~ /redhat/ || $distro =~ /rhel/) {
-            if ($major_version >= 5) {
-                $package_format = "rpm";
-                $package_management = "yum";
-            } else {
-                $package_format = "rpm";
-                $package_management = "up2date";
-            }
-        }
-        # else unknown.
-    }
+    $package_format = $g->inspect_get_package_format ($root);
+    $package_management = $g->inspect_get_package_management ($root);
 
     $xml->dataElement (package_format => $package_format)
-        if defined $package_format;
+        if $package_format ne "unknown";
     $xml->dataElement (package_management => $package_management)
-        if defined $package_management;
+        if $package_management ne "unknown";
 
     # Do we know how to get a list of applications?
-    if (defined $package_format) {
-        if ($package_format eq "rpm") {
-            output_applications_rpm ($root);
-        }
-        elsif ($package_format eq "deb") {
-            output_applications_deb ($root);
-        }
+    if ($package_format eq "rpm") {
+        output_applications_rpm ($root);
+    }
+    elsif ($package_format eq "deb") {
+        output_applications_deb ($root);
     }
 }
 
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 6dbbeec..65ca4f2 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -181,6 +181,25 @@ enum inspect_os_distro {
   OS_DISTRO_MEEGO,
 };
 
+enum inspect_os_package_format {
+  OS_PACKAGE_FORMAT_UNKNOWN = 0,
+  OS_PACKAGE_FORMAT_RPM,
+  OS_PACKAGE_FORMAT_DEB,
+  OS_PACKAGE_FORMAT_PACMAN,
+  OS_PACKAGE_FORMAT_EBUILD,
+  OS_PACKAGE_FORMAT_PISI
+};
+
+enum inspect_os_package_management {
+  OS_PACKAGE_MANAGEMENT_UNKNOWN = 0,
+  OS_PACKAGE_MANAGEMENT_YUM,
+  OS_PACKAGE_MANAGEMENT_UP2DATE,
+  OS_PACKAGE_MANAGEMENT_APT,
+  OS_PACKAGE_MANAGEMENT_PACMAN,
+  OS_PACKAGE_MANAGEMENT_PORTAGE,
+  OS_PACKAGE_MANAGEMENT_PISI,
+};
+
 struct inspect_fs {
   int is_root;
   char *device;
@@ -189,6 +208,8 @@ struct inspect_fs {
   enum inspect_fs_content content;
   enum inspect_os_type type;
   enum inspect_os_distro distro;
+  enum inspect_os_package_format package_format;
+  enum inspect_os_package_management package_management;
   char *product_name;
   int major_version;
   int minor_version;
diff --git a/src/inspect.c b/src/inspect.c
index 2b61a75..3b2720c 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -197,6 +197,8 @@ static int parse_unsigned_int (guestfs_h *g, const char *str);
 static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
                             const char *spec, const char *mp);
 static char *resolve_fstab_device (guestfs_h *g, const char *spec);
+static void check_package_format (guestfs_h *g, struct inspect_fs *fs);
+static void check_package_management (guestfs_h *g, struct inspect_fs *fs);
 
 static int
 check_for_filesystem_on (guestfs_h *g, const char *device)
@@ -516,6 +518,10 @@ check_linux_root (guestfs_h *g, struct inspect_fs *fs)
 
  skip_release_checks:;
 
+  /* If distro test above was successful, work out the package format. */
+  check_package_format (g, fs);
+  check_package_management (g, fs);
+
   /* Determine the architecture. */
   const char *binaries[] =
     { "/bin/bash", "/bin/ls", "/bin/echo", "/bin/rm", "/bin/sh" };
@@ -776,6 +782,9 @@ check_windows_root (guestfs_h *g, struct inspect_fs *fs)
   if (check_windows_registry (g, fs) == -1)
     return -1;
 
+  check_package_format (g, fs);
+  check_package_management (g, fs);
+
   return 0;
 }
 
@@ -972,6 +981,84 @@ parse_unsigned_int (guestfs_h *g, const char *str)
   return ret;
 }
 
+/* At the moment, package format and package management is just a
+ * simple function of the distro and major_version fields, so these
+ * can never return an error.  We might be cleverer in future.
+ */
+static void
+check_package_format (guestfs_h *g, struct inspect_fs *fs)
+{
+  switch (fs->distro) {
+  case OS_DISTRO_FEDORA:
+  case OS_DISTRO_MEEGO:
+  case OS_DISTRO_REDHAT_BASED:
+  case OS_DISTRO_RHEL:
+    fs->package_format = OS_PACKAGE_FORMAT_RPM;
+    break;
+
+  case OS_DISTRO_DEBIAN:
+  case OS_DISTRO_UBUNTU:
+    fs->package_format = OS_PACKAGE_FORMAT_DEB;
+    break;
+
+  case OS_DISTRO_ARCHLINUX:
+    fs->package_format = OS_PACKAGE_FORMAT_PACMAN;
+    break;
+  case OS_DISTRO_GENTOO:
+    fs->package_format = OS_PACKAGE_FORMAT_EBUILD;
+    break;
+  case OS_DISTRO_PARDUS:
+    fs->package_format = OS_PACKAGE_FORMAT_PISI;
+    break;
+
+  case OS_DISTRO_WINDOWS:
+  case OS_DISTRO_UNKNOWN:
+  default:
+    fs->package_format = OS_PACKAGE_FORMAT_UNKNOWN;
+    break;
+  }
+}
+
+static void
+check_package_management (guestfs_h *g, struct inspect_fs *fs)
+{
+  switch (fs->distro) {
+  case OS_DISTRO_FEDORA:
+  case OS_DISTRO_MEEGO:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_YUM;
+    break;
+
+  case OS_DISTRO_REDHAT_BASED:
+  case OS_DISTRO_RHEL:
+    if (fs->major_version >= 5)
+      fs->package_management = OS_PACKAGE_MANAGEMENT_YUM;
+    else
+      fs->package_management = OS_PACKAGE_MANAGEMENT_UP2DATE;
+    break;
+
+  case OS_DISTRO_DEBIAN:
+  case OS_DISTRO_UBUNTU:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_APT;
+    break;
+
+  case OS_DISTRO_ARCHLINUX:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_PACMAN;
+    break;
+  case OS_DISTRO_GENTOO:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_PORTAGE;
+    break;
+  case OS_DISTRO_PARDUS:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_PISI;
+    break;
+
+  case OS_DISTRO_WINDOWS:
+  case OS_DISTRO_UNKNOWN:
+  default:
+    fs->package_management = OS_PACKAGE_MANAGEMENT_UNKNOWN;
+    break;
+  }
+}
+
 static struct inspect_fs *
 search_for_root (guestfs_h *g, const char *root)
 {
@@ -1194,6 +1281,53 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
   return ret;
 }
 
+char *
+guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
+{
+  struct inspect_fs *fs = search_for_root (g, root);
+  if (!fs)
+    return NULL;
+
+  char *ret;
+  switch (fs->package_format) {
+  case OS_PACKAGE_FORMAT_RPM: ret = safe_strdup (g, "rpm"); break;
+  case OS_PACKAGE_FORMAT_DEB: ret = safe_strdup (g, "deb"); break;
+  case OS_PACKAGE_FORMAT_PACMAN: ret = safe_strdup (g, "pacman"); break;
+  case OS_PACKAGE_FORMAT_EBUILD: ret = safe_strdup (g, "ebuild"); break;
+  case OS_PACKAGE_FORMAT_PISI: ret = safe_strdup (g, "pisi"); break;
+  case OS_PACKAGE_FORMAT_UNKNOWN:
+  default:
+    ret = safe_strdup (g, "unknown");
+    break;
+  }
+
+  return ret;
+}
+
+char *
+guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
+{
+  struct inspect_fs *fs = search_for_root (g, root);
+  if (!fs)
+    return NULL;
+
+  char *ret;
+  switch (fs->package_management) {
+  case OS_PACKAGE_MANAGEMENT_YUM: ret = safe_strdup (g, "yum"); break;
+  case OS_PACKAGE_MANAGEMENT_UP2DATE: ret = safe_strdup (g, "up2date"); break;
+  case OS_PACKAGE_MANAGEMENT_APT: ret = safe_strdup (g, "apt"); break;
+  case OS_PACKAGE_MANAGEMENT_PACMAN: ret = safe_strdup (g, "pacman"); break;
+  case OS_PACKAGE_MANAGEMENT_PORTAGE: ret = safe_strdup (g, "portage"); break;
+  case OS_PACKAGE_MANAGEMENT_PISI: ret = safe_strdup (g, "pisi"); break;
+  case OS_PACKAGE_MANAGEMENT_UNKNOWN:
+  default:
+    ret = safe_strdup (g, "unknown");
+    break;
+  }
+
+  return ret;
+}
+
 #else /* no PCRE or hivex at compile time */
 
 /* XXX These functions should be in an optgroup. */
@@ -1268,6 +1402,18 @@ guestfs__inspect_get_filesystems (guestfs_h *g, const char *root)
   NOT_IMPL(NULL);
 }
 
+char *
+guestfs__inspect_get_package_format (guestfs_h *g, const char *root)
+{
+  NOT_IMPL(NULL);
+}
+
+char *
+guestfs__inspect_get_package_management (guestfs_h *g, const char *root)
+{
+  NOT_IMPL(NULL);
+}
+
 #endif /* no PCRE or hivex at compile time */
 
 void
-- 
1.7.3.2



More information about the Libguestfs mailing list