|
1 | 1 | # @summary Create GlusterFS volumes, and maybe extend them |
2 | 2 | # |
| 3 | +# @param ensure |
| 4 | +# whether volume should be created ('present') or removed ('absent') |
3 | 5 | # @param stripe |
4 | 6 | # the stripe count to use for a striped volume |
5 | 7 | # @param replica |
|
43 | 45 | define gluster::volume ( |
44 | 46 | Array[String, 1] $bricks, |
45 | 47 |
|
| 48 | + Enum['present', 'absent'] $ensure = 'present', |
46 | 49 | Boolean $force = false, |
47 | 50 | Enum['tcp', 'rdma', 'tcp,rdma'] $transport = 'tcp', |
48 | 51 | Boolean $rebalance = true, |
|
110 | 113 | if $already_exists == false { |
111 | 114 | # this volume has not yet been created |
112 | 115 |
|
113 | | - exec { "gluster create volume ${title}": |
114 | | - command => "${::gluster_binary} volume create ${title} ${args}", |
115 | | - } |
| 116 | + # nothing to do if volume does not exist and it should be absent |
| 117 | + if $ensure == 'present' { |
| 118 | + exec { "gluster create volume ${title}": |
| 119 | + command => "${::gluster_binary} volume create ${title} ${args}", |
| 120 | + } |
116 | 121 |
|
117 | | - # if we have volume options, activate them now |
118 | | - # |
119 | | - # Note: $options is an array, but create_resources requires |
120 | | - # a hash of hashes. We do some contortions to get the |
121 | | - # array into the hash of hashes that looks like: |
122 | | - # |
123 | | - # option.name: |
124 | | - # value: value |
125 | | - # |
126 | | - # Note 2: we're using the $_options variable, which contains the |
127 | | - # sorted list of options. |
128 | | - if $_options { |
129 | | - # first we need to prefix each array element with the volume name |
130 | | - # so that we match the gluster::volume::option title format of |
131 | | - # volume:option |
132 | | - $vol_opts = prefix( $_options, "${title}:" ) |
133 | | - # now we make some YAML, and then parse that to get a Puppet hash |
134 | | - $yaml = join( regsubst( $vol_opts, ': ', ":\n value: ", 'G'), "\n") |
135 | | - $hoh = parseyaml($yaml) |
| 122 | + # if we have volume options, activate them now |
| 123 | + # |
| 124 | + # Note: $options is an array, but create_resources requires |
| 125 | + # a hash of hashes. We do some contortions to get the |
| 126 | + # array into the hash of hashes that looks like: |
| 127 | + # |
| 128 | + # option.name: |
| 129 | + # value: value |
| 130 | + # |
| 131 | + # Note 2: we're using the $_options variable, which contains the |
| 132 | + # sorted list of options. |
| 133 | + if $_options { |
| 134 | + # first we need to prefix each array element with the volume name |
| 135 | + # so that we match the gluster::volume::option title format of |
| 136 | + # volume:option |
| 137 | + $vol_opts = prefix( $_options, "${title}:" ) |
| 138 | + # now we make some YAML, and then parse that to get a Puppet hash |
| 139 | + $yaml = join( regsubst( $vol_opts, ': ', ":\n value: ", 'G'), "\n") |
| 140 | + $hoh = parseyaml($yaml) |
136 | 141 |
|
137 | | - # safety check |
138 | | - assert_type(Hash, $hoh) |
139 | | - # we need to ensure that these are applied AFTER the volume is created |
140 | | - # but BEFORE the volume is started |
141 | | - $new_volume_defaults = { |
142 | | - require => Exec["gluster create volume ${title}"], |
143 | | - before => Exec["gluster start volume ${title}"], |
144 | | - } |
| 142 | + # safety check |
| 143 | + assert_type(Hash, $hoh) |
| 144 | + # we need to ensure that these are applied AFTER the volume is created |
| 145 | + # but BEFORE the volume is started |
| 146 | + $new_volume_defaults = { |
| 147 | + require => Exec["gluster create volume ${title}"], |
| 148 | + before => Exec["gluster start volume ${title}"], |
| 149 | + } |
145 | 150 |
|
146 | | - create_resources(::gluster::volume::option, $hoh, $new_volume_defaults) |
147 | | - } |
| 151 | + create_resources(::gluster::volume::option, $hoh, $new_volume_defaults) |
| 152 | + } |
148 | 153 |
|
149 | | - # don't forget to start the new volume! |
150 | | - exec { "gluster start volume ${title}": |
151 | | - command => "${::gluster_binary} volume start ${title}", |
152 | | - require => Exec["gluster create volume ${title}"], |
| 154 | + # don't forget to start the new volume! |
| 155 | + exec { "gluster start volume ${title}": |
| 156 | + command => "${::gluster_binary} volume start ${title}", |
| 157 | + require => Exec["gluster create volume ${title}"], |
| 158 | + } |
153 | 159 | } |
154 | 160 | } elsif $already_exists { |
155 | 161 | # this volume exists |
156 | 162 |
|
157 | | - # our fact lists bricks comma-separated, but we need an array |
158 | | - $vol_bricks = split( getvar( "::gluster_volume_${title}_bricks" ), ',') |
159 | | - if $bricks != $vol_bricks { |
160 | | - # this resource's list of bricks does not match the existing |
161 | | - # volume's list of bricks |
162 | | - $new_bricks = difference($bricks, $vol_bricks) |
| 163 | + if $ensure == 'present' { |
| 164 | + # our fact lists bricks comma-separated, but we need an array |
| 165 | + $vol_bricks = split( getvar( "::gluster_volume_${title}_bricks" ), ',') |
| 166 | + if $bricks != $vol_bricks { |
| 167 | + # this resource's list of bricks does not match the existing |
| 168 | + # volume's list of bricks |
| 169 | + $new_bricks = difference($bricks, $vol_bricks) |
163 | 170 |
|
164 | | - $vol_count = count($vol_bricks) |
165 | | - if count($bricks) > $vol_count { |
166 | | - # adding bricks |
| 171 | + $vol_count = count($vol_bricks) |
| 172 | + if count($bricks) > $vol_count { |
| 173 | + # adding bricks |
167 | 174 |
|
168 | | - # if we have a stripe or replica volume, make sure the |
169 | | - # number of bricks to add is a factor of that value |
170 | | - if $stripe { |
171 | | - if ( count($new_bricks) % $stripe ) != 0 { |
172 | | - fail("Number of bricks to add is not a multiple of stripe count ${stripe}") |
| 175 | + # if we have a stripe or replica volume, make sure the |
| 176 | + # number of bricks to add is a factor of that value |
| 177 | + if $stripe { |
| 178 | + if ( count($new_bricks) % $stripe ) != 0 { |
| 179 | + fail("Number of bricks to add is not a multiple of stripe count ${stripe}") |
| 180 | + } |
| 181 | + $s = "stripe ${stripe}" |
| 182 | + } else { |
| 183 | + $s = '' |
173 | 184 | } |
174 | | - $s = "stripe ${stripe}" |
175 | | - } else { |
176 | | - $s = '' |
177 | | - } |
178 | 185 |
|
179 | | - if $replica { |
180 | | - if $arbiter and $arbiter != 0 { |
181 | | - $r = "replica ${replica} arbiter ${arbiter}" |
182 | | - } else { |
183 | | - if ( count($bricks) % $replica ) != 0 { |
184 | | - fail("Number of bricks to add is not a multiple of replica count ${replica}") |
| 186 | + if $replica { |
| 187 | + if $arbiter and $arbiter != 0 { |
| 188 | + $r = "replica ${replica} arbiter ${arbiter}" |
| 189 | + } else { |
| 190 | + if ( count($bricks) % $replica ) != 0 { |
| 191 | + fail("Number of bricks to add is not a multiple of replica count ${replica}") |
| 192 | + } |
| 193 | + $r = "replica ${replica}" |
185 | 194 | } |
186 | | - $r = "replica ${replica}" |
| 195 | + } else { |
| 196 | + $r = '' |
187 | 197 | } |
188 | | - } else { |
189 | | - $r = '' |
190 | | - } |
191 | 198 |
|
192 | | - $new_bricks_list = join($new_bricks, ' ') |
193 | | - exec { "gluster add bricks to ${title}": |
194 | | - command => "${::gluster_binary} volume add-brick ${title} ${s} ${r} ${new_bricks_list} ${_force}", |
195 | | - } |
| 199 | + $new_bricks_list = join($new_bricks, ' ') |
| 200 | + exec { "gluster add bricks to ${title}": |
| 201 | + command => "${::gluster_binary} volume add-brick ${title} ${s} ${r} ${new_bricks_list} ${_force}", |
| 202 | + } |
196 | 203 |
|
197 | | - if $rebalance { |
198 | | - exec { "gluster rebalance ${title}": |
199 | | - command => "${::gluster_binary} volume rebalance ${title} start", |
200 | | - require => Exec["gluster add bricks to ${title}"], |
| 204 | + if $rebalance { |
| 205 | + exec { "gluster rebalance ${title}": |
| 206 | + command => "${::gluster_binary} volume rebalance ${title} start", |
| 207 | + require => Exec["gluster add bricks to ${title}"], |
| 208 | + } |
201 | 209 | } |
202 | | - } |
203 | 210 |
|
204 | | - if $replica and $heal { |
205 | | - # there is a delay after which a brick is added before |
206 | | - # the self heal daemon comes back to life. |
207 | | - # as such, we sleep 5 here before starting the heal |
208 | | - exec { "gluster heal ${title}": |
209 | | - command => "/bin/sleep 5; ${::gluster_binary} volume heal ${title} full", |
210 | | - require => Exec["gluster add bricks to ${title}"], |
| 211 | + if $replica and $heal { |
| 212 | + # there is a delay after which a brick is added before |
| 213 | + # the self heal daemon comes back to life. |
| 214 | + # as such, we sleep 5 here before starting the heal |
| 215 | + exec { "gluster heal ${title}": |
| 216 | + command => "/bin/sleep 5; ${::gluster_binary} volume heal ${title} full", |
| 217 | + require => Exec["gluster add bricks to ${title}"], |
| 218 | + } |
211 | 219 | } |
| 220 | + } elsif count($bricks) < $vol_count { |
| 221 | + # removing bricks |
| 222 | + notify { 'removing bricks is not currently supported.': } |
| 223 | + } else { |
| 224 | + notify { "unable to resolve brick changes for Gluster volume ${title}!\nDefined: ${_bricks}\nCurrent: ${vol_bricks}": } |
212 | 225 | } |
213 | | - } elsif count($bricks) < $vol_count { |
214 | | - # removing bricks |
215 | | - notify { 'removing bricks is not currently supported.': } |
216 | | - } else { |
217 | | - notify { "unable to resolve brick changes for Gluster volume ${title}!\nDefined: ${_bricks}\nCurrent: ${vol_bricks}": } |
218 | 226 | } |
219 | | - } |
220 | 227 |
|
221 | | - # did the options change? |
222 | | - $current_options_hash = pick(fact("gluster_volumes.${title}.options"), {}) |
223 | | - $_current = sort(join_keys_to_values($current_options_hash, ': ')) |
| 228 | + # did the options change? |
| 229 | + $current_options_hash = pick(fact("gluster_volumes.${title}.options"), {}) |
| 230 | + $_current = sort(join_keys_to_values($current_options_hash, ': ')) |
224 | 231 |
|
225 | | - if $_current != $_options { |
226 | | - # |
227 | | - # either of $current_options or $_options may be empty. |
228 | | - # we need to account for this situation |
229 | | - # |
230 | | - if is_array($_current) and is_array($_options) { |
231 | | - $to_remove = difference($_current, $_options) |
232 | | - $to_add = difference($_options, $_current) |
233 | | - } else { |
234 | | - if is_array($_current) { |
235 | | - # $_options is not an array, so remove all currently set options |
236 | | - $to_remove = $_current |
237 | | - } elsif is_array($_options) { |
238 | | - # $current_options is not an array, so add all our defined options |
239 | | - $to_add = $_options |
240 | | - } |
241 | | - } |
242 | | - if ! empty($to_remove) { |
243 | | - # we have some options active that are not defined here. Remove them |
| 232 | + if $_current != $_options { |
244 | 233 | # |
245 | | - # the syntax to remove ::gluster::volume::options is a little different |
246 | | - # so build up the hash correctly |
| 234 | + # either of $current_options or $_options may be empty. |
| 235 | + # we need to account for this situation |
247 | 236 | # |
248 | | - $remove_opts = prefix( $to_remove, "${title}:" ) |
249 | | - $remove_yaml = join( regsubst( $remove_opts, ': .+$', ":\n ensure: absent", 'G' ), "\n" ) |
250 | | - $remove = parseyaml($remove_yaml) |
251 | | - if $remove_options { |
252 | | - create_resources( ::gluster::volume::option, $remove ) |
| 237 | + if is_array($_current) and is_array($_options) { |
| 238 | + $to_remove = difference($_current, $_options) |
| 239 | + $to_add = difference($_options, $_current) |
253 | 240 | } else { |
254 | | - $remove_str = join( keys($remove), ', ' ) |
255 | | - notice("NOT REMOVING the following options for volume ${title}: ${remove_str}.") |
| 241 | + if is_array($_current) { |
| 242 | + # $_options is not an array, so remove all currently set options |
| 243 | + $to_remove = $_current |
| 244 | + } elsif is_array($_options) { |
| 245 | + # $current_options is not an array, so add all our defined options |
| 246 | + $to_add = $_options |
| 247 | + } |
| 248 | + } |
| 249 | + if ! empty($to_remove) { |
| 250 | + # we have some options active that are not defined here. Remove them |
| 251 | + # |
| 252 | + # the syntax to remove ::gluster::volume::options is a little different |
| 253 | + # so build up the hash correctly |
| 254 | + # |
| 255 | + $remove_opts = prefix( $to_remove, "${title}:" ) |
| 256 | + $remove_yaml = join( regsubst( $remove_opts, ': .+$', ":\n ensure: absent", 'G' ), "\n" ) |
| 257 | + $remove = parseyaml($remove_yaml) |
| 258 | + if $remove_options { |
| 259 | + create_resources( ::gluster::volume::option, $remove ) |
| 260 | + } else { |
| 261 | + $remove_str = join( keys($remove), ', ' ) |
| 262 | + notice("NOT REMOVING the following options for volume ${title}: ${remove_str}.") |
| 263 | + } |
| 264 | + } |
| 265 | + if ! empty($to_add) { |
| 266 | + # we have some options defined that are not active. Add them |
| 267 | + $add_opts = prefix( $to_add, "${title}:" ) |
| 268 | + $add_yaml = join( regsubst( $add_opts, ': ', ":\n value: ", 'G' ), "\n" ) |
| 269 | + $add = parseyaml($add_yaml) |
| 270 | + create_resources( ::gluster::volume::option, $add ) |
256 | 271 | } |
257 | 272 | } |
258 | | - if ! empty($to_add) { |
259 | | - # we have some options defined that are not active. Add them |
260 | | - $add_opts = prefix( $to_add, "${title}:" ) |
261 | | - $add_yaml = join( regsubst( $add_opts, ': ', ":\n value: ", 'G' ), "\n" ) |
262 | | - $add = parseyaml($add_yaml) |
263 | | - create_resources( ::gluster::volume::option, $add ) |
| 273 | + } else { |
| 274 | + # stop and remove volume |
| 275 | + exec { "gluster stop and remove ${title}": |
| 276 | + command => "/bin/yes | ( ${::gluster_binary} volume stop ${title} force && ${::gluster_binary} volume delete ${title} )", |
264 | 277 | } |
265 | 278 | } |
266 | 279 | } |
|
0 commit comments