The code accounts for the config file not existing but it does not account for the parent directory missing. This is currently breaking any Ironic jobs that disable Nova. Change-Id: Ia5fcfe6c63f5cc40b11f7e1f3be244d7897f26f6
		
			
				
	
	
		
			224 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Bash
		
	
	
	
	
	
#!/bin/bash
 | 
						|
#
 | 
						|
# **lib/meta-config** - Configuration file manipulation functions
 | 
						|
#
 | 
						|
# Support for DevStack's local.conf meta-config sections
 | 
						|
#
 | 
						|
# These functions have no external dependencies and the following side-effects:
 | 
						|
#
 | 
						|
# CONFIG_AWK_CMD is defined, default is ``awk``
 | 
						|
 | 
						|
# Meta-config files contain multiple INI-style configuration files
 | 
						|
# using a specific new section header to delimit them:
 | 
						|
#
 | 
						|
#   [[group-name|file-name]]
 | 
						|
#
 | 
						|
# group-name refers to the group of configuration file changes to be processed
 | 
						|
# at a particular time.  These are called phases in ``stack.sh`` but
 | 
						|
# group here as these functions are not DevStack-specific.
 | 
						|
#
 | 
						|
# file-name is the destination of the config file
 | 
						|
 | 
						|
# Save trace setting
 | 
						|
_XTRACE_INC_META=$(set +o | grep xtrace)
 | 
						|
set +o xtrace
 | 
						|
 | 
						|
 | 
						|
# Allow the awk command to be overridden on legacy platforms
 | 
						|
CONFIG_AWK_CMD=${CONFIG_AWK_CMD:-awk}
 | 
						|
 | 
						|
# Get the section for the specific group and config file
 | 
						|
# get_meta_section infile group configfile
 | 
						|
function get_meta_section {
 | 
						|
    local file=$1
 | 
						|
    local matchgroup=$2
 | 
						|
    local configfile=$3
 | 
						|
 | 
						|
    [[ -r $file ]] || return 0
 | 
						|
    [[ -z $configfile ]] && return 0
 | 
						|
 | 
						|
    $CONFIG_AWK_CMD -v matchgroup=$matchgroup -v configfile=$configfile '
 | 
						|
        BEGIN { group = "" }
 | 
						|
        /^\[\[.+\|.*\]\]/ {
 | 
						|
            gsub("[][]", "", $1);
 | 
						|
            split($1, a, "|");
 | 
						|
            if (a[1] == matchgroup && a[2] == configfile) {
 | 
						|
                group=a[1]
 | 
						|
            } else {
 | 
						|
                group=""
 | 
						|
            }
 | 
						|
            next
 | 
						|
        }
 | 
						|
        {
 | 
						|
            if (group != "")
 | 
						|
                print $0
 | 
						|
        }
 | 
						|
    ' $file
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Get a list of config files for a specific group
 | 
						|
# get_meta_section_files infile group
 | 
						|
function get_meta_section_files {
 | 
						|
    local file=$1
 | 
						|
    local matchgroup=$2
 | 
						|
 | 
						|
    [[ -r $file ]] || return 0
 | 
						|
 | 
						|
    $CONFIG_AWK_CMD -v matchgroup=$matchgroup '
 | 
						|
        /^\[\[.+\|.*\]\]/ {
 | 
						|
            gsub("[][]", "", $1);
 | 
						|
            split($1, a, "|");
 | 
						|
            if (a[1] == matchgroup)
 | 
						|
                print a[2]
 | 
						|
        }
 | 
						|
    ' $file
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Merge the contents of a meta-config file into its destination config file
 | 
						|
# If configfile does not exist it will be created.
 | 
						|
# merge_config_file infile group configfile
 | 
						|
function merge_config_file {
 | 
						|
    local file=$1
 | 
						|
    local matchgroup=$2
 | 
						|
    local configfile=$3
 | 
						|
 | 
						|
    # note, configfile might be a variable (note the iniset, etc
 | 
						|
    # created in the mega-awk below is "eval"ed too, so we just leave
 | 
						|
    # it alone.
 | 
						|
    local real_configfile
 | 
						|
    real_configfile=$(eval echo $configfile)
 | 
						|
    if [ ! -f $real_configfile ]; then
 | 
						|
        mkdir -p $(dirname $real_configfile) || die $LINENO "could not create the directory of $real_configfile ($configfile)"
 | 
						|
        touch $real_configfile || die $LINENO "could not create config file $real_configfile ($configfile)"
 | 
						|
    fi
 | 
						|
 | 
						|
    get_meta_section $file $matchgroup $configfile | \
 | 
						|
    $CONFIG_AWK_CMD -v configfile=$configfile '
 | 
						|
        BEGIN {
 | 
						|
            section = ""
 | 
						|
            last_section = ""
 | 
						|
            section_count = 0
 | 
						|
        }
 | 
						|
        /^\[.+\]/ {
 | 
						|
            gsub("[][]", "", $1);
 | 
						|
            section=$1
 | 
						|
            next
 | 
						|
        }
 | 
						|
        /^ *\#/ {
 | 
						|
            next
 | 
						|
        }
 | 
						|
        /^[^ \t]+/ {
 | 
						|
            # get offset of first '=' in $0
 | 
						|
            eq_idx = index($0, "=")
 | 
						|
            # extract attr & value from $0
 | 
						|
            attr = substr($0, 1, eq_idx - 1)
 | 
						|
            value = substr($0, eq_idx + 1)
 | 
						|
            # only need to strip trailing whitespace from attr
 | 
						|
            sub(/[ \t]*$/, "", attr)
 | 
						|
            # need to strip leading & trailing whitespace from value
 | 
						|
            sub(/^[ \t]*/, "", value)
 | 
						|
            sub(/[ \t]*$/, "", value)
 | 
						|
 | 
						|
            # cfg_attr_count: number of config lines per [section, attr]
 | 
						|
            # cfg_attr: three dimensional array to keep all the config lines per [section, attr]
 | 
						|
            # cfg_section: keep the section names in the same order as they appear in local.conf
 | 
						|
            # cfg_sec_attr_name: keep the attr names in the same order as they appear in local.conf
 | 
						|
            if (! (section, attr) in cfg_attr_count) {
 | 
						|
                if (section != last_section) {
 | 
						|
                    cfg_section[section_count++] = section
 | 
						|
                    last_section = section
 | 
						|
                }
 | 
						|
                attr_count = cfg_sec_attr_count[section_count - 1]++
 | 
						|
                cfg_sec_attr_name[section_count - 1, attr_count] = attr
 | 
						|
 | 
						|
                cfg_attr[section, attr, 0] = value
 | 
						|
                cfg_attr_count[section, attr] = 1
 | 
						|
            } else {
 | 
						|
                lno = cfg_attr_count[section, attr]++
 | 
						|
                cfg_attr[section, attr, lno] = value
 | 
						|
            }
 | 
						|
        }
 | 
						|
        END {
 | 
						|
            # Process each section in order
 | 
						|
            for (sno = 0; sno < section_count; sno++) {
 | 
						|
                section = cfg_section[sno]
 | 
						|
                # The ini routines simply append a config item immediately
 | 
						|
                # after the section header. To keep the same order as defined
 | 
						|
                # in local.conf, invoke the ini routines in the reverse order
 | 
						|
                for (attr_no = cfg_sec_attr_count[sno] - 1; attr_no >=0; attr_no--) {
 | 
						|
                    attr = cfg_sec_attr_name[sno, attr_no]
 | 
						|
                    if (cfg_attr_count[section, attr] == 1)
 | 
						|
                        print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, 0] "\""
 | 
						|
                    else {
 | 
						|
                        # For multiline, invoke the ini routines in the reverse order
 | 
						|
                        count = cfg_attr_count[section, attr]
 | 
						|
                        print "inidelete " configfile " " section " " attr
 | 
						|
                        print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, count - 1] "\""
 | 
						|
                        for (l = count -2; l >= 0; l--)
 | 
						|
                            print "iniadd_literal " configfile " " section " " attr " \"" cfg_attr[section, attr, l] "\""
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    ' | while read a; do eval "$a"; done
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
# Merge all of the files specified by group
 | 
						|
# merge_config_group infile group [group ...]
 | 
						|
function merge_config_group {
 | 
						|
    local localfile=$1; shift
 | 
						|
    local matchgroups=$@
 | 
						|
 | 
						|
    [[ -r $localfile ]] || return 0
 | 
						|
 | 
						|
    local configfile group
 | 
						|
    for group in $matchgroups; do
 | 
						|
        for configfile in $(get_meta_section_files $localfile $group); do
 | 
						|
            local realconfigfile
 | 
						|
            local dir
 | 
						|
 | 
						|
            realconfigfile=$(eval "echo $configfile")
 | 
						|
            if [[ -z $realconfigfile ]]; then
 | 
						|
                warn $LINENO "unknown config file specification: $configfile is undefined"
 | 
						|
                break
 | 
						|
            fi
 | 
						|
            dir=$(dirname $realconfigfile)
 | 
						|
            if [[ -d $dir ]]; then
 | 
						|
                merge_config_file $localfile $group $configfile
 | 
						|
            else
 | 
						|
                die $LINENO "bogus config file specification $configfile ($configfile=$realconfigfile, $dir is not a directory)"
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    done
 | 
						|
}
 | 
						|
 | 
						|
function extract_localrc_section {
 | 
						|
    local configfile=$1    # top_dir/local.conf
 | 
						|
    local localrcfile=$2   # top_dir/localrc
 | 
						|
    local localautofile=$3 # top_dir/.localrc.auto
 | 
						|
 | 
						|
    if [[ -r $configfile ]]; then
 | 
						|
        LRC=$(get_meta_section_files $configfile local)
 | 
						|
        for lfile in $LRC; do
 | 
						|
            if [[ "$lfile" == "localrc" ]]; then
 | 
						|
                if [[ -r $localrcfile ]]; then
 | 
						|
                    echo "localrc and local.conf:[[local]] both exist, using localrc"
 | 
						|
                else
 | 
						|
                    echo "# Generated file, do not edit" >$localautofile
 | 
						|
                    get_meta_section $configfile local $lfile >>$localautofile
 | 
						|
                fi
 | 
						|
            fi
 | 
						|
        done
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
# Restore xtrace
 | 
						|
$_XTRACE_INC_META
 | 
						|
 | 
						|
# Local variables:
 | 
						|
# mode: shell-script
 | 
						|
# End:
 |