[augeas-devel] Syslinux config file lens

Matthew Palmer matt at anchor.net.au
Sat Aug 1 00:56:05 UTC 2009


Finally got it doing everything I want!  Basically, this lens just manages
the configuration for the syslinux family of bootloaders.  I personally only
use it for our boot servers' pxelinux configs, but the Internets assure me
that the format is the same for all of them.

Share and enjoy!


-- 
Windows is too dangerous to be left to Windows admins.
		-- James Riden, ASR
-------------- next part --------------
(* syslinux (and all other *linux boot loaders) lens definition for Augeas
   Author: Matt Palmer <mpalmer at hezmatt.org>

   Copyright (C) 2009 Matt Palmer, All Rights Reserved
   Copyright (C) 2009 Anchor Systems Pty Ltd, All Rights Reserved

   This program is free software: you can redistribute it and/or modify it
   under the terms of the GNU General Public License version 2 as published
   by the Free Software Foundation.
               
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
   Public License for more details.
                       
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.

This lens is designed to parse a pxelinux/isolinux/syslinux/<foo>linux boot
loaderconfig file (such as "default", "isolinux.cfg", or
"01-00-00-12-34-56-78").

These files typically contain a series of simple key/value pairs, each on their
own line, with the key and value separated by whitespace, like so:

---8<---
prompt 1
timeout 600
default foo
--->8---

This lens turns those into simple key/value pairs in the tree:

set /prompt 1
set /timeout 600
set /default foo

There is one exception to this simple key/value rule, and that is the
"append" option, which gives default append options to be used for all boot
configurations.  Because the append parameter is a key/value store of it's
own, we represent it a bit differently. This string:

append initrd=/initrd.img ramdisk_size=15240 rw --

is translated like this in the tree:

set /append[1] initrd=/initrd.img
set /append[2] ramdisk_size=15240
set /append[3] rw
set /append[4] --

The reason why this is an array of options rather than some sort of
key/value list of it's own is that appended options can have slashes in them
(think "preseed/file=/preseed.cfg"), and Augeas doesn't like slashes in it's
keys.  So, sorry 'bout that, but it's an array of options all the way, I'm
afraid.

Apart from setting configurations globally, you also provide boot
configurations, which are the different names you can type at the <foo>linux
prompt to choose between, say, normal install, expert install, and a rescue
environment.  These look like this in the file:

label xyzzy
	kernel vmlinuz-xyzzy
	append initrd=initrd-xyzzy vga=normal --

This gets turned into this in the tree:

set /label[0] xyzzy
set /label[0]/kernel vmlinuz-xyzzy
set /label[0]/append[1] initrd=initrd-xyzzy
set /label[0]/append[2] vga=normal
set /label[0]/append[3] --

Effectively, the same key/value association (with the special handling for
"append") happens inside each boot label, just as it does at the top level. 
Hopefully this makes for consistent usage and minimal confusion.

Comments in <foo>linux config files are hash ('#') prefixed, and continue to
end-of-line. These are represented with "#comment" tags in the tree, as per
standard convention.

*)

module Syslinux =
	autoload xfm

	(* Store whitespace *)
	let wsp = del /[ \t]+/ " "
	
	let indent = del /[ \t]+/ "	"
	
	(* It's the end of the line as we know it... doo, doo, dooooo *)
	let eol = Util.eol
	
	(* In the beginning, the earth was without form, and void *)
	let empty = Util.empty
	
	let comment = Util.comment

	(***************************
	 * GENERIC OPTION HANDLING
	 ***************************)

	let option_value = wsp . store /[^ \t\n][^\n]*/ . del /\n/ "\n"

	let global_option = [ del /[Ii][Nn][Cc][Ll][Uu][Dd][Ee]/ "include" . label "include" . option_value ]
	                   |[ del /[Kk][Ee][Rr][Nn][Ee][Ll]/ "kernel" . label "kernel" . option_value ]
	                   |[ del /[Ll][Ii][Nn][Uu][Xx]/ "linux" . label "linux" . option_value ]
	                   |[ del /[Bb][Oo][Oo][Tt]/ "boot" . label "boot" . option_value ]
	                   |[ del /[Bb][Ss][Ss]/ "bss" . label "bss" . option_value ]
	                   |[ del /[Pp][Xx][Ee]/ "pxe" . label "pxe" . option_value ]
	                   |[ del /[Ff][Dd][Ii][Mm][Aa][Gg][Ee]/ "fdimage" . label "fdimage" . option_value ]
	                   |[ del /[Cc][Oo][Mm][Bb][Oo][Oo][Tt]/ "comboot" . label "comboot" . option_value ]
	                   |[ del /[Cc][Oo][Mm]32/ "com32" . label "com32" . option_value ]
	                   |[ del /[Cc][Oo][Nn][Ff][ii][Gg]/ "config" . label "config" . option_value ]
	                   |[ del /[Ii][Pp][Aa][Pp][Pp][Ee][Nn][Dd]/ "ipappend" . label "ipappend" . option_value ]
	                   |[ del /[Ll][Oo][Cc][Aa][Ll][Bb][Oo][Oo][Tt]/ "localboot" . label "localboot" . option_value ]
	                   |[ del /[Ii][Nn][Ii][Tt][Rr][Dd]/ "initrd" . label "initrd" . option_value ]
	                   |[ del /[Dd][Ee][Ff][Aa][Uu][Ll][Tt]/ "default" . label "default" . option_value ]
	                   |[ del /[Uu][Ii]/ "ui" . label "ui" . option_value ]
	                   |[ del /[Pp][Rr][Oo][Mm][Pp][Tt]/ "prompt" . label "prompt" . option_value ]
	                   |[ del /[Nn][Oo][Ee][Ss][Cc][Aa][Pp][Ee]/ "noescape" . label "noescape" . option_value ]
	                   |[ del /[Nn][Oo][Cc][Oo][Mm][Pp][Ll][Ee][Tt][Ee]/ "nocomplete" . label "nocomplete" . option_value ]
	                   |[ del /[Ii][Mm][Pp][Ll][Ii][Cc][Ii][Tt]/ "implicit" . label "implicit" . option_value ]
	                   |[ del /[Aa][Ll][Ll][Oo][Ww][Oo][Pp][Tt][Ii][Oo][Nn][Ss]/ "allowoptions" . label "allowoptions" . option_value ]
	                   |[ del /[Tt][Ii][Mm][Ee][Oo][Uu][Tt]/ "timeout" . label "timeout" . option_value ]
	                   |[ del /[Tt][Oo][Tt][Aa][Ll][Tt][Ii][Mm][Ee][Oo][Uu][Tt]/ "totaltimeout" . label "totaltimeout" . option_value ]
	                   |[ del /[Oo][Nn][Tt][Ii][Mm][Ee][Oo][Uu][Tt]/ "ontimeout" . label "ontimeout" . option_value ]
	                   |[ del /[Oo][Nn][Ee][Rr][Rr][Oo][Rr]/ "onerror" . label "onerror" . option_value ]
	                   |[ del /[Ss][Ee][Rr][Ii][Aa][Ll]/ "serial" . label "serial" . option_value ]
	                   |[ del /[Cc][Oo][Nn][Ss][Oo][Ll][Ee]/ "console" . label "console" . option_value ]
	                   |[ del /[Ff][Oo][Nn][Tt]/ "font" . label "font" . option_value ]
	                   |[ del /[Kk][Bb][Dd][Mm][Aa][Pp]/ "kbdmap" . label "kbdmap" . option_value ]
	                   |[ del /[Ss][Aa][Yy]/ "say" . label "say" . option_value ]
	                   |[ del /[Dd][Ii][Ss][Pp][Ll][Aa][Yy]/ "display" . label "display" . option_value ]
	                   |[ key /F(1[12]?|[2-9])/ . option_value ]
	
(*	let global_option = [ valid_option   key ( /[^ \t\n\/#]+/ - /([Aa][Pp][Pp][Ee][Nn][Dd]|[Ll][Aa][Bb][Ee][Ll])/ )
	                      . wsp
	                      . store /[^ \t\n].*/
	                      . del /\n/ "\n"
	                    ]
*)

	(***************************
	 * APPEND OPTION HANDLING
	 ***************************)
	
	let append_opt = [ seq "append_seq" . wsp . store /[^ \t\n]+/ ]
	
	let global_append = [ del /[Aa][Pp][Pp][Ee][Nn][Dd]/ "append"
	                      . label "append"
	                      . counter "append_seq"
	                      . append_opt+
	                      . eol
	                    ]

	(***********************
	 * LABEL
	 ***********************)

	let label_line = del /[Ll][Aa][Bb][Ee][Ll]/ "label" . label "label" . wsp . store /[^ \t\n]+/ . eol
	let label_option = indent . global_option
	let label_append = indent . global_append
		
	let label = [ label_line
	              . (label_option|label_append)*
	            ]

	(***********************
	 * LENS / FILTER
	 ***********************)

	let lns = (comment|empty|global_option|global_append|label)*
	
	let filter = (incl "/tftpboot/pxelinux.cfg/default")
	             . (incl "/tftpboot/pxelinux.cfg/[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]-[0-9a-f][0-9a-f]")
	             . Util.stdexcl
	             
	let xfm = transform lns filter
-------------- next part --------------
module Test_syslinux =

	(* The standard "parse a bucket of text" test *)
	let conf = "# Blah di blah comment

prompt 1
timeout 600
default local
display welcome.msg
F1 help.msg
F2 opts.msg
F3 images.msg

label mem
	kernel memtest

LABEL local
	localboot 0x80

LABEL burn
	kernel vmlinuz-rhel
	append initrd=initrd.img-rhel text ks=/kickstart.ks

label lenny64
	kernel vmlinuz-lenny64
	append vga=normal initrd=initrd.img-lenny64 preseed/url=http://localhost/preseed.cfg --
"

	test Syslinux.lns get conf =
		{ "#comment" = "Blah di blah comment" }
		{}
		{ "prompt" = "1" }
		{ "timeout" = "600" }
		{ "default" = "local" }
		{ "display" = "welcome.msg" }
		{ "F1" = "help.msg" }
		{ "F2" = "opts.msg" }
		{ "F3" = "images.msg" }
		{}
		{ "label" = "mem"
			{ "kernel" = "memtest" }
		}
		{}
		{ "label" = "local"
			{ "localboot" = "0x80" }
		}
		{}
		{ "label" = "burn"
			{ "kernel" = "vmlinuz-rhel" }
			{ "append"
				{ "1" = "initrd=initrd.img-rhel" }
				{ "2" = "text" }
				{ "3" = "ks=/kickstart.ks" }
			}
		}
		{}
		{ "label" = "lenny64"
			{ "kernel" = "vmlinuz-lenny64" }
			{ "append"
				{ "1" = "vga=normal" }
				{ "2" = "initrd=initrd.img-lenny64" }
				{ "3" = "preseed/url=http://localhost/preseed.cfg" }
				{ "4" = "--" }
			}
		}

(**************************************************************************)

	(* Test new file creation *)
	
	test Syslinux.lns put "" after
		set "/default" "mem";
		set "/prompt" "1";
		set "/timeout" "600";
		set "/label[1]" "mem";
		set "/label[1]/kernel" "memtest";
		set "/label[2]" "lenny64";
		set "/label[2]/kernel" "vmlinuz-lenny64";
		set "/label[2]/append/1" "vga=normal";
		set "/label[2]/append/2" "initrd=initrd.img-lenny64";
		set "/label[2]/append/3" "preseed/url=http://172.1.7.2/preseed.cfg";
		set "/label[2]/append/4" "--"
	= "default mem
prompt 1
timeout 600
label mem
	kernel memtest
label lenny64
	kernel vmlinuz-lenny64
	append vga=normal initrd=initrd.img-lenny64 preseed/url=http://172.1.7.2/preseed.cfg --
"


More information about the augeas-devel mailing list