Tags:
create new tag
view all tags

Introduction to LCFG : Part 3

The following examples assume you are using the virtual appliance described in IntroductoryTutorial.

The LCFG Environment

The first step is to familiarise yourself with the LCFG environment. Typically a machine will just be running the LCFG client (rdxprof) but in the case of the teaching environment it's a self-contained self-hosting LCFG environment so there is also an LCFG server (mkxprof) running.

To check the status of these two services and monitor what they are doing you should check the logs in /var/log/lcfg. Start a couple of terminal windows and watch the files using the tail command like this:

tail -f /var/log/lcfg/server

and

tail -f /var/log/lcfg/client

Note, if you want to finish tailing a file you can just use ctrl-c to close the process.

When you make a change to any input file (profile, header or package list) the LCFG server will spot the modification, it has an internal database of dependencies for files which it uses to trigger rebuilds of all affected profiles. A change will first appear in the server log and then a few moments later in the client log.

Open a third terminal window and move to the /var/lib/lcfg/conf/server, listing that directory will show a number of sub-directories including:

cd /var/lib/lcfg/conf/server
ls

  • defaults - schema files for the components
  • include - headers for various options
  • packages - package lists
  • source - source profiles

In the source directory there is a single profile, named lcfg-tutorial, this is a plain text file which controls the configuration for the virtual machine. All the examples will be based around modifying that file. Look at the profile:

cat source/lcfg-tutorial

The profile should look like:

/* Basic example profile */

#include <local/os/ubuntu/minimal_focal.h>
#include <lcfg/hw/virtualbox.h>
#include <lcfg/options/desktop.h>
#include <lcfg/options/lcfg-server.h>

!profile.comment mSET(my first change)

/* eof */

This describes a machine which is using a minimal lcfg configuration for a desktop running Ubuntu Focal Fossa in a Virtualbox environment. One extra option has been enabled to include the LCFG server service.

As an example the value for a single resource has been mutated.

All the included files can be found in the server include directory. The local directory has been added to make it easier to work through examples without messing with the standard lcfg headers. The local/os/ubuntu/minimal_focal.h we're using is a thin wrapper around the standard lcfg/os/ubuntu/minimal_focal.h header, this is how most sites will use the lcfg headers, for example in Informatics we have dice/os/ubuntu/focal.h. This OS header enables the minimal environment and sets some ACLs which are required for the server to allow access to the client XML profile. Just ignore the local/site.h file, it's there to satisfy some requirements in the headers, we won't be exploring that file but every site will have one, for example in Informatics we have dice/options/inf-site.h

The source profiles and headers use the C Pre Processor (cpp) to handle the inclusion of additional files. Anything between the /* and */ markers is a C-style comment, note that comments beginning with a # are NOT supported as that character is already used by cpp for its directives.

A minimal LCFG environment means that it is not responsible for the management of the entire configuration of the system. There will only be a small number of LCFG components, in particular we will be looking at sysinfo, client and file components.

To see a full list of the components which are registered in the profile use the qxprof utility. This tool queries the components and resources stored in the LCFG client database.

qxprof profile.components

You can also try using the -v option to get more information:

qxprof -v profile.comment

profile.comment:
   value=my first change
    type=default
  derive=/var/lib/lcfg/conf/server/source/lcfg-tutorial:8

You can see that the client knows the resource type and derivation information (file and line number) as well as the value.

You can see all possible resources for a component by just passing the name of the component to qxprof, for example:

qxprof sysinfo

If you have access to a standard LCFG environment then why not try this there as well? If it doesn't work then you are probably not in the lcfg group, add yourself to that group, logout and back in again and you should have access.

See the qxprof(8) manual page for further options which you may find useful.

Status Pages

The LCFG server provides a set of status web pages which are useful when debugging problems with profiles.

In the virtual appliance start a web browser (e.g. firefox) and go to http://localhost/cgi/index.cgi

The index page lists all known profiles, where there is an error you will see a red bug icon. Following the link for the profile will give a status page which summarises the state of the components on the machine and shows various other information including a description of any errors.

First Change

To modify the source profile you will need a root shell, you can get that using sudo, like this:

sudo bash

Edit the file using your favourite editor (e.g. emacs), if you want you can install another editor using the apt tool.

Make a change to the text inside the brackets for the profile.comment resource, save the file and watch what happens in the server and client logs. Once the change has reached the client you should use qxprof to verify for yourself that the change really has happened.

If you're happy with that then you could go on to try a few other mutators instead of the mSET, what can you do with mADD, mEXTRA, mSUBST?

Note that it is strictly only necessary to mutate the value when it has already been set but since it's often quite hard to know whether or not a resource has previously been defined it's common to just always use mutators.

Order of resource changes

The LCFG server processes profiles and headers from top to bottom working through all of the files from the first #include statement, then the next in turn until the end of the profile is reached. Modifications which appear later in a file will override earlier settings.

Try a combination of a few mutations, something like:

!profile.comment mSET(one)
!profile.comment mEXTRA(two)
!profile.comment mADD(one)
!profile.comment mADD(two)
!profile.comment mREPLACE(two,four)

Save the file, watch the changes in the server and client logs and then use qxprof to query the result.

Resource references

One particular useful feature is that the value for a resource may contain a reference to another resource value. This avoids duplication of data and makes reuse of headers easier since an administrator only has to change one value for all related settings to be changed.

A reference is made using a pair of delimiters like <% and %>, note that the server does NOT allow spaces in the reference block. For example:

!profile.comment mSET(This machine is running <%sysinfo.platform%>)

Again save the file, watch the server and client logs and then query the resource using qxprof. You should see:

comment=This machine is running ubu2004

It is important to note that the reference is resolved as late as possible. This can occasionally have surprising results. What value is produced here?

!sysinfo.location mSET(AT-7.10)
!profile.comment mSET(This machine is located in <%sysinfo.location%>)
!sysinfo.location mSET(AT-7.12)

Usually this will be what you want but occasionally you will really need to store the current value, in that case use the <%% and %%> delimiters (note the double percent signs). These beasts are rare and hardly ever spotted in the wild.

Resource Validation

Some resources have types which describe the valid values which may be specified. The standard ones are:

  • integer
  • boolean
  • string with regular expression matching
  • LCFG tag list

If you specify an invalid value the server will show an error in the log and it will NOT rebuild the profile.

Strings

For example, the sysinfo.criticality resource may only be set to one of the strings low, medium or high. Try setting it to an invalid value to see what happens:

!sysinfo.criticality          mSET(ultra)

In the server log you will see there is an error but that does not give any hint as to what caused the problem. You can find that information from the status web pages

Booleans

For boolean values you may use true, false, yes, no, off and on they will be translated to yes for a true value and the empty string for a false value.

One slightly surprising side-effect of false values being represented as an empty string is that qxprof does not show them when you list the resources for a component. To see all possible resources including those with no value use the -a option, for example:

qxprof -a client

The main benefit of it being an empty string for false is that the value is then easy to test as part of a conditional in programming languages like Perl and bash.

Tag lists

With an LCFG tag list you must only add tags which contain alphanumeric and underscore characters. For example foo_bar is acceptable but foo-bar is not. Try this example and see what you get in the logs:

!sysinfo.paths mADD(foo-bar)

You will see that the server does not throw an error (it should) but the client does, there is a slight inconsistency in the validation which will be rectified at some point...

Working with Tag Lists

One of the more confusing aspects of working with LCFG resources is tag lists. These effectively allow for the creation of more complex data structures, you add a tag to the list and then specify a number of related sub-resources.

Here's a simple example which defines an additional system path in the sysinfo component:

!sysinfo.paths               mADD(tmpdir)
sysinfo.path_tmpdir      /tmp

Note that you have to mutate the sysinfo.paths resource but, since the sysinfo.path_tmpdir resource has not previously been defined, you do not need to use a mutator, any subsequent change would need a mutation though.

-- squinney - 2021-03-19

Topic revision: r2 - 2021-03-22 - squinney
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback