This document was last modified

Nuggets: System File Management

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.

Typographical conventions

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.

Some major facets of nuggets worth discussing:

  1. Prerequisite Host-level Variables
  2. Nugget Organization
  3. The Nugget Control File
  4. Configuration Parameters

Prerequisite Host-level Variables

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.

Nugget Organization

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

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.
}

The format of the nugget control file

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 inner meaning of stanzas

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 readignoredignoredignored
bunch rcs.rrsl readreadignoredignored
bunch rcs.rrsl.radar readreadreadignored
bunch rcs.dcl ignoredignoredignoredread

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.

Configuration Parameters

Stanzas

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.

Stanza Name

Number of matches

Allowed values

comments

nugget name

1


The name of the file this nugget creates

arch name 1

rh71-ia32

RedHat 7.1 on Intel Pentium family

rh71-ia64

RedHat 7.1 on Intel Itanium

rh71-alpha

RedHat 7.1 on DEC Alpha

Solaris8-ia32

Sun Solaris 8 on Intel Pentium

Solaris8-ia64

Sun Solaris 8 on Intel Itanium

Solaris8-sparc

Sun Solaris 8 on Sun SPARC and UltraSPARC

SuSE73-ppc

SuSE Linux 7.3 on PowerPC (RS/6000)

aix433-ppc

IBM AIX 4.3.3 on PowerPC (RS/6000)

bunch name

0 or 1

RCS

subbunches are GNL, RRSL, BRL, DCL.
RRSL has a subsubbunch: radar
In other labs, the machines can be distingushed by their duties.

SSLI

subbunches are orca, music

VLSI

subbunches are ACME, CAD, analog, madtest, mtml, mtml.tahoe

duty name

0 or many

workstation


afsserver


backupserver


bbdisplayserver


bbpagerserver


commserver


computeserver


dhcpserver


fileserver


firewall


imapserver


ircserver


infrastructure

Logins restricted by Unix group membership

jumpstartserver


kickstartserver


lab


ldapserver


licenseserver


logserver


nameserver


mysqlserver


nismasterserver


nisslaveserver


ntpserver


peepserver


popserver


printserver


rtserver


smbserver


smtpserver


test


webserver




Nugget control file parameter list

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
IP address list

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.



Master Controlfile Processor (MCP) Program

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