3 Parses disk_config files for FAI
5 Author: Raphael Pinson <raphink@gmail.com>
8 This lens tries to keep as close as possible to the FAI wiki where possible:
9 http://wiki.fai-project.org/wiki/Setup-storage#New_configuration_file_syntax
12 This file is licensed under the LGPL v2+, like the rest of Augeas.
15 The <Test_FAI_DiskConfig> file contains various examples and tests.
18 module FAI_DiskConfig =
22 (************************************************************************
23 * Group: USEFUL PRIMITIVES
24 *************************************************************************)
26 (* Group: Generic primitives *)
34 let empty = Util.empty
36 (* Variable: comment *)
37 let comment = Util.comment
40 A generic tag beginning with a colon *)
41 let tag (re:regexp) = [ Util.del_str ":" . key re ]
43 (* Variable: generic_opt
44 A generic key/value option *)
45 let generic_opt (type:string) (kw:regexp) =
46 [ key type . Util.del_str ":" . store kw ]
48 (* Variable: generic_opt_list
49 A generic key/list option *)
50 let generic_opt_list (type:string) (kw:regexp) =
51 [ key type . Util.del_str ":" . counter "locallist"
52 . Build.opt_list [seq "locallist" . store kw] Sep.comma ]
55 (************************************************************************
57 *************************************************************************)
62 (* Variable: mountpoint_kw *)
63 let mountpoint_kw = "-" (* do not mount *)
64 | "swap" (* swap space *)
65 (* fully qualified path; if :encrypt is given, the partition
66 * will be encrypted, the key is generated automatically *)
71 let encrypt = tag "encrypt"
73 (* Variable: mountpoint *)
74 let mountpoint = [ label "mountpoint" . store mountpoint_kw
75 (* encrypt is only for the fspath, but we parse it anyway *)
80 let resize = tag "resize"
84 let size_kw = /[0-9]+[kMGTP%]?(-([0-9]+[kMGTP%]?)?)?/
88 let size = [ label "size" . store size_kw . resize? ]
90 (* Variable: filesystem_kw
91 Regexps for filesystem *)
92 let filesystem_kw = "-"
94 (* NOTE: Restraining this regexp would improve perfs *)
95 | (Rx.no_spaces - ("-" | "swap")) (* mkfs.xxx must exist *)
97 (* Variable: filesystem *)
98 let filesystem = [ label "filesystem" . store filesystem_kw ]
101 (* Variable: mount_option_value *)
102 let mount_option_value = [ label "value" . Util.del_str "="
103 . store /[^,= \t\n]+/ ]
105 (* Variable: mount_option
107 let mount_option = [ seq "mount_option"
108 . store /[^,= \t\n]+/
109 . mount_option_value? ]
111 (* Variable: mount_options
112 An array of <mount_option>s *)
113 let mount_options = [ label "mount_options"
114 . counter "mount_option"
115 . Build.opt_list mount_option Sep.comma ]
117 (* Variable: fs_option *)
119 [ key /createopts|tuneopts/
120 . Util.del_str "=\"" . store /[^"\n]*/ . Util.del_str "\"" ]
122 (* Variable: fs_options
123 An array of <fs_option>s *)
125 (* options to append to mkfs.xxx and to the filesystem-specific
127 [ label "fs_options" . Build.opt_list fs_option Sep.space ]
129 (* Variable: volume_full *)
130 let volume_full (type:lens) (third_field:lens) =
133 (* The third field changes depending on types *)
134 . third_field . space
137 . (space . fs_options)?
141 LVM volume group name *)
142 let name = [ label "name" . store /[^\/ \t\n]+/ ]
144 (* Variable: partition
145 An optional partition number for <disk> *)
146 let partition = [ label "partition" . Util.del_str "." . store /[0-9]+/ ]
149 let disk = [ label "disk" . store /[^., \t\n]+/ . partition? ]
151 (* Variable: vg_option
152 An option for <volume_vg> *)
155 . Util.del_str "=\"" . store /[^"\n]*/ . Util.del_str "\"" ]
157 (* Variable: volume_vg *)
158 let volume_vg = [ key "vg"
161 . (space . vg_option)?
164 (* Variable: spare_missing *)
165 let spare_missing = tag /spare|missing/
167 (* Variable: disk_with_opt
168 A <disk> with a spare/missing option for raids *)
169 let disk_with_opt = [ label "disk" . store /[^:., \t\n]+/ . partition?
172 (* Variable: disk_list
173 A list of <disk_with_opt>s *)
174 let disk_list = Build.opt_list disk_with_opt Sep.comma
176 (* Variable: type_label_lv *)
177 let type_label_lv = label "lv"
178 . [ label "vg" . store (/[^# \t\n-]+/ - "raw") ]
180 . [ label "name" . store /[^ \t\n]+/ ]
182 (* Variable: volume_tmpfs *)
184 [ key "tmpfs" . space
188 . (space . fs_options)?
191 (* Variable: volume_lvm *)
192 let volume_lvm = volume_full type_label_lv size (* lvm logical volume: vg name and lv name *)
195 (* Variable: volume_raid *)
196 let volume_raid = volume_full (key /raid[0156]/) disk_list (* raid level *)
198 (* Variable: device *)
199 let device = [ label "device" . store Rx.fspath ]
201 (* Variable: volume_cryptsetup *)
202 let volume_cryptsetup = volume_full (key ("swap"|"tmp"|"luks")) device
204 (* Variable: volume *)
205 let volume = volume_full (key "primary") size (* for physical disks only *)
206 | volume_full (key "logical") size (* for physical disks only *)
207 | volume_full (key "raw-disk") size
209 (* Variable: volume_or_comment
210 A succesion of <volume>s and <comment>s *)
211 let volume_or_comment (vol:lens) =
212 (vol|empty|comment)* . vol
214 (* Variable: disk_config_entry *)
215 let disk_config_entry (kw:regexp) (opt:lens) (vol:lens) =
216 [ key "disk_config" . space . store kw
217 . (space . opt)* . eol
218 . (volume_or_comment vol)? ]
220 (* Variable: lvmoption *)
222 (* preserve partitions -- always *)
223 generic_opt "preserve_always" /[^\/, \t\n-]+-[^\/, \t\n-]+(,[^\/, \t\n-]+-[^\/, \t\n-]+)*/
224 (* preserve partitions -- unless the system is installed
225 * for the first time *)
226 | generic_opt "preserve_reinstall" /[^\/, \t\n-]+-[^\/, \t\n-]+(,[^\/, \t\n-]+-[^\/, \t\n-]+)*/
227 (* attempt to resize partitions *)
228 | generic_opt "resize" /[^\/, \t\n-]+-[^\/, \t\n-]+(,[^\/, \t\n-]+-[^\/, \t\n-]+)*/
229 (* when creating the fstab, the key used for defining the device
230 * may be the device (/dev/xxx), a label given using -L, or the uuid *)
231 | generic_opt "fstabkey" /device|label|uuid/
233 (* Variable: raidoption *)
235 (* preserve partitions -- always *)
236 generic_opt_list "preserve_always" (Rx.integer | "all")
237 (* preserve partitions -- unless the system is installed
238 * for the first time *)
239 | generic_opt_list "preserve_reinstall" Rx.integer
240 (* when creating the fstab, the key used for defining the device
241 * may be the device (/dev/xxx), a label given using -L, or the uuid *)
242 | generic_opt "fstabkey" /device|label|uuid/
244 (* Variable: option *)
246 (* preserve partitions -- always *)
247 generic_opt_list "preserve_always" (Rx.integer | "all")
248 (* preserve partitions -- unless the system is installed
249 for the first time *)
250 | generic_opt_list "preserve_reinstall" Rx.integer
251 (* attempt to resize partitions *)
252 | generic_opt_list "resize" Rx.integer
253 (* write a disklabel - default is msdos *)
254 | generic_opt "disklabel" /msdos|gpt/
255 (* mark a partition bootable, default is / *)
256 | generic_opt "bootable" Rx.integer
257 (* do not assume the disk to be a physical device, use with xen *)
259 (* when creating the fstab, the key used for defining the device
260 * may be the device (/dev/xxx), a label given using -L, or the uuid *)
261 | generic_opt "fstabkey" /device|label|uuid/
262 | generic_opt_list "always_format" Rx.integer
263 | generic_opt "sameas" Rx.fspath
268 (* Variable: disk_config *)
270 let excludes = "lvm" | "raid" | "end" | /disk[0-9]+/
271 | "cryptsetup" | "tmpfs" in
272 let other_label = Rx.fspath - excludes in
273 disk_config_entry "lvm" lvmoption volume_lvm
274 | disk_config_entry "raid" raidoption volume_raid
275 | disk_config_entry "tmpfs" option volume_tmpfs
276 | disk_config_entry "end" option volume (* there shouldn't be an option here *)
277 | disk_config_entry /disk[0-9]+/ option volume
278 | disk_config_entry "cryptsetup" cryptoption volume_cryptsetup
279 | disk_config_entry other_label option volume
282 The disk_config lens *)
283 let lns = (disk_config|comment|empty)*
286 (* let xfm = transform lns Util.stdexcl *)