From 2b6d7d8d933144c4104b3c06abd445fc48cf197f Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Thu, 22 Aug 2013 19:14:23 -0400 Subject: [PATCH] doc: Add a section about how atomic upgrades work Migrating some content from https://live.gnome.org/OSTree/DeploymentModel2 --- doc/Makefile.am | 1 + doc/atomic-upgrades.xml | 201 ++++++++++++++++++++++++++++++++++++++++ doc/deployment.xml | 11 +++ doc/ostree-docs.xml | 1 + 4 files changed, 214 insertions(+) create mode 100644 doc/atomic-upgrades.xml diff --git a/doc/Makefile.am b/doc/Makefile.am index e67b6508..2748a70a 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -77,6 +77,7 @@ content_files= \ overview.xml \ repo.xml \ deployment.xml \ + atomic-upgrades.xml \ $(NULL) # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded diff --git a/doc/atomic-upgrades.xml b/doc/atomic-upgrades.xml new file mode 100644 index 00000000..9fb20304 --- /dev/null +++ b/doc/atomic-upgrades.xml @@ -0,0 +1,201 @@ + + +]> + + Atomic Upgrades + + You can turn off the power anytime you want... + + At the time of this writing, it's common for released versions + of mainstream operating systems (the Playstation OS, Microsoft + Windows, Debian GNU/Linux, and Red Hat Enterprise Linux) to have + non-atomic upgrades; that is, the good ones pop up a screen that + says "Please do not turn off the power". The bad ones don't + even tell you that it's unsafe. The really + bad ones actually mutate your running filesystem without taking + precautions to prevent corrupting running processes. + + + + In contrast, OSTree is designed to implement fully atomic and + safe upgrades; more generally, atomic transitions between lists + of bootable deployments. If the system crashes or you pull the + power, you will have either the old system, or the new one. + + + + + Simple upgrades via HTTP + + First, the most basic model OSTree supports is one where it + replicates pre-generated filesystem trees from a server over + HTTP, tracking exactly one ref, which is stored in the .origin file for the deployment. + The command ostree admin upgrade implements + this. + + + + To begin a simple upgrade, OSTree fetches the contents of the + ref from the remote server. Suppose we're tracking a ref named + gnome-ostree/buildmaster/x86_64-runtime. + OSTree fetches the URL + http://example.com/repo/refs/gnome-ostree/buildmaster/x86_64-runtime, + which contains a SHA256 checksum. This determines the tree to + deploy, and /etc will be + merged from currently booted tree. + + + + If we do not have this commit, then, then we perform a pull + process. At present (without static deltas), this involves + quite simply just fetching each individual object that we do not + have, asynchronously. Put in other words, we only download + changed files (zlib-compressed). Each object has its checksum + validated and is stored in /ostree/repo/objects/. + + + + Once the pull is complete, we have all the objects locally + we need to perform a deployment. + + + + + Upgrades via external tools (e.g. package managers) + + + As mentioned in the introduction, OSTree is also designed to + allow a model where filesystem trees are computed on the client. + It is completely agnostic as to how those trees are generated; + they could be computed with traditional packages, packages with + post-deployment scripts on top, or built by developers directly + from revision control locally, etc. + + + + At a practical level, most package managers today + (dpkg and rpm) operate + "live" on the currently booted filesystem. The way they could + work with OSTree is instead to take the list of installed + packages in the currently booted tree, and compute a new + filesystem from that. + + + + The most basic implementation of this would be something like + taking the result of rpm -qa, and doing + yum --installroot=/var/tmp/newroot install + package1 + package2 .... Then, + ostree commit -b osname/localtree + --tree=dir=/var/tmp/newroot. This would checksum all + of the input files and store them in local /ostree/repo repository, creating + a new commit. + + + + Now, we can move on to deployment. + + + + + Assembling a new deployment directory + + Given a commit to deploy, OSTree first allocates a directory for + it. This is of the form /boot/loader/entries/ostree-osname-checksum.serial.conf. + The serial is normally 0, but if a + given commit is deployed more than once, it will be incremented. + This is supported because the previous deployment may have + configuration in /etc + that we do not want to use or overwrite. + + + + Now that we have a deployment directory, a 3-way merge is + performed between the (by default) currently booted deployment's + /etc, its default + configuration, and the new deployment (based on its /usr/etc). + + + + + Atomically swapping boot configuration + + At this point, a new deployment directory has been created as a + hardlink farm; the running system is untouched, and the + bootloader configuration is untouched. We want to add this deployment + to the "deployment list". + + + + To support a more general case, OSTree supports atomic + transitioning between arbitrary sets of deployments, with the + restriction that the currently booted deployment must always be + in the new set. In the normal case, we have exactly one + deployment, which is the booted one, and we want to add the new + deployment to the list. A more complex command might allow + creating 100 deployments as part of one atomic transaction, so + that one can set up an automated system to bisect across them. + + + + The bootversion + + OSTree allows swapping between boot configurations by + implementing the "swapped directory pattern" in /boot. This means it is a + symbolic link to one of two directories /ostree/boot.[0|1]. + To swap the contents atomically, if the current version is + 0, we create /ostree/boot.1, populate it with + the new contents, then atomically swap the symbolic link. Finally, + the old contents can be garbage collected at any point. + + + + + The /ostree/boot directory + + However, we want to optimize for the case where we the set of + kernel/initramfs pairs is the same between both the old and + new deployment lists. This happens when doing an upgrade that + does not include the kernel; think of a simple translation + update. OSTree optimizes for this case because on some + systems /boot may be on + a separate medium such as flash storage not optimized for + significant amounts of write traffic. + + + + To implement this, OSTree also maintains the directory + /ostree/boot.bootversion, + which is a set of symbolic links to the deployment + directories. The bootversion here + must match the version of /boot. However, in order to + allow atomic transitions of this + directory, this is also a swapped directory, so just like + /boot, it has a version + of 0 or 1 appended. + + + + Each bootloader entry has a special ostree= + argument which refers to one of these symbolic links. This is + parsed at runtime in the initramfs. + + + + + + + diff --git a/doc/deployment.xml b/doc/deployment.xml index 69216e77..489850ae 100644 --- a/doc/deployment.xml +++ b/doc/deployment.xml @@ -111,6 +111,17 @@ class='directory'>/usr, but this is not a hard requirement. + + + Finally, a deployment may have a .origin file, stored next to its + directory. This file tells ostree admin + upgrade how to upgrade it. At the moment, OSTree only + supports upgrading a single refspec. However, in the future + OSTree may support a syntax for composing layers of trees, for + example. + + diff --git a/doc/ostree-docs.xml b/doc/ostree-docs.xml index 46b4cd0b..cf953c13 100644 --- a/doc/ostree-docs.xml +++ b/doc/ostree-docs.xml @@ -14,6 +14,7 @@ + API Reference