1f65fd64ce
With multiline support for local.conf, the first line is created with iniset, which will set *all* previous lines to the same thing, and then subsequent lines will be added. Modify the multiline support to first clear existing lines from the section. This causes fatal errors with neutron.conf, which defines drivers with a bunch of service_provider= options, and the current code ends up with the first driver defined in local.conf being present twice. Change-Id: If132a94e53545d9134859aa508da7b9819ede2f8
184 lines
5.9 KiB
Bash
184 lines
5.9 KiB
Bash
#!/bin/bash
|
|
#
|
|
# lib/config - Configuration file manipulation functions
|
|
|
|
# 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
|
|
C_XTRACE=$(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 = "" }
|
|
/^\[\[.+\|.*\]\]/ {
|
|
if (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
|
|
|
|
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
|
|
if [[ -d $(dirname $(eval "echo $configfile")) ]]; then
|
|
merge_config_file $localfile $group $configfile
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
|
|
# Restore xtrace
|
|
$C_XTRACE
|
|
|
|
# Local variables:
|
|
# mode: shell-script
|
|
# End:
|