From 8cf4758c521ab4ff94161225a64a187d86f72f7f Mon Sep 17 00:00:00 2001 From: Martin Schwenke Date: Thu, 12 Jul 2018 20:10:35 +1000 Subject: [PATCH] ctdb-doc: Provide an example script for migrating old configuration Include an example ctdbd.conf-style file for testing. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13550 Signed-off-by: Martin Schwenke Reviewed-by: Amitay Isaacs Autobuild-User(master): Martin Schwenke Autobuild-Date(master): Mon Jul 30 14:30:06 CEST 2018 on sn-devel-144 (cherry picked from commit 4fcbaae57b129deaacfab0a226cefca99aa78256) --- ctdb/doc/examples/config_migrate.sh | 688 ++++++++++++++++++++ ctdb/doc/examples/config_migrate.test_input | 45 ++ 2 files changed, 733 insertions(+) create mode 100755 ctdb/doc/examples/config_migrate.sh create mode 100644 ctdb/doc/examples/config_migrate.test_input diff --git a/ctdb/doc/examples/config_migrate.sh b/ctdb/doc/examples/config_migrate.sh new file mode 100755 index 00000000000..8eefd031a79 --- /dev/null +++ b/ctdb/doc/examples/config_migrate.sh @@ -0,0 +1,688 @@ +#!/bin/sh + +# config_migrate.sh - migrate old ctdbd.conf file to new configuration files +# +# Input files are old-style CTDB configuration files, including: +# +# /etc/ctdb/ctdbd.conf +# /usr/local/etc/ctdb/ctdbd.conf +# /etc/sysconfig/ctdb +# /etc/defaults/ctdb +# +# These files are sourced by this script. They used to be sourced by +# ctdbd_wrapper, so this should not be too surprising. +# +# By default, the output directory is the given configuration +# directory. An alternate output directory can be specified if this +# isn't desired. +# +# The output directory will contain the following if non-empty: +# +# * ctdb.conf (may be empty) +# * script.options +# * ctdb.tunables +# * ctdb.sysconfig - consider installing as /etc/sysconfig/ctdb, +# /etc/default/ctdb, or similar +# * commands.sh - consider running commands in this files +# * README.warn - warnings about removed/invalid configuration options + +usage () +{ + cat <] [-o ] ... +EOF + exit 1 +} + +config_dir="" +out_dir="" +force=false + +while getopts "d:fho:?" opt ; do + case "$opt" in + d) config_dir="$OPTARG" ;; + f) force=true ;; + o) out_dir="$OPTARG" ;; + \?|h) usage ;; + esac +done +shift $((OPTIND - 1)) + +if [ $# -lt 1 ] ; then + usage +fi + +if [ -z "$config_dir" ] ; then + echo "Assuming \"/etc/ctdb\" as ctdb configuration directory" + echo "If that's not correct, please specify config dir with -d" + echo + config_dir="/etc/ctdb" +else + echo "Using \"$config_dir\" as ctdb configuration directory" + echo +fi + +if [ -z "$out_dir" ] ; then + echo "No output directory specified, using \"$config_dir\"" + echo + out_dir="$config_dir" +fi + +############################################################ + +# +# Output file handling +# + +out_file_check_and_create () +{ + _out_file="$1" + + if [ -f "$_out_file" ] ; then + if ! $force ; then + echo "Not overwriting existing file: ${_out_file}" >&2 + return 1 + fi + mv -v "$_out_file" "${_out_file}.convertsave" + fi + + touch "$_out_file" + + return 0 +} + +out_file_remove_if_empty () +{ + _out_file="$1" + + if [ ! -s "$_out_file" ] ; then + rm "$_out_file" + fi +} + +############################################################ + +# +# Option/tunable/service conversion and validity checking +# +# This is basically the data that drives most of the rest of the +# script +# + +# Convert a ctdbd.conf opt+val into a ctdb.conf section+opt +# +# If opt is matched and val is empty then output is printed, allowing +# this function to be reused to check if opt is valid. +get_ctdb_conf_option () +{ + _opt="$1" + _val="$2" + + awk -v opt="${_opt}" -v val="${_val}" \ + '$3 == opt { if (!$4 || !val || val ==$4) { print $1, $2 } }' </dev/null +} + +############################################################ + +# +# Utilities +# + +# List all options starting with "CTDB_" set in given configuration files +list_options () +{ + set | + sed -n 's|^\(CTDB_[^=]*\)=\(.*\)|\1 \2|p' | + while read -r _var _val ; do + # Strip quotes from value + _val=$(echo "$_val" | sed -e "s|^'||" -e "s|'\$||") + + echo "${_var} ${_val}" + done +} + +# List all tunables set in the given configuration files +list_tunables () +{ + list_options | + while read -r _opt _val ; do + case "$_opt" in + CTDB_SET_*) echo "${_opt#CTDB_SET_} ${_val}" ;; + esac + done +} + +# List all managed services according to the given configuration files +list_managed_services () +{ + # + # CTDB_MANAGES_="yes" + # + list_options | + while read -r _opt _val ; do + case "$_opt" in + CTDB_MANAGES_*) : ;; + *) continue ;; + esac + + if [ "$_val" != "yes" ] ; then + continue + fi + + # Trim and downcase + echo "${_opt#CTDB_MANAGES_}" | tr '[:upper:]' '[:lower:]' + done + + # + # CTDB_MANAGED_SERVICES + # + for _service in $CTDB_MANAGED_SERVICES ; do + echo "$_service" + done +} + +############################################################ + +# +# Print warnings for removed and unknown options +# + + +# Print a warning as a bullet list item +# +# Arguments after the 1st are printed as a subsequent paragraph. +warn () +{ + bullet="$1" ; shift + + printf '* %s\n\n' "$bullet" + + if [ $# -gt 0 ] ; then + printf ' %s\n\n' "$*" + fi +} + +warn_about_CTDB_DBDIR_tmpfs_yes () +{ + if $ctdb_dbdir_tmpfs_magic ; then + warn "Option \"CTDB_DBDIR=tmpfs\" is no longer available:" \ + "Permanently mount a tmpfs filesystem on the volatile" \ + "database directory" + fi +} + +warn_about_unknown_managed_services () +{ + list_managed_services | + while read -r _s ; do + if check_valid_service "$_s" ; then + continue + fi + warn "Unknown service \"${_s}\" marked as managed" \ + "If this is a 3rd party service, please enable it manually" + done +} + +warn_about_removed_and_unknown_options () +{ + list_options | + while read -r _opt _val ; do + if check_ctdb_conf_option "$_opt" ; then + continue + fi + + if check_valid_script_option "$_opt" ; then + continue + fi + + case "$_opt" in + CTDB_MANAGED_SERVICES|\ + CTDB_MANAGES_*|\ + CTDB_SET_*|\ + CTDB_NODES|\ + CTDB_PUBLIC_ADDRESSES|\ + CTDB_MAX_OPEN_FILES|\ + CTDB_SUPPRESS_COREFILE) + # Handled elsewhere + continue + ;; + esac + + if check_removed_option "$_opt" ; then + warn "Option \"${_opt}\" is no longer available" \ + "Please see the WHATSNEW.txt" + continue + fi + + warn "Option \"${_opt}\" is unknown" + done +} + +warn_about_removed_and_unknown_tunables () +{ + list_tunables | + while read -r _var _val ; do + if check_valid_tunable "$_var" ; then + continue + fi + + if check_removed_tunable "$_var" ; then + warn "Tunable \"${_var}\" is no longer available" \ + "Please see the WHATSNEW.txt" + continue + fi + + warn "Tunable \"${_var}\" is unknown" + done +} + +############################################################ + +# +# Top-level file builders +# + +build_ctdb_conf () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + list_options | + while read -r _opt _val ; do + _out=$(get_ctdb_conf_option "$_opt" "$_val") + if [ -z "$_out" ] ; then + continue + fi + + # ctdb.conf needs true/false, not yes/no + case "$_val" in + yes) _val="true" ;; + no) _val="false" ;; + esac + + # $_out is section and key, replace dashes with spaces + # Intentional word splitting + # shellcheck disable=SC2086 + set -- $_out + _section=$(echo "$1" | sed -e 's|-| |g') + _key=$(echo "$2" | sed -e 's|-| |g') + + if ! grep -Fqx "[${_section}]" "$_out_file" ; then + # Add blank line if file is not empty + if [ -s "$_out_file" ] ; then + echo >>"$_out_file" + fi + # Create section at end of file + echo "[${_section}]" >>"$_out_file" + fi + + # Must escape leading TAB or sed eats it + sed -i -e "/\\[${_section}\\]/a\ +\\ ${_key} = ${_val} +" "$_out_file" + + done + +} + +build_script_options () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + list_options | + while read -r _var _val ; do + if check_valid_script_option "$_var" ; then + echo "${_var}=${_val}" + fi + done >>"$_out_file" + + out_file_remove_if_empty "$_out_file" +} + +build_ctdb_tunables () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + list_tunables | + while read -r _var _val ; do + if ! check_valid_tunable "$_var" ; then + continue + fi + echo "${_var}=${_val}" + done >>"$_out_file" + + out_file_remove_if_empty "$_out_file" +} + +build_ctdb_sysconfig () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + if [ -n "$CTDB_SUPPRESS_COREFILE" ] ; then + if [ "$CTDB_SUPPRESS_COREFILE" = "yes" ] ; then + echo "ulimit -c 0" + else + echo "ulimit -c unlimited" + fi >>"$_out_file" + fi + + if [ -n "$CTDB_MAX_OPEN_FILES" ] ; then + echo "ulimit -n ${CTDB_MAX_OPEN_FILES}" >>"$_out_file" + fi + + out_file_remove_if_empty "$_out_file" +} + +build_commands_sh () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + # + # Enable script for managed services + # + list_managed_services | + while read -r _service ; do + print_event_script_enable_command "$_service" + done >>"$_out_file" + + # + # CTDB_NODES no longer available + # + if [ -n "$CTDB_NODES" ] ; then + if [ "$CTDB_NODES" = "${config_dir}/nodes" ] ; then + cat <>"$_out_file" + fi + + # + # CTDB_PUBLIC_ADDRESSES no longer available + # + if [ -n "$CTDB_PUBLIC_ADDRESSES" ] ; then + _pa="public_addresses" + if [ "$CTDB_PUBLIC_ADDRESSES" = "${config_dir}/${_pa}" ] ; then + cat <>"$_out_file" + fi + + out_file_remove_if_empty "$_out_file" +} + +build_README_warn () +{ + _out_file="$1" + + out_file_check_and_create "$_out_file" || return + + { + warn_about_CTDB_DBDIR_tmpfs_yes + warn_about_unknown_managed_services + warn_about_removed_and_unknown_options + warn_about_removed_and_unknown_tunables + } >>"$_out_file" + + out_file_remove_if_empty "$_out_file" +} + +############################################################ + +mkdir -p "$out_dir" || exit 1 + +# Source the input files +for i ; do + # Unknown non-constant source + # shellcheck disable=SC1090 + . "$i" +done + +# Special case +ctdb_dbdir_tmpfs_magic=false +if [ "$CTDB_DBDIR" = "tmpfs" ] ; then + ctdb_dbdir_tmpfs_magic=true + unset CTDB_DBDIR +fi + +build_ctdb_conf "${out_dir}/ctdb.conf" +build_script_options "${out_dir}/script.options" +build_ctdb_tunables "${out_dir}/ctdb.tunables" +build_ctdb_sysconfig "${out_dir}/ctdb.sysconfig" +build_commands_sh "${out_dir}/commands.sh" +build_README_warn "${out_dir}/README.warn" diff --git a/ctdb/doc/examples/config_migrate.test_input b/ctdb/doc/examples/config_migrate.test_input new file mode 100644 index 00000000000..593ca4c697c --- /dev/null +++ b/ctdb/doc/examples/config_migrate.test_input @@ -0,0 +1,45 @@ +CTDB_RECOVERY_LOCK="/some/place/on/shared/storage" + +CTDB_NODES="/etc/ctdb/nodes" + +CTDB_PUBLIC_ADDRESSES="/clusterfs/.ctdb/public_addresses" + +CTDB_SOCKET="/var/run/ctdb.sock" + +CTDB_MANAGES_SAMBA="yes" +CTDB_MANAGES_WINBIND="yes" +CTDB_MANAGES_NFS="yes" +CTDB_MANAGED_SERVICES="vsftpd" +CTDB_MANAGES_FOOBAR="yes" + +CTDB_MAX_OPEN_FILES=10000 + +CTDB_LOGGING="syslog" +CTDB_DEBUGLEVEL="ERROR" + +CTDB_SAMBA_CHECK_PORTS="445" +CTDB_SAMBA_SKIP_SHARE_CHECK="yes" + +CTDB_START_AS_STOPPED="yes" +CTDB_CAPABILITY_RECMASTER="no" +CTDB_CAPABILITY_LMASTER="yes" + +CTDB_FOO="bar" + +CTDB_NATGW_PUBLIC_IP=10.1.1.121/24 +CTDB_NATGW_PUBLIC_IFACE=eth1 +CTDB_NATGW_DEFAULT_GATEWAY=10.1.1.254 +CTDB_NATGW_PRIVATE_NETWORK=192.168.1.0/24 +CTDB_NATGW_NODES=/etc/ctdb/natgw_nodes + +CTDB_SET_TDBMutexEnabled=1 +CTDB_SET_IPALLOCALGORITHM=0 +CTDB_SET_noiphostonalldisabled=0 +CTDB_SET_foobar=0 + +CTDB_SUPPRESS_COREFILE="yes" +CTDB_MAX_OPEN_FILES="1048576" + +CTDB_NOTIFY_SCRIPT=/etc/ctdb/notify-custom.sh + +CTDB_DBDIR=tmpfs -- 2.17.1