From 47f08ff01a85d9567e68b5083fbbff4887aae89e Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 5 Jan 2017 11:29:41 -0500 Subject: [PATCH] upgrade: Add support for --pull-only and --deploy-only This makes it easier to script downloading updates in the background, and only do deployments just before rebooting. Partially addresses https://github.com/ostreedev/ostree/issues/640 --- Makefile-tests.am | 1 + man/ostree-admin-upgrade.xml | 23 +++++++++- src/libostree/ostree-sysroot-upgrader.c | 3 +- src/libostree/ostree-sysroot-upgrader.h | 3 +- src/ostree/ot-admin-builtin-upgrade.c | 41 +++++++++++++++-- tests/test-admin-pull-deploy-split.sh | 59 +++++++++++++++++++++++++ 6 files changed, 124 insertions(+), 6 deletions(-) create mode 100755 tests/test-admin-pull-deploy-split.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 8dbd38114c..fd755ee15a 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -83,6 +83,7 @@ dist_test_scripts = \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ tests/test-admin-pull-deploy-commit.sh \ + tests/test-admin-pull-deploy-split.sh \ tests/test-admin-locking.sh \ tests/test-admin-deploy-clean.sh \ tests/test-repo-checkout-subpath.sh \ diff --git a/man/ostree-admin-upgrade.xml b/man/ostree-admin-upgrade.xml index ddd33dc63a..7766c66e4e 100644 --- a/man/ostree-admin-upgrade.xml +++ b/man/ostree-admin-upgrade.xml @@ -57,7 +57,10 @@ Boston, MA 02111-1307, USA. Description - Downloads the latest version of the current ref from the build server and deploys it, if it changed. Reboot the machine for the changes to take effect. + Downloads the latest version of the current ref from the build + server and deploys it, if it changed. Reboot the machine for the + changes to take effect. These phases can be split via + and . @@ -73,6 +76,24 @@ Boston, MA 02111-1307, USA. + + + + Only perform a pull into the repository; do not + create a deployment. This option can hence safely be used in a + background scheduled job with the assurance of not changing + system state. + + + + + + Create a new deployment from the latest commit + in the tracked origin refspec. This option is intended to be used + by a scheduled system that detected changes via , + and is ready to deploy them. + + , diff --git a/src/libostree/ostree-sysroot-upgrader.c b/src/libostree/ostree-sysroot-upgrader.c index daf2445c11..232f843583 100644 --- a/src/libostree/ostree-sysroot-upgrader.c +++ b/src/libostree/ostree-sysroot-upgrader.c @@ -552,7 +552,8 @@ ostree_sysroot_upgrader_pull_one_dir (OstreeSysrootUpgrader *self, g_assert (self->merge_deployment); from_revision = ostree_deployment_get_csum (self->merge_deployment); - if (self->origin_remote) + if (self->origin_remote && + (upgrader_flags & OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_SYNTHETIC) == 0) { if (!ostree_repo_pull_one_dir (repo, self->origin_remote, dir_to_pull, refs_to_fetch, flags, progress, diff --git a/src/libostree/ostree-sysroot-upgrader.h b/src/libostree/ostree-sysroot-upgrader.h index 77bc8a1d20..83c4ad3259 100644 --- a/src/libostree/ostree-sysroot-upgrader.h +++ b/src/libostree/ostree-sysroot-upgrader.h @@ -85,7 +85,8 @@ gboolean ostree_sysroot_upgrader_check_timestamps (OstreeRepo *repo, typedef enum { OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_NONE = 0, - OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER = (1 << 0) + OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER = (1 << 0), + OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_SYNTHETIC = (1 << 1) /* Don't actually do a pull, just check timestamps/changed */ } OstreeSysrootUpgraderPullFlags; _OSTREE_PUBLIC diff --git a/src/ostree/ot-admin-builtin-upgrade.c b/src/ostree/ot-admin-builtin-upgrade.c index 394b339a9b..0186333bc7 100644 --- a/src/ostree/ot-admin-builtin-upgrade.c +++ b/src/ostree/ot-admin-builtin-upgrade.c @@ -34,6 +34,8 @@ static gboolean opt_reboot; static gboolean opt_allow_downgrade; +static gboolean opt_pull_only; +static gboolean opt_deploy_only; static char *opt_osname; static char *opt_override_commit; @@ -42,6 +44,8 @@ static GOptionEntry options[] = { { "reboot", 'r', 0, G_OPTION_ARG_NONE, &opt_reboot, "Reboot after a successful upgrade", NULL }, { "allow-downgrade", 0, 0, G_OPTION_ARG_NONE, &opt_allow_downgrade, "Permit deployment of chronologically older trees", NULL }, { "override-commit", 0, 0, G_OPTION_ARG_STRING, &opt_override_commit, "Deploy CHECKSUM instead of the latest tree", "CHECKSUM" }, + { "pull-only", 0, 0, G_OPTION_ARG_NONE, &opt_pull_only, "Do not create a deployment, just download", NULL }, + { "deploy-only", 0, 0, G_OPTION_ARG_NONE, &opt_deploy_only, "Do not pull, only deploy", NULL }, { NULL } }; @@ -64,6 +68,19 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr &sysroot, cancellable, error)) goto out; + if (opt_pull_only && opt_deploy_only) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Cannot simultaneously specify --pull-only and --deploy-only"); + goto out; + } + else if (opt_pull_only && opt_reboot) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Cannot simultaneously specify --pull-only and --reboot"); + goto out; + } + if (!ostree_sysroot_load (sysroot, cancellable, error)) goto out; @@ -104,6 +121,21 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr } } + /* In the pull-only case, we do a cleanup here to ensure that if multiple + * commits were pulled, we garbage collect any intermediate data before + * pulling more. This is really a best practice in general, but for maximum + * compatiblity, we only do cleanup if a user specifies the new --pull-only + * option. Otherwise, we would break the case of trying to deploy a commit + * that isn't directly referenced. + */ + if (opt_pull_only) + { + if (!ostree_sysroot_cleanup (sysroot, cancellable, error)) + goto out; + } + else if (opt_deploy_only) + upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_SYNTHETIC; + { g_auto(GLnxConsoleRef) console = { 0, }; glnx_console_lock (&console); @@ -112,7 +144,7 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr if (opt_allow_downgrade) upgraderpullflags |= OSTREE_SYSROOT_UPGRADER_PULL_FLAGS_ALLOW_OLDER; - + if (!ostree_sysroot_upgrader_pull (upgrader, 0, upgraderpullflags, progress, &changed, cancellable, error)) @@ -128,8 +160,11 @@ ot_admin_builtin_upgrade (int argc, char **argv, GCancellable *cancellable, GErr } else { - if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error)) - goto out; + if (!opt_pull_only) + { + if (!ostree_sysroot_upgrader_deploy (upgrader, cancellable, error)) + goto out; + } if (opt_reboot) { diff --git a/tests/test-admin-pull-deploy-split.sh b/tests/test-admin-pull-deploy-split.sh new file mode 100755 index 0000000000..7a6750e2d4 --- /dev/null +++ b/tests/test-admin-pull-deploy-split.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# Copyright (C) 2017 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# See https://github.com/ostreedev/ostree/pull/642 + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +echo "1..1" + +setup_os_repository "archive-z2" "syslinux" + +cd ${test_tmpdir} +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote add --set=gpg-verify=false testos $(cat httpd-address)/ostree/testos-repo +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull testos testos/buildmaster/x86_64-runtime +rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) +parent_rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse ${rev}^) +${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull testos testos/buildmaster/x86_64-runtime@${parent_rev} +${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime +assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 +assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 +# Do a pull, this one should get us new content +${CMD_PREFIX} ostree admin upgrade --os=testos --pull-only --os=testos > out.txt +assert_not_file_has_content out.txt 'No update available' +# And pull again should still tell us we have new content +${CMD_PREFIX} ostree admin upgrade --os=testos --pull-only --os=testos > out.txt +assert_not_file_has_content out.txt 'No update available' +assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 +assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 +assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'TestOS 42 1.0.9' +assert_streq "${rev}" $(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) +# Now, generate new content upstream; we shouldn't pull it +os_repository_new_commit +${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt +assert_not_file_has_content out.txt 'No update available' +assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'TestOS 42 1.0.10' +assert_has_dir sysroot/ostree/deploy/testos/deploy/${parent_rev}.0 +assert_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 +${CMD_PREFIX} ostree admin upgrade --os=testos --deploy-only --os=testos > out.txt +assert_file_has_content out.txt 'No update available' + +echo 'ok upgrade --pull-only + --deploy-only'