This document was last modified
In order to keep namespace control files intact and homogeneous across hosts, we have developed a mechanism currently known as "nuggets". This name may change in the future :) . Each system file that would normally be hand-edited on all hosts can now be managed via the mount located at /usr/nikola/nugget. Either triggered manually or automatically, each host will determine if a newer version exists, and if so, compile the nugget into the desired system file(s). This allows us to quickly distribute system namespace changes to multiple hosts with a minimum amount of duplicated effort.
Normal prose is in this times font. Computer files are underlined, fixed width; while the text that is output is just fixed width. Where a substitution should be made, the substitution text is italicized, fixed width. Text in square brackets [] is optional.
The syntax diagrams are really meant for tool writers, and they are modified Bachus-Nauer format (BNF). Keywords and required punctuation are bolded. Text enclosed in {} is repeated between the lower and upper bounds, given as subscript and superscript.
A nugget should not begin to compile if the following variables are not either declared or guessed for the host:
These variables will be used throughout this document.
To facilitate the fact that Nikola will run on multiple system architectures, nuggets will be broken up into a format much like this:
The nugget control file is a single file that controls which of the possible variations get compiled into the rendered system file. The file is organized into brace-separated stanzas, like this:
nugget chicken { masterfile=chicken.master # A test comment. postproc=chicken.postproc generatedby=justin bunch ssli { duty webserver { postfile=chicken.webserver.postfile postproc=chicken.webserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile postproc+chicken.rh71-ia32.postproc } } duty fileserver { postfile=chicken.fileserver.postfile postproc=chicken.fileserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc.fileserver } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile.fileserver postproc+chicken.rh71-ia32.postproc # test comment } } # end of duty fileserver } bunch vlsi { duty webserver { postfile=chicken.webserver.postfile postproc=chicken.webserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile postproc+chicken.rh71-ia32.postproc } } duty fileserver { postfile=chicken.vlsi.testserver.postfile postproc=chicken.vlsi.testserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc.fileserver } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile.fileserver postproc+chicken.rh71-ia32.postproc # test comment } } # end of duty fileserver } bunch rcs { duty webserver { postfile=chicken.webserver.postfile postproc=chicken.webserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile postproc+chicken.rh71-ia32.postproc } } duty fileserver { postfile=chicken.rcs.testserver.postfile postproc=chicken.rcs.testserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc.fileserver } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile.fileserver postproc+chicken.rh71-ia32.postproc # test comment } } # end of duty fileserver } bunch rcs.gnl { duty webserver { postfile=chicken.webserver.postfile postproc=chicken.webserver.postproc } duty fileserver { postfile=chicken.rcsgnl.testserver.postfile postproc=chicken.rcsgnl.testserver.postproc } # end of duty fileserver for GNL } # Radar lab is special in its requirements bunch rcs.rrsl { duty computeserver { postfile=chicken.rcsrrsl.computeserver.postfile postproc=chicken.rcsrrsl.computeserver.postproc } # end of duty computeserver for RRSL } duty computeserver { postfile=chicken.computeserver.postfile postproc=chicken.computeserver.postproc arch rh71-ia32 { postproc+chicken.rh71-ia32.postproc } arch sol8-sparc { postfile=chicken.sol8-sparc.postfile postproc+chicken.rh71-ia32.postproc } } # Here is a comment that spans the entire line. }
This is the modified BNF of the nugget control file.
nugget_conf_file ::== {stanza}+ stanza ::== stanza_type stanza_name { {parameter_assignment}* stanza } stanza_type ::== nugget | arch | bunch | duty stanza_name ::== see discussion of stanza names below. parameter_assignment ::== assignment | append assignment ::== parameter=value append ::== parameter+value value ::== see discussion of datatypes below. parameter ::== letter{letter_digit_underscore}*
Comments are introduced by a pound sign (#) and terminated by the end of a line. Parameters are case-insensitive.
Each of these control files is required to include at least the one nugget stanza, and can then be followed by any number of arch, bunch, or duty stanzas to provide information specific to that category. Allowed values for bunch or duty are listed in the Nikola FAQ. Stanzas will be read in order, so to keep stanza heirarchy intact, all key/value pairs must occur before nesting of another stanza begins. Pairs can use either the = operator to assign a value or the + operator to append/concatonate.
In version 1, the format of the control file is restricted. The stanza introductions must be keyword value {. Each stanza ends with }. There can be only a single assignment or concatenation per line. Each line may have as much white space as desired. In version 2, the format of the control file is unrestricted. Comments begin with a # and end at the end of the line.
The operation of the master controlfile parser can be understood in terms of
set theory. The universe of discourse is the set of all computers that a
nikola installation supports. The MCP extracts subsets. The different
stanza names are different ways to slice and dice the subsets. For example,
if we run
mcp -b rcs -d nameserver,fileserver,workstation
then the stanza
bunch rcs { ... duty nameserver { ... } duty fileserver { ... }
would be accepted. The stanza
bunch rcs.dcl { ... duty nameserver { ... } duty fileserver { ... } }
would also be accepted, because bunch rcs.dcl is a subbunch of rcs.
By way of contrast, the stanza
bunch rcs.dcl { foo=seven duty computeserver { foo+fourteen } }
foo+fourteen would be rejected because computeserver is not a duty we're handling in this run, but foo=seven would be accepted.
Note that the rules are associative. The stanza
bunch rcs.dcl { duty timeserver { foo=bar } duty nisserver { foo=pool } }
is exactly the same as the stanzas
duty timeserver { bunch rcs.dcl { foo=bar } } duty nisserver { bunch rcs.dcl { foo=pool } }
For example, here are 4 stanza beginnings and 4 different bunches specified with the -b switch.
Stanza | -b rcs | -b rcs.rrsl | -b rcs.rrsl.radar | -b rcs.dcl |
---|---|---|---|---|
bunch rcs | read | ignored | ignored | ignored |
bunch rcs.rrsl | read | read | ignored | ignored |
bunch rcs.rrsl.radar | read | read | read | ignored |
bunch rcs.dcl | ignored | ignored | ignored | read |
Note that the only stanza that is required is the nugget stanza although this requirement is not enforced in the current version of the MCP. In particular, the arch stanza is not required, and if a given subset was always on a single architecture, then it could be left out. For example,
nugget wisdom { arch rh71-intel { bunch rcs { duty nameserver { foo+rachel } } } }
is completely equivalent to
nugget wisdom { bunch rcs { duty nameserver { foo+rachel } } }
because all of the RCS nameservers are on RedHat 7.1 based machines.
The differences in the subsetting rules for the stanzas are
Note that it is possible to create impossible stanzas, e.g.:
nugget dumb { arch rh71-intel { bunch rcs { duty nameserver { foo+rachel bunch ssli.nameservers { foo+leah } } } }
Since bunch ssli.nameservers is not a subbunch of rcs, leah will never be appended to foo. This might occur if you were sloppy cutting and pasting.
This is the current list of allowed values for the stanza names. The Nikola Team will add new values as the need arises. So, for example, when RedHat software releases Red Hat 8.0 and if we decide that we will support it, then we will add the values rh80_ia32, rh80_ia64, rh80_alpha.
Parameter name |
datatype |
Usage or meaning |
testing/comment |
---|---|---|---|
generatedby |
string |
Required. A free form string which identifies how this file was made, including possibly the person who did it, the software that did it, the time it was done, what machine it was done on. |
You could put the $id$ tag here if the control file is under RCS or CVS control. See rcsintro(1)
or co(1) for details. |
gid |
String or integer |
Required. The group ID of the generated file |
Must be in the group NIS map or in /etc/group |
masterfile |
string |
Required. The name of the source master file |
Must either be in form filename.master or filename@dbname (@dbname is not supported in Nikola 1.0) |
perms |
permission |
Required. The protection of the generated file |
Must be a 3 or 4 digit octal number |
production |
bool |
Required. Must be yes for nugget to be installed. Only valid in main or 'duty test' stanzas. |
|
uid |
String or integer |
Required. The user ID of the generated file |
Must be in the password NIS map or in /etc/passwd |
filename |
string |
Optional. Overrides the nuggetname as the name of the resulting file. source files must be named after the target file, not the nugget name. |
|
delete |
bool |
Optional. N (default) says not to delete this nugget |
|
keepold |
bool |
Optional. Y (default) says to keep the previous file as .old. |
|
nver |
string |
Optional. nikola version string. |
|
prefile |
string |
Optional. The file to prepend to the target file. |
|
preproc |
string |
Optional. File(s) to execute before the configuration changes are made |
Must be a file that exists, is readable and executable by root |
postfile |
string |
Optional. The file to postpend to the target file. |
|
postproc |
string |
Optional. File(s) to execute after the configuration changes are made |
Must be a file that exists, is readable and executable by root |
Data types understood by the nikola database include:
Datatype |
Description of values |
---|---|
boolean |
0,f,F,FALSE,False,N,No,no or 1,t,T,TRUE,True,Y,Yes,yes |
integers |
Unsigned integers from 0 to machine range. If it begins with 0x then it is expressed in base 16; if it begins with one or more leading zeros, then octal; otherwise base 10. Numbers outside of the range are signaled as errors. |
permission |
Standard UNIX 12 bit permissions expressed as an octal number (see chmod(1) for details) |
String |
Allow White space? Double Quotes? |
IP address |
A 32 bit number, expressed either as 4 base 10 numbers, 0 to 255, separated by periods (preferred); or as an integer. Use of this data type is highly discouraged. |
Date or time |
A string in the format of the date command (see date(1) for details). [MMDDhhmm[[CC]YY][.ss]] where MM is the month (0..11), DD is the day of the month (1..31, depending on month), hh is the hour of the day (0..23), mm is the minute of the hour (0..59), ss is the second (0..59), CC is the century (should be 20) and YY is the year of the century. I experimented with the formats that date uses, and it is inconsistent. Date also refers to RFC-822 and ISO-8601. |
|
|
The Master Controlfile Processor (MCP) program accepts a control file and some switches and emits key/value pairs appropriate for further processing.
The usage of the MCP is:
mcp -c controlfile -b bunch -d duties -n narch [-v]
mcp -h | --help | -V
mcp -H hostname | --host hostname -c controlfile
where:
controlfile is the name of the control file as described above.
bunch is the name of a group of computers. Subbunches are appended to the bunch with a period, e.g. rcs.gnl
duties is a comma separated list of duties.
narch is an architecture from the list above.
-v run verbosely. This is most commonly used for debugging
hostname is the name of the host for which we wish to run this controlfile. The mcp will lookup the parameters in a database and use them instead of the command line switches. This will be implemented in a future version.
EXAMPLE
mcp -c ted -b vlsi.mtml -d workstation,time -n sol8-sparc -v
would read the control file ted nugget and process it for the vlsi bunch and mtml subbunch; generating
all of the outputs required for a workstation and a timeserver running on a SPARCstationTM, Sun Microsystems
running Solaris version 8.
mcp -H truk -c genetic In version 2, this will lookup truk in the nikola host database and generate all of the outputs required based on the input genetic nugget.
mcp -c $NUGGET -b `cat /var/nugget/bunch` -d `cat /var/nugget/duties` -n `cat /var/nugget/arch` -v
This would read the control file in the shell variable NUGGET and process it according the bunch and duties
in the files in /var/nugget. This idiom would probably go in a script and would be run on many different
machines without changes.
Copyright (c) 2001, University of Washington, UW/EE