From 8ee71e67f49ff673db3844498521dd289e40cd27 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Tue, 2 Jun 2020 22:33:30 +0200 Subject: [PATCH 01/17] [__lxc_container] initial work for lxc contaienr type This should theoretically work, but is untested. It is able to create and delete, change basic configuration and start/stop/freeze the container. --- .../conf/type/__lxc_container/explorer/config | 37 ++++ .../type/__lxc_container/explorer/lxcpath | 16 ++ .../conf/type/__lxc_container/explorer/state | 18 ++ cdist/conf/type/__lxc_container/gencode-local | 54 +++++ .../conf/type/__lxc_container/gencode-remote | 203 ++++++++++++++++++ cdist/conf/type/__lxc_container/helper-exec | 68 ++++++ cdist/conf/type/__lxc_container/helper-param | 27 +++ cdist/conf/type/__lxc_container/issue.txt | 1 + cdist/conf/type/__lxc_container/man.rst | 125 +++++++++++ cdist/conf/type/__lxc_container/manifest | 106 +++++++++ .../type/__lxc_container/parameter/boolean | 1 + .../__lxc_container/parameter/default/state | 1 + .../__lxc_container/parameter/default/user | 1 + .../type/__lxc_container/parameter/optional | 10 + .../parameter/optional_multiple | 3 + cdist/conf/type/__lxc_container/todo.txt | 28 +++ 16 files changed, 699 insertions(+) create mode 100755 cdist/conf/type/__lxc_container/explorer/config create mode 100755 cdist/conf/type/__lxc_container/explorer/lxcpath create mode 100755 cdist/conf/type/__lxc_container/explorer/state create mode 100755 cdist/conf/type/__lxc_container/gencode-local create mode 100755 cdist/conf/type/__lxc_container/gencode-remote create mode 100644 cdist/conf/type/__lxc_container/helper-exec create mode 100644 cdist/conf/type/__lxc_container/helper-param create mode 100644 cdist/conf/type/__lxc_container/issue.txt create mode 100644 cdist/conf/type/__lxc_container/man.rst create mode 100755 cdist/conf/type/__lxc_container/manifest create mode 100644 cdist/conf/type/__lxc_container/parameter/boolean create mode 100644 cdist/conf/type/__lxc_container/parameter/default/state create mode 100644 cdist/conf/type/__lxc_container/parameter/default/user create mode 100644 cdist/conf/type/__lxc_container/parameter/optional create mode 100644 cdist/conf/type/__lxc_container/parameter/optional_multiple create mode 100644 cdist/conf/type/__lxc_container/todo.txt diff --git a/cdist/conf/type/__lxc_container/explorer/config b/cdist/conf/type/__lxc_container/explorer/config new file mode 100755 index 00000000..d82dbb25 --- /dev/null +++ b/cdist/conf/type/__lxc_container/explorer/config @@ -0,0 +1,37 @@ +#!/bin/sh -e +# explorer/config + +# Prints out the current container configuration (if required). This makes +# it easy to differ changes. + +# abort if container will be absent - no config required +if [ "$(cat "$__object/parameter/state")" = "absent" ]; then + exit 0 +fi + + +# read the lxcpath (reusing explorer) +lxcpath="$( "$__type_explorer/lxcpath" )" + +# get name +name="$__object/parameter/name" +if [ -f "$name" ]; then + name="$(cat "$name")" +else + name="$__object_id" +fi + + +# assemble the container configuration file +config="$lxcpath/$name/config" + +# check if the file exist +if [ -r "$config" ]; then + # print configuration and strip files to just values + # grep will hide all comments and empty lines - all others must be key-values + # sed will uniform patterns, that no spaces will be problematic (before, in the middle and at end) + grep -E -v "^([[:blank:]]*)(#|$)" "$config" | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' +else + >&2 printf "config file \"%s\" does not exist or is not readable\n" "$config" + exit 1 +fi diff --git a/cdist/conf/type/__lxc_container/explorer/lxcpath b/cdist/conf/type/__lxc_container/explorer/lxcpath new file mode 100755 index 00000000..a3505f94 --- /dev/null +++ b/cdist/conf/type/__lxc_container/explorer/lxcpath @@ -0,0 +1,16 @@ +#!/bin/sh -e +# explorer/lxcpath + +# Echos the lxcpath variable for all container instances + +# Load important functions and parameter handling +. "$__type/helper-param" +. "$__type/helper-exec" + + +# lxcpath parameter +if [ -z "$lxcpath" ]; then + lxc_g config "lxc.lxcpath" +else + echo "$lxcpath" +fi diff --git a/cdist/conf/type/__lxc_container/explorer/state b/cdist/conf/type/__lxc_container/explorer/state new file mode 100755 index 00000000..23900ba6 --- /dev/null +++ b/cdist/conf/type/__lxc_container/explorer/state @@ -0,0 +1,18 @@ +#!/bin/sh -e +# explorer/state + +# Outputs if the container exist +# possible values: present || absent || running || stopped || frozen + +# source param lib +. "$__type/helper-param" +. "$__type/helper-exec" + +# the lxc-info command will exit non-zero if container not exist +if ! lxc_c info -H -S >/dev/null 2>&1; then + # not exist + echo "absent" +else + # print state (command output matches to type states) + lxc_c info -H -s | tr '[[:upper:]]' '[[:lower:]]' +fi diff --git a/cdist/conf/type/__lxc_container/gencode-local b/cdist/conf/type/__lxc_container/gencode-local new file mode 100755 index 00000000..1c8a18c8 --- /dev/null +++ b/cdist/conf/type/__lxc_container/gencode-local @@ -0,0 +1,54 @@ +#!/bin/sh -e +# gencode-local + +# This uploads the diff of the configuration file, which is applied by gencode-remote + + +# check both states +state_is="$(cat "$__object/explorer/state")" +state_should="$(cat "$__object/parameter/state")" + +# Check the configurations only if the container exists +if [ "$state_should" != "absent" ]; then + # do changes + + # predict remote lxc config file + container_config="$(cat "$__object/explorer/lxcpath")/$name/config" + + # IPv6 fix + if echo "${__target_host}" | grep -q -E '^[0-9a-fA-F:]+$' + then + my_target_host="[${__target_host}]" + else + my_target_host="${__target_host}" + fi + + + # config-present + # remove all config lines from config-present that are already set or absent anyway + if grep -v -f "$__object/explorer/config" -f "$__object/files/config-absent" \ + "$__object/files/config-present" > "$__object/files/config.add"; then + + # get temp file name + add_dest="$($__remote_exec $__target_host "mktemp $container_config-add.XXXXXXXXXX")" + printf "%s" "$add_dest" > "$__object/files/remote-tmpfile_add" + # upload diff + cat < "$__object/files/config.del"; then + + # get temp file name + del_dest="$($__remote_exec $__target_host "mktemp $container_config-del.XXXXXXXXXX")" + printf "%s" "$del_dest" > "$__object/files/remote-tmpfile_del" + # upload diff + cat <> "$__messages_out" + ;; + + absent) + # shutdown and delete the container + # we could force-delete, but better be polite + # snapshots are deleted, too - to keep everything clean. May someone does not want it? + cat <> "$__messages_out" + ;; + + # error handling: invalid state + *) + printf "Container '%s' in unknown state %s\n" "$name" "$state_should" >&2 + exit 2 + ;; + esac + + # end of su here-document + echo "SU" +fi + + +# Check the configurations only if the container exists and there are changes +if [ "$state_should" != "absent" ] && \ + ( [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ] ); then + # shortcut + tmppath="$__object/files/remote-tmpfile" + + # generate config path + container_config="$(cat "$__object/explorer/lxcpath")/$name/config" + # create remote tmpfile for config + cat <> "\$tmpconfig" +rm -rf "$(cat "${tmppath}_add")" +DONE + fi + + # check if smth. to be deleted + if [ -f "${tmppath}_del" ]; then + cat < "\$tmpconfig" +rm -rf "$(cat "${tmppath}_del")" +DONE + fi + + + # apply all changes + cat <> "$__messages_out" +fi + + +# TODO user context again +# Check if there is a difference within the states +if [ "$state_is" != "$state_should" ] && [ "$state_should" != "absent" ]; then + # change privileges (too complex to make exceptions) + cat <&2 echo "error: can not create and clone a container at once!" + >&2 echo "error: --template and --clone can not work together" + exit 2 +fi + +# no clone option if --template given +if [ -f "$param/template" ]; then + if [ -f "$param/clonepath" ] + then + >&2 echo "error: container will created by template, no clone options required!" + exit 2 + fi +fi + +# no template options if --clone given +if [ -f "$__object/parameter/clone" ]; then + if [ -f "$param/template-opts" ] \ + || [ -f "$param/default-config" ] \ + || [ -f "$param/no-default-config" ] \ + || [ -f "$param/release" ] \ + || [ -f "$param/arch" ] + then + >&2 echo "error: container will created by clone, no template options required!" + exit 2 + fi +fi + + + + +# ============================== # +# == CONFIGURATION HANDLING == # +# ============================== # + +# Function to read multiple parameter input for configuration and print it to a single file. +# It will handle file paths as well as the stdin. Instead of the file, the content will be printed. +# +# Parameters: +# 1: parameter name +# 2: file to print +write_multi_param() { + touch "$2" + while read line; do + if [ "$line" = "-" ]; then + # append stdin + cat "$__object/stdin" >> "$2" + elif [ -f "$line" ]; then + # append file content + cat "$line" >> "$2" + else + # print out content + printf "%s\n" "$line" >> "$2" + fi + done < "$__object/parameter/$1" +} + +# Function to get rid of whitespaces inside of key-value pairs. It will clear all of these. +# +# Parameters: +# 1: the file which should be handled +trimm_whitespaces() { + cp "$1" "$1"~ # backup file to see original content + grep -E -v "^([[:blank:]]*)(#|$)" "$1" \ + | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' +} + +# Only required if container will not be absent +# get the wanted configuration lines +if [ "$(cat "$__object/parameter/state")" != "absent" ]; then + # Create the files directory + mkdir "$__object/files/" + + # Create the file of the locally configuration + conffile="$__object/files/config-present" + write_multi_param config "$conffile" + trimm_whitespaces "$conffile" > "$conffile" + + # Create the file of the absent configuration + absentfile="$__object/files/config-absent" + write_multi_param config-absent "$absentfile" + trimm_whitespaces "$absentfile" > "$absentfile" +fi diff --git a/cdist/conf/type/__lxc_container/parameter/boolean b/cdist/conf/type/__lxc_container/parameter/boolean new file mode 100644 index 00000000..caf89a8e --- /dev/null +++ b/cdist/conf/type/__lxc_container/parameter/boolean @@ -0,0 +1 @@ +no-default-config diff --git a/cdist/conf/type/__lxc_container/parameter/default/state b/cdist/conf/type/__lxc_container/parameter/default/state new file mode 100644 index 00000000..e7f6134f --- /dev/null +++ b/cdist/conf/type/__lxc_container/parameter/default/state @@ -0,0 +1 @@ +present diff --git a/cdist/conf/type/__lxc_container/parameter/default/user b/cdist/conf/type/__lxc_container/parameter/default/user new file mode 100644 index 00000000..d8649da3 --- /dev/null +++ b/cdist/conf/type/__lxc_container/parameter/default/user @@ -0,0 +1 @@ +root diff --git a/cdist/conf/type/__lxc_container/parameter/optional b/cdist/conf/type/__lxc_container/parameter/optional new file mode 100644 index 00000000..fc4bb71b --- /dev/null +++ b/cdist/conf/type/__lxc_container/parameter/optional @@ -0,0 +1,10 @@ +name +user +state +lxcpath +template +default-config +release +arch +clone +clonepath diff --git a/cdist/conf/type/__lxc_container/parameter/optional_multiple b/cdist/conf/type/__lxc_container/parameter/optional_multiple new file mode 100644 index 00000000..069c02b1 --- /dev/null +++ b/cdist/conf/type/__lxc_container/parameter/optional_multiple @@ -0,0 +1,3 @@ +config +config-absent +template-opts diff --git a/cdist/conf/type/__lxc_container/todo.txt b/cdist/conf/type/__lxc_container/todo.txt new file mode 100644 index 00000000..17c4edaf --- /dev/null +++ b/cdist/conf/type/__lxc_container/todo.txt @@ -0,0 +1,28 @@ +# List of all featues that should be implemented +storage: + - backing_storage + - other settings prior to storage +template: + - type: a.E. debian, ubuntu -> what on change? + - release + - arch + - possible ssh auth key? + - possible root_password? + - possible packages? + - possible mirrors? + - other options?? +auto..: + - group + - start +lxc config .. +how to find lxc containers path? +lxc-copy: ephemeral containers? -> seperate type if it makes sense + +If config already created, it's considered the container is already created + -> first create; then setup + detection if template changed?? + + +lxc configuration at startup: + flag -f can used to set a default config (instead the system default) + there is no problem to change config before the first startup From 1b735fb1508edbe144263f892b5b1a1fdc03c95e Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sun, 28 Jun 2020 14:12:49 +0200 Subject: [PATCH 02/17] [__lxc_container] fix SC2021 Problems with backets and tr. --- cdist/conf/type/__lxc_container/explorer/state | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__lxc_container/explorer/state b/cdist/conf/type/__lxc_container/explorer/state index 23900ba6..0c79d3c8 100755 --- a/cdist/conf/type/__lxc_container/explorer/state +++ b/cdist/conf/type/__lxc_container/explorer/state @@ -14,5 +14,5 @@ if ! lxc_c info -H -S >/dev/null 2>&1; then echo "absent" else # print state (command output matches to type states) - lxc_c info -H -s | tr '[[:upper:]]' '[[:lower:]]' + lxc_c info -H -s | tr '[:upper:]' '[:lower:]' fi From 939abf6d45eca4ba6fb6133acbb8fc936c9a2d3b Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Tue, 30 Jun 2020 18:05:19 +0200 Subject: [PATCH 03/17] [__lxc_container] got type to fly with heavier changes Helper scripts do not work with explorers, so there are useless; and some other problems detected at runtime. `gencode-remote` *will be refactored - be aware* --- .../conf/type/__lxc_container/explorer/config | 5 +- .../type/__lxc_container/explorer/lxcpath | 15 ++- .../conf/type/__lxc_container/explorer/state | 35 +++++- cdist/conf/type/__lxc_container/gencode-local | 2 +- .../conf/type/__lxc_container/gencode-remote | 108 +++++++++++------- cdist/conf/type/__lxc_container/helper-exec | 68 ----------- cdist/conf/type/__lxc_container/helper-param | 27 ----- cdist/conf/type/__lxc_container/manifest | 28 +++-- 8 files changed, 128 insertions(+), 160 deletions(-) delete mode 100644 cdist/conf/type/__lxc_container/helper-exec delete mode 100644 cdist/conf/type/__lxc_container/helper-param diff --git a/cdist/conf/type/__lxc_container/explorer/config b/cdist/conf/type/__lxc_container/explorer/config index d82dbb25..287a5063 100755 --- a/cdist/conf/type/__lxc_container/explorer/config +++ b/cdist/conf/type/__lxc_container/explorer/config @@ -25,13 +25,10 @@ fi # assemble the container configuration file config="$lxcpath/$name/config" -# check if the file exist +# check if the file exist, else the container is absent if [ -r "$config" ]; then # print configuration and strip files to just values # grep will hide all comments and empty lines - all others must be key-values # sed will uniform patterns, that no spaces will be problematic (before, in the middle and at end) grep -E -v "^([[:blank:]]*)(#|$)" "$config" | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' -else - >&2 printf "config file \"%s\" does not exist or is not readable\n" "$config" - exit 1 fi diff --git a/cdist/conf/type/__lxc_container/explorer/lxcpath b/cdist/conf/type/__lxc_container/explorer/lxcpath index a3505f94..a4116b9b 100755 --- a/cdist/conf/type/__lxc_container/explorer/lxcpath +++ b/cdist/conf/type/__lxc_container/explorer/lxcpath @@ -3,14 +3,21 @@ # Echos the lxcpath variable for all container instances -# Load important functions and parameter handling -. "$__type/helper-param" -. "$__type/helper-exec" +# get parameter if exist +lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # lxcpath parameter if [ -z "$lxcpath" ]; then - lxc_g config "lxc.lxcpath" + user="$(cat "$__object/parameter/user")" + + # gather default value from config + if [ "$user" != "$USER" ]; then + su -s "$(which -- lxc-config)" -- "$user" lxc.lxcpath + else + lxc-config lxc.lxcpath + fi else + # output the parameter echo "$lxcpath" fi diff --git a/cdist/conf/type/__lxc_container/explorer/state b/cdist/conf/type/__lxc_container/explorer/state index 0c79d3c8..fc37edf7 100755 --- a/cdist/conf/type/__lxc_container/explorer/state +++ b/cdist/conf/type/__lxc_container/explorer/state @@ -4,15 +4,40 @@ # Outputs if the container exist # possible values: present || absent || running || stopped || frozen -# source param lib -. "$__type/helper-param" -. "$__type/helper-exec" +# general parameters +name="$__object/parameter/name" +if [ -f "$name" ]; then + name="$(cat "$name")" +else + name="$__object_id" +fi +user="$(cat "$__object/parameter/user")" + +# lxcpath +lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" + +# assemble optional parameters +LXC_PARAM="" +if [ "$lxcpath" ]; then + LXC_PARAM="$LXC_PARAM -P \"$lxcpath\"" +fi + + +# function to get information +lxc_info() { + if [ "$user" != "$USER" ]; then + su -s "$(which -- lxc-info)" -- "$user" $LXC_PARAM -n "$name" -H "$@" + else + lxc-info $LXC_PARAM -n "$name" -H "$@" + fi +} + # the lxc-info command will exit non-zero if container not exist -if ! lxc_c info -H -S >/dev/null 2>&1; then +if ! lxc_info -S >/dev/null 2>&1; then # not exist echo "absent" else # print state (command output matches to type states) - lxc_c info -H -s | tr '[:upper:]' '[:lower:]' + lxc_info -s | tr '[:upper:]' '[:lower:]' fi diff --git a/cdist/conf/type/__lxc_container/gencode-local b/cdist/conf/type/__lxc_container/gencode-local index 1c8a18c8..dbfca7e8 100755 --- a/cdist/conf/type/__lxc_container/gencode-local +++ b/cdist/conf/type/__lxc_container/gencode-local @@ -48,7 +48,7 @@ OUT printf "%s" "$del_dest" > "$__object/files/remote-tmpfile_del" # upload diff cat <> "$__messages_out" - ;; + # end of su here-document + echo "SU" - absent) - # shutdown and delete the container - # we could force-delete, but better be polite - # snapshots are deleted, too - to keep everything clean. May someone does not want it? - cat <> "$__messages_out" + ;; + + absent) + # change privileges (too complex to make exceptions) + cat <> "$__messages_out" - ;; + # end of su here-document + echo "SU" - # error handling: invalid state - *) - printf "Container '%s' in unknown state %s\n" "$name" "$state_should" >&2 - exit 2 - ;; - esac + # write to the message system + echo "destroy" >> "$__messages_out" + ;; - # end of su here-document - echo "SU" -fi + # error handling: invalid state + *) + printf "Container '%s' in unknown state %s\n" "$name" "$state_should" >&2 + exit 2 + ;; +esac +# shortcut +tmppath="$__object/files/remote-tmpfile" + # Check the configurations only if the container exists and there are changes if [ "$state_should" != "absent" ] && \ ( [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ] ); then - # shortcut - tmppath="$__object/files/remote-tmpfile" # generate config path container_config="$(cat "$__object/explorer/lxcpath")/$name/config" @@ -123,6 +152,15 @@ tmpconfig="\$(mktemp "$container_config.XXXXXXXXXX")" cp -p "$container_config" "\$tmpconfig" DONE + # check if smth. to be deleted + # must be before adding, because it takes the content of the original file + if [ -f "${tmppath}_del" ]; then + cat < "\$tmpconfig" +rm -rf "$(cat "${tmppath}_del")" +DONE + fi + # check if smth. to be added if [ -f "${tmppath}_add" ]; then cat < "\$tmpconfig" -rm -rf "$(cat "${tmppath}_del")" -DONE - fi - # apply all changes cat <> "$2" + cat "$__object/stdin" elif [ -f "$line" ]; then # append file content - cat "$line" >> "$2" + cat "$line" else # print out content - printf "%s\n" "$line" >> "$2" + printf "%s\n" "$line" fi done < "$__object/parameter/$1" } @@ -83,24 +85,26 @@ write_multi_param() { # Parameters: # 1: the file which should be handled trimm_whitespaces() { - cp "$1" "$1"~ # backup file to see original content - grep -E -v "^([[:blank:]]*)(#|$)" "$1" \ - | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' + mv "$1" "$1"~ # backup file to see original content + grep -E -v "^([[:blank:]]*)(#|$)" "$1"~ \ + | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' \ + > "$1" } + # Only required if container will not be absent -# get the wanted configuration lines +# prepare the wanted configuration lines if [ "$(cat "$__object/parameter/state")" != "absent" ]; then # Create the files directory mkdir "$__object/files/" # Create the file of the locally configuration conffile="$__object/files/config-present" - write_multi_param config "$conffile" - trimm_whitespaces "$conffile" > "$conffile" + write_multi_param config > "$conffile" + trimm_whitespaces "$conffile" # Create the file of the absent configuration absentfile="$__object/files/config-absent" - write_multi_param config-absent "$absentfile" - trimm_whitespaces "$absentfile" > "$absentfile" + write_multi_param config-absent > "$absentfile" + trimm_whitespaces "$absentfile" fi From c92d56293488eebf8df96f55153a0ca1fb16edc7 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sat, 4 Jul 2020 14:25:13 +0200 Subject: [PATCH 04/17] [__lxc_container] refactored gencode-remote processing litte changes to `gencode-local` and more messages, too. --- cdist/conf/type/__lxc_container/gencode-local | 3 +- .../conf/type/__lxc_container/gencode-remote | 133 ++++++++++++------ cdist/conf/type/__lxc_container/man.rst | 12 ++ 3 files changed, 101 insertions(+), 47 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-local b/cdist/conf/type/__lxc_container/gencode-local index dbfca7e8..04935070 100755 --- a/cdist/conf/type/__lxc_container/gencode-local +++ b/cdist/conf/type/__lxc_container/gencode-local @@ -4,8 +4,7 @@ # This uploads the diff of the configuration file, which is applied by gencode-remote -# check both states -state_is="$(cat "$__object/explorer/state")" +# Check desired state state_should="$(cat "$__object/parameter/state")" # Check the configurations only if the container exists diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index b03f13d2..d1e06b6e 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -2,6 +2,16 @@ # gencode-remote # Does all common stuff for the container on the host +# +# Following stages need to be observed when executing this type +# 1. Container creation IF $state_is = absent +# 2. patching container config IF NOT $state_should = absent +# 3. look after runstates (running,frozen,stopped) +# 4. Container destruction IF $state_should = absent +# +# It is only required if: +# - $state_is != $state_should +# - config changed (detects if changes are uploaded) # Parameter gathering @@ -18,7 +28,7 @@ state_is="$(cat "$__object/explorer/state")" state_should="$(cat "$__object/parameter/state")" # general lxc things -lxcpath="$(cat "$__object/parameter/lxcpath" || true)" +lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # Summerize common parameter arguments, listed in manual as "COMMON OPTIONS" @@ -31,9 +41,25 @@ if [ -n "$lxcpath" ]; then fi +# shortcut +tmppath="$__object/files/remote-tmpfile" +# shortcut function +config_changes() { + if ( [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ] ); then + return 0 + else + return 1 + fi +} + + +# Short curcit if nothing changed +if [ "$state_is" = "$state_should" ] && ( ! config_changes ); then exit; fi + # handle if the container should exist or not case "$state_should" in + # all states where the container should exist present|running|stopped|frozen) # only relevant if the container does not exist before if [ "$state_is" = "absent" ]; then @@ -98,35 +124,25 @@ LXC cat <> "$__messages_out" fi - - # end of su here-document - echo "SU" - - # write to the message system - echo "create" >> "$__messages_out" ;; + + # list other states to get a correct error message in the wildcard case absent) - # change privileges (too complex to make exceptions) - cat <> "$__messages_out" ;; # error handling: invalid state @@ -137,13 +153,8 @@ LXC esac -# shortcut -tmppath="$__object/files/remote-tmpfile" - # Check the configurations only if the container exists and there are changes -if [ "$state_should" != "absent" ] && \ - ( [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ] ); then - +if config_changes; then # generate config path container_config="$(cat "$__object/explorer/lxcpath")/$name/config" # create remote tmpfile for config @@ -180,54 +191,86 @@ DONE fi -# TODO user context again # Check if there is a difference within the states -if [ "$state_is" != "$state_should" ] && [ "$state_should" != "absent" ]; then +if [ "$state_is" != "$state_should" ] && [ "$state_should" != "present" ]; then # change privileges (too complex to make exceptions) cat <> "$__messages_out" + fi + # handle if the container should exist or not case "$state_should" in running) - if [ "$state_is" = "frozen" ]; then + # already running if unfreezed + if [ "$state_is" != "frozen" ]; then cat <> "$__messages_out" + fi ;; + # stop the container if it should be removed stopped) - if [ "$state_is" = "frozen" ]; then - cat <> "$__messages_out" + ;; + + # container should be stopped if not already done + absent) + if [ "$state_is" != "stopped" ]; then + cat <> "$__messages_out" fi cat <> "$__messages_out" ;; *) - ;; # must be checked by previous case + # must be checked by previous case + ;; esac # end of su here-document echo "SU" fi + + +# Check if the container needs to be removed +if [ "$state_should" = "absent" ]; then + # change privileges (too complex to make exceptions) + # then, shutdown and delete the container + # we could force-delete, but better be polite + # snapshots are deleted, too - to keep everything clean. May someone does not want it? + cat <> "$__messages_out" +fi diff --git a/cdist/conf/type/__lxc_container/man.rst b/cdist/conf/type/__lxc_container/man.rst index f84b0619..ddf08daa 100644 --- a/cdist/conf/type/__lxc_container/man.rst +++ b/cdist/conf/type/__lxc_container/man.rst @@ -123,3 +123,15 @@ destroy config The container configuration changed. + +start + Started the container. + +stop + Stopped the container. + +freeze + Freezed all container processes. The container will be started if not yet done to be able to freeze. + +melt + Unfreezed all container processes. Will be done if any other state (except `present`) should be reached. From e9256b6e8e3403e1435e4f1b65726dbb5dd991eb Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sat, 4 Jul 2020 18:19:46 +0200 Subject: [PATCH 05/17] [__lxc_container] create: added backingstore and template options With some minor changes, the backingstore parameters and some more template options where added (incl. `man.rst`). --- cdist/conf/type/__lxc_container/gencode-local | 22 ++++++- .../conf/type/__lxc_container/gencode-remote | 56 ++++++++++++++---- cdist/conf/type/__lxc_container/man.rst | 59 +++++++++++++++++-- cdist/conf/type/__lxc_container/manifest | 39 ++++++++++-- .../type/__lxc_container/parameter/optional | 9 +++ cdist/conf/type/__lxc_container/todo.txt | 17 +----- 6 files changed, 161 insertions(+), 41 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-local b/cdist/conf/type/__lxc_container/gencode-local index 04935070..e0572bb4 100755 --- a/cdist/conf/type/__lxc_container/gencode-local +++ b/cdist/conf/type/__lxc_container/gencode-local @@ -4,9 +4,18 @@ # This uploads the diff of the configuration file, which is applied by gencode-remote -# Check desired state +# Get required parameters +name="$__object/parameter/name" +if [ -f "$name" ]; then + name="$(cat "$name")" +else + name="$__object_id" +fi + +state_is="$(cat "$__object/explorer/state")" state_should="$(cat "$__object/parameter/state")" + # Check the configurations only if the container exists if [ "$state_should" != "absent" ]; then # do changes @@ -22,6 +31,13 @@ if [ "$state_should" != "absent" ]; then my_target_host="${__target_host}" fi + # create remote container directory if container is not yet available + if [ "$state_is" = "absent" ]; then + # this must be done because the container will be created after the configuration is uploaded + # would also be possible to do everything in gencode-remote to keep the order + $__remote_exec $__target_host "mkdir $(dirname "$container_config")" + fi + # config-present # remove all config lines from config-present that are already set or absent anyway @@ -31,7 +47,7 @@ if [ "$state_should" != "absent" ]; then # get temp file name add_dest="$($__remote_exec $__target_host "mktemp $container_config-add.XXXXXXXXXX")" printf "%s" "$add_dest" > "$__object/files/remote-tmpfile_add" - # upload diff + # upload delta cat < "$__object/files/remote-tmpfile_del" - # upload diff + # upload delta cat <&2 echo "error: --bdev-dir is only possible for backingstore 'dir' or 'none'" + exit 2 + fi + fi + + if [ "$backingstore" != "lvm" ] && [ "$backingstore" != "loop" ]; then + if [ -f "$param/bdev-fstype" ] \ + || [ -f "$param/bdev-fssize" ] + then + >&2 echo "error: --bdev-fstype and --bdev-fssize only available for backingstore 'lvm' or 'loop'" + exit 2 + fi + fi + + if [ "$backingstore" != "lvm" ]; then + if [ -f "$param/bdev-lvname" ] \ + || [ -f "$param/bdev-vgname" ] \ + || [ -f "$param/bdev-thinpool" ] + then + >&2 echo "error: --bdev-{lv,vg}name and --bdev-thinpool only available for backingstore 'lvm'" + exit 2 + fi + fi +fi + diff --git a/cdist/conf/type/__lxc_container/parameter/optional b/cdist/conf/type/__lxc_container/parameter/optional index fc4bb71b..257283d8 100644 --- a/cdist/conf/type/__lxc_container/parameter/optional +++ b/cdist/conf/type/__lxc_container/parameter/optional @@ -6,5 +6,14 @@ template default-config release arch +mirror +ssh-key clone clonepath +backingstore +bdev-dir +bdev-fstype +bdev-fssize +bdev-lvname +bdev-vgname +bdev-thinpool diff --git a/cdist/conf/type/__lxc_container/todo.txt b/cdist/conf/type/__lxc_container/todo.txt index 17c4edaf..e5f8f471 100644 --- a/cdist/conf/type/__lxc_container/todo.txt +++ b/cdist/conf/type/__lxc_container/todo.txt @@ -1,28 +1,13 @@ # List of all featues that should be implemented -storage: - - backing_storage - - other settings prior to storage template: - type: a.E. debian, ubuntu -> what on change? - - release - - arch - - possible ssh auth key? - possible root_password? - possible packages? - - possible mirrors? - other options?? -auto..: +auto.. (lxc autostart): - group - start -lxc config .. -how to find lxc containers path? -lxc-copy: ephemeral containers? -> seperate type if it makes sense If config already created, it's considered the container is already created -> first create; then setup detection if template changed?? - - -lxc configuration at startup: - flag -f can used to set a default config (instead the system default) - there is no problem to change config before the first startup From 1c8eee17499012a1f8b318b502603d37ca01dc13 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sun, 5 Jul 2020 11:52:34 +0200 Subject: [PATCH 06/17] [__lxc_container] Updated manpage (incl. examples, copyright, ..) Should be fine now. --- .../conf/type/__lxc_container/gencode-remote | 2 +- cdist/conf/type/__lxc_container/man.rst | 99 ++++++++++++++++--- 2 files changed, 86 insertions(+), 15 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index 8ee5623b..ef61c66d 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -105,7 +105,7 @@ USER # check, if the container should be created or cloned if [ -f "$__object/parameter/clone" ]; then copy_from="$(cat "$__object/parameter/clone")" - copypath="$(cat "$__object/parameter/clonepath" || true)" + copypath="$(cat "$__object/parameter/clonepath" 2>/dev/null || true)" # assemble own optional lxc options lxc_opts="" diff --git a/cdist/conf/type/__lxc_container/man.rst b/cdist/conf/type/__lxc_container/man.rst index 547178c5..991c86fb 100644 --- a/cdist/conf/type/__lxc_container/man.rst +++ b/cdist/conf/type/__lxc_container/man.rst @@ -3,16 +3,19 @@ cdist-type__lxc_container(7) NAME ---- -cdist-type__lxc_container - Controls the configuration of a lxc container +cdist-type__lxc_container - Controls the state and configuration of a lxc container DESCRIPTION ----------- -TBA. +This type handles lxc containers. It supports containers from different users and paths. +The state describes if the container exists and is running. The container will be created +with the template or clone parameters if required, whatever is set. These options will +be ignored if the container is already created, as the template script only runs at +creation time. REQUIRED PARAMETERS ------------------- - None. OPTIONAL PARAMETERS @@ -28,17 +31,17 @@ user state The state of the container, if it should exist or not. + present + The container exist, but it is ignored if the container will run or not **(default)** + running - The container exist and is running (default) + The container exist and is running stopped The container exist, but does not run frozen - The container exist and is frozen - - present - The container exist, but it is ignored if the container will run or not + The container exist and is frozen. If it is stopped before, it will be started and then freezed. absent The container does not exist @@ -59,7 +62,6 @@ config-absent BOOLEAN PARAMETERS ------------------ - None. CREATE PARAMETERS @@ -103,6 +105,7 @@ bdev-thinpool TEMPLATE PARAMETERS ------------------- + This or the *CLONE PARAMETERS* are required to create an container and must be present if the container should be created. If the template parameters are choosen, `--template` must be present. Then, none of the *CLONE PARAMETERS* must be present. @@ -119,9 +122,9 @@ template this argument and should exist on the target host. default-config - Alternative path to the user-defined default config. For the root user, this is commonly at - `/etc/lxc/default.conf`. It will be included into the container configuration file at creation - time. + Alternative path to the user-defined default config. This file must exist on the target machine. + For the root user, this is commonly at `/etc/lxc/default.conf`. It will be included into the + container configuration file at creation time. no-default-config **(Boolean value)** This parameter avoids using a default config file by using an empty file instead. @@ -149,13 +152,15 @@ ssh-key CLONE PARAMETERS ---------------- + This or the *TEMPLATE PARAMETERS* are required to create an container and must be present if the container should be created. If the clone parameters are choosen, `--clone` must be present. Then, none of the *TEMPLATE PARAMETERS* must be present. clone Instead of creating a new container with a given template, clone an other container and use him. The - argument takes the container name, which will be cloned. He should exist. + argument takes the container name, which will be cloned. He should exist and must be stopped. Else, + the clone will not work. clonepath The container path for the container to clone. It is like the `--lxcpath` parameter, but for the container @@ -180,7 +185,73 @@ stop Stopped the container. freeze - Freezed all container processes. The container will be started if not yet done to be able to freeze. + Freezed all container processes. The container will be started too if the container is stopped before. melt Unfreezed all container processes. Will be done if any other state (except `present`) should be reached. + +ABORTS +------ +Aborts in the following cases: + +The type aborts if there are incompatible arguments found. This may be *CLONE* and *TEMPLATE PARAMETERS*, +backingstorage parameters for the wrong storage or incompatible template option shortcuts. + +When cloning, it aborts if the container to clone from does not exist or is not stopped with no warning. It +may be possible to clone while the container is running, which requires a backing storage supporting it, but +there is nothing in lxc-copy(1) which indicades something about the container state while cloning. + +EXAMPLES +-------- + +.. code-block:: sh + + # create a container that "just should exist" (does not start the container) + # --template is required if the container needs to be created + __lxc_container foo --template debian + __lxc_container foo --state present --template debian + + # remove the container + __lxc_container bar --state absent + + # container that should definitely running + __lxc_container foobar --state running + # freeze this one + __lxc_container water --state frozen + + # create with some template options + __lxc_container special --state stopped --template debian \ + --release stretch --arch amd64 \ + --template-opts "--packages=foo,bar --flush-cache" + + # clone a container instead of creating it + # foo must be stopped that this will work + __lxc_container foofighters --clone foo --state running + + # handle configuration + __lxc_container peter --state running \ + --config "$__files/lxc/default.conf" \ # content of files are possible + --config "lxc.group = onboot" \ # one lines + --config "lxc.start.auto = 1" \ # spaces around the equal sign are ignored + --config-absent "lxc.group = testing" \ # configuration options can be removed + --config - < + +COPYRIGHT +--------- +Copyright \(C) 2020 Matthias Stecher. You can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. From 211393814a8c997d9f1ca27f86367ea8aace7cec Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sun, 5 Jul 2020 20:15:41 +0200 Subject: [PATCH 07/17] [__lxc_container] Updated manpage (completly proof-read it) I think it should be fine now .. :-) --- cdist/conf/type/__lxc_container/man.rst | 116 +++++++++++++----------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/cdist/conf/type/__lxc_container/man.rst b/cdist/conf/type/__lxc_container/man.rst index 991c86fb..d0abf2e2 100644 --- a/cdist/conf/type/__lxc_container/man.rst +++ b/cdist/conf/type/__lxc_container/man.rst @@ -14,6 +14,13 @@ with the template or clone parameters if required, whatever is set. These option be ignored if the container is already created, as the template script only runs at creation time. +The container can be `absent`, which means nothing exists. `present` is the opposite and +completely does not care if the container runs or not. Further states imply that the +container exists. There is `running` and `stopped`, which should be self-explainable. +The state `frozen` means all container processes are frozen. If it moves from `stopped` +to `frozen`, the container will be first started to be frozen. From `frozen` to any other +state, the container will be first unfrozen to continue. + REQUIRED PARAMETERS ------------------- None. @@ -23,13 +30,14 @@ OPTIONAL PARAMETERS name String which will used as container name instead of the object id. This should only required - if multiple lxc instances used from different users/directories (in junction with `--lxcpath`). + if multiple lxc instances used from different users/directories (in junction with ``--user`` + and ``--lxcpath``). user - The unix user name in which lxc commands are executed. Each user have a different lxc instance. + The unix user name with all lxc commands are executed. Each user have a different lxc instance. state - The state of the container, if it should exist or not. + The state of the container, if it should exist or not, and running. present The container exist, but it is ignored if the container will run or not **(default)** @@ -41,23 +49,23 @@ state The container exist, but does not run frozen - The container exist and is frozen. If it is stopped before, it will be started and then freezed. + The container exist and all processes are frozen absent The container does not exist lxcpath Set an other directory as lxc container location instead of the program default. This will passed - to all lxc commands who do smth. with containers. + to all lxc commands. config Contains configuration file paths and/or single configuration lines to assemble the lxc container - configuration file. There is no deep dive into files referenced with `lxc.include`. Can be used + configuration file. There is no deep dive into files referenced with ``lxc.include``. Can be used multiple times. config-absent - Contains configuration file paths and/ro single configuration lines which makes the same as the - `--config` parameter execpt all configuration lines will be removed instead of being added, Can + Contains configuration file paths and/or single configuration lines which makes the same as the + ``--config`` parameter execpt all configuration lines will be removed instead of being added. Can be used multiple times. BOOLEAN PARAMETERS @@ -67,63 +75,63 @@ None. CREATE PARAMETERS ----------------- -This parameters will be used with *TEMPLATE PARAMETERS* or *CLONE PARAMETERS* to create the container +This parameters will be used with **TEMPLATE PARAMETERS** or **CLONE PARAMETERS** to create the container if the container is absent. All of these parameters will only used if the container will be created, in all other cases, these parameters will be ignored. -All backingstore parameters (incl. all bdev-* ones) can be read from the manual lxc-create(1) at option -`--bdev` or lxc-copy(1) at option `--backingstore`. The possibilities may differ from creating and cloning. -The bdev-* parameters are only available for some backingstores. If used for other backingstores, the -type aborts. +All backingstore parameters (incl. all `bdev-*` ones) can be read from the manual lxc-create(1) at option +``--bdev`` or lxc-copy(1) at option ``--backingstore``. The possibilities may differ from creating and +cloning. The `bdev-*` parameters are only available for some backingstores. If used for other backingstores, +the type aborts. backingstore - Set the storage for the container root partition. Commonly, there should be at minimum `dir` (or `none`), - `lvm`, `loop`, `btrfs`, `zfs` or `best` be possible. + Set the storage for the container root filesystem. Commonly, there should be at minimum ``dir`` (or ``none``), + ``lvm``, ``loop``, ``btrfs``, ``zfs`` or ``best`` be possible. bdev-dir Specifies an other path for the rootfs directory instead in the lxc configuration directoy. Only - available for the backingstore `dir` or `none`. + available for the backingstore ``dir`` or ``none``. bdev-fstype Specifies the filesystem to be created instead of the default value. Only available for the - backingstore `lvm` and `loop`. + backingstore ``lvm`` and ``loop``. bdev-fssize Specifies the filesystem size to be created instead of the default value. Only available for the - backingstore `lvm` and `loop`. + backingstore ``lvm`` and ``loop``. bdev-lvname The custom LVM logical volume that will be created for the new container. Only availabe for the - backingstore `lvm`. + backingstore ``lvm``. bdev-vgname - The custon LVM volume group in there the logical volume will be created. Only available for the - backingstore `lvm`. + The custon LVM volume group in where the logical volume will be created. Only available for the + backingstore ``lvm``. bdev-thinpool - The custom thinpool the logical volume will created in. Only available for the backingstore `lvm`. + The custom thinpool the logical volume will created in. Only available for the backingstore ``lvm``. TEMPLATE PARAMETERS ------------------- -This or the *CLONE PARAMETERS* are required to create an container and must be present if the container -should be created. If the template parameters are choosen, `--template` must be present. Then, none of -the *CLONE PARAMETERS* must be present. +This or the **CLONE PARAMETERS** are required to create an container and must be present if the container +should be created. If the template parameters are choosen, ``--template`` must be present. Then, none of +the **CLONE PARAMETERS** must be present. Because the templates vary in the possiblities of arguments and unkown arguments causing the abort of the container creation, the type will throw an error if the compatibility is not garanteed to the given template. -The template options are only applied if the container will be created, there are not applied when -the container is already present. +The template options are only applied if the container will be created. There are not applied if the +container is already present. template - The template which is used to create the the container. The name of the template must passed with + The template which is used to create the the container. The name of the template must passed by this argument and should exist on the target host. default-config - Alternative path to the user-defined default config. This file must exist on the target machine. - For the root user, this is commonly at `/etc/lxc/default.conf`. It will be included into the + Alternative path for the user-defined default config. This file must exist on the target machine. + For the root user, this is commonly at ``/etc/lxc/default.conf``. It will be included into the container configuration file at creation time. no-default-config @@ -131,31 +139,31 @@ no-default-config template-opts Raw options which get passed to the template directly. Can be used multiple times. If the argument - contain spaces, it will be interpreted as multiple arguments and must be escaped for an normal posix - shell if this is not wanted. + contain spaces, it will be interpreted as multiple arguments by the target host and must be escaped + for a normal posix shell if this is not wanted. The following parameters are shortcuts for some template options. As templates may support it or not, you should be careful when using them. You can check all available template options with -`lxc-create -t $template -h` (incl. lxc-create help, too) or `/usr/share/lxc/templates/lxc-$template -h`. +``lxc-create -t $template -h`` (incl. lxc-create help, too) or ``/usr/share/lxc/templates/lxc-$template -h``. release - Sets the release for the wanted distribution. Uses the `-r` option. + Sets the release for the wanted distribution. Uses the ``-r`` option. arch - Sets the architecture used for the creating container. Uses the `-a` option. + Sets the architecture used for the creating container. Uses the ``-a`` option. mirror - Sets the mirror to download from. Uses the `--mirror=` option. + Sets the mirror to download from. Uses the ``--mirror=`` option. ssh-key - Sets the ssh key for the root user- Uses the `-S` option. + Sets the ssh key for the root user. Uses the ``-S`` option. CLONE PARAMETERS ---------------- -This or the *TEMPLATE PARAMETERS* are required to create an container and must be present if the container -should be created. If the clone parameters are choosen, `--clone` must be present. Then, none of the -*TEMPLATE PARAMETERS* must be present. +This or the **TEMPLATE PARAMETERS** are required to create an container and must be present if the container +should be created. If the clone parameters are choosen, ``--clone`` must be present. Then, none of the +**TEMPLATE PARAMETERS** must be present. clone Instead of creating a new container with a given template, clone an other container and use him. The @@ -163,8 +171,8 @@ clone the clone will not work. clonepath - The container path for the container to clone. It is like the `--lxcpath` parameter, but for the container - which will be cloned, not the target container. + The container path for the container to clone from. It is like the ``--lxcpath`` parameter, but for the + container from where will be cloned, not the target container (the container given by ``--clone``). MESSAGES -------- @@ -179,27 +187,27 @@ config The container configuration changed. start - Started the container. + Container was started. stop - Stopped the container. + Container was stopped. freeze - Freezed all container processes. The container will be started too if the container is stopped before. + Freezed all container processes. melt - Unfreezed all container processes. Will be done if any other state (except `present`) should be reached. + Unfreezed all container processes. ABORTS ------ Aborts in the following cases: -The type aborts if there are incompatible arguments found. This may be *CLONE* and *TEMPLATE PARAMETERS*, +The type aborts if there are incompatible arguments found. This may be **CLONE** and **TEMPLATE PARAMETERS**, backingstorage parameters for the wrong storage or incompatible template option shortcuts. -When cloning, it aborts if the container to clone from does not exist or is not stopped with no warning. It -may be possible to clone while the container is running, which requires a backing storage supporting it, but -there is nothing in lxc-copy(1) which indicades something about the container state while cloning. +When cloning, it aborts if the container to clone from does not exist or is not stopped with no warning. +It may be possible to clone while the container is running, which requires a backing storage supporting +it, but there is nothing in lxc-copy(1) which indicades something about the container state while cloning. EXAMPLES -------- @@ -221,7 +229,7 @@ EXAMPLES # create with some template options __lxc_container special --state stopped --template debian \ - --release stretch --arch amd64 \ + --release buster --arch amd64 \ --template-opts "--packages=foo,bar --flush-cache" # clone a container instead of creating it @@ -235,9 +243,9 @@ EXAMPLES --config "lxc.start.auto = 1" \ # spaces around the equal sign are ignored --config-absent "lxc.group = testing" \ # configuration options can be removed --config - < Date: Sun, 5 Jul 2020 20:50:40 +0200 Subject: [PATCH 08/17] [__lxc_container] fix some shellchecks (incl. warnings) To the error in the `explorer/state`: It's intended, as it passes possible parameters to the command. Varibale will set unquoted, so word splitting take action, but the quotes inside the variable work. --- cdist/conf/type/__lxc_container/explorer/state | 2 ++ cdist/conf/type/__lxc_container/gencode-remote | 6 +++--- cdist/conf/type/__lxc_container/manifest | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cdist/conf/type/__lxc_container/explorer/state b/cdist/conf/type/__lxc_container/explorer/state index fc37edf7..c3c7f30f 100755 --- a/cdist/conf/type/__lxc_container/explorer/state +++ b/cdist/conf/type/__lxc_container/explorer/state @@ -19,12 +19,14 @@ lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # assemble optional parameters LXC_PARAM="" if [ "$lxcpath" ]; then + # shellcheck disable=SC2089 LXC_PARAM="$LXC_PARAM -P \"$lxcpath\"" fi # function to get information lxc_info() { + # shellcheck disable=SC2090 disable=SC2086 if [ "$user" != "$USER" ]; then su -s "$(which -- lxc-info)" -- "$user" $LXC_PARAM -n "$name" -H "$@" else diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index ef61c66d..2177e377 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -44,7 +44,7 @@ fi # shortcut for checking config changes tmppath="$__object/files/remote-tmpfile" config_changes() { - if ( [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ] ); then + if [ -f "${tmppath}_add" ] || [ -f "${tmppath}_del" ]; then return 0 else return 1 @@ -91,7 +91,7 @@ USER backingstore_opts="" if [ -f "$__object/parameter/backingstore" ]; then # -B works for both types, they have different long opts - backingstore_opts="-B '$(cat "$__object/parameter/backingstore")'" + backingstore_opts="$backingstore_opts -B '$(cat "$__object/parameter/backingstore")'" # add parameters if available bdev_add_if_available dir @@ -149,7 +149,7 @@ LXC # at last, apply custom options if [ -f "$__object/parameter/template-opts" ]; then - while read line; do + while read -r line; do template_opts="$template_opts $line" done < "$__object/parameter/template-opts" fi diff --git a/cdist/conf/type/__lxc_container/manifest b/cdist/conf/type/__lxc_container/manifest index d903fa1c..4a74ea18 100755 --- a/cdist/conf/type/__lxc_container/manifest +++ b/cdist/conf/type/__lxc_container/manifest @@ -93,7 +93,7 @@ fi write_multi_param() { if ! [ -f "$__object/parameter/$1" ]; then return 0; fi - while read line; do + while read -r line; do if [ "$line" = "-" ]; then # append stdin cat "$__object/stdin" From 304d974f7bbb488ba80a522cb0f01fc3b79aa1b2 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sat, 11 Jul 2020 18:18:55 +0200 Subject: [PATCH 09/17] [__lxc_container] moved config diff incl. gencode-local to gencode-remote Rather than the config handling is split up over gencode-{local,remote} and the manifest, it is now completly moved to the gencode-remote script. This avoids complexity, file uploading and direct ssh interactions as it was used before. The diff creation was extracted into an extra script, and the gencode-local was removed. Now, the gencode-remote script executes the config diff script before the short curcuit and uses here-documents and pipes if the diff is required on the remote host. With this, the script size grows, but should be no difference if the file is downloaded temporarily. With this, the remote handling of an empty configuration file was enhanced by handling it completely into the code-remote script (hope escaping works correctly). --- .../type/__lxc_container/diff-conf-changes.sh | 72 +++++++++++++++++++ cdist/conf/type/__lxc_container/gencode-local | 69 ------------------ .../conf/type/__lxc_container/gencode-remote | 30 +++++--- cdist/conf/type/__lxc_container/manifest | 59 --------------- 4 files changed, 91 insertions(+), 139 deletions(-) create mode 100755 cdist/conf/type/__lxc_container/diff-conf-changes.sh delete mode 100755 cdist/conf/type/__lxc_container/gencode-local diff --git a/cdist/conf/type/__lxc_container/diff-conf-changes.sh b/cdist/conf/type/__lxc_container/diff-conf-changes.sh new file mode 100755 index 00000000..37d9f195 --- /dev/null +++ b/cdist/conf/type/__lxc_container/diff-conf-changes.sh @@ -0,0 +1,72 @@ +#!/bin/sh -e +# diff-conf-changes.sh + +# This script handles the configuration given to the type. It will be diffed against the existing +# container options and write the "to be done"-options to a separate file. +# +# Output files in "$__object/files/" : +# - config-{present,absent} +# - config.add +# - config.del + + +# Function to read multiple parameter input for configuration and print it to a single file. +# It will handle file paths as well as the stdin. Instead of the file, the content will be printed. +# +# Parameters: +# 1: parameter name +# 2: file to print +write_multi_param() { + if ! [ -f "$__object/parameter/$1" ]; then return 0; fi + + while read -r line; do + if [ "$line" = "-" ]; then + # append stdin + cat "$__object/stdin" + elif [ -f "$line" ]; then + # append file content + cat "$line" + else + # print out content + printf "%s\n" "$line" + fi + done < "$__object/parameter/$1" +} + +# Function to get rid of whitespaces inside of key-value pairs. It will clear all of these. +# +# Parameters: +# 1: the file which should be handled +trimm_whitespaces() { + mv "$1" "$1"~ # backup file to read write back original file + grep -E -v "^([[:blank:]]*)(#|$)" "$1"~ \ + | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' \ + > "$1" + rm -f "$1"~ +} + + +# Only required if container will not be absent +# prepare the wanted configuration lines +if [ "$(cat "$__object/parameter/state")" != "absent" ]; then + # create the files directory + mkdir "$__object/files/" + + # Summary of the locally given configuration options + # config-present + conffile="$__object/files/config-present" + write_multi_param config > "$conffile" + trimm_whitespaces "$conffile" + # config-absent + absentfile="$__object/files/config-absent" + write_multi_param config-absent > "$absentfile" + trimm_whitespaces "$absentfile" + + # Diff the configuration options by removing duplicate config options + # config.add + grep -v -f "$__object/explorer/config" -f "$__object/files/config-absent" \ + "$__object/files/config-present" > "$__object/files/config.add" || true + # config.del + grep -f "$__object/explorer/config" \ + "$__object/files/config-absent" > "$__object/files/config.del" || true +fi diff --git a/cdist/conf/type/__lxc_container/gencode-local b/cdist/conf/type/__lxc_container/gencode-local deleted file mode 100755 index e0572bb4..00000000 --- a/cdist/conf/type/__lxc_container/gencode-local +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/sh -e -# gencode-local - -# This uploads the diff of the configuration file, which is applied by gencode-remote - - -# Get required parameters -name="$__object/parameter/name" -if [ -f "$name" ]; then - name="$(cat "$name")" -else - name="$__object_id" -fi - -state_is="$(cat "$__object/explorer/state")" -state_should="$(cat "$__object/parameter/state")" - - -# Check the configurations only if the container exists -if [ "$state_should" != "absent" ]; then - # do changes - - # predict remote lxc config file - container_config="$(cat "$__object/explorer/lxcpath")/$name/config" - - # IPv6 fix - if echo "${__target_host}" | grep -q -E '^[0-9a-fA-F:]+$' - then - my_target_host="[${__target_host}]" - else - my_target_host="${__target_host}" - fi - - # create remote container directory if container is not yet available - if [ "$state_is" = "absent" ]; then - # this must be done because the container will be created after the configuration is uploaded - # would also be possible to do everything in gencode-remote to keep the order - $__remote_exec $__target_host "mkdir $(dirname "$container_config")" - fi - - - # config-present - # remove all config lines from config-present that are already set or absent anyway - if grep -v -f "$__object/explorer/config" -f "$__object/files/config-absent" \ - "$__object/files/config-present" > "$__object/files/config.add"; then - - # get temp file name - add_dest="$($__remote_exec $__target_host "mktemp $container_config-add.XXXXXXXXXX")" - printf "%s" "$add_dest" > "$__object/files/remote-tmpfile_add" - # upload delta - cat < "$__object/files/config.del"; then - - # get temp file name - del_dest="$($__remote_exec $__target_host "mktemp $container_config-del.XXXXXXXXXX")" - printf "%s" "$del_dest" > "$__object/files/remote-tmpfile_del" - # upload delta - cat < $file' will not work (> opens before command reads it) + if [ -s "$__object/files/config.del" ]; then cat < "\$tmpconfig" -rm -rf "$(cat "${tmppath}_del")" +grep -v -f - <<'ABSENT' "$container_config" > "\$tmpconfig" +$(cat "$__object/files/config.del") +ABSENT DONE fi # check if smth. to be added - if [ -f "${tmppath}_add" ]; then + if [ -s "$__object/files/config.add" ]; then cat <> "\$tmpconfig" -rm -rf "$(cat "${tmppath}_add")" +cat <<'PRESENT' >> "\$tmpconfig" +$(cat "$__object/files/config.add") +PRESENT DONE fi diff --git a/cdist/conf/type/__lxc_container/manifest b/cdist/conf/type/__lxc_container/manifest index 4a74ea18..99cfa1c0 100755 --- a/cdist/conf/type/__lxc_container/manifest +++ b/cdist/conf/type/__lxc_container/manifest @@ -76,62 +76,3 @@ if [ -f "$param/backingstore" ]; then fi fi fi - - - - -# ============================== # -# == CONFIGURATION HANDLING == # -# ============================== # - -# Function to read multiple parameter input for configuration and print it to a single file. -# It will handle file paths as well as the stdin. Instead of the file, the content will be printed. -# -# Parameters: -# 1: parameter name -# 2: file to print -write_multi_param() { - if ! [ -f "$__object/parameter/$1" ]; then return 0; fi - - while read -r line; do - if [ "$line" = "-" ]; then - # append stdin - cat "$__object/stdin" - elif [ -f "$line" ]; then - # append file content - cat "$line" - else - # print out content - printf "%s\n" "$line" - fi - done < "$__object/parameter/$1" -} - -# Function to get rid of whitespaces inside of key-value pairs. It will clear all of these. -# -# Parameters: -# 1: the file which should be handled -trimm_whitespaces() { - mv "$1" "$1"~ # backup file to see original content - grep -E -v "^([[:blank:]]*)(#|$)" "$1"~ \ - | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' \ - > "$1" -} - - -# Only required if container will not be absent -# prepare the wanted configuration lines -if [ "$(cat "$__object/parameter/state")" != "absent" ]; then - # Create the files directory - mkdir "$__object/files/" - - # Create the file of the locally configuration - conffile="$__object/files/config-present" - write_multi_param config > "$conffile" - trimm_whitespaces "$conffile" - - # Create the file of the absent configuration - absentfile="$__object/files/config-absent" - write_multi_param config-absent > "$absentfile" - trimm_whitespaces "$absentfile" -fi From 6d29b0542a82f6cf12429291aec488c649bf1323 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sun, 12 Jul 2020 20:37:59 +0200 Subject: [PATCH 10/17] [__lxc_container] better support config modifications at creation time When a container is created, the configuration is unknown to the explorer. To do the job without the knowleage, following is added: If the container will be created, it adds all absent configuration options to be deleted. Because it do not know which configuration options exist, it tries to remove all if there exists. This behaviour is extended for containers that will be cloned: Because the container who will be cloned is known and it will copy the config nearly one to one, so it will read this configuration. The removal of configuration is generally improved by generating a pattern to ignore spaces at the beginning, near the equal sign and at the end. This deletes the correct configuration lines even they have malformed whitespaces. --- .../type/__lxc_container/diff-conf-changes.sh | 15 +++++++++++++- .../conf/type/__lxc_container/explorer/config | 20 +++++++++++++++++-- .../conf/type/__lxc_container/gencode-remote | 8 ++++++-- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/cdist/conf/type/__lxc_container/diff-conf-changes.sh b/cdist/conf/type/__lxc_container/diff-conf-changes.sh index 37d9f195..d860a8b8 100755 --- a/cdist/conf/type/__lxc_container/diff-conf-changes.sh +++ b/cdist/conf/type/__lxc_container/diff-conf-changes.sh @@ -46,9 +46,13 @@ trimm_whitespaces() { } +# save states +state_should="$(cat "$__object/parameter/state")" +state_is="$(cat "$__object/explorer/state")" + # Only required if container will not be absent # prepare the wanted configuration lines -if [ "$(cat "$__object/parameter/state")" != "absent" ]; then +if [ "$state_should" != "absent" ]; then # create the files directory mkdir "$__object/files/" @@ -69,4 +73,13 @@ if [ "$(cat "$__object/parameter/state")" != "absent" ]; then # config.del grep -f "$__object/explorer/config" \ "$__object/files/config-absent" > "$__object/files/config.del" || true + + + # fallback: if template parameter exists and container currently absent; try to remove all configs + # If the container is currently absent, nothing will be removed, even it's in the default config + # In this case, it will try to delete every configuration option to be sure + # only the cloning configuration is known, but not if the container will be created in an other way + if [ "$state_is" = "absent" ] && ! [ -f "$__object/parameter/clone" ]; then + cp "$__object/files/config-absent" "$__object/files/config.del" + fi fi diff --git a/cdist/conf/type/__lxc_container/explorer/config b/cdist/conf/type/__lxc_container/explorer/config index 287a5063..16fcf14a 100755 --- a/cdist/conf/type/__lxc_container/explorer/config +++ b/cdist/conf/type/__lxc_container/explorer/config @@ -22,8 +22,24 @@ else fi -# assemble the container configuration file -config="$lxcpath/$name/config" +# if the container will be cloned, use the configuration of the container to clone from +# else, just use the normal container configuration +clone="$__object/parameter/clone" +if [ -f "$clone" ] && [ "$("$__type_explorer/state")" = "absent" ]; then + clone="$(cat "$clone")" + clonepath="$__object/parameter/clonepath" + if [ -f "$clonepath" ]; then + clonepath="$(cat "$clonepath")" + else + clonepath="$lxcpath" + fi + + # set the config path of the container to clone from + config="$clonepath/$clone/config" +else + # assemble the configuration file of the container + config="$lxcpath/$name/config" +fi # check if the file exist, else the container is absent if [ -r "$config" ]; then diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index ca2f2827..bd3f49b6 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -205,10 +205,14 @@ DONE # check if smth. to be deleted # must be before adding, because it takes the content of the original file # because 'cat $file > $file' will not work (> opens before command reads it) + # will create extended regex pattern for grep with malformed spaces if [ -s "$__object/files/config.del" ]; then cat < "\$tmpconfig" -$(cat "$__object/files/config.del") +grep -v -E -f - <<'ABSENT' "$container_config" > "\$tmpconfig" +$(awk -v FS=' = ' -v OFS=' = ' -v blank='[[:blank:]]*' ' +function ntostring(n) { ret=""; for(i=n; i<=NF; i++) ret=ret $i (i Date: Sun, 12 Jul 2020 21:30:44 +0200 Subject: [PATCH 11/17] [__lxc_container] handle $empty_conf for --no-default-config correctly Fixed wrong variable spelling and correct check to remove the tempfile again (forgotten from 304d974f). --- cdist/conf/type/__lxc_container/gencode-remote | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index bd3f49b6..ddba593a 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -132,10 +132,11 @@ LXC create_opts="" if [ -f "$__object/parameter/no-default-config" ]; then # generate a random empty file and append + # maybe work with an nonexistant file - but just be correct cat < Date: Mon, 13 Jul 2020 20:31:18 +0200 Subject: [PATCH 12/17] [__lxc_container] add --restart-if-changed parameter to apply changes This parameter restarts the container if configuration changes and it is already running and should keept running. It handles the freeze state, because it would be expected to apply changes in this state, too. --- .../conf/type/__lxc_container/gencode-remote | 49 ++++++++++++++++++- cdist/conf/type/__lxc_container/man.rst | 6 ++- .../type/__lxc_container/parameter/boolean | 1 + 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index ddba593a..480d7d41 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -234,8 +234,55 @@ DONE rm -rf "$container_config" mv "\$tmpconfig" "$container_config" DONE - # write message echo "config" >> "$__messages_out" + + + # restart container only if it is running + # do not echo messages start/stop or melt/start/stop/freeze; only restart to avoid junk + case "$state_is" in + running|frozen) + # only do it if the container will run again + case "$state_should" in + present|running|frozen) + # su stuff + cat <> "$__messages_out" + fi + fi + + # ending + echo "restart" >> "$__messages_out" + echo "SU" + ;; + esac + ;; + esac fi diff --git a/cdist/conf/type/__lxc_container/man.rst b/cdist/conf/type/__lxc_container/man.rst index d0abf2e2..7d1f6522 100644 --- a/cdist/conf/type/__lxc_container/man.rst +++ b/cdist/conf/type/__lxc_container/man.rst @@ -70,7 +70,11 @@ config-absent BOOLEAN PARAMETERS ------------------ -None. + +restart-if-changed + Restarts the container if configuration changes. It stop and start the container that new configuration + can be applied. If it whould be restarted with ``lxc-stop -n $name --reboot``, configuration changes + would be ignored. CREATE PARAMETERS ----------------- diff --git a/cdist/conf/type/__lxc_container/parameter/boolean b/cdist/conf/type/__lxc_container/parameter/boolean index caf89a8e..724fa14b 100644 --- a/cdist/conf/type/__lxc_container/parameter/boolean +++ b/cdist/conf/type/__lxc_container/parameter/boolean @@ -1 +1,2 @@ no-default-config +restart-if-changed From 5d6f90555bdf60354dc298c87e06cf8a551a2b1c Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Mon, 13 Jul 2020 21:16:18 +0200 Subject: [PATCH 13/17] [__lxc_container] s/\t/ /g; renewed todo.txt file Replaced all tabs with 4 spaces (~/.vimrc is modified, too). The issue.txt is not required anymore and the todo.txt was updated. --- .../type/__lxc_container/diff-conf-changes.sh | 86 ++-- .../conf/type/__lxc_container/explorer/config | 32 +- .../type/__lxc_container/explorer/lxcpath | 18 +- .../conf/type/__lxc_container/explorer/state | 24 +- .../conf/type/__lxc_container/gencode-remote | 396 +++++++++--------- cdist/conf/type/__lxc_container/issue.txt | 1 - cdist/conf/type/__lxc_container/manifest | 86 ++-- cdist/conf/type/__lxc_container/todo.txt | 10 +- 8 files changed, 328 insertions(+), 325 deletions(-) delete mode 100644 cdist/conf/type/__lxc_container/issue.txt diff --git a/cdist/conf/type/__lxc_container/diff-conf-changes.sh b/cdist/conf/type/__lxc_container/diff-conf-changes.sh index d860a8b8..b18b9fe4 100755 --- a/cdist/conf/type/__lxc_container/diff-conf-changes.sh +++ b/cdist/conf/type/__lxc_container/diff-conf-changes.sh @@ -17,20 +17,20 @@ # 1: parameter name # 2: file to print write_multi_param() { - if ! [ -f "$__object/parameter/$1" ]; then return 0; fi + if ! [ -f "$__object/parameter/$1" ]; then return 0; fi - while read -r line; do - if [ "$line" = "-" ]; then - # append stdin - cat "$__object/stdin" - elif [ -f "$line" ]; then - # append file content - cat "$line" - else - # print out content - printf "%s\n" "$line" - fi - done < "$__object/parameter/$1" + while read -r line; do + if [ "$line" = "-" ]; then + # append stdin + cat "$__object/stdin" + elif [ -f "$line" ]; then + # append file content + cat "$line" + else + # print out content + printf "%s\n" "$line" + fi + done < "$__object/parameter/$1" } # Function to get rid of whitespaces inside of key-value pairs. It will clear all of these. @@ -38,11 +38,11 @@ write_multi_param() { # Parameters: # 1: the file which should be handled trimm_whitespaces() { - mv "$1" "$1"~ # backup file to read write back original file - grep -E -v "^([[:blank:]]*)(#|$)" "$1"~ \ - | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' \ - > "$1" - rm -f "$1"~ + mv "$1" "$1"~ # backup file to read write back original file + grep -E -v "^([[:blank:]]*)(#|$)" "$1"~ \ + | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' \ + > "$1" + rm -f "$1"~ } @@ -53,33 +53,33 @@ state_is="$(cat "$__object/explorer/state")" # Only required if container will not be absent # prepare the wanted configuration lines if [ "$state_should" != "absent" ]; then - # create the files directory - mkdir "$__object/files/" + # create the files directory + mkdir "$__object/files/" - # Summary of the locally given configuration options - # config-present - conffile="$__object/files/config-present" - write_multi_param config > "$conffile" - trimm_whitespaces "$conffile" - # config-absent - absentfile="$__object/files/config-absent" - write_multi_param config-absent > "$absentfile" - trimm_whitespaces "$absentfile" + # Summary of the locally given configuration options + # config-present + conffile="$__object/files/config-present" + write_multi_param config > "$conffile" + trimm_whitespaces "$conffile" + # config-absent + absentfile="$__object/files/config-absent" + write_multi_param config-absent > "$absentfile" + trimm_whitespaces "$absentfile" - # Diff the configuration options by removing duplicate config options - # config.add - grep -v -f "$__object/explorer/config" -f "$__object/files/config-absent" \ - "$__object/files/config-present" > "$__object/files/config.add" || true - # config.del - grep -f "$__object/explorer/config" \ - "$__object/files/config-absent" > "$__object/files/config.del" || true + # Diff the configuration options by removing duplicate config options + # config.add + grep -v -f "$__object/explorer/config" -f "$__object/files/config-absent" \ + "$__object/files/config-present" > "$__object/files/config.add" || true + # config.del + grep -f "$__object/explorer/config" \ + "$__object/files/config-absent" > "$__object/files/config.del" || true - # fallback: if template parameter exists and container currently absent; try to remove all configs - # If the container is currently absent, nothing will be removed, even it's in the default config - # In this case, it will try to delete every configuration option to be sure - # only the cloning configuration is known, but not if the container will be created in an other way - if [ "$state_is" = "absent" ] && ! [ -f "$__object/parameter/clone" ]; then - cp "$__object/files/config-absent" "$__object/files/config.del" - fi + # fallback: if template parameter exists and container currently absent; try to remove all configs + # If the container is currently absent, nothing will be removed, even it's in the default config + # In this case, it will try to delete every configuration option to be sure + # only the cloning configuration is known, but not if the container will be created in an other way + if [ "$state_is" = "absent" ] && ! [ -f "$__object/parameter/clone" ]; then + cp "$__object/files/config-absent" "$__object/files/config.del" + fi fi diff --git a/cdist/conf/type/__lxc_container/explorer/config b/cdist/conf/type/__lxc_container/explorer/config index 16fcf14a..5aa020e4 100755 --- a/cdist/conf/type/__lxc_container/explorer/config +++ b/cdist/conf/type/__lxc_container/explorer/config @@ -6,7 +6,7 @@ # abort if container will be absent - no config required if [ "$(cat "$__object/parameter/state")" = "absent" ]; then - exit 0 + exit 0 fi @@ -26,25 +26,25 @@ fi # else, just use the normal container configuration clone="$__object/parameter/clone" if [ -f "$clone" ] && [ "$("$__type_explorer/state")" = "absent" ]; then - clone="$(cat "$clone")" - clonepath="$__object/parameter/clonepath" - if [ -f "$clonepath" ]; then - clonepath="$(cat "$clonepath")" - else - clonepath="$lxcpath" - fi + clone="$(cat "$clone")" + clonepath="$__object/parameter/clonepath" + if [ -f "$clonepath" ]; then + clonepath="$(cat "$clonepath")" + else + clonepath="$lxcpath" + fi - # set the config path of the container to clone from - config="$clonepath/$clone/config" + # set the config path of the container to clone from + config="$clonepath/$clone/config" else - # assemble the configuration file of the container - config="$lxcpath/$name/config" + # assemble the configuration file of the container + config="$lxcpath/$name/config" fi # check if the file exist, else the container is absent if [ -r "$config" ]; then - # print configuration and strip files to just values - # grep will hide all comments and empty lines - all others must be key-values - # sed will uniform patterns, that no spaces will be problematic (before, in the middle and at end) - grep -E -v "^([[:blank:]]*)(#|$)" "$config" | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' + # print configuration and strip files to just values + # grep will hide all comments and empty lines - all others must be key-values + # sed will uniform patterns, that no spaces will be problematic (before, in the middle and at end) + grep -E -v "^([[:blank:]]*)(#|$)" "$config" | sed 's/^[[:blank:]]*//; s/[[:blank:]]*=[[:blank:]]*/ = /; s/[[:blank:]]*$//' fi diff --git a/cdist/conf/type/__lxc_container/explorer/lxcpath b/cdist/conf/type/__lxc_container/explorer/lxcpath index a4116b9b..e633cff6 100755 --- a/cdist/conf/type/__lxc_container/explorer/lxcpath +++ b/cdist/conf/type/__lxc_container/explorer/lxcpath @@ -9,15 +9,15 @@ lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # lxcpath parameter if [ -z "$lxcpath" ]; then - user="$(cat "$__object/parameter/user")" + user="$(cat "$__object/parameter/user")" - # gather default value from config - if [ "$user" != "$USER" ]; then - su -s "$(which -- lxc-config)" -- "$user" lxc.lxcpath - else - lxc-config lxc.lxcpath - fi + # gather default value from config + if [ "$user" != "$USER" ]; then + su -s "$(which -- lxc-config)" -- "$user" lxc.lxcpath + else + lxc-config lxc.lxcpath + fi else - # output the parameter - echo "$lxcpath" + # output the parameter + echo "$lxcpath" fi diff --git a/cdist/conf/type/__lxc_container/explorer/state b/cdist/conf/type/__lxc_container/explorer/state index c3c7f30f..86831ce2 100755 --- a/cdist/conf/type/__lxc_container/explorer/state +++ b/cdist/conf/type/__lxc_container/explorer/state @@ -19,27 +19,27 @@ lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # assemble optional parameters LXC_PARAM="" if [ "$lxcpath" ]; then - # shellcheck disable=SC2089 - LXC_PARAM="$LXC_PARAM -P \"$lxcpath\"" + # shellcheck disable=SC2089 + LXC_PARAM="$LXC_PARAM -P \"$lxcpath\"" fi # function to get information lxc_info() { - # shellcheck disable=SC2090 disable=SC2086 - if [ "$user" != "$USER" ]; then - su -s "$(which -- lxc-info)" -- "$user" $LXC_PARAM -n "$name" -H "$@" - else - lxc-info $LXC_PARAM -n "$name" -H "$@" - fi + # shellcheck disable=SC2090 disable=SC2086 + if [ "$user" != "$USER" ]; then + su -s "$(which -- lxc-info)" -- "$user" $LXC_PARAM -n "$name" -H "$@" + else + lxc-info $LXC_PARAM -n "$name" -H "$@" + fi } # the lxc-info command will exit non-zero if container not exist if ! lxc_info -S >/dev/null 2>&1; then - # not exist - echo "absent" + # not exist + echo "absent" else - # print state (command output matches to type states) - lxc_info -s | tr '[:upper:]' '[:lower:]' + # print state (command output matches to type states) + lxc_info -s | tr '[:upper:]' '[:lower:]' fi diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index 480d7d41..f9e4dceb 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -44,31 +44,31 @@ fi # shortcut for checking config changes # returns success (0) if there are changes config_changes() { - if [ -s "$__object/files/config.add" ] || [ -s "$__object/files/config.del" ]; then - return 0 - else - return 1 - fi + if [ -s "$__object/files/config.add" ] || [ -s "$__object/files/config.del" ]; then + return 0 + else + return 1 + fi } # shortcut to add bdev parameters if available # $1: $__object parameter name without "bdev-" # $2: target parameter flag (like --foo), else "--$1" will be used bdev_add_if_available() { - _param_path="$__object/parameter/bdev-$1" - if [ -f "$_param_path" ]; then - backingstore_opts="$backingstore_opts ${2:---$1} '$(cat "$_param_path")'" - fi + _param_path="$__object/parameter/bdev-$1" + if [ -f "$_param_path" ]; then + backingstore_opts="$backingstore_opts ${2:---$1} '$(cat "$_param_path")'" + fi } # shortcut to add template parameters if available # $1: $__object parameter # $2: target parameter flag (like --foo), else "--$1" will be used template_add_if_available() { - _param_path="$__object/parameter/$1" - if [ -f "$_param_path" ]; then - template_opts="$template_opts ${2:---$1} '$(cat "$_param_path")'" - fi + _param_path="$__object/parameter/$1" + if [ -f "$_param_path" ]; then + template_opts="$template_opts ${2:---$1} '$(cat "$_param_path")'" + fi } @@ -81,291 +81,291 @@ if [ "$state_is" = "$state_should" ] && ( ! config_changes ); then exit; fi # handle if the container should exist or not case "$state_should" in - # all states where the container should exist - present|running|stopped|frozen) - # only relevant if the container does not exist before - if [ "$state_is" = "absent" ]; then - # change privileges (too complex to make exceptions) - cat </dev/null || true)" + # check, if the container should be created or cloned + if [ -f "$__object/parameter/clone" ]; then + copy_from="$(cat "$__object/parameter/clone")" + copypath="$(cat "$__object/parameter/clonepath" 2>/dev/null || true)" - # assemble own optional lxc options - lxc_opts="" - if [ -n "$copypath" ]; then - # this is set as the default $lxcpath, because it is the origin - lxc_opts="$lxc_opts -P \"$copypath\"" - fi - if [ -n "$lxcpath" ]; then - # this is set as the newpath, because it is the destination - lxc_opts="$lxc_opts -p \"$lxcpath\"" - fi + # assemble own optional lxc options + lxc_opts="" + if [ -n "$copypath" ]; then + # this is set as the default $lxcpath, because it is the origin + lxc_opts="$lxc_opts -P \"$copypath\"" + fi + if [ -n "$lxcpath" ]; then + # this is set as the newpath, because it is the destination + lxc_opts="$lxc_opts -p \"$lxcpath\"" + fi - # print lxc-copy code (because of the lxcpath thing, $LXC_PARAM conflicts) - cat <> "$__messages_out" - fi - ;; + # write to the message system + echo "create" >> "$__messages_out" + fi + ;; - # list other states to get a correct error message in the wildcard case - absent) - ;; + # list other states to get a correct error message in the wildcard case + absent) + ;; - # error handling: invalid state - *) - printf "Container '%s' in unknown state %s\n" "$name" "$state_should" >&2 - exit 2 - ;; + # error handling: invalid state + *) + printf "Container '%s' in unknown state %s\n" "$name" "$state_should" >&2 + exit 2 + ;; esac # Check the configurations only if the container exists and there are changes if config_changes; then - # generate config path - container_config="$(cat "$__object/explorer/lxcpath")/$name/config" - # create remote tmpfile for config - cat < $file' will not work (> opens before command reads it) - # will create extended regex pattern for grep with malformed spaces - if [ -s "$__object/files/config.del" ]; then - cat < $file' will not work (> opens before command reads it) + # will create extended regex pattern for grep with malformed spaces + if [ -s "$__object/files/config.del" ]; then + cat < "\$tmpconfig" $(awk -v FS=' = ' -v OFS=' = ' -v blank='[[:blank:]]*' ' function ntostring(n) { ret=""; for(i=n; i<=NF; i++) ret=ret $i (i> "\$tmpconfig" $(cat "$__object/files/config.add") PRESENT DONE - fi + fi - # apply all changes - cat <> "$__messages_out" + echo "config" >> "$__messages_out" - # restart container only if it is running - # do not echo messages start/stop or melt/start/stop/freeze; only restart to avoid junk - case "$state_is" in - running|frozen) - # only do it if the container will run again - case "$state_should" in - present|running|frozen) - # su stuff - cat <> "$__messages_out" - fi - fi + else + # correct current state + state_is="running" + echo "melt" >> "$__messages_out" + fi + fi - # ending - echo "restart" >> "$__messages_out" - echo "SU" - ;; - esac - ;; - esac + # ending + echo "restart" >> "$__messages_out" + echo "SU" + ;; + esac + ;; + esac fi # Check if there is a difference within the states if [ "$state_is" != "$state_should" ] && [ "$state_should" != "present" ]; then - # change privileges (too complex to make exceptions) - cat <> "$__messages_out" - fi + echo "melt" >> "$__messages_out" + fi - # handle if the container should exist or not - case "$state_should" in - running) - # already running if unfreezed - if [ "$state_is" != "frozen" ]; then - cat <> "$__messages_out" - fi - ;; + echo "start" >> "$__messages_out" + fi + ;; - # stop the container if it should be removed - stopped) - cat <> "$__messages_out" - ;; + echo "stop" >> "$__messages_out" + ;; - # container should be stopped if not already done - absent) - if [ "$state_is" != "stopped" ]; then - cat <> "$__messages_out" - fi - cat <> "$__messages_out" + fi + cat <> "$__messages_out" - ;; + echo "freeze" >> "$__messages_out" + ;; - *) - # must be checked by previous case - ;; - esac + *) + # must be checked by previous case + ;; + esac - # end of su here-document - echo "SU" + # end of su here-document + echo "SU" fi # Check if the container needs to be removed if [ "$state_should" = "absent" ]; then - # change privileges (too complex to make exceptions) - # then, shutdown and delete the container - # we could force-delete, but better be polite - # snapshots are deleted, too - to keep everything clean. May someone does not want it? - cat <> "$__messages_out" + # write to the message system + echo "destroy" >> "$__messages_out" fi diff --git a/cdist/conf/type/__lxc_container/issue.txt b/cdist/conf/type/__lxc_container/issue.txt deleted file mode 100644 index f65f9780..00000000 --- a/cdist/conf/type/__lxc_container/issue.txt +++ /dev/null @@ -1 +0,0 @@ -$__object_id == name ? sperate parameter required?? multiple same names possible due to --lxcpath! diff --git a/cdist/conf/type/__lxc_container/manifest b/cdist/conf/type/__lxc_container/manifest index 99cfa1c0..0071c4fb 100755 --- a/cdist/conf/type/__lxc_container/manifest +++ b/cdist/conf/type/__lxc_container/manifest @@ -17,62 +17,62 @@ param="$__object/parameter/" # valid check if only --template or --clone given if [ -f "$param/template" ] && [ -f "$param/clone" ]; then - # error and exit - >&2 echo "error: can not create and clone a container at once!" - >&2 echo "error: --template and --clone can not work together" - exit 2 + # error and exit + >&2 echo "error: can not create and clone a container at once!" + >&2 echo "error: --template and --clone can not work together" + exit 2 fi # no clone option if --template given if [ -f "$param/template" ]; then - if [ -f "$param/clonepath" ] - then - >&2 echo "error: container will created by template, no clone options required!" - exit 2 - fi + if [ -f "$param/clonepath" ] + then + >&2 echo "error: container will created by template, no clone options required!" + exit 2 + fi fi # no template options if --clone given if [ -f "$param/clone" ]; then - if [ -f "$param/template-opts" ] \ - || [ -f "$param/default-config" ] \ - || [ -f "$param/no-default-config" ] \ - || [ -f "$param/release" ] \ - || [ -f "$param/arch" ] - then - >&2 echo "error: container will created by clone, no template options required!" - exit 2 - fi + if [ -f "$param/template-opts" ] \ + || [ -f "$param/default-config" ] \ + || [ -f "$param/no-default-config" ] \ + || [ -f "$param/release" ] \ + || [ -f "$param/arch" ] + then + >&2 echo "error: container will created by clone, no template options required!" + exit 2 + fi fi # check backingstore values if [ -f "$param/backingstore" ]; then - backingstore="$(cat "$param/backingstore")" + backingstore="$(cat "$param/backingstore")" - if [ "$backingstore" != "dir" ] && [ "$backingstore" != "none" ]; then - if [ -f "$param/bdev-dir" ] - then - >&2 echo "error: --bdev-dir is only possible for backingstore 'dir' or 'none'" - exit 2 - fi - fi + if [ "$backingstore" != "dir" ] && [ "$backingstore" != "none" ]; then + if [ -f "$param/bdev-dir" ] + then + >&2 echo "error: --bdev-dir is only possible for backingstore 'dir' or 'none'" + exit 2 + fi + fi - if [ "$backingstore" != "lvm" ] && [ "$backingstore" != "loop" ]; then - if [ -f "$param/bdev-fstype" ] \ - || [ -f "$param/bdev-fssize" ] - then - >&2 echo "error: --bdev-fstype and --bdev-fssize only available for backingstore 'lvm' or 'loop'" - exit 2 - fi - fi + if [ "$backingstore" != "lvm" ] && [ "$backingstore" != "loop" ]; then + if [ -f "$param/bdev-fstype" ] \ + || [ -f "$param/bdev-fssize" ] + then + >&2 echo "error: --bdev-fstype and --bdev-fssize only available for backingstore 'lvm' or 'loop'" + exit 2 + fi + fi - if [ "$backingstore" != "lvm" ]; then - if [ -f "$param/bdev-lvname" ] \ - || [ -f "$param/bdev-vgname" ] \ - || [ -f "$param/bdev-thinpool" ] - then - >&2 echo "error: --bdev-{lv,vg}name and --bdev-thinpool only available for backingstore 'lvm'" - exit 2 - fi - fi + if [ "$backingstore" != "lvm" ]; then + if [ -f "$param/bdev-lvname" ] \ + || [ -f "$param/bdev-vgname" ] \ + || [ -f "$param/bdev-thinpool" ] + then + >&2 echo "error: --bdev-{lv,vg}name and --bdev-thinpool only available for backingstore 'lvm'" + exit 2 + fi + fi fi diff --git a/cdist/conf/type/__lxc_container/todo.txt b/cdist/conf/type/__lxc_container/todo.txt index e5f8f471..41822842 100644 --- a/cdist/conf/type/__lxc_container/todo.txt +++ b/cdist/conf/type/__lxc_container/todo.txt @@ -8,6 +8,10 @@ auto.. (lxc autostart): - group - start -If config already created, it's considered the container is already created - -> first create; then setup - detection if template changed?? +config: + - remove whole sections + - keep prettier config files? + + +if multi-valued object ids come to be a thing, following pattern is also used internal at lxc: + $lxcpath:$name From e8aede1e912f24ec7fde1d087dcd06f249d7701a Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Mon, 19 Oct 2020 18:00:05 +0200 Subject: [PATCH 14/17] __lxc_container: do not call rm recusivly for a file --- cdist/conf/type/__lxc_container/gencode-remote | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index f9e4dceb..42e1e43e 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -168,7 +168,7 @@ LXC # remove empty tempfile if it was created if [ -f "$__object/parameter/no-default-config" ]; then cat <> "$__messages_out" From 4e06ea78166c181cad37a6f9e3b8880719d6d386 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Tue, 20 Oct 2020 17:03:14 +0200 Subject: [PATCH 15/17] __lxc_container: no grep ERE used, switching to BRE When checking for lxc configuration that should be removed, it says to grep to use extended regular expressions (ERE). But there are no characters not covered by basic regular expressions (BRE). So switching to to BRE, as it may not match user input as regex. --- cdist/conf/type/__lxc_container/gencode-remote | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index 42e1e43e..6bef504e 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -207,10 +207,10 @@ DONE # check if smth. to be deleted # must be before adding, because it takes the content of the original file # because 'cat $file > $file' will not work (> opens before command reads it) - # will create extended regex pattern for grep with malformed spaces + # will create a basic regex pattern for grep to ignore malformed spaces if [ -s "$__object/files/config.del" ]; then cat < "\$tmpconfig" +grep -v -f - <<'ABSENT' "$container_config" > "\$tmpconfig" $(awk -v FS=' = ' -v OFS=' = ' -v blank='[[:blank:]]*' ' function ntostring(n) { ret=""; for(i=n; i<=NF; i++) ret=ret $i (i Date: Sun, 29 Nov 2020 15:01:46 +0100 Subject: [PATCH 16/17] __lxc_container: remove default --quiet parameter Because we want to see error messages, too. And lxc isn't that verbose. --- cdist/conf/type/__lxc_container/gencode-remote | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdist/conf/type/__lxc_container/gencode-remote b/cdist/conf/type/__lxc_container/gencode-remote index 6bef504e..6f698768 100755 --- a/cdist/conf/type/__lxc_container/gencode-remote +++ b/cdist/conf/type/__lxc_container/gencode-remote @@ -33,7 +33,7 @@ lxcpath="$(cat "$__object/parameter/lxcpath" 2>/dev/null || true)" # Summerize common parameter arguments, listed in manual as "COMMON OPTIONS" # will passed raw; must qouted manually -LXC_PARAM="-q" +LXC_PARAM="" # if lxcpath given if [ -n "$lxcpath" ]; then From 6da0f9e0c53aa926ae27e7e38fd0ac37925e0847 Mon Sep 17 00:00:00 2001 From: Matthias Stecher Date: Sun, 29 Nov 2020 18:14:34 +0100 Subject: [PATCH 17/17] __lxc_container: updated todo.txt about type splitting Because it will get a mess when adding every option to __lxc_container .. --- cdist/conf/type/__lxc_container/todo.txt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/cdist/conf/type/__lxc_container/todo.txt b/cdist/conf/type/__lxc_container/todo.txt index 41822842..05b4d95c 100644 --- a/cdist/conf/type/__lxc_container/todo.txt +++ b/cdist/conf/type/__lxc_container/todo.txt @@ -1,5 +1,5 @@ # List of all featues that should be implemented -template: +template (common parameters): - type: a.E. debian, ubuntu -> what on change? - possible root_password? - possible packages? @@ -7,10 +7,27 @@ template: auto.. (lxc autostart): - group - start +handling networking? + - address + - bridge? (at default file?) config: - remove whole sections - keep prettier config files? + - own type for config? + does it conflict with the current one? +own __lxc_default type? + `lxc-config lxc.default_config` + without lxcpath cause singleton? + +Splitting up type? (all times the library question :-) ) + __lxc_container (umbrella; creating,cloning,destroying??) + __lxc_container_config (single key-values) + __lxc_container_state (only running,freezed,stopped??) + __lxc_container_network + __lxc_container_mount + ... +All common library files (except explorer things sadly) could be kept under __lxc_container. if multi-valued object ids come to be a thing, following pattern is also used internal at lxc: