Nikos Skalkotos
2015-May-29 09:24 UTC
[Libguestfs] [PATCH 2/3] inspection: Add support for CoreOS
* Implement coreos distro * Detect CoreOS images Signed-off-by: Nikos Skalkotos <skalkoto@grnet.gr> --- generator/actions.ml | 4 +++ src/guestfs-internal.h | 3 +++ src/inspect-fs-unix.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++--- src/inspect-fs.c | 21 +++++++++++++++ src/inspect-icon.c | 1 + src/inspect.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 3 deletions(-) diff --git a/generator/actions.ml b/generator/actions.ml index e9374a3..e1b14ca 100644 --- a/generator/actions.ml +++ b/generator/actions.ml @@ -1073,6 +1073,10 @@ Cirros. =item \"debian\" +CoreOS. + +=item \"coreos\" + Debian. =item \"fedora\" diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h index 01cbca7..1462673 100644 --- a/src/guestfs-internal.h +++ b/src/guestfs-internal.h @@ -551,6 +551,7 @@ enum inspect_os_distro { OS_DISTRO_ORACLE_LINUX, OS_DISTRO_FREEBSD, OS_DISTRO_NETBSD, + OS_DISTRO_COREOS, }; enum inspect_os_package_format { @@ -797,6 +798,8 @@ extern int guestfs_int_check_netbsd_root (guestfs_h *g, struct inspect_fs *fs); extern int guestfs_int_check_openbsd_root (guestfs_h *g, struct inspect_fs *fs); extern int guestfs_int_check_hurd_root (guestfs_h *g, struct inspect_fs *fs); extern int guestfs_int_check_minix_root (guestfs_h *g, struct inspect_fs *fs); +extern int guestfs_int_check_coreos_root (guestfs_h *g, struct inspect_fs *fs); +extern int guestfs_int_check_coreos_usr (guestfs_h *g, struct inspect_fs *fs); /* inspect-fs-windows.c */ extern char *guestfs_int_case_sensitive_path_silently (guestfs_h *g, const char *); diff --git a/src/inspect-fs-unix.c b/src/inspect-fs-unix.c index 2abbf24..ff50b2a 100644 --- a/src/inspect-fs-unix.c +++ b/src/inspect-fs-unix.c @@ -160,11 +160,16 @@ parse_release_file (guestfs_h *g, struct inspect_fs *fs, * DISTRIB_CODENAME=Henry_Farman * DISTRIB_DESCRIPTION="Mandriva Linux 2010.1" * Mandriva also has a normal release file called /etc/mandriva-release. + * + * CoreOS has a /etc/lsb-release link to /usr/share/coreos/lsb-release containing: + * DISTRIB_ID=CoreOS + * DISTRIB_RELEASE=647.0.0 + * DISTRIB_CODENAME="Red Dog" + * DISTRIB_DESCRIPTION="CoreOS 647.0.0" */ static int -parse_lsb_release (guestfs_h *g, struct inspect_fs *fs) +parse_lsb_release (guestfs_h *g, struct inspect_fs *fs, const char *filename) { - const char *filename = "/etc/lsb-release"; int64_t size; CLEANUP_FREE_STRING_LIST char **lines = NULL; size_t i; @@ -208,6 +213,11 @@ parse_lsb_release (guestfs_h *g, struct inspect_fs *fs) fs->distro = OS_DISTRO_MAGEIA; r = 1; } + else if (fs->distro == 0 && + STREQ (lines[i], "DISTRIB_ID=CoreOS")) { + fs->distro = OS_DISTRO_COREOS; + r = 1; + } else if (STRPREFIX (lines[i], "DISTRIB_RELEASE=")) { char *major, *minor; if (match2 (g, &lines[i][16], re_major_minor, &major, &minor)) { @@ -338,7 +348,7 @@ guestfs_int_check_linux_root (guestfs_h *g, struct inspect_fs *fs) if (guestfs_is_file_opts (g, "/etc/lsb-release", GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { - r = parse_lsb_release (g, fs); + r = parse_lsb_release (g, fs, "/etc/lsb-release"); if (r == -1) /* error */ return -1; if (r == 1) /* ok - detected the release from this file */ @@ -795,6 +805,59 @@ guestfs_int_check_minix_root (guestfs_h *g, struct inspect_fs *fs) return 0; } +/* The currently mounted device is a CoreOS root. From this partition we can + * only determine the hostname. All immutable OS files are under a separate + * read-only /usr partition. + */ +int +guestfs_int_check_coreos_root (guestfs_h *g, struct inspect_fs *fs) +{ + fs->type = OS_TYPE_LINUX; + fs->distro = OS_DISTRO_COREOS; + + /* Determine hostname. */ + if (check_hostname_unix (g, fs) == -1) + return -1; + + /* CoreOS does not contain /etc/fstab to determine the mount points. + * Associate this filesystem with the "/" mount point. + */ + if (add_fstab_entry (g, fs, fs->mountable, "/") == -1) + return -1; + + return 0; +} + +/* The currently mounted device looks like a CoreOS /usr. In CoreOS + * the read-only /usr contains the OS version. The /etc/os-release is a + * link to /usr/share/coreos/os-release. + */ +int +guestfs_int_check_coreos_usr (guestfs_h *g, struct inspect_fs *fs) +{ + int r; + + fs->type = OS_TYPE_LINUX; + fs->distro = OS_DISTRO_COREOS; + if (guestfs_is_file_opts (g, "/share/coreos/lsb-release", + GUESTFS_IS_FILE_OPTS_FOLLOWSYMLINKS, 1, -1) > 0) { + r = parse_lsb_release (g, fs, "/share/coreos/lsb-release"); + if (r == -1) /* error */ + return -1; + } + + /* Determine the architecture. */ + check_architecture (g, fs); + + /* CoreOS does not contain /etc/fstab to determine the mount points. + * Associate this filesystem with the "/usr" mount point. + */ + if (add_fstab_entry (g, fs, fs->mountable, "/usr") == -1) + return -1; + + return 0; +} + static void check_architecture (guestfs_h *g, struct inspect_fs *fs) { diff --git a/src/inspect-fs.c b/src/inspect-fs.c index 5f55f1d..64f904f 100644 --- a/src/inspect-fs.c +++ b/src/inspect-fs.c @@ -232,6 +232,17 @@ check_filesystem (guestfs_h *g, const char *mountable, if (guestfs_int_check_linux_root (g, fs) == -1) return -1; } + /* CoreOS root? */ + else if (is_dir_etc && + guestfs_is_dir (g, "/root") > 0 && + guestfs_is_dir (g, "/home") > 0 && + guestfs_is_dir (g, "/usr") > 0 && + guestfs_is_file (g, "/etc/coreos/update.conf") > 0) { + fs->is_root = 1; + fs->format = OS_FORMAT_INSTALLED; + if (guestfs_int_check_coreos_root (g, fs) == -1) + return -1; + } /* Linux /usr/local? */ else if (is_dir_etc && is_dir_bin && @@ -246,6 +257,14 @@ check_filesystem (guestfs_h *g, const char *mountable, guestfs_is_dir (g, "/local") > 0 && guestfs_is_file (g, "/etc/fstab") == 0) ; + /* CoreOS /usr? */ + else if (is_dir_bin && + is_dir_share && + guestfs_is_dir (g, "/local") > 0 && + guestfs_is_dir (g, "/share/coreos") > 0) { + if (guestfs_int_check_coreos_usr (g, fs) == -1) + return -1; + } /* Linux /var? */ else if (guestfs_is_dir (g, "/log") > 0 && guestfs_is_dir (g, "/run") > 0 && @@ -476,6 +495,7 @@ guestfs_int_check_package_format (guestfs_h *g, struct inspect_fs *fs) case OS_DISTRO_SLACKWARE: case OS_DISTRO_TTYLINUX: + case OS_DISTRO_COREOS: case OS_DISTRO_WINDOWS: case OS_DISTRO_BUILDROOT: case OS_DISTRO_CIRROS: @@ -546,6 +566,7 @@ guestfs_int_check_package_management (guestfs_h *g, struct inspect_fs *fs) case OS_DISTRO_SLACKWARE: case OS_DISTRO_TTYLINUX: + case OS_DISTRO_COREOS: case OS_DISTRO_WINDOWS: case OS_DISTRO_BUILDROOT: case OS_DISTRO_CIRROS: diff --git a/src/inspect-icon.c b/src/inspect-icon.c index fb998c2..57b2ce3 100644 --- a/src/inspect-icon.c +++ b/src/inspect-icon.c @@ -169,6 +169,7 @@ guestfs_impl_inspect_get_icon (guestfs_h *g, const char *root, size_t *size_r, /* These are just to keep gcc warnings happy. */ case OS_DISTRO_ARCHLINUX: case OS_DISTRO_BUILDROOT: + case OS_DISTRO_COREOS: case OS_DISTRO_FREEDOS: case OS_DISTRO_GENTOO: case OS_DISTRO_LINUX_MINT: diff --git a/src/inspect.c b/src/inspect.c index f528bf2..dd6a06f 100644 --- a/src/inspect.c +++ b/src/inspect.c @@ -42,6 +42,7 @@ COMPILE_REGEXP (re_primary_partition, "^/dev/(?:h|s|v)d.[1234]$", 0) static void check_for_duplicated_bsd_root (guestfs_h *g); +static int collect_coreos_inspection_info (guestfs_h *g); /* The main inspection code. */ char ** @@ -70,6 +71,15 @@ guestfs_impl_inspect_os (guestfs_h *g) } } + /* The OS inspection information for CoreOS are gathered by inspecting + * multiple filesystems. Gather all the inspected information in the + * inspect_fs struct of the root filesystem. + */ + if (collect_coreos_inspection_info (g)) { + guestfs_int_free_inspect_info (g); + return NULL; + } + /* Check if the same filesystem was listed twice as root in g->fses. * This may happen for the *BSD root partition where an MBR partition * is a shadow of the real root partition probably /dev/sda5 @@ -87,6 +97,57 @@ guestfs_impl_inspect_os (guestfs_h *g) return ret; } +/* Traverse through the filesystem list and find out if it contains the + * "/" and "/usr" filesystems of a CoreOS image. If this is the case, + * sum up all the collected information on the root fs. + */ +static int +collect_coreos_inspection_info (guestfs_h *g) +{ + size_t i; + struct inspect_fs *root = NULL, *usr = NULL; + + for (i = 0; i < g->nr_fses; ++i) { + struct inspect_fs *fs = &g->fses[i]; + + if (fs->distro == OS_DISTRO_COREOS && fs->is_root) + root = fs; + } + + if (root == NULL) + return 0; + + for (i = 0; i < g->nr_fses; ++i) { + struct inspect_fs *fs = &g->fses[i]; + + if (fs->distro != OS_DISTRO_COREOS || fs->is_root != 0) + continue; + + /* CoreOS is designed to contain 2 /usr partitions (USR-A, USR-B): + * https://coreos.com/docs/sdk-distributors/sdk/disk-partitions/ + * One is active and one passive. During the initial boot, the passive + * partition is empty and it gets filled up when an update is performed. + * Then, when the system reboots, the boot loader is instructed to boot + * from the passive partition. If both partitions are valid, we cannot + * determine which the active and which the passive is, unless we peep into + * the boot loader. As a workaround, we check the OS versions and pick the + * one with the higher version as active. + */ + if (usr && + (usr->major_version > fs->major_version || + (usr->major_version == fs->major_version && + usr->minor_version > fs->minor_version))) + continue; + + usr = fs; + } + + if (usr == NULL) + return 0; + + return guestfs_int_merge_fs_inspections (g, root, usr); +} + /* On *BSD systems, sometimes /dev/sda[1234] is a shadow of the real root * filesystem that is probably /dev/sda5 * (see: http://www.freebsd.org/doc/handbook/disk-organization.html) @@ -201,6 +262,7 @@ guestfs_impl_inspect_get_distro (guestfs_h *g, const char *root) case OS_DISTRO_BUILDROOT: ret = safe_strdup (g, "buildroot"); break; case OS_DISTRO_CENTOS: ret = safe_strdup (g, "centos"); break; case OS_DISTRO_CIRROS: ret = safe_strdup (g, "cirros"); break; + case OS_DISTRO_COREOS: ret = safe_strdup (g, "coreos"); break; case OS_DISTRO_DEBIAN: ret = safe_strdup (g, "debian"); break; case OS_DISTRO_FEDORA: ret = safe_strdup (g, "fedora"); break; case OS_DISTRO_FREEBSD: ret = safe_strdup (g, "freebsd"); break; -- 2.1.0
Richard W.M. Jones
2015-Jun-02 14:10 UTC
Re: [Libguestfs] [PATCH 2/3] inspection: Add support for CoreOS
On Fri, May 29, 2015 at 12:24:58PM +0300, Nikos Skalkotos wrote:> + if (collect_coreos_inspection_info (g)) { > + guestfs_int_free_inspect_info (g); > + return NULL; > + }Although this is stylistic, I think it's easier to understand if you change the if condition to: if (collect_coreos_inspection_info (g) == -1) { ... Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
Nikos Skalkotos
2015-Jun-02 15:18 UTC
Re: [Libguestfs] [PATCH 2/3] inspection: Add support for CoreOS
On 02/06/15 17:10, Richard W.M. Jones wrote: Hello,> On Fri, May 29, 2015 at 12:24:58PM +0300, Nikos Skalkotos wrote: >> + if (collect_coreos_inspection_info (g)) { >> + guestfs_int_free_inspect_info (g); >> + return NULL; >> + } > Although this is stylistic, I think it's easier to understand if > you change the if condition to: > > if (collect_coreos_inspection_info (g) == -1) { > ... >Since we 'll be using safe_realloc, I don't think there is a need for any of: * guestfs_int_merge_fs_inspections() * collect_coreos_inspection_info() to be returning a value at all. So, I'll remove the if check completely. Nikos P.S. You have a check like this one on guestfs_int_check_for_filesystem_on() a few lines above :-)> Rich. > > >
Maybe Matching Threads
- [PATCH 2/3] inspection: Add support for CoreOS
- [PATCH] inspect: use os-release for CoreOS
- Re: [PATCH] inspect: use os-release for CoreOS
- Re: [PATCH] inspect: use os-release for CoreOS
- [PATCH 5/5] inspect: gather info from /usr filesystems as well (RHBZ#1401474)