summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alvarez <pedro.alvarez@codethink.co.uk>2016-10-17 08:10:28 +0000
committerPedro Alvarez <pedro.alvarez@codethink.co.uk>2016-10-17 08:10:28 +0000
commit3b387c376c813d611df05667e8f3490678ef5ba4 (patch)
tree57dc868983c639f8c3e53c0e1c5dac25d35ccf2b
parent36f7e4923ae5d03dd345d74f7fcade48c99a498d (diff)
downloaddefinitions-staging/jjardon/ostree.write.tar.gz
Add ostree.write deployment extensionstaging/jjardon/ostree.writejjardon/ostree.write
Reverts commit 36f7e4923ae5d03dd345d74f7fcade48c99a498d This is a simple deployment extension to write the results of a Baserock build to an OSTree repo. See ostree.write.help for more information. The Baserock reference systems contain static device nodes, which are not supported by OSTree, and are obsolete on Linux systems. To work around this problem, I added a strip-device-nodes.configure extension. The systems should still work the same as devtmpfs will create the device nodes. I've tested this by deploying minimal-system-x86_64 to an OSTree repo, then checking it out into a temporary directory, creating a read-only bind-mount of the temporary directory and chrooting then into it. This is only going to be useful for containers systems and chroots for the time being. We would need to make some quite major changes to the Baserock reference systems to enable deployment to VMs or bare metal using OSTree. Change-Id: Ic393bdec7b28341fc5dfa56bb684217d964be5ff
-rw-r--r--clusters/minimal-system-deploy-ostree.morph22
-rw-r--r--extensions/ostree.check67
-rw-r--r--extensions/ostree.write88
-rw-r--r--extensions/ostree.write.help73
-rw-r--r--extensions/strip-device-nodes.configure40
-rw-r--r--extensions/strip-device-nodes.configure.help29
-rw-r--r--systems/minimal-system-x86_64-generic.morph1
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