Imported Upstream version 1.7.0
[platform/upstream/augeas.git] / lenses / mdadm_conf.aug
1 (******************************************************************************
2 Mdadm_conf module for Augeas
3
4 Author: Matthew Booth <mbooth@redhat.com>
5
6 Copyright (C):
7     2011 Red Hat Inc.
8
9 Reference:
10     mdadm(5)
11     config.c and policy.c from mdadm-3.2.2
12
13 License:
14     This file is licensed under the LGPL v2+.
15
16 This is a lens for /etc/mdadm.conf. It aims to parse every valid configuration
17 file as of version 3.2.2, and many invalid ones too. This last point is a
18 feature, not a bug! madm will generate warnings for invalid configuration which
19 do not prevent correct operation of the tool. Wherever possible, we try to
20 allow for this behaviour.
21
22 Keywords in mdadm.conf are matched with a case-insensitive prefix match of at
23 least 3 characters. Keys in key/value pairs are also matched case-insensitively,
24 but require a full match. The exception is POLICY and PART-POLICY, where keys
25 are matched case-sensitively.
26
27 N.B. We can't use case-insensitive regular expressions in most places due to bug
28 #147.
29 *******************************************************************************)
30
31 module Mdadm_conf =
32
33    autoload xfm
34
35
36 (******************************************************************************
37  * PRIMITIVES
38  ******************************************************************************)
39
40 let eol             = Util.comment_or_eol
41 let comment         = Util.comment
42 let empty           = Util.empty
43 let value           = /[^ \t\n#]+/
44 let value_no_eq     = /[^ \t\n#=]+/
45 let value_no_eq_sl  = /[^ \t\n#=\/]+/
46
47 let continuation = /\n[ \t]+/
48 let space = /[ \t]+/
49 let value_sep = ( del ( continuation | space . continuation? ) " "
50                   | comment . del space " " )
51
52 (* We parse specific keys rather than having a catch-all owing to the varying
53 case of the syntax. This means the user can rely on 'array/uuid' rather than
54 additionally testing for 'array/UUID'.
55
56 It would be good to have an additional catchall, but I haven't been able to make
57 that work.
58 *)
59 let keyvalue (r:regexp) (lc:string) (uc:string) =
60     [ del ( r . /=/ ) ( uc . "=" ) . label lc . store value ]
61
62 let simplevalue (r:regexp) (lc:string) (uc:string) =
63     [ del r uc . label lc
64       . ( value_sep . [ label "value" . store value ] )* . eol ]
65
66
67 (******************************************************************************
68  * DEVICES
69  ******************************************************************************)
70
71 let dev_re = /dev(i(ce?)?)?/i
72
73 let dev_containers_re = /containers/i
74 let dev_partitions_re = /partitions/i
75
76 let dev_containers = [ del dev_containers_re "containers" . label "containers" ]
77 let dev_partitions = [ del dev_partitions_re "partitions" . label "partitions" ]
78 let dev_device = [ label "name". store ( value - (dev_containers_re | dev_partitions_re)) ]
79
80 (* Strictly there must be at least 1 device, but we err on the side of parsing
81 *)
82 let dev_devices = ( value_sep . ( dev_containers
83                                   | dev_partitions
84                                   | dev_device ) )*
85
86 let device = [ del dev_re "DEVICE" . label "device" . dev_devices . eol ]
87
88
89 (******************************************************************************
90  * ARRAY
91  ******************************************************************************)
92
93 let array_re  = /arr(ay?)?/i
94
95 let arr_auto_re         = /auto/i
96 let arr_bitmap_re       = /bitmap/i
97 let arr_container_re    = /container/i
98 let arr_devices_re      = /devices/i
99 let arr_disks_re        = /disks/i (* Undocumented *)
100 let arr_level_re        = /level/i
101 let arr_member_re       = /member/i
102 let arr_metadata_re     = /metadata/i
103 let arr_name_re         = /name/i
104 let arr_num_devices_re  = /num-devices/i
105 let arr_spare_group_re  = /spare-group/i
106 let arr_spares_re       = /spares/i
107 let arr_super_minor_re  = /super-minor/i
108 let arr_uuid_re         = /uuid/i
109
110 let arr_devicename      = [ store value_no_eq . label "devicename" ]
111
112 let arr_auto        = keyvalue arr_auto_re "auto" "AUTO"
113 let arr_bitmap      = keyvalue arr_bitmap_re "bitmap" "BITMAP"
114 let arr_container   = keyvalue arr_container_re "container" "CONTAINER"
115 let arr_devices     = keyvalue arr_devices_re "devices" "DEVICES"
116 let arr_disks       = keyvalue arr_disks_re "disks" "DISKS"
117 let arr_level       = keyvalue arr_level_re "level" "LEVEL"
118 let arr_member      = keyvalue arr_member_re "member" "MEMBER"
119 let arr_metadata    = keyvalue arr_metadata_re "metadata" "METADATA"
120 let arr_name        = keyvalue arr_name_re "name" "NAME"
121 let arr_num_devices = keyvalue arr_num_devices_re "num-devices" "NUM-DEVICES"
122 let arr_spare_group = keyvalue arr_spare_group_re "spare-group" "SPARE-GROUP"
123 let arr_spares      = keyvalue arr_spares_re "spares" "SPARES"
124 let arr_super_minor = keyvalue arr_super_minor_re "super-minor" "SUPER-MINOR"
125 let arr_uuid        = keyvalue arr_uuid_re "uuid" "UUID"
126
127 let arr_options = ( value_sep . ( arr_devicename
128                                   | arr_auto
129                                   | arr_bitmap
130                                   | arr_container
131                                   | arr_devices
132                                   | arr_disks
133                                   | arr_level
134                                   | arr_member
135                                   | arr_metadata
136                                   | arr_name
137                                   | arr_num_devices
138                                   | arr_spare_group
139                                   | arr_spares
140                                   | arr_super_minor
141                                   | arr_uuid ) )*
142
143 let array  = [ del array_re "ARRAY" . label "array" . arr_options . eol ]
144
145
146 (******************************************************************************
147  * MAILADDR
148  ******************************************************************************)
149
150 let mailaddr_re = /mai(l(a(d(dr?)?)?)?)?/i
151
152 (* We intentially allow multiple mailaddr values here, even though this is
153 invalid and would produce a warning. This is better than not parsing the file.
154 *)
155 let mailaddr = simplevalue mailaddr_re "mailaddr" "MAILADDR"
156
157
158 (******************************************************************************
159  * MAILFROM
160  ******************************************************************************)
161
162 (* N.B. MAILFROM can only be abbreviated to 5 characters *)
163 let mailfrom_re = /mailf(r(om?)?)?/i
164
165 let mailfrom = [ del mailfrom_re "MAILFROM" . label "mailfrom"
166                  . ( value_sep . [ label "value" . store value ] )* . eol ]
167
168
169 (******************************************************************************
170  * PROGRAM
171  ******************************************************************************)
172
173 let program_re = /pro(g(r(am?)?)?)?/i
174
175 let program = simplevalue program_re "program" "PROGRAM"
176
177
178 (******************************************************************************
179  * CREATE
180  ******************************************************************************)
181
182 let create_re = /cre(a(te?)?)?/i
183
184 let cre_auto_re     = /auto/i
185 let cre_owner_re    = /owner/i
186 let cre_group_re    = /group/i
187 let cre_mode_re     = /mode/i
188 let cre_metadata_re = /metadata/i
189 let cre_symlinks_re = /symlinks/i
190
191 let cre_auto        = keyvalue cre_auto_re "auto" "AUTO"
192 let cre_group       = keyvalue cre_group_re "group" "GROUP"
193 let cre_metadata    = keyvalue cre_metadata_re "metadata" "METADATA"
194 let cre_mode        = keyvalue cre_mode_re "mode" "MODE"
195 let cre_owner       = keyvalue cre_owner_re "owner" "OWNER"
196 let cre_symlinks    = keyvalue cre_symlinks_re "symlinks" "SYMLINKS"
197
198 let cre_options = ( value_sep . ( arr_auto
199                                   | cre_owner
200                                   | cre_group
201                                   | cre_mode
202                                   | cre_metadata
203                                   | cre_symlinks) )*
204
205 let create  = [ del create_re "CREATE" . label "create" . cre_options . eol ]
206
207
208 (******************************************************************************
209  * HOMEHOST
210  ******************************************************************************)
211
212 let homehost_re = /hom(e(h(o(st?)?)?)?)?/i
213
214 let homehost = simplevalue homehost_re "homehost" "HOMEHOST"
215
216
217 (******************************************************************************
218  * AUTO
219  ******************************************************************************)
220
221 let auto_re = /auto?/i
222
223 let aut_plus        = [ key "+" . store value ]
224 let aut_minus       = [ key "-" . store value ]
225 let aut_homehost    = [ del /homehost/i "homehost" . label "homehost" ]
226
227 let aut_list = ( value_sep . ( aut_plus | aut_minus | aut_homehost ) )*
228
229 let auto = [ del auto_re "AUTO" . label "auto" . aut_list . eol ]
230
231
232 (******************************************************************************
233  * POLICY and PART-POLICY
234  ******************************************************************************)
235
236 (* PART-POLICY is undocumented. A cursory inspection of the parsing code
237 suggests it's parsed the same way as POLICY, but treated slightly differently
238 thereafter. *)
239
240 let policy_re = /pol(i(cy?)?)?/i
241 let part_policy_re = /par(t(-(p(o(l(i(cy?)?)?)?)?)?)?)?/i
242
243 (* Unlike everything else, policy keys are matched case sensitive. This means we
244 don't have to mess around with explicit option matching, as the match string is
245 fixed for a working configuration. *)
246
247 let pol_option (act:string) =
248     [ del ( act . "=" ) ( act . "=" ) . label act . store value ]
249
250 let pol_options = ( value_sep . [ key value_no_eq_sl . del "=" "="
251                                   . store value ] )*
252
253 let policy      = [ del policy_re "POLICY" . label "policy"
254                     . pol_options . eol ]
255 let part_policy = [ del part_policy_re "PART-POLICY" . label "part-policy"
256                     . pol_options . eol ]
257
258
259 (******************************************************************************
260  * LENS
261  ******************************************************************************)
262
263 let lns = (comment
264            | empty
265            | device
266            | array
267            | mailaddr
268            | mailfrom
269            | program
270            | create
271            | homehost
272            | auto
273            | policy
274            | part_policy )*
275
276 let filter     = incl "/etc/mdadm.conf"
277                . incl "/etc/mdadm/mdadm.conf"
278
279 let xfm        = transform lns filter