Skip to content

Commit

Permalink
dir-overlay: initial commit
Browse files Browse the repository at this point in the history
The Directory Overlay Update Module installs a user defined file tree
structure into a given destination directory in the target.

Changelog: Add dir-overlay module

Signed-off-by: Mirza Krak <mirza.krak@northern.tech>
  • Loading branch information
mirzak committed May 7, 2019
1 parent 3658fe8 commit 891d4b1
Show file tree
Hide file tree
Showing 3 changed files with 319 additions and 0 deletions.
54 changes: 54 additions & 0 deletions dir-overlay/README.md
@@ -0,0 +1,54 @@
## Description

The Directory Overlay Update Module installs a user defined file tree structure into a given destination directory in the target.

Before the deploy into the destination folder on the device, the Update Module will take a backup copy of the current contents, allowing restore of it using the rollback mechanism of the Mender client if something goes wrong. The Update Module will also delete the current installed content that was previously installed using the same module, this means that each deployment is self contained and there is no residues left on the system from the previous deployment.

Example use-cases:
* Deploy root filesystem overlays

For a more detailed tutorial on how to use this Update Module please visit [Mender Hub](https://hub.mender.io/t/directory-overlay/)

### Specification

|||
| --- | --- |
|Module name| dir-overlay |
|Supports rollback|yes|
|Requires restart|no|
|Artifact generation script|yes|
|Full system updater|no|
|Source code|[Update Module](https://github.com/mendersoftware/mender-update-modules/tree/master/dir-overlay/module), [Artifact Generator](https://github.com/mendersoftware/mender-update-modules/blob/master/dir-overlay/module-artifact-gen/dir-overlay-artifact-gen)|

### Install the Update Module

Download the latest version of this Update Module by running:

mkdir -p /usr/share/mender/modules/v3 && wget -P /usr/share/mender/modules/v3 https://raw.githubusercontent.com/mendersoftware/mender-update-modules/master/dir-overlay/module/dir-overlay && chmod +x /usr/share/mender/modules/v3/dir-overlay

### Create artifact

To download dir-overlay-artifact-gen, run the following:

wget https://raw.githubusercontent.com/mendersoftware/mender-update-modules/master/dir-overlay/module-artifact-gen/dir-overlay-artifact-gen

Make it executable by running,

chmod +x dir-overlay-artifact-gen

Generate Mender Artifacts using the following command:

ARTIFACT_NAME="my-update-1.0"
DEVICE_TYPE="my-device-type"
OUTPUT_PATH="my-update-1.0.mender"
DEST_DIR="/"
OVERLAY_TREE="rootfs_overlay"
./dir-overlay-artifact-gen -n ${ARTIFACT_NAME} -t ${DEVICE_TYPE} -d ${DEST_DIR} -o ${OUTPUT_PATH} ${OVERLAY_TREE}

### Maintainer

The author and maintainer of this Update Module is:

- Mirza Krak - <mirza.krak@northern.tech> - [mirzak](https://github.com/mirzak)

Always include the original author when suggesting code changes to this update module.
164 changes: 164 additions & 0 deletions dir-overlay/module-artifact-gen/dir-overlay-artifact-gen
@@ -0,0 +1,164 @@
#!/bin/bash

set -e

show_help() {
cat << EOF
Simple tool to generate Mender Artifact suitable for dir-overlay Update Module
Usage: $0 [options] file-tree
Options: [ -n|artifact-name -t|--device-type -d|--dest-dir -o|--output_path -h|--help ]
--artifact-name - Artifact name
--device-type - Target device type identification
--dest-dir - Target destination directory where to deploy the update (Defaults to "/")
--output-path - Path to output file. Default: file-install-artifact.mender
--help - Show help and exit
file-tree - Directory tree to bundle in the update
Common use-case for the dir-overlay is to install files overlayed
on the root file-system.
Example tree to deploy:
$ tree
.
├── etc
│   └── app.conf
└── usr
├── bin
│   └── app
└── share
└── app
└── data.txt
EOF
}

show_help_and_exit_error() {
show_help
exit 1
}

check_dependency() {
hash "$1" || \
(echo "Fatal error: $1 not found in PATH." && exit 1)
}

check_dependency mender-artifact

device_type=""
artifact_name=""
dest_dir="/"
dest_dir_file="dest_dir"
output_path="file-install-artifact.mender"
update_files_tar="update.tar"
directories_file="directories"
manifest_file="manifest"
file_tree=""

while (( "$#" )); do
case "$1" in
--device-type | -t)
if [ -z "$2" ]; then
show_help_and_exit_error
fi
device_type=$2
shift 2
;;
--artifact-name | -n)
if [ -z "$2" ]; then
show_help_and_exit_error
fi
artifact_name=$2
shift 2
;;
--dest-dir | -d)
if [ -z "$2" ]; then
show_help_and_exit_error
fi
dest_dir=$2
shift 2
;;
--output-path | -o)
if [ -z "$2" ]; then
show_help_and_exit_error
fi
output_path=$2
shift 2
;;
-h | --help)
show_help
exit 0
;;
-*)
echo "Error: unsupported option $1"
show_help_and_exit_error
;;
*)
if [ -n "$file_tree" ]; then
echo "File tree already specified. Unrecognized argument \"$1\""
show_help_and_exit_error
fi
file_tree="$1"
shift
;;
esac
done

if [ -z "${artifact_name}" ]; then
echo "Artifact name not specified. Aborting."
show_help_and_exit_error
fi

if [ -z "${device_type}" ]; then
echo "Device type not specified. Aborting."
show_help_and_exit_error
fi

if [ -z "${file_tree}" ]; then
echo "File tree not specified. Aborting."
show_help_and_exit_error
fi

# Check dest-dir is an absolute path
case $dest_dir in
/*)
;;
*)
echo "Destination dir must be an absolute path. Aborting"
exit 1
;;
esac

if [ -d "${file_tree}" ]; then
tar -cf ${update_files_tar} -C "${file_tree}" .
else
echo "Error: \"${file_tree}\" is not a directory or does not exit. Aborting."
exit 1
fi

find $file_tree -type f | sed "s|^$file_tree/||" > $manifest_file

# Create dest_dir file in plain text
echo "$dest_dir" > $dest_dir_file

mender-artifact write module-image \
-T dir-overlay \
-t $device_type \
-o $output_path \
-n $artifact_name \
-f $update_files_tar \
-f $dest_dir_file \
-f $manifest_file

rm $update_files_tar
rm $dest_dir_file
rm $manifest_file

echo "Artifact $output_path generated successfully:"
mender-artifact read $output_path

exit 0
101 changes: 101 additions & 0 deletions dir-overlay/module/dir-overlay
@@ -0,0 +1,101 @@
#!/bin/sh

set -e
set -x

STATE="$1"
FILES="$2"

backup_dir="$FILES"/tmp
dest_dir_file="$FILES"/files/dest_dir
manifest_file_from_deployment="$FILES"/files/manifest
update_files_tar="$FILES"/files/update.tar


state_dir="/var/lib/mender/dir-overlay-install"
manifest_file="$state_dir/manifest"
manifest_file_prev="$state_dir/manifest.prev"
prev_files_tar="$state_dir/backup.tar"

# Summary of module implementation
#
# NOTE! This module stores state in /var/lib/mender
#
# In ArtifactInstall state:
#
# If a manifest file exists, which means that there has been a previous
# successful deployment with this module:
#
# 1. Create a backup of current deployment, the manifest file
# is parsed to determinate which files where installed on last successful
# deployment.
#
# 2. The current deployment is removed from the system, the manifest file
# is parsed to determinate which files where installed on last
# successful deployment.
#
# 3. Mark the current manifest file as previous (manifest.prev), note at
# this stage there is currently no active manifest. It can be restored
# in two ways. Either a roll-back is performed or deployment in progress
# finishes successfully.
#
# 4. Unpack/install content
#
# If manifest file does not exist, which means no previous deploy:
#
# 1. Unpack/install content
#
# In ArtifactCommit state:
#
# 1. Restore the "current manifest" file based on the manifest that is part of
# the deployment
#

case "$STATE" in

NeedsArtifactReboot)
echo "No"
;;

SupportsRollback)
echo "Yes"
;;

ArtifactInstall)
dest_dir=$(cat $dest_dir_file)
mkdir -p $dest_dir $state_dir

if [ -e $manifest_file ]; then
mkdir -p $backup_dir
for file in $(cat $manifest_file); do
cp $dest_dir/$file $backup_dir/
done
tar -cf ${prev_files_tar} -C ${backup_dir} .

for file in $(cat $manifest_file); do
rm $dest_dir/$file
done

mv $manifest_file $manifest_file_prev
fi

mkdir -p ${dest_dir}
tar -xf ${update_files_tar} -C ${dest_dir}
sync
;;

ArtifactCommit)
mv $manifest_file_from_deployment $manifest_file
;;

ArtifactRollback)
dest_dir=$(cat $dest_dir_file)

[[ -f $prev_files_tar ]] || exit 0

cp $manifest_file_prev $manifest_file
tar -xf ${prev_files_tar} -C ${dest_dir}
;;
esac

exit 0

0 comments on commit 891d4b1

Please sign in to comment.