[ostree] doc: Add a section about how atomic upgrades work



commit 2b6d7d8d933144c4104b3c06abd445fc48cf197f
Author: Colin Walters <walters verbum org>
Date:   Thu Aug 22 19:14:23 2013 -0400

    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(+), 0 deletions(-)
---
diff --git a/doc/Makefile.am b/doc/Makefile.am
index e67b650..2748a70 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 0000000..9fb2030
--- /dev/null
+++ b/doc/atomic-upgrades.xml
@@ -0,0 +1,201 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
+<!ENTITY version SYSTEM "../version.xml">
+]>
+<part id="atomic-upgrades">
+  <title>Atomic Upgrades</title>
+  <chapter id="upgrades-intro">
+    <title>You can turn off the power anytime you want...</title>
+    <para>
+      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 <emphasis>really</emphasis>
+      bad ones actually mutate your running filesystem without taking
+      precautions to prevent corrupting running processes.
+    </para>
+
+    <para>
+      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.
+    </para>
+  </chapter>
+
+  <chapter id="simple-http">
+    <title>Simple upgrades via HTTP</title>
+    <para>
+      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 <filename
+      class='extension'>.origin</filename> file for the deployment.
+      The command <command>ostree admin upgrade</command> implements
+      this.
+    </para>
+
+    <para>
+      To begin a simple upgrade, OSTree fetches the contents of the
+      ref from the remote server.  Suppose we're tracking a ref named
+      <literal>gnome-ostree/buildmaster/x86_64-runtime</literal>.
+      OSTree fetches the URL
+      
<literal>http://<replaceable>example.com</replaceable>/repo/refs/gnome-ostree/buildmaster/x86_64-runtime</literal>,
+      which contains a SHA256 checksum.  This determines the tree to
+      deploy, and <filename class='directory'>/etc</filename> will be
+      merged from currently booted tree.
+    </para>
+
+    <para>
+      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 <filename
+      class='directory'>/ostree/repo/objects/</filename>.
+    </para>
+
+    <para>
+      Once the pull is complete, we have all the objects locally
+      we need to perform a deployment.
+    </para>
+  </chapter>
+
+  <chapter id="package-manager">
+    <title>Upgrades via external tools (e.g. package managers)</title>
+
+    <para>
+      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.
+    </para>
+      
+    <para>
+      At a practical level, most package managers today
+      (<command>dpkg</command> and <command>rpm</command>) 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.
+    </para>
+
+    <para>
+      The most basic implementation of this would be something like
+      taking the result of <command>rpm -qa</command>, and doing
+      <command>yum --installroot=/var/tmp/newroot install
+      <replaceable>package1</replaceable>
+      <replaceable>package2</replaceable> ...</command>.  Then,
+      <command>ostree commit -b osname/localtree
+      --tree=dir=/var/tmp/newroot</command>.  This would checksum all
+      of the input files and store them in local <filename
+      class='directory'>/ostree/repo</filename> repository, creating
+      a new commit.
+    </para>
+
+    <para>
+      Now, we can move on to deployment.
+    </para>
+  </chapter>
+
+  <chapter id="deployment-dir">
+    <title>Assembling a new deployment directory</title>
+    <para>
+      Given a commit to deploy, OSTree first allocates a directory for
+      it.  This is of the form <filename
+      
class='directory'>/boot/loader/entries/ostree-<replaceable>osname</replaceable>-<replaceable>checksum</replaceable>.<replaceable>serial</replaceable>.conf</filename>.
+      The <replaceable>serial</replaceable> 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 <filename class='directory'>/etc</filename>
+      that we do not want to use or overwrite.
+    </para>
+    
+    <para>
+      Now that we have a deployment directory, a 3-way merge is
+      performed between the (by default) currently booted deployment's
+      <filename class='directory'>/etc</filename>, its default
+      configuration, and the new deployment (based on its <filename
+      class='directory'>/usr/etc</filename>).
+    </para>
+  </chapter>
+
+  <chapter id="swapping-boot">
+    <title>Atomically swapping boot configuration</title>
+    <para>
+      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".
+    </para>
+
+    <para>
+      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.
+    </para>
+
+    <simplesect id="bootversion">
+      <title>The bootversion</title>
+      <para>
+       OSTree allows swapping between boot configurations by
+       implementing the "swapped directory pattern" in <filename
+       class='directory'>/boot</filename>.  This means it is a
+       symbolic link to one of two directories <filename
+       class='directory'>/ostree/boot.<replaceable>[0|1]</replaceable></filename>.
+       To swap the contents atomically, if the current version is
+       <literal>0</literal>, we create <filename
+       class='directory'>/ostree/boot.1</filename>, populate it with
+       the new contents, then atomically swap the symbolic link.  Finally,
+       the old contents can be garbage collected at any point.
+      </para>
+    </simplesect>
+
+    <simplesect id="ostree-bootversion">
+      <title>The /ostree/boot directory</title>
+      <para>
+       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 <filename class='directory'>/boot</filename> may be on
+       a separate medium such as flash storage not optimized for
+       significant amounts of write traffic.
+      </para>
+
+      <para>
+       To implement this, OSTree also maintains the directory
+       <filename
+       class='directory'>/ostree/boot.<replaceable>bootversion</replaceable></filename>,
+       which is a set of symbolic links to the deployment
+       directories.  The <replaceable>bootversion</replaceable> here
+       must match the version of <filename
+       class='directory'>/boot</filename>.  However, in order to
+       allow atomic transitions of <emphasis>this</emphasis>
+       directory, this is also a swapped directory, so just like
+       <filename class='directory'>/boot</filename>, it has a version
+       of <literal>0</literal> or <literal>1</literal> appended.
+      </para>
+
+      <para>
+       Each bootloader entry has a special <literal>ostree=</literal>
+       argument which refers to one of these symbolic links.  This is
+       parsed at runtime in the initramfs.
+      </para>
+
+    </simplesect>
+
+  </chapter>
+
+</part>
diff --git a/doc/deployment.xml b/doc/deployment.xml
index 69216e7..489850a 100644
--- a/doc/deployment.xml
+++ b/doc/deployment.xml
@@ -111,6 +111,17 @@
       class='directory'>/usr</filename>, but this is not a hard
       requirement.
     </para>
+
+    <para>
+      Finally, a deployment may have a <filename
+      class='extension'>.origin</filename> file, stored next to its
+      directory.  This file tells <command>ostree admin
+      upgrade</command> 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.
+    </para>
+
   </chapter>
   
   <chapter id="managing-boot">
diff --git a/doc/ostree-docs.xml b/doc/ostree-docs.xml
index 46b4cd0..cf953c1 100644
--- a/doc/ostree-docs.xml
+++ b/doc/ostree-docs.xml
@@ -14,6 +14,7 @@
        <xi:include href="overview.xml"/>
        <xi:include href="repo.xml"/>
        <xi:include href="deployment.xml"/>
+       <xi:include href="atomic-upgrades.xml"/>
 
        <chapter xml:id="reference">
                <title>API Reference</title>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]