mirror of
https://github.com/ostreedev/ostree.git
synced 2024-12-22 17:35:55 +03:00
lib/sysroot: Support /usr/lib/modules/$kver for kernel/initramfs
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
This commit is contained in:
parent
984d22303d
commit
3ab0d5e664
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
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)
|
||||
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)
|
||||
{
|
||||
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 *kernel_checksum = NULL;
|
||||
g_autofree char *initramfs_checksum = NULL;
|
||||
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);
|
||||
|
||||
glnx_fd_close int ret_boot_dfd = glnx_opendirat_with_errno (deployment_dfd, "usr/lib/ostree-boot", TRUE);
|
||||
if (ret_boot_dfd == -1)
|
||||
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_usrlib_modules (int deployment_dfd,
|
||||
OstreeKernelLayout **out_layout,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
return glnx_throw_errno_prefix (error, "%s", "openat(usr/lib/ostree-boot)");
|
||||
else
|
||||
{
|
||||
if (!glnx_opendirat (deployment_dfd, "boot", TRUE, &ret_boot_dfd, error))
|
||||
return FALSE;
|
||||
}
|
||||
/* 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 ();
|
||||
|
||||
for (guint i = 0; i < G_N_ELEMENTS (legacy_paths); i++)
|
||||
{
|
||||
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 (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.
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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}
|
||||
|
Loading…
Reference in New Issue
Block a user