diff options
author | Jonathan Lebon <jlebon@redhat.com> | 2017-08-23 12:15:46 -0400 |
---|---|---|
committer | Atomic Bot <atomic-devel@projectatomic.io> | 2017-08-25 01:02:15 +0000 |
commit | 9342be6e34b26891c38b671ec285bdcbc9107acd (patch) | |
tree | 0f91f5606ecb11213356aa9424f468d672a6f8d2 | |
parent | d0f40a6af8fb391d5ee34ca6d4bc2abfc5b21e16 (diff) | |
download | ostree-9342be6e34b26891c38b671ec285bdcbc9107acd.tar.gz |
ostree-sysroot: make simple_write_deployment smarter
This is a follow-up to https://github.com/ostreedev/ostree/pull/1097.
We make simple_write_deployment smart enough so that it can be used for
rpm-ostree's purposes. This is mostly an upstreaming of logic that
already existed there.
Notably we correctly append NOT_DEFAULT deployments *after* the booted
deployment and we now support RETAIN_PENDING and RETAIN_ROLLBACK flags
to have more granularity on deployment pruning.
Expose these new flags on the CLI using new options (as well as expose
the previously existing NOT_DEFAULT flag as --not-as-default).
I couldn't add tests for --retain-pending because the merge deployment
is always the topmost one. Though I did check that it worked in a VM.
Closes: #1110
Approved by: cgwalters
-rw-r--r-- | bash/ostree | 3 | ||||
-rw-r--r-- | man/ostree-admin-deploy.xml | 24 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.c | 70 | ||||
-rw-r--r-- | src/libostree/ostree-sysroot.h | 2 | ||||
-rw-r--r-- | src/ostree/ot-admin-builtin-deploy.c | 42 | ||||
-rw-r--r-- | tests/admin-test.sh | 35 | ||||
-rwxr-xr-x | tests/test-admin-deploy-grub2.sh | 4 | ||||
-rwxr-xr-x | tests/test-admin-deploy-syslinux.sh | 4 | ||||
-rwxr-xr-x | tests/test-admin-deploy-uboot.sh | 4 |
9 files changed, 145 insertions, 43 deletions
diff --git a/bash/ostree b/bash/ostree index f4305f69..fadb054d 100644 --- a/bash/ostree +++ b/bash/ostree @@ -253,6 +253,9 @@ _ostree_admin_deploy() { local boolean_options=" $main_boolean_options --retain + --retain-pending + --retain-rollback + --not-as-default --karg-proc-cmdline " diff --git a/man/ostree-admin-deploy.xml b/man/ostree-admin-deploy.xml index 347a4ba9..ec705b93 100644 --- a/man/ostree-admin-deploy.xml +++ b/man/ostree-admin-deploy.xml @@ -90,6 +90,30 @@ Boston, MA 02111-1307, USA. </varlistentry> <varlistentry> + <term><option>--retain-pending</option></term> + + <listitem><para> + Do not delete pending deployments. + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>--retain-rollback</option></term> + + <listitem><para> + Do not delete rollback deployments. + </para></listitem> + </varlistentry> + + <varlistentry> + <term><option>--not-as-default</option></term> + + <listitem><para> + Append rather than prepend new deployment. + </para></listitem> + </varlistentry> + + <varlistentry> <term><option>--karg-proc-cmdline</option></term> <listitem><para> diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c index 65cfb7c3..8e6c475c 100644 --- a/src/libostree/ostree-sysroot.c +++ b/src/libostree/ostree-sysroot.c @@ -1487,6 +1487,12 @@ ostree_sysroot_init_osname (OstreeSysroot *self, * If %OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN is * specified, then all current deployments will be kept. * + * If %OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_PENDING is + * specified, then pending deployments will be kept. + * + * If %OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_ROLLBACK is + * specified, then rollback deployments will be kept. + * * If %OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT is * specified, then instead of prepending, the new deployment will be * added right after the booted or merge deployment, instead of first. @@ -1507,10 +1513,14 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, { const gboolean postclean = (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN) == 0; - const gboolean retain = - (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN) > 0; const gboolean make_default = !((flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT) > 0); + const gboolean retain_pending = + (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_PENDING) > 0; + const gboolean retain_rollback = + (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_ROLLBACK) > 0; + gboolean retain = + (flags & OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN) > 0; g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot); OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); @@ -1526,34 +1536,54 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot, added_new = TRUE; } + /* without a booted and a merge deployment, retain_pending/rollback become meaningless; + * let's just retain all deployments in that case */ + if (!booted_deployment && !merge_deployment && (retain_pending || retain_rollback)) + retain = TRUE; + + /* tracks when we come across the booted deployment */ + gboolean before_booted = TRUE; + gboolean before_merge = TRUE; for (guint i = 0; i < deployments->len; i++) { OstreeDeployment *deployment = deployments->pdata[i]; - const gboolean is_merge_or_booted = - ostree_deployment_equal (deployment, booted_deployment) || - ostree_deployment_equal (deployment, merge_deployment); - - /* Keep deployments with different osnames, as well as the - * booted and merge deployments + const gboolean osname_matches = + (osname == NULL || g_str_equal (ostree_deployment_get_osname (deployment), osname)); + const gboolean is_booted = ostree_deployment_equal (deployment, booted_deployment); + const gboolean is_merge = ostree_deployment_equal (deployment, merge_deployment); + + if (is_booted) + before_booted = FALSE; + if (is_merge) + before_merge = FALSE; + + /* use the booted deployment as the "crossover" point between pending and rollback + * deployments, fall back on merge deployment */ + const gboolean passed_crossover = booted_deployment ? !before_booted : !before_merge; + + /* Retain deployment if: + * - we're explicitly asked to, or + * - the deployment is for another osname, or + * - we're keeping pending deployments and this is a pending deployment, or + * - this is the merge or boot deployment, or + * - we're keeping rollback deployments and this is a rollback deployment */ - if (retain || - (osname != NULL && strcmp (ostree_deployment_get_osname (deployment), osname) != 0) || - is_merge_or_booted) - { - g_ptr_array_add (new_deployments, g_object_ref (deployment)); - } - - if ((!added_new) && is_merge_or_booted) + if (retain + || !osname_matches + || (retain_pending && !passed_crossover) + || (is_booted || is_merge) + || (retain_rollback && passed_crossover)) + g_ptr_array_add (new_deployments, g_object_ref (deployment)); + + /* add right after booted/merge deployment */ + if (!added_new && passed_crossover) { g_ptr_array_add (new_deployments, g_object_ref (new_deployment)); added_new = TRUE; } } - /* In this non-default case , an improvement in the future would be - * to put the new deployment right after the current default in the - * order. - */ + /* add it last if no crossover defined (or it's the first deployment in the sysroot) */ if (!added_new) { g_ptr_array_add (new_deployments, g_object_ref (new_deployment)); diff --git a/src/libostree/ostree-sysroot.h b/src/libostree/ostree-sysroot.h index 3d2446f9..f2573d6b 100644 --- a/src/libostree/ostree-sysroot.h +++ b/src/libostree/ostree-sysroot.h @@ -207,6 +207,8 @@ typedef enum { OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN = (1 << 0), OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT = (1 << 1), OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN = (1 << 2), + OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_PENDING = (1 << 3), + OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_ROLLBACK = (1 << 4), } OstreeSysrootSimpleWriteDeploymentFlags; _OSTREE_PUBLIC diff --git a/src/ostree/ot-admin-builtin-deploy.c b/src/ostree/ot-admin-builtin-deploy.c index d67de791..fa588f87 100644 --- a/src/ostree/ot-admin-builtin-deploy.c +++ b/src/ostree/ot-admin-builtin-deploy.c @@ -33,6 +33,9 @@ #include <glib/gi18n.h> static gboolean opt_retain; +static gboolean opt_retain_pending; +static gboolean opt_retain_rollback; +static gboolean opt_not_as_default; static char **opt_kernel_argv; static char **opt_kernel_argv_append; static gboolean opt_kernel_proc_cmdline; @@ -47,7 +50,10 @@ static char *opt_origin_path; static GOptionEntry options[] = { { "os", 0, 0, G_OPTION_ARG_STRING, &opt_osname, "Use a different operating system root than the current one", "OSNAME" }, { "origin-file", 0, 0, G_OPTION_ARG_FILENAME, &opt_origin_path, "Specify origin file", "FILENAME" }, - { "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployment", NULL }, + { "retain", 0, 0, G_OPTION_ARG_NONE, &opt_retain, "Do not delete previous deployments", NULL }, + { "retain-pending", 0, 0, G_OPTION_ARG_NONE, &opt_retain_pending, "Do not delete pending deployments", NULL }, + { "retain-rollback", 0, 0, G_OPTION_ARG_NONE, &opt_retain_rollback, "Do not delete rollback deployments", NULL }, + { "not-as-default", 0, 0, G_OPTION_ARG_NONE, &opt_not_as_default, "Append rather than prepend new deployment", NULL }, { "karg-proc-cmdline", 0, 0, G_OPTION_ARG_NONE, &opt_kernel_proc_cmdline, "Import current /proc/cmdline", NULL }, { "karg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv, "Set kernel argument, like root=/dev/sda1; this overrides any earlier argument with the same name", "NAME=VALUE" }, { "karg-append", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_kernel_argv_append, "Append kernel argument; useful with e.g. console= that can be used multiple times", "NAME=VALUE" }, @@ -145,22 +151,28 @@ ot_admin_builtin_deploy (int argc, char **argv, GCancellable *cancellable, GErro _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append); } - { - g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); - g_autoptr(OstreeDeployment) new_deployment = NULL; - if (!ostree_sysroot_deploy_tree (sysroot, - opt_osname, revision, origin, - merge_deployment, kargs_strv, - &new_deployment, - cancellable, error)) - return FALSE; - } + g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs); + if (!ostree_sysroot_deploy_tree (sysroot, opt_osname, revision, origin, merge_deployment, + kargs_strv, &new_deployment, cancellable, error)) + return FALSE; + + OstreeSysrootSimpleWriteDeploymentFlags flags = 0; + if (opt_retain) + flags |= OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN; + else + { + if (opt_retain_pending) + flags |= OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_PENDING; + if (opt_retain_rollback) + flags |= OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN_ROLLBACK; + } + + if (opt_not_as_default) + flags |= OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NOT_DEFAULT; - if (!ostree_sysroot_simple_write_deployment (sysroot, opt_osname, - new_deployment, merge_deployment, - opt_retain ? OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN : 0, - cancellable, error)) + if (!ostree_sysroot_simple_write_deployment (sysroot, opt_osname, new_deployment, + merge_deployment, flags, cancellable, error)) return FALSE; return TRUE; diff --git a/tests/admin-test.sh b/tests/admin-test.sh index 55de7235..d5566959 100644 --- a/tests/admin-test.sh +++ b/tests/admin-test.sh @@ -19,6 +19,8 @@ set -euo pipefail +echo "1..$((21 + ${extra_admin_tests:-0}))" + function validate_bootloader() { cd ${test_tmpdir}; bootloader="" @@ -130,6 +132,8 @@ rm -r sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/testdirectory rm sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/aconfigfile ln -s /ENOENT sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/a-new-broken-symlink ${CMD_PREFIX} ostree admin deploy --retain --os=testos testos:testos/buildmaster/x86_64-runtime +assert_not_has_dir sysroot/boot/loader.0 +assert_has_dir sysroot/boot/loader.1 linktarget=$(readlink sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/a-new-broken-symlink) test "${linktarget}" = /ENOENT assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/os-release 'NAME=TestOS' @@ -138,9 +142,36 @@ assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/a-new-c assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/aconfigfile ${CMD_PREFIX} ostree admin status validate_bootloader - echo "ok deploy with modified /etc" +# we now have 5 deployments, let's bring that back down to 1 +for i in $(seq 4); do + ${CMD_PREFIX} ostree admin undeploy 0 +done +assert_has_file sysroot/boot/loader/entries/ostree-testos-0.conf +assert_not_has_file sysroot/boot/loader/entries/ostree-testos-1.conf +assert_not_has_file sysroot/boot/loader/entries/ostree-otheros-1.conf +${CMD_PREFIX} ostree admin deploy --not-as-default --os=otheros testos:testos/buildmaster/x86_64-runtime +assert_has_dir sysroot/boot/loader.0 +assert_not_has_dir sysroot/boot/loader.1 +assert_has_file sysroot/boot/loader/entries/ostree-testos-0.conf +assert_has_file sysroot/boot/loader/entries/ostree-otheros-1.conf +${CMD_PREFIX} ostree admin status +validate_bootloader + +echo "ok deploy --not-as-default" + +${CMD_PREFIX} ostree admin deploy --retain-rollback --os=otheros testos:testos/buildmaster/x86_64-runtime +assert_not_has_dir sysroot/boot/loader.0 +assert_has_dir sysroot/boot/loader.1 +assert_has_file sysroot/boot/loader/entries/ostree-otheros-0.conf +assert_has_file sysroot/boot/loader/entries/ostree-testos-1.conf +assert_has_file sysroot/boot/loader/entries/ostree-otheros-2.conf +${CMD_PREFIX} ostree admin status +validate_bootloader + +echo "ok deploy --retain-rollback" + os_repository_new_commit ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos:testos/buildmaster/x86_64-runtime) @@ -153,7 +184,7 @@ assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/os-r assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/a-new-default-config-file "a new default config file" assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/new-default-dir/moo "a new default dir and file" # And persist /etc changes from before -assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/aconfigfile +assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/aconfigfile ${CMD_PREFIX} ostree admin status validate_bootloader diff --git a/tests/test-admin-deploy-grub2.sh b/tests/test-admin-deploy-grub2.sh index 6f785df5..60c7d05f 100755 --- a/tests/test-admin-deploy-grub2.sh +++ b/tests/test-admin-deploy-grub2.sh @@ -19,11 +19,11 @@ set -euo pipefail -echo "1..19" - . $(dirname $0)/libtest.sh # Exports OSTREE_SYSROOT so --sysroot not needed. setup_os_repository "archive-z2" "grub2 ostree-grub-generator" +extra_admin_tests=0 + . $(dirname $0)/admin-test.sh diff --git a/tests/test-admin-deploy-syslinux.sh b/tests/test-admin-deploy-syslinux.sh index 3516c478..08f26b5e 100755 --- a/tests/test-admin-deploy-syslinux.sh +++ b/tests/test-admin-deploy-syslinux.sh @@ -19,13 +19,13 @@ set -euo pipefail -echo "1..22" - . $(dirname $0)/libtest.sh # Exports OSTREE_SYSROOT so --sysroot not needed. setup_os_repository "archive-z2" "syslinux" +extra_admin_tests=3 + . $(dirname $0)/admin-test.sh # Test the legacy dirs diff --git a/tests/test-admin-deploy-uboot.sh b/tests/test-admin-deploy-uboot.sh index c7a6c751..55059b34 100755 --- a/tests/test-admin-deploy-uboot.sh +++ b/tests/test-admin-deploy-uboot.sh @@ -20,13 +20,13 @@ set -euo pipefail -echo "1..20" - . $(dirname $0)/libtest.sh # Exports OSTREE_SYSROOT so --sysroot not needed. setup_os_repository "archive-z2" "uboot" +extra_admin_tests=1 + . $(dirname $0)/admin-test.sh cd ${test_tmpdir} |