From 66cc593886ef6ef54e0475a1f5914173babc34bf Mon Sep 17 00:00:00 2001 From: Robert Collins Date: Mon, 14 Oct 2013 21:45:13 +1300 Subject: [PATCH] Introduce support for persistent state in /mnt. Since instances that have ephemeral volumes, which we plan to use for persistent state (yes the name is confusing) start with the volume empty, we need some support to aid in placing state files (and configuration files we want to generate dynamically) on that partition - we can't just move stuff there during build, or it will be mounted over by cloud-init. Change-Id: Iff9e329ba6217e5f7290b7ab65b1808f4a8d8f9a --- elements/use-ephemeral/README.md | 49 ++++++++++++ .../use-ephemeral/bin/register-state-path | 74 +++++++++++++++++++ elements/use-ephemeral/element-deps | 1 + .../pre-configure.d/01-setup-stateful-paths | 33 +++++++++ 4 files changed, 157 insertions(+) create mode 100644 elements/use-ephemeral/README.md create mode 100755 elements/use-ephemeral/bin/register-state-path create mode 100644 elements/use-ephemeral/element-deps create mode 100755 elements/use-ephemeral/os-refresh-config/pre-configure.d/01-setup-stateful-paths diff --git a/elements/use-ephemeral/README.md b/elements/use-ephemeral/README.md new file mode 100644 index 000000000..a2f8669c3 --- /dev/null +++ b/elements/use-ephemeral/README.md @@ -0,0 +1,49 @@ +Provides tools to aid in relocating state to /mnt/state + +In a cloud instance /mnt/state is on the cloud ephemeral device when one +exists, or the root when one doesn't. + +The pattern for having state on /mnt/state is: + +- The service/daemon can make its own state files on startup (as /mnt + is always empty on first-boot). + +- Alternatively os-refresh-config can be used to populate any initial state so + that the daemon/service works (so until the first os-refresh-config run that + daemon/service will be broken). + +- If the state needs migrating (e.g. PostgreSQL 9.1 to 9.2) then a migration + script should be added to os-refresh-config's migrations.d tree to perform + that migration that state (if the migration can be done after the service + starts) or to configure.d if the service cannot start without the migration + being done). + +- state should live in /mnt/state/original-path e.g. + /mnt/state/etc/ssh/ssh\_host\_dsa\_key. + +- where there are hardcoded specific paths, we leave symlinks in that path + pointing into /mnt/state - e.g. /etc/ssh/ss\_host\_dsa\_key will be a symlink + to /mnt/state/etc/ssh/ssh\_host\_dsa\_key. + +To factor out common code elements can invoke register-state-path during +install.d to request that a particular path be registered as a stateful path. + +- If there is content at the path at registration time, it will be moved to + /var/lib/use-ephemeral/original-path. + +- If --leave-symlink is passed, a symlink will be created at that path pointing + to /mnt/state/original-path. + +- Stateful paths are listed in /var/lib/use-ephemeral/stateful-paths, one path + per line - e.g. /etc/ssh/ssh\_host\_dsa\_key. + +Once registered: + +- During pre-configure.d the parent directories leading up to the path will be + asserted on startup. + +- If there is a content at /var/lib/use-ephemeral/original-path during + pre-configure.d, and the new path does not exist in /mnt/state then an + rsync -a will be made into /mnt/state/original-path reinstating a pristine + copy of what was preserved. This is only done when the path does not exist + to avoid corrupting evolved or migrated state. diff --git a/elements/use-ephemeral/bin/register-state-path b/elements/use-ephemeral/bin/register-state-path new file mode 100755 index 000000000..2328d5028 --- /dev/null +++ b/elements/use-ephemeral/bin/register-state-path @@ -0,0 +1,74 @@ +#!/bin/bash +# +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +set -eux +set -o pipefail + +SCRIPT_NAME=$(basename $0) +SCRIPT_HOME=$(dirname $0) + +function show_options () { + echo "Usage: $SCRIPT_NAME [options] " + echo + echo "Register as a state path." + echo + echo "This will register path as being part of the state of the machine." + echo "If there is content at it will be moved to " + echo "/var/lib/use-ephemeral/." + echo + echo "Paths are recorded in /var/lib/use-ephemeral/stateful-paths." + echo + echo "Options:" + echo " --leave-symlink -- create a symlink from to /mnt/state/." + echo + exit $1 +} + +LEAVE_SYMLINK="" + +TEMP=`getopt -o h -l help,leave-symlink -n $SCRIPT_NAME -- "$@"` +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +while true ; do + case "$1" in + --leave-symlink) LEAVE_SYMLINK="true"; shift 1 ;; + -h | --help) show_options 0;; + --) shift ; break ;; + *) echo "Error: unsupported option $1." ; exit 1 ;; + esac +done + +STATE_PATH=${1:-""} +EXTRA=${2:-""} + +if [ -z "$STATE_PATH" -o -n "$EXTRA" ]; then + show_options 1 +fi + +mkdir -p /var/lib/use-ephemeral +echo $STATE_PATH >> /var/lib/use-ephemeral/stateful-paths +if [ -e "$STATE_PATH" -o -L "$STATE_PATH" ]; then + backup_dir=/var/lib/use-ephemeral/$(dirname "$STATE_PATH") + mkdir -p "$backup_dir" + mv "$STATE_PATH" "$backup_dir" +fi +if [ -n "$LEAVE_SYMLINK" ]; then + ln -s "/mnt/state/$STATE_PATH" "$STATE_PATH" +fi diff --git a/elements/use-ephemeral/element-deps b/elements/use-ephemeral/element-deps new file mode 100644 index 000000000..33d7e82b2 --- /dev/null +++ b/elements/use-ephemeral/element-deps @@ -0,0 +1 @@ +os-refresh-config diff --git a/elements/use-ephemeral/os-refresh-config/pre-configure.d/01-setup-stateful-paths b/elements/use-ephemeral/os-refresh-config/pre-configure.d/01-setup-stateful-paths new file mode 100755 index 000000000..602de083f --- /dev/null +++ b/elements/use-ephemeral/os-refresh-config/pre-configure.d/01-setup-stateful-paths @@ -0,0 +1,33 @@ +#!/bin/bash +# +# Copyright 2013 Hewlett-Packard Development Company, L.P. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +set -eux +set -o pipefail + +if [ ! -e "/var/lib/use-ephemeral/stateful-paths" ]; then + exit 0 +fi + +while read -r; do + state_path="/mnt/state/$REPLY" + state_dir=$(dirname "$state_path") + reference_path="/var/lib/use-ephemeral/$REPLY" + mkdir -p "$state_dir" + if [ -e "$reference_path" -a ! -L "$state_path" -a ! -e "$state_path" ]; then + rsync -av "$reference_path" "$state_path" + fi +done < "/var/lib/use-ephemeral/stateful-paths"