#!/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+val # # If opt is matched and val is empty then output is printed, allowing # this function to be reused to check if opt is valid. # # Note that for boolean options, the expected value and the new value # form part of the data. get_ctdb_conf_option () { _opt="$1" _val="$2" awk -v opt="${_opt}" -v val="${_val}" \ '$3 == opt { if (!$4 || !val || val == $4) { if ($5) { print $1, $2, $5 } else { print $1, $2, val } } }' </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 case "$_opt" in CTDB_SET_*) _opt="${_opt#CTDB_SET_}" _out=$(get_ctdb_conf_tunable_option "$_opt" "$_val") ;; *) _out=$(get_ctdb_conf_option "$_opt" "$_val") esac if [ -z "$_out" ] ; then continue fi # $_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') _newval="$3" 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} = ${_newval} " "$_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_ctdb_conf_tunable_option "$_var" ; then continue fi 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"