diff options
-rw-r--r-- | clusters/minimal-system-deploy-ostree.morph | 22 | ||||
-rw-r--r-- | extensions/ostree.check | 67 | ||||
-rw-r--r-- | extensions/ostree.write | 88 | ||||
-rw-r--r-- | extensions/ostree.write.help | 73 | ||||
-rw-r--r-- | extensions/strip-device-nodes.configure | 40 | ||||
-rw-r--r-- | extensions/strip-device-nodes.configure.help | 29 | ||||
-rw-r--r-- | systems/minimal-system-x86_64-generic.morph | 1 |
7 files changed, 320 insertions, 0 deletions
diff --git a/clusters/minimal-system-deploy-ostree.morph b/clusters/minimal-system-deploy-ostree.morph new file mode 100644 index 00000000..c0f4ed7c --- /dev/null +++ b/clusters/minimal-system-deploy-ostree.morph @@ -0,0 +1,22 @@ +name: minimal-system-deploy-ostree +kind: cluster +description: | + Example of deploying a minimal system to a local OSTree repo. +systems: +- morph: systems/minimal-system-x86_64-generic.morph + deploy: + minimal-system: + type: extensions/ostree + + # This is the default location for the repo on systems that were + # *deployed* with OSTree. You can use any repo created with `ostree init` + # here for testing purposes. + location: /ostree/repo + + OSTREE_BRANCH: minimal-system-x86_64 + OSTREE_COMMIT_SUBJECT: Example deployment of minimal-system-x86_64 + + STRIP_DEVICE_NODES: true + + HOSTNAME: tiny-x86_64 + INIT_SYSTEM: busybox diff --git a/extensions/ostree.check b/extensions/ostree.check new file mode 100644 index 00000000..e5fefe36 --- /dev/null +++ b/extensions/ostree.check @@ -0,0 +1,67 @@ +#!/usr/bin/python +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + +'''Preparatory checks for Baserock 'ostree' write extension.''' + +from gi.repository import GLib +from gi.repository import Gio +from gi.repository import OSTree + +import logging +import os +import urlparse + +import writeexts + + +class OSTreeCheckExtension(writeexts.WriteExtension): + + def process_args(self, args): + if len(args) != 1: + raise writeexts.ExtensionError( + 'Wrong number of command line args') + + upgrade = self.get_environment_boolean('UPGRADE') + if upgrade: + raise writeexts.ExtensionError( + 'Use the `ssh-rsync` write extension to deploy upgrades to an ' + 'existing remote system.') + + location = args[0] + self.check_location(location) + + self.check_ostree_parameters() + + def check_location(self, location): + repo = OSTree.Repo.new(Gio.File.new_for_path(location)) + try: + repo.open() + except GLib.GError as e: + logging.debug("Error from OSTree: %s", e) + if 'No such file or directory' in e.message: + raise writeexts.ExtensionError( + "OSTree repo %s was not found." % location) + else: + raise writeexts.ExtensionError( + "Error opening OSTree repo %s: %s" % (location, e)) + + def check_ostree_parameters(self): + required = ['OSTREE_BRANCH', 'OSTREE_COMMIT_SUBJECT'] + for var in required: + if os.environ.get(var, '') == '': + raise writeexts.ExtensionError('%s was not given' % var) + + +OSTreeCheckExtension().run() diff --git a/extensions/ostree.write b/extensions/ostree.write new file mode 100644 index 00000000..b2b5d6e1 --- /dev/null +++ b/extensions/ostree.write @@ -0,0 +1,88 @@ +#!/usr/bin/python +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + + +'''A Baserock write extension for deploying to OSTree repositories.''' + + +from gi.repository import GLib +from gi.repository import Gio +from gi.repository import OSTree + +import os +import subprocess +import tempfile +import urlparse + +import writeexts + + +def ostree_repo_resolve_rev(repo, branch, allow_noent=True): + '''Return the SHA256 corresponding to 'branch'.''' + return repo.resolve_rev(branch, allow_noent)[1] + + +def ostree_repo_commit_tree(repo, tree_dir, branch, commit_subject, + commit_body=''): + '''Commit the contents of 'tree_dir' to 'branch'.''' + + repo.prepare_transaction(None) + + parent = ostree_repo_resolve_rev(repo, branch) + + ostree_mtree = OSTree.MutableTree() + tree_dir_gfile = Gio.file_new_for_path(tree_dir) + repo.write_directory_to_mtree(tree_dir_gfile, ostree_mtree, None, None) + + root = repo.write_mtree(ostree_mtree, None)[1] + checksum = repo.write_commit( + parent, commit_subject, commit_body, None, root, None)[1] + + repo.transaction_set_ref(None, branch, checksum) + + stats = repo.commit_transaction(None) + return stats + + +class OSTreeWriteExtension(writeexts.WriteExtension): + '''See ostree.write.help for documentation.''' + + def process_args(self, args): + if len(args) != 2: + raise writeexts.ExtensionError( + 'Wrong number of command line args') + + temp_root, location = args + + repo = OSTree.Repo.new(Gio.File.new_for_path(location)) + repo.open() + + branch = os.environ.get('OSTREE_BRANCH') + commit_subject = os.environ.get('OSTREE_COMMIT_SUBJECT') + commit_body = os.environ.get('OSTREE_COMMIT_BODY') + + try: + ostree_repo_commit_tree(repo, temp_root, branch, commit_subject, commit_body) + except GLib.GError as e: + raise writeexts.ExtensionError( + '%s. Failed to commit system to repo %s.' % + (e.message, location)) + + self.status( + msg='Created commit on branch %s in OSTree repo at %s' % ( + branch, location)) + + +OSTreeWriteExtension().run() diff --git a/extensions/ostree.write.help b/extensions/ostree.write.help new file mode 100644 index 00000000..90a181be --- /dev/null +++ b/extensions/ostree.write.help @@ -0,0 +1,73 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see <http://www.gnu.org/licenses/>. + +help: | + + Deploy a Baserock system to an existing OSTree repository. + + Parameters: + + * location: the path to the OSTree repo. + + * OSTREE_BRANCH=branchname: the branch to commit to + + * OSTREE_COMMIT_SUBJECT=subject: one-line commit title + + * OSTREE_COMMIT_BODY=text: full commit message (optional) + + See `morph help deploy` for details of how to pass parameters to write + extensions. + + This extension requires a local OSTree repository to deploy to, which must + already exist. You can create a new repository using the `ostree init` + command. + + If you want to deploy straight to the local machine, you should use a + 'bare' mode repository, which allows the resulting system to be quickly + checked out. + + If you want to serve the results of a deployment from an OSTree server, + you need to use a local 'archive-z2' mode repository. You can then use + `ostree pull` on the server to pull the results of the deployment from the + build machine. Note that 'push' style transfers are not currently supported + by OSTree. + + For full OSTree documentation, see <https://wiki.gnome.org/Projects/OSTree>. + + IMPORTANT NOTE: OSTree can only store regular files. It cannot store device + nodes. If your system contains static device nodes (which all of the + Baserock reference systems do, at time of writing) you can use the + strip-device-nodes.configure extension to remove them, and leave devtmpfs + to create the device nodes. + + If you seen an error like "Not a regular file or symlink: null.", you have + hit this problem. + + ANOTHER IMPORTANT NOTE: OSTree uses hardlinks to checkout files quickly. + This has an important consequence: any files checked out from OSTree MUST + not be overwritten at runtime, or you *will* cause corruption in the + repository and/or your checked-out system. In general, if you want to + use OSTree for container systems or chroots, it is enough to create a + read-only bindmount: + + mount --bind ./ostree-checkout-dir ./sysroot-dir + mount -o bind,remount,ro ./sysroot-dir + + If you want to run a system using OSTree as the real OS of a system, you + are best off following this guide: + + https://developer.gnome.org/ostree/stable/adapting-existing.html + + This extension requires that the libostree-1 library and the Python + GObject-introspection bindings are available. diff --git a/extensions/strip-device-nodes.configure b/extensions/strip-device-nodes.configure new file mode 100644 index 00000000..9f09b560 --- /dev/null +++ b/extensions/strip-device-nodes.configure @@ -0,0 +1,40 @@ +#!/bin/sh +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# See strip-device-nodes.configure.help for documentation. + +set -eu + +case "$STRIP_DEVICE_NODES" in + yes|Yes|YES|true|True|TRUE|1) + run=yes ;; + *) + run=no ;; +esac + +if [ "$run" = "yes" ]; then + echo "Stripping device nodes" + + root="$1" + + # Be VERY CAREFUL because this runs in the host system as root. + if [ "$(readlink -f $1)" = / ]; then + echo "Refusing to remove files from /, as a safety precausion." + exit 1 + fi + + rm -R "$1"/dev/* +fi diff --git a/extensions/strip-device-nodes.configure.help b/extensions/strip-device-nodes.configure.help new file mode 100644 index 00000000..43b79a77 --- /dev/null +++ b/extensions/strip-device-nodes.configure.help @@ -0,0 +1,29 @@ +# Copyright (C) 2015 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see <http://www.gnu.org/licenses/>. + +help: | + A Baserock configuration extension for removing static device nodes. + + Parameters: + + STRIP_DEVICE_NODES=<1|0>: whether to strip device nodes + + This extension is a workaround for a flaw in the Baserock reference systems. + They still contain statically created device nodes, which is not useful any + more for Linux systems due to the existance of the 'devtmpfs' filesystem. + The 'devtmpfs' filesystem creates device nodes automatically at run time. + + Static device nodes are deliberately not supported by the OSTree tool, so this + .configure extension is needed to use the Baserock reference systems with the + ostree.write deployment extension. diff --git a/systems/minimal-system-x86_64-generic.morph b/systems/minimal-system-x86_64-generic.morph index afd9460c..418c3ac3 100644 --- a/systems/minimal-system-x86_64-generic.morph +++ b/systems/minimal-system-x86_64-generic.morph @@ -19,3 +19,4 @@ configuration-extensions: - extensions/install-files - extensions/busybox-init - extensions/install-essential-files +- extensions/strip-device-nodes |