lib/sysroot: Support /usr/lib/modules/$kver for kernel/initramfs
authorColin Walters <walters@verbum.org>
Tue, 15 Aug 2017 15:22:21 +0000 (11:22 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Fri, 18 Aug 2017 17:34:36 +0000 (17:34 +0000)
This is the new Fedora kernel standard layout; it has the advantage
of being in `/usr` like `/usr/lib/ostree-boot`, but it's not OSTree
specific.

Further, I think in practice forcing tree builders to compute the checksum is an
annoying stumbling block; since we already switched to e.g. computing checksums
always when doing pulls, the cost of doing another checksum for the
kernel/initramfs is tiny. The "bootcsum" becomes more of an internal
implementation detail.

Now, there is a transition; my current thought for this is that rpm-ostree will
change to default to injecting into both `/usr/lib/ostree-boot` and
`/usr/lib/modules`, and stop doing `/boot`, then maybe next year say we drop the
`/usr/lib/ostree-boot` by default.

A twist here is that the default Fedora kernel RPM layout (and what's in
rpm-ostree today) includes a kernel but *not* an initramfs in
`/usr/lib/modules`. If we looked only there, we'd just find the kernel. So we
need to look in both, and then special case this - pick the legacy layout if we
have `/usr/lib/modules` but not an initramfs.

While here, rework the code to have an `OstreeKernelLayout` struct which makes
dealing with all of the variables nicer.

Closes: #1079
Approved by: jlebon

docs/manual/deployment.md
src/libostree/ostree-sysroot-deploy.c
tests/libtest.sh
tests/test-admin-deploy-syslinux.sh
tests/test-admin-deploy-uboot.sh

index 76d057014431f562e2cb82ed407118b9436bb89a..0db03117c10ffe05e18cf46c1346470bf805f4b4 100644 (file)
@@ -43,8 +43,13 @@ to a filesystem tree that represents the underlying basis of a
 deployment.  For short, we will call this the "tree", to
 distinguish it from the concept of a deployment.
 
-First, the tree must include a kernel stored as
-`vmlinuz(-.*)?-$checksum` in either `/boot` or `/usr/lib/ostree-boot`.
+First, the tree must include a kernel (and optionally an initramfs).  The
+current standard locations for these are `/usr/lib/modules/$kver/vmlinuz` and
+`/usr/lib/modules/$kver/initramfs`.  The "boot checksum" will be computed
+automatically.  This follows the current Fedora kernel layout, and is
+the current recommended path.  However, older versions of libostree don't
+support this; you may need to also put kernels in the previous (legacy)
+paths, which are `vmlinuz(-.*)?-$checksum` in either `/boot` or `/usr/lib/ostree-boot`.
 The checksum should be a SHA256 hash of the kernel contents; it must be
 pre-computed before storing the kernel in the repository.  Optionally,
 the directory can also contain an initramfs, stored as
index 60fbc1d3f1ecb059ff0374937d68184b8788d83e..8b2f5e4bfada2448255d145722164869581a923f 100644 (file)
@@ -882,46 +882,173 @@ ostree_sysroot_write_origin_file (OstreeSysroot         *sysroot,
                                      cancellable, error);
 }
 
-/* Originally OSTree defined kernels to be found underneath /boot
- * in the tree.  But that means when mounting /boot at runtime
- * we end up masking the content underneath, triggering a warning.
- *
- * For that reason, and also consistency with the "/usr defines the OS" model we
- * later switched to defining the in-tree kernels to be found under
- * /usr/lib/ostree-boot.
- */
+typedef struct {
+  int   boot_dfd;
+  char *kernel_srcpath;
+  char *kernel_namever;
+  char *initramfs_srcpath;
+  char *initramfs_namever;
+  char *bootcsum;
+} OstreeKernelLayout;
+static void
+_ostree_kernel_layout_free (OstreeKernelLayout *layout)
+{
+  if (layout->boot_dfd != -1)
+    (void) close (layout->boot_dfd);
+  g_free (layout->kernel_srcpath);
+  g_free (layout->kernel_namever);
+  g_free (layout->initramfs_srcpath);
+  g_free (layout->initramfs_namever);
+  g_free (layout->bootcsum);
+  g_free (layout);
+}
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(OstreeKernelLayout, _ostree_kernel_layout_free);
+
+static OstreeKernelLayout*
+_ostree_kernel_layout_new (void)
+{
+  OstreeKernelLayout *ret = g_new0 (OstreeKernelLayout, 1);
+  ret->boot_dfd = -1;
+  return ret;
+}
+
+/* See get_kernel_from_tree() below */
 static gboolean
-get_kernel_from_tree (int             deployment_dfd,
-                      int            *out_boot_dfd,
-                      char          **out_kernel_srcpath,
-                      char          **out_kernel_namever,
-                      char          **out_initramfs_srcpath,
-                      char          **out_initramfs_namever,
-                      char          **out_bootcsum,
-                      GCancellable   *cancellable,
-                      GError        **error)
+get_kernel_from_tree_usrlib_modules (int                  deployment_dfd,
+                                     OstreeKernelLayout **out_layout,
+                                     GCancellable        *cancellable,
+                                     GError             **error)
 {
-  g_autofree char *ret_kernel_srcpath = NULL;
-  g_autofree char *ret_kernel_namever = NULL;
-  g_autofree char *ret_initramfs_srcpath = NULL;
-  g_autofree char *ret_initramfs_namever = NULL;
+  g_autofree char *kver = NULL;
+  /* Look in usr/lib/modules */
+  g_auto(GLnxDirFdIterator) mod_dfditer = { 0, };
+  gboolean exists;
+  if (!ot_dfd_iter_init_allow_noent (deployment_dfd, "usr/lib/modules", &mod_dfditer,
+                                     &exists, error))
+    return FALSE;
+  if (!exists)
+    {
+      /* No usr/lib/modules?  We're done */
+      *out_layout = NULL;
+      return TRUE;
+    }
+
+  g_autoptr(OstreeKernelLayout) ret_layout = _ostree_kernel_layout_new ();
+
+  /* Reusable buffer for path string */
+  g_autoptr(GString) pathbuf = g_string_new ("");
+  /* Loop until we find something that looks like a valid /usr/lib/modules/$kver */
+  while (ret_layout->boot_dfd == -1)
+    {
+      struct dirent *dent;
+      struct stat stbuf;
+
+      if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&mod_dfditer, &dent, cancellable, error))
+        return FALSE;
+      if (dent == NULL)
+        break;
+      if (dent->d_type != DT_DIR)
+        continue;
+
+      /* It's a directory, look for /vmlinuz as a regular file */
+      g_string_truncate (pathbuf, 0);
+      g_string_append_printf (pathbuf, "%s/vmlinuz", dent->d_name);
+      if (fstatat (mod_dfditer.fd, pathbuf->str, &stbuf, 0) < 0)
+        {
+          if (errno != ENOENT)
+            return glnx_throw_errno_prefix (error, "fstatat(%s)", pathbuf->str);
+          else
+            continue;
+        }
+      else
+        {
+          /* Not a regular file? Loop again */
+          if (!S_ISREG (stbuf.st_mode))
+            continue;
+        }
+
+      /* Looks valid, this should exit the loop */
+      if (!glnx_opendirat (mod_dfditer.fd, dent->d_name, FALSE, &ret_layout->boot_dfd, error))
+        return FALSE;
+      kver = g_strdup (dent->d_name);
+      ret_layout->kernel_srcpath = g_strdup ("vmlinuz");
+      ret_layout->kernel_namever = g_strdup_printf ("vmlinuz-%s", kver);
+    }
+
+  if (ret_layout->boot_dfd == -1)
+    {
+      *out_layout = NULL;
+      /* No kernel found?  We're done. */
+      return TRUE;
+    }
+
+  /* We found a module directory, compute the checksum */
+  g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256);
+  glnx_fd_close int fd = -1;
+  /* Checksum the kernel */
+  if (!glnx_openat_rdonly (ret_layout->boot_dfd, "vmlinuz", TRUE, &fd, error))
+    return FALSE;
+  g_autoptr(GInputStream) in = g_unix_input_stream_new (fd, FALSE);
+  if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
+    return FALSE;
+  g_clear_object (&in);
+  (void) close (fd); fd = -1;
+
+  /* Look for an initramfs, but it's optional */
+  if (!ot_openat_ignore_enoent (ret_layout->boot_dfd, "initramfs", &fd, error))
+    return FALSE;
+  if (fd != -1)
+    {
+      ret_layout->initramfs_srcpath = g_strdup ("initramfs");
+      ret_layout->initramfs_namever = g_strdup_printf ("initramfs-%s", kver);
+      in = g_unix_input_stream_new (fd, FALSE);
+      if (!ot_gio_splice_update_checksum (NULL, in, checksum, cancellable, error))
+        return FALSE;
+    }
+
+  ret_layout->bootcsum = g_strdup (g_checksum_get_string (checksum));
+
+  *out_layout = g_steal_pointer (&ret_layout);
+  return TRUE;
+}
+
+/* See get_kernel_from_tree() below */
+static gboolean
+get_kernel_from_tree_legacy_layouts (int                  deployment_dfd,
+                                     OstreeKernelLayout **out_layout,
+                                     GCancellable        *cancellable,
+                                     GError             **error)
+{
+  const char *legacy_paths[] = {"usr/lib/ostree-boot", "boot"};
   g_autofree char *kernel_checksum = NULL;
   g_autofree char *initramfs_checksum = NULL;
+  g_autoptr(OstreeKernelLayout) ret_layout = _ostree_kernel_layout_new ();
 
-  glnx_fd_close int ret_boot_dfd = glnx_opendirat_with_errno (deployment_dfd, "usr/lib/ostree-boot", TRUE);
-  if (ret_boot_dfd == -1)
+  for (guint i = 0; i < G_N_ELEMENTS (legacy_paths); i++)
     {
-      if (errno != ENOENT)
-        return glnx_throw_errno_prefix (error, "%s", "openat(usr/lib/ostree-boot)");
-      else
+      const char *path = legacy_paths[i];
+      ret_layout->boot_dfd = glnx_opendirat_with_errno (deployment_dfd, path, TRUE);
+      if (ret_layout->boot_dfd == -1)
         {
-          if (!glnx_opendirat (deployment_dfd, "boot", TRUE, &ret_boot_dfd, error))
-            return FALSE;
+          if (errno != ENOENT)
+            return glnx_throw_errno_prefix (error, "openat(%s)", path);
         }
+      else
+        break;
+    }
+
+  if (ret_layout->boot_dfd == -1)
+    {
+      /* No legacy found?  We're done */
+      *out_layout = NULL;
+      return TRUE;
     }
 
+  /* ret_layout->boot_dfd will point to either /usr/lib/ostree-boot or /boot, let's
+   * inspect it.
+   */
   g_auto(GLnxDirFdIterator) dfditer = { 0, };
-  if (!glnx_dirfd_iterator_init_at (ret_boot_dfd, ".", FALSE, &dfditer, error))
+  if (!glnx_dirfd_iterator_init_at (ret_layout->boot_dfd, ".", FALSE, &dfditer, error))
     return FALSE;
 
   while (TRUE)
@@ -930,62 +1057,143 @@ get_kernel_from_tree (int             deployment_dfd,
 
       if (!glnx_dirfd_iterator_next_dent (&dfditer, &dent, cancellable, error))
         return FALSE;
-
       if (dent == NULL)
         break;
 
       const char *name = dent->d_name;
-      if (ret_kernel_srcpath == NULL && g_str_has_prefix (name, "vmlinuz-"))
+      /* See if this is the kernel */
+      if (ret_layout->kernel_srcpath == NULL && g_str_has_prefix (name, "vmlinuz-"))
         {
           const char *dash = strrchr (name, '-');
           g_assert (dash);
+          /* In this version, we require that the tree builder generated a
+           * sha256 of the kernel+initramfs and appended it to the file names.
+           */
           if (ostree_validate_structureof_checksum_string (dash + 1, NULL))
             {
               kernel_checksum = g_strdup (dash + 1);
-              ret_kernel_srcpath = g_strdup (name);
-              ret_kernel_namever = g_strndup (name, dash - name);
+              ret_layout->kernel_srcpath = g_strdup (name);
+              ret_layout->kernel_namever = g_strndup (name, dash - name);
             }
         }
-      else if (ret_initramfs_srcpath == NULL && g_str_has_prefix (name, "initramfs-"))
+      /* See if this is the initramfs  */
+      else if (ret_layout->initramfs_srcpath == NULL && g_str_has_prefix (name, "initramfs-"))
         {
           const char *dash = strrchr (name, '-');
           g_assert (dash);
           if (ostree_validate_structureof_checksum_string (dash + 1, NULL))
             {
               initramfs_checksum = g_strdup (dash + 1);
-              ret_initramfs_srcpath = g_strdup (name);
-              ret_initramfs_namever = g_strndup (name, dash - name);
+              ret_layout->initramfs_srcpath = g_strdup (name);
+              ret_layout->initramfs_namever = g_strndup (name, dash - name);
             }
         }
 
-      if (ret_kernel_srcpath != NULL && ret_initramfs_srcpath != NULL)
+      /* If we found both a kernel and initramfs, break out of the loop */
+      if (ret_layout->kernel_srcpath != NULL && ret_layout->initramfs_srcpath != NULL)
         break;
     }
 
-  if (ret_kernel_srcpath == NULL)
+  /* No kernel found?  We're done */
+  if (ret_layout->kernel_srcpath == NULL)
     {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                   "Failed to find kernel in /usr/lib/ostree-boot or /boot");
-      return FALSE;
+      *out_layout = NULL;
+      return TRUE;
     }
 
-  if (ret_initramfs_srcpath != NULL)
+  /* The kernel/initramfs checksums must be the same */
+  if (ret_layout->initramfs_srcpath != NULL)
     {
+      g_assert (kernel_checksum != NULL);
+      g_assert (initramfs_checksum != NULL);
       if (strcmp (kernel_checksum, initramfs_checksum) != 0)
+        return glnx_throw (error, "Mismatched kernel checksum vs initrd");
+      ret_layout->bootcsum = g_steal_pointer (&kernel_checksum);
+    }
+
+  *out_layout = g_steal_pointer (&ret_layout);
+  return TRUE;
+}
+
+/* Locate kernel/initramfs in the tree; the current standard is to look in
+ * /usr/lib/modules/$kver/vmlinuz first.
+ *
+ * Originally OSTree defined kernels to be found underneath /boot
+ * in the tree.  But that means when mounting /boot at runtime
+ * we end up masking the content underneath, triggering a warning.
+ *
+ * For that reason, and also consistency with the "/usr defines the OS" model we
+ * later switched to defining the in-tree kernels to be found under
+ * /usr/lib/ostree-boot. But since then, Fedora at least switched to storing the
+ * kernel in /usr/lib/modules, which makes sense and isn't ostree-specific, so
+ * we prefer that now. However, the default Fedora layout doesn't put the
+ * initramfs there, so we need to look in /usr/lib/ostree-boot first.
+ */
+static gboolean
+get_kernel_from_tree (int                  deployment_dfd,
+                      OstreeKernelLayout **out_layout,
+                      GCancellable        *cancellable,
+                      GError             **error)
+{
+  g_autoptr(OstreeKernelLayout) usrlib_modules_layout = NULL;
+  g_autoptr(OstreeKernelLayout) legacy_layout = NULL;
+
+  /* First, gather from usr/lib/modules/$kver if it exists */
+  if (!get_kernel_from_tree_usrlib_modules (deployment_dfd, &usrlib_modules_layout, cancellable, error))
+    return FALSE;
+
+  /* Gather the legacy layout */
+  if (!get_kernel_from_tree_legacy_layouts (deployment_dfd, &legacy_layout, cancellable, error))
+    return FALSE;
+
+  /* Evaluate the state of both layouts.  If there's no legacy layout
+   * If a legacy layout exists, and it has
+   * an initramfs but the module layout doesn't, the legacy layout wins. This is
+   * what happens with rpm-ostree with Fedora today, until rpm-ostree learns the
+   * new layout.
+   */
+  if (legacy_layout == NULL)
+    {
+      /* No legacy layout, let's see if we have a module layout...*/
+      if (usrlib_modules_layout == NULL)
         {
+          /* Both layouts are not found?  Throw. */
           g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-                       "Mismatched kernel checksum vs initrd");
+                       "Failed to find kernel in /usr/lib/modules, /usr/lib/ostree-boot or /boot");
           return FALSE;
         }
+      else
+        {
+          /* No legacy, just usr/lib/modules?  We're done */
+          *out_layout = g_steal_pointer (&usrlib_modules_layout);
+          return TRUE;
+        }
+    }
+  else if (usrlib_modules_layout != NULL &&
+           usrlib_modules_layout->initramfs_srcpath == NULL &&
+           legacy_layout->initramfs_srcpath != NULL)
+    {
+      /* Does the module path not have an initramfs, but the legacy does?  Prefer
+       * the latter then, to make rpm-ostree work as is today.
+       */
+      *out_layout = g_steal_pointer (&legacy_layout);
+      return TRUE;
+    }
+  /* Prefer module layout */
+  else if (usrlib_modules_layout != NULL)
+    {
+      *out_layout = g_steal_pointer (&usrlib_modules_layout);
+      return TRUE;
+    }
+  else
+    {
+      /* And finally fall back to legacy; we know one exists since we
+       * checked first above.
+       */
+      g_assert (legacy_layout->kernel_srcpath);
+      *out_layout = g_steal_pointer (&legacy_layout);
+      return TRUE;
     }
-
-  *out_boot_dfd = glnx_steal_fd (&ret_boot_dfd);
-  *out_kernel_srcpath = g_steal_pointer (&ret_kernel_srcpath);
-  *out_kernel_namever = g_steal_pointer (&ret_kernel_namever);
-  *out_initramfs_srcpath = g_steal_pointer (&ret_initramfs_srcpath);
-  *out_initramfs_namever = g_steal_pointer (&ret_initramfs_namever);
-  *out_bootcsum = g_steal_pointer (&kernel_checksum);
-  return TRUE;
 }
 
 /* We used to syncfs(), but that doesn't flush the journal on XFS,
@@ -1315,18 +1523,8 @@ install_deployment_kernel (OstreeSysroot   *sysroot,
     return FALSE;
 
   /* Find the kernel/initramfs in the tree */
-  glnx_fd_close int tree_boot_dfd = -1;
-  g_autofree char *tree_kernel_srcpath = NULL;
-  g_autofree char *tree_kernel_namever = NULL;
-  g_autofree char *tree_initramfs_srcpath = NULL;
-  g_autofree char *tree_initramfs_namever = NULL;
-  g_autofree char *tree_bootcsum = NULL;
-  if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd,
-                             &tree_kernel_srcpath,
-                             &tree_kernel_namever,
-                             &tree_initramfs_srcpath,
-                             &tree_initramfs_namever,
-                             &tree_bootcsum,
+  g_autoptr(OstreeKernelLayout) kernel_layout = NULL;
+  if (!get_kernel_from_tree (deployment_dfd, &kernel_layout,
                              cancellable, error))
     return FALSE;
 
@@ -1336,7 +1534,7 @@ install_deployment_kernel (OstreeSysroot   *sysroot,
 
   const char *osname = ostree_deployment_get_osname (deployment);
   const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
-  g_assert_cmpstr (bootcsum, ==, tree_bootcsum);
+  g_assert_cmpstr (kernel_layout->bootcsum, ==, bootcsum);
   g_autofree char *bootcsumdir = g_strdup_printf ("ostree/%s-%s", osname, bootcsum);
   g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", new_bootversion);
   g_autofree char *bootconf_name = g_strdup_printf ("ostree-%s-%d.conf", osname,
@@ -1355,12 +1553,13 @@ install_deployment_kernel (OstreeSysroot   *sysroot,
    * it doesn't exist already.
    */
   struct stat stbuf;
-  if (fstatat (bootcsum_dfd, tree_kernel_namever, &stbuf, 0) != 0)
+  if (fstatat (bootcsum_dfd, kernel_layout->kernel_namever, &stbuf, 0) != 0)
     {
       if (errno != ENOENT)
-        return glnx_throw_errno_prefix (error, "fstat %s", tree_kernel_namever);
-      if (!hardlink_or_copy_at (tree_boot_dfd, tree_kernel_srcpath,
-                                bootcsum_dfd, tree_kernel_namever,
+        return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->kernel_namever);
+      if (!hardlink_or_copy_at (kernel_layout->boot_dfd,
+                                kernel_layout->kernel_srcpath,
+                                bootcsum_dfd, kernel_layout->kernel_namever,
                                 sysroot->debug_flags,
                                 cancellable, error))
         return FALSE;
@@ -1369,15 +1568,15 @@ install_deployment_kernel (OstreeSysroot   *sysroot,
   /* If we have an initramfs, then install it into
    * /boot/ostree/osname-${bootcsum} if it doesn't exist already.
    */
-  if (tree_initramfs_srcpath)
+  if (kernel_layout->initramfs_srcpath)
     {
-      g_assert (tree_initramfs_namever);
-      if (fstatat (bootcsum_dfd, tree_initramfs_namever, &stbuf, 0) != 0)
+      g_assert (kernel_layout->initramfs_namever);
+      if (fstatat (bootcsum_dfd, kernel_layout->initramfs_namever, &stbuf, 0) != 0)
         {
           if (errno != ENOENT)
-            return glnx_throw_errno_prefix (error, "fstat %s", tree_initramfs_namever);
-          if (!hardlink_or_copy_at (tree_boot_dfd, tree_initramfs_srcpath,
-                                    bootcsum_dfd, tree_initramfs_namever,
+            return glnx_throw_errno_prefix (error, "fstat %s", kernel_layout->initramfs_namever);
+          if (!hardlink_or_copy_at (kernel_layout->boot_dfd, kernel_layout->initramfs_srcpath,
+                                    bootcsum_dfd, kernel_layout->initramfs_namever,
                                     sysroot->debug_flags,
                                     cancellable, error))
             return FALSE;
@@ -1458,12 +1657,12 @@ install_deployment_kernel (OstreeSysroot   *sysroot,
 
   g_autofree char *version_key = g_strdup_printf ("%d", n_deployments - ostree_deployment_get_index (deployment));
   ostree_bootconfig_parser_set (bootconfig, OSTREE_COMMIT_META_KEY_VERSION, version_key);
-  g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", tree_kernel_namever, NULL);
+  g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->kernel_namever, NULL);
   ostree_bootconfig_parser_set (bootconfig, "linux", boot_relpath);
 
-  if (tree_initramfs_namever)
+  if (kernel_layout->initramfs_namever)
     {
-      g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", tree_initramfs_namever, NULL);
+      g_autofree char * boot_relpath = g_strconcat ("/", bootcsumdir, "/", kernel_layout->initramfs_namever, NULL);
       ostree_bootconfig_parser_set (bootconfig, "initrd", boot_relpath);
     }
 
@@ -2084,22 +2283,12 @@ ostree_sysroot_deploy_tree (OstreeSysroot     *self,
       return FALSE;
     }
 
-  glnx_fd_close int tree_boot_dfd = -1;
-  g_autofree char *tree_kernel_srcpath = NULL;
-  g_autofree char *tree_kernel_namever = NULL;
-  g_autofree char *tree_initramfs_srcpath = NULL;
-  g_autofree char *tree_initramfs_namever = NULL;
-  g_autofree char *tree_bootcsum = NULL;
-  if (!get_kernel_from_tree (deployment_dfd, &tree_boot_dfd,
-                             &tree_kernel_srcpath,
-                             &tree_kernel_namever,
-                             &tree_initramfs_srcpath,
-                             &tree_initramfs_namever,
-                             &new_bootcsum,
+  g_autoptr(OstreeKernelLayout) kernel_layout = NULL;
+  if (!get_kernel_from_tree (deployment_dfd, &kernel_layout,
                              cancellable, error))
     return FALSE;
 
-  _ostree_deployment_set_bootcsum (new_deployment, new_bootcsum);
+  _ostree_deployment_set_bootcsum (new_deployment, kernel_layout->bootcsum);
 
   /* Create an empty boot configuration; we will merge things into
    * it as we go.
index ff096505328dccc8837a1b69154f2fc70c297f5b..ce7cc3d9ae41fc2420f8e6afc6275ba36491a420 100755 (executable)
@@ -366,7 +366,7 @@ setup_os_repository () {
     shift
     bootmode=$1
     shift
-    bootdir=${1:-usr/lib/ostree-boot}
+    bootdir=${1:-usr/lib/modules/3.6.0}
 
     oldpwd=`pwd`
 
@@ -381,17 +381,24 @@ setup_os_repository () {
     cd ${test_tmpdir}
     mkdir osdata
     cd osdata
-    mkdir -p usr/bin usr/lib/modules/3.6.0 usr/share usr/etc
-    mkdir -p ${bootdir}
-    echo "a kernel" > ${bootdir}/vmlinuz-3.6.0
-    echo "an initramfs" > ${bootdir}/initramfs-3.6.0
-    bootcsum=$(cat ${bootdir}/vmlinuz-3.6.0 ${bootdir}/initramfs-3.6.0 | sha256sum | cut -f 1 -d ' ')
+    mkdir -p usr/bin ${bootdir} usr/lib/modules/3.6.0 usr/share usr/etc
+    kernel_path=${bootdir}/vmlinuz
+    initramfs_path=${bootdir}/initramfs
+    # /usr/lib/modules just uses "vmlinuz", since the version is in the module
+    # directory name.
+    if [[ $bootdir != usr/lib/modules/* ]]; then
+        kernel_path=${kernel_path}-3.6.0
+        initramfs_path=${initramfs_path}-3.6.0
+    fi
+    echo "a kernel" > ${kernel_path}
+    echo "an initramfs" > ${initramfs_path}
+    bootcsum=$(cat ${kernel_path} ${initramfs_path} | sha256sum | cut -f 1 -d ' ')
     export bootcsum
     # Add the checksum for legacy dirs (/boot, /usr/lib/ostree-boot), but not
     # /usr/lib/modules.
-    if [[ $bootdir != usr/lib/modules ]]; then
-        mv ${bootdir}/vmlinuz-3.6.0{,-${bootcsum}}
-        mv ${bootdir}/initramfs-3.6.0{,-${bootcsum}}
+    if [[ $bootdir != usr/lib/modules/* ]]; then
+        mv ${kernel_path}{,-${bootcsum}}
+        mv ${initramfs_path}{,-${bootcsum}}
     fi
 
     echo "an executable" > usr/bin/sh
@@ -412,7 +419,7 @@ EOF
     echo "a default daemon file" > usr/etc/testdirectory/test
 
     ${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
-    
+
     # Ensure these commits have distinct second timestamps
     sleep 2
     echo "a new executable" > usr/bin/sh
@@ -447,7 +454,7 @@ EOF
         setup_os_boot_grub2 "${bootmode}"
             ;;
     esac
-    
+
     cd ${test_tmpdir}
     mkdir ${test_tmpdir}/httpd
     cd httpd
@@ -465,17 +472,30 @@ os_repository_new_commit ()
     branch=${3:-testos/buildmaster/x86_64-runtime}
     echo "BOOT ITERATION: $boot_checksum_iteration"
     cd ${test_tmpdir}/osdata
-    bootdir=usr/lib/ostree-boot
-    if ! test -d ${bootdir}; then
-        bootdir=boot
+    if test -f usr/lib/modules/3.6.0/vmlinuz; then
+        bootdir=usr/lib/modules/3.6.0
+    else
+        if test -d usr/lib/ostree-boot; then
+            bootdir=usr/lib/ostree-boot
+        else
+            bootdir=boot
+        fi
     fi
     rm ${bootdir}/*
-    echo "new: a kernel ${boot_checksum_iteration}" > ${bootdir}/vmlinuz-3.6.0
-    echo "new: an initramfs ${boot_checksum_iteration}" > ${bootdir}/initramfs-3.6.0
-    bootcsum=$(cat ${bootdir}/vmlinuz-3.6.0 ${bootdir}/initramfs-3.6.0 | sha256sum | cut -f 1 -d ' ')
+    kernel_path=${bootdir}/vmlinuz
+    initramfs_path=${bootdir}/initramfs
+    if [[ $bootdir != usr/lib/modules/* ]]; then
+        kernel_path=${kernel_path}-3.6.0
+        initramfs_path=${initramfs_path}-3.6.0
+    fi
+    echo "new: a kernel ${boot_checksum_iteration}" > ${kernel_path}
+    echo "new: an initramfs ${boot_checksum_iteration}" > ${initramfs_path}
+    bootcsum=$(cat ${kernel_path} ${initramfs_path} | sha256sum | cut -f 1 -d ' ')
     export bootcsum
-    mv ${bootdir}/vmlinuz-3.6.0 ${bootdir}/vmlinuz-3.6.0-${bootcsum}
-    mv ${bootdir}/initramfs-3.6.0 ${bootdir}/initramfs-3.6.0-${bootcsum}
+    if [[ $bootdir != usr/lib/modules/* ]]; then
+        mv ${kernel_path}{,-${bootcsum}}
+        mv ${initramfs_path}{,-${bootcsum}}
+    fi
 
     echo "a new default config file" > usr/etc/a-new-default-config-file
     mkdir -p usr/etc/new-default-dir
index b19a74f07dbe85947ac9edae846ffc98702a84ea..2a3c497db41375a0f04ab111bfe7197bf5438eb4 100755 (executable)
@@ -19,7 +19,7 @@
 
 set -euo pipefail
 
-echo "1..20"
+echo "1..22"
 
 . $(dirname $0)/libtest.sh
 
@@ -28,22 +28,43 @@ setup_os_repository "archive-z2" "syslinux"
 
 . $(dirname $0)/admin-test.sh
 
+# Test the legacy dirs
+for test_bootdir in "boot" "usr/lib/ostree-boot"; do
+    cd ${test_tmpdir}
+    rm httpd osdata testos-repo sysroot -rf
+    setup_os_repository "archive" "syslinux" $test_bootdir
+    ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
+    rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
+    ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
+    assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.* root=LABEL=MOO'
+    assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.* quiet'
+    assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel'
+    assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0 'an initramfs'
+    # kernel/initrams should also be in the tree's /boot with the checksum
+    assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/$test_bootdir/vmlinuz-3.6.0-${bootcsum} 'a kernel'
+    assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/$test_bootdir/initramfs-3.6.0-${bootcsum} 'an initramfs'
+    assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/os-release 'NAME=TestOS'
+    assert_file_has_content sysroot/ostree/boot.1/testos/${bootcsum}/0/etc/os-release 'NAME=TestOS'
+    ${CMD_PREFIX} ostree admin status
+    validate_bootloader
+    echo "ok kernel in $test_bootdir"
+done
+
+# And test that legacy overrides /usr/lib/modules
 cd ${test_tmpdir}
 rm httpd osdata testos-repo sysroot -rf
-setup_os_repository "archive-z2" "syslinux" "boot"
-
+setup_os_repository "archive" "syslinux" "usr/lib/ostree-boot"
+cd osdata
+echo "this is a kernel without an initramfs like Fedora 26" > usr/lib/modules/3.6.0/vmlinuz
+usrlib_modules_bootcsum=$(cat usr/lib/modules/3.6.0/vmlinuz | sha256sum | cut -f 1 -d ' ')
+${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
+cd ${test_tmpdir}
 ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
 rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
 ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
 assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.* root=LABEL=MOO'
-assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.* quiet'
 assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel'
 assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0 'an initramfs'
-# kernel/initrams should also be in the tree's /boot with the checksum
-assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/boot/vmlinuz-3.6.0-${bootcsum} 'a kernel'
-assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/boot/initramfs-3.6.0-${bootcsum} 'an initramfs'
-assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.0/etc/os-release 'NAME=TestOS'
-assert_file_has_content sysroot/ostree/boot.1/testos/${bootcsum}/0/etc/os-release 'NAME=TestOS'
-${CMD_PREFIX} ostree admin status
-validate_bootloader
-echo "ok kernel in tree's /boot"
+# Note this bootcsum shouldn't be the modules one
+assert_not_streq "${bootcsum}" "${usrlib_modules_bootcsum}"
+echo "ok kernel in /usr/lib/modules and /usr/lib/ostree-boot"
index 3685e31ef21181eb3bd7e7bec5f9c27f0413caa9..c7a6c751cb558bdab42e21fa54cae48a6f6b0f15 100755 (executable)
@@ -30,6 +30,7 @@ setup_os_repository "archive-z2" "uboot"
 . $(dirname $0)/admin-test.sh
 
 cd ${test_tmpdir}
+mkdir -p osdata/usr/lib/ostree-boot
 cat << 'EOF' > osdata/usr/lib/ostree-boot/uEnv.txt
 loaduimage=load mmc ${bootpart} ${loadaddr} ${kernel_image}
 loadfdt=load mmc ${bootpart} ${fdtaddr} ${bootdir}${fdtfile}