blob: a4d032864b96ee76e97648f5ffb5940fca046fde [file] [log] [blame]
Dean Troyer893e6632013-09-13 15:05:51 -05001# lib/config - Configuration file manipulation functions
2
3# These functions have no external dependencies and the following side-effects:
4#
5# CONFIG_AWK_CMD is defined, default is ``awk``
6
7# Meta-config files contain multiple INI-style configuration files
8# using a specific new section header to delimit them:
9#
10# [[group-name|file-name]]
11#
12# group-name refers to the group of configuration file changes to be processed
Sean Dague537d4022013-10-22 07:43:22 -040013# at a particular time. These are called phases in ``stack.sh`` but
Dean Troyer893e6632013-09-13 15:05:51 -050014# group here as these functions are not DevStack-specific.
15#
16# file-name is the destination of the config file
17
18# Save trace setting
19C_XTRACE=$(set +o | grep xtrace)
20set +o xtrace
21
22
23# Allow the awk command to be overridden on legacy platforms
24CONFIG_AWK_CMD=${CONFIG_AWK_CMD:-awk}
25
26# Get the section for the specific group and config file
27# get_meta_section infile group configfile
Ian Wienandaee18c72014-02-21 15:35:08 +110028function get_meta_section {
Dean Troyer893e6632013-09-13 15:05:51 -050029 local file=$1
30 local matchgroup=$2
31 local configfile=$3
32
33 [[ -r $file ]] || return 0
34 [[ -z $configfile ]] && return 0
35
36 $CONFIG_AWK_CMD -v matchgroup=$matchgroup -v configfile=$configfile '
37 BEGIN { group = "" }
Isaku Yamahatabff00142013-12-20 11:55:08 +090038 /^\[\[.+\|.*\]\]/ {
Dean Troyer893e6632013-09-13 15:05:51 -050039 if (group == "") {
40 gsub("[][]", "", $1);
41 split($1, a, "|");
42 if (a[1] == matchgroup && a[2] == configfile) {
43 group=a[1]
44 }
45 } else {
46 group=""
47 }
48 next
49 }
50 {
51 if (group != "")
52 print $0
53 }
54 ' $file
55}
56
57
58# Get a list of config files for a specific group
59# get_meta_section_files infile group
Ian Wienandaee18c72014-02-21 15:35:08 +110060function get_meta_section_files {
Dean Troyer893e6632013-09-13 15:05:51 -050061 local file=$1
62 local matchgroup=$2
63
64 [[ -r $file ]] || return 0
65
66 $CONFIG_AWK_CMD -v matchgroup=$matchgroup '
Sean Dague537d4022013-10-22 07:43:22 -040067 /^\[\[.+\|.*\]\]/ {
68 gsub("[][]", "", $1);
69 split($1, a, "|");
70 if (a[1] == matchgroup)
71 print a[2]
72 }
Dean Troyer893e6632013-09-13 15:05:51 -050073 ' $file
74}
75
76
77# Merge the contents of a meta-config file into its destination config file
78# If configfile does not exist it will be created.
79# merge_config_file infile group configfile
Ian Wienandaee18c72014-02-21 15:35:08 +110080function merge_config_file {
Dean Troyer893e6632013-09-13 15:05:51 -050081 local file=$1
82 local matchgroup=$2
83 local configfile=$3
84
Dean Troyer893e6632013-09-13 15:05:51 -050085 get_meta_section $file $matchgroup $configfile | \
86 $CONFIG_AWK_CMD -v configfile=$configfile '
Robert Li751ad1a2014-10-15 21:40:53 -040087 BEGIN {
88 section = ""
89 last_section = ""
90 section_count = 0
91 }
Dean Troyer893e6632013-09-13 15:05:51 -050092 /^\[.+\]/ {
93 gsub("[][]", "", $1);
94 section=$1
95 next
96 }
97 /^ *\#/ {
98 next
99 }
Dean Troyer2ac8b3f2013-12-04 17:20:28 -0600100 /^[^ \t]+/ {
Fergal Mc Carthycc87c282014-10-09 16:16:42 -0400101 # get offset of first '=' in $0
102 eq_idx = index($0, "=")
103 # extract attr & value from $0
104 attr = substr($0, 1, eq_idx - 1)
105 value = substr($0, eq_idx + 1)
106 # only need to strip trailing whitespace from attr
107 sub(/[ \t]*$/, "", attr)
108 # need to strip leading & trailing whitespace from value
109 sub(/^[ \t]*/, "", value)
110 sub(/[ \t]*$/, "", value)
Robert Li751ad1a2014-10-15 21:40:53 -0400111
112 # cfg_attr_count: number of config lines per [section, attr]
113 # cfg_attr: three dimensional array to keep all the config lines per [section, attr]
114 # cfg_section: keep the section names in the same order as they appear in local.conf
115 # cfg_sec_attr_name: keep the attr names in the same order as they appear in local.conf
116 if (! (section, attr) in cfg_attr_count) {
117 if (section != last_section) {
118 cfg_section[section_count++] = section
119 last_section = section
120 }
121 attr_count = cfg_sec_attr_count[section_count - 1]++
122 cfg_sec_attr_name[section_count - 1, attr_count] = attr
123
124 cfg_attr[section, attr, 0] = value
125 cfg_attr_count[section, attr] = 1
126 } else {
127 lno = cfg_attr_count[section, attr]++
128 cfg_attr[section, attr, lno] = value
129 }
130 }
131 END {
132 # Process each section in order
133 for (sno = 0; sno < section_count; sno++) {
134 section = cfg_section[sno]
135 # The ini routines simply append a config item immediately
136 # after the section header. To keep the same order as defined
137 # in local.conf, invoke the ini routines in the reverse order
138 for (attr_no = cfg_sec_attr_count[sno] - 1; attr_no >=0; attr_no--) {
139 attr = cfg_sec_attr_name[sno, attr_no]
140 if (cfg_attr_count[section, attr] == 1)
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100141 print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, 0] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400142 else {
143 # For multiline, invoke the ini routines in the reverse order
144 count = cfg_attr_count[section, attr]
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100145 print "iniset " configfile " " section " " attr " \"" cfg_attr[section, attr, count - 1] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400146 for (l = count -2; l >= 0; l--)
Ian Wienandf3bf8b62014-10-29 21:53:56 +1100147 print "iniadd_literal " configfile " " section " " attr " \"" cfg_attr[section, attr, l] "\""
Robert Li751ad1a2014-10-15 21:40:53 -0400148 }
149 }
150 }
Dean Troyer893e6632013-09-13 15:05:51 -0500151 }
152 ' | while read a; do eval "$a"; done
Dean Troyer893e6632013-09-13 15:05:51 -0500153}
154
155
156# Merge all of the files specified by group
157# merge_config_group infile group [group ...]
Ian Wienandaee18c72014-02-21 15:35:08 +1100158function merge_config_group {
Dean Troyer893e6632013-09-13 15:05:51 -0500159 local localfile=$1; shift
160 local matchgroups=$@
161
162 [[ -r $localfile ]] || return 0
163
Dean Troyerb1e3d0f2014-07-25 14:57:54 -0500164 local configfile group
Dean Troyer893e6632013-09-13 15:05:51 -0500165 for group in $matchgroups; do
166 for configfile in $(get_meta_section_files $localfile $group); do
Ryota MIBU410f5c02014-04-04 02:00:31 +0900167 if [[ -d $(dirname $(eval "echo $configfile")) ]]; then
Dean Troyer893e6632013-09-13 15:05:51 -0500168 merge_config_file $localfile $group $configfile
169 fi
170 done
171 done
172}
173
174
175# Restore xtrace
176$C_XTRACE
177
178# Local variables:
179# mode: shell-script
180# End: