Object Oriented System Management

Table of Contents

1. Overview
Object Oriented Infants
Object Model under Unix
The Implementation
Provided facilities
Example Object
The prompt command
Usage Scenarios
Related work
2. Further reading
3. Links

Chapter 1. Overview


Examples added


The project is in an early stage and you will probably not be able to compile it easily or use it for significant work. There are lots of things which are not documented yet, as they only work occasionally ;). As the current written code is only a framework, no real application of it yet exists, there are still much things to invent. Get involved.


This software package represents a meta program used to manage unix programs. It is a class library in the domain of system administration. It is similar to Microsoft .NET or corba or Unix as it is language independent. Indeed, a method can be written in any language, because the interface of a method is the same as that of a unix command. That means a method is passed an array of arguments, it has a standard input, standard output and standard error channel and returns a small integer exit code. The difference to a shell script is that there is no actual execve system call involved in calling a method, but the method is in a shared object that can be linked dynamically into the running process. With interpreted languages like perl, first the interpreter is dynamically linked into the current process which in turn executes the method written in the target language. That means that the second call of a certain method only involves some lookup in internal data structures to find the already loaded (c++, perl) and byte-compiled (perl) implementation.

But this is only half of the story. The power of object orientation to a certain degree comes from the fact that you have abstract interfaces and concrete implementations which are interchangeable to a certain extend. This fact is still true of course, when you map the OO paradigm to the Unix shell and the domain of system management. But unfortunately this principle was not honored by the software that exists on posix compatible systems so far. An example of an interface relating to system management and configuration is internet server software configuration. There a many ways to configure on which port a piece of software should listen. In apache, you write Listen or BindAddress, the tcpserver from ucspi-tcp expects a command line argument, the inetd superserver expects it as the first column of a table in a free-form textfile. It is therefore impossible to know where an arbitrary server listens if you do not write specialized parser code for every configuration file format in existence. It would be so much easier to have an interface that has a method called port that you can call to either query the port or set it. Then you can call the exact same method on any server that implements the interface and don't have to care about syntax rules. That's a common concept to an OO Programmer. Forum

Object Oriented Infants

There are some examples of object oriented concepts in current unix software that move towards object orientation. These approaches have two problems. First, they are developed by different designers and do not share a common model or structure. Second, they only implicitely implement an object model and do not provide things that are a common good in the OO world such as reflection or a meta class protocol. I will give examples on such implicit OO patterns found in current unix software.

The debian distribution offers kind of meta programs that one uses to configure the system in turn. One example is the update-inetd that adds, removes, disables or enables an internet server in your system and takes care of the difference between an xinetd configuration and an inetd configuration. One uses the exact same command regardless of the superserver used.

The apache web server and the proftp server share the same configuration file format. One uses the same syntactical constructs to configure features that both software systems equally provide, such as port configuration. Or seen the from the other side, the apache web server and the proftp server are two implementations of the same interface, which is the apache-style configuration file format.


Object Model under Unix

This section describes the Object Model in its only existing current implementation, as a posix application.

A method call can be made from the shell prompt, simply by typing the name of the method and arguments. Indeed, unix is already object oriented, because one can type pwd to get the current directory. Seen the object oriented way, the user just called the method pwd on the object that corresponds to the current directory. If we see directories as objects, in the standard unix model, every object would be of the same class, as the set of methods that can be called is the same, independent of the current directory. Of course this is not entirely true, because the command make would behave differently depending on the current directory. It depends on a file called Makefile. So one can see a directory containing a Makefile to be of the class that has a make method in its interface specification.

Now consider changing the PATH environment variable depending on information from the current directory. There exists an environment variable called PROMPT_COMMAND in the bash, that calls a command everytime a prompt is printed. Other shells have similar facilities. When there is a directory called .methods in the current working dir, then one can simply add $(pwd)/.methods to the current PATH environment variable to change the set of commands/methods that can be executed.

To make the previous paragraph clear, look at the fact, that even completions depend on the current object you are in, because you have another set of methods that you can call, you get some completions for them installed in the shell. These are removed as soon as you change your current object (cd to another direcotry). This installation of completions is of course done only, when the object is accessed via the shell on an interactive console.

The object model is comparable to javascript, because it is prototype based and does not make a distinction between class and object. But certain objects can be more used as a class than certain others just by not setting variables in them but using them only as a provider of methods.


The Implementation

There exists an implementation with a C++ core that can execute methods written in C++ efficiently (by loading a shared object), and also perl (by loading libperl.so dynamically) and javascript (by loading libmozjs). Methods can still be written in any language as long as it is possible to call execve(2) on some file.

It is possible to store the class data (superclass list, etc.) in a directory. It will be possible to store multiple classes in a single file, the implementation exists and has still bugs that make in unusable. Objects do not even need to be stored on disk, but can be created in RAM only by using a ramdisk, that is implemented using LD_PRELOAD and overrides stdio syscalls such as fopen, fread, fwrite, fseek. So it is possible to generate a bunch of objects from a /etc/fstab or /etc/passwd file on the fly and treat its contents as normal objects. The implementation for this feature exists but is still buggy.

There are different ways to store the variables of a class, one can write them into a file in the object directory or store all variables of all objects in a single flat file or dbm file. An sql schema will not exist unless one finds a reason to use a full blown database. An XML backend should be implemented, too.

Variables are simply methods that modify a backend store if called with extra arguments or print out a value from that backend store if called without extra args. Vector types support add, del, count, find and other operations. Table types support a limited subset of the semantics of SQL (WHERE clauses, field selection), but the syntactical interface is not SQL compatible and much less powerful.


Provided facilities

The processing and compilation of method source files is handled by the framework. If the method source is well-formed, it is usually enough to execute compile-method <method-name>. In the more complicated case one has to write a class that handles the pecularities of a language to make the above mentioned possible. Adding a language is as easy as defining some file extensions and writing a method that generates a makefile that conforms to some specification of required make targets.

There is a reflection interface used to iterate through the methods and variables of a class and list their properties.

There is a navigation interface that allows you to do some tree operations on a tree of objects, such as finding siblings, children and ancestors. It is similar to xpath but of course much simpler.

Variables come in different types. These are for example string, vector, table, boolean.

Example Object

$ ls universal
drwxr-xr-x  11 sascha sascha  408 2005-07-21 18:51 .
drwxr-xr-x  30 sascha sascha  976 2005-07-20 11:00 ..
-rw-r--r--   1 sascha sascha  171 2005-07-07 21:20 .bmember
stores boolean variables
-rw-r--r--   1 sascha sascha  205 2005-06-26 21:21 .clsdesc
the class documentation
drwxr-xr-x   3 sascha sascha  136 2005-06-28 11:27 .fmember
stores vector and table variables
drwxr-xr-x   4 sascha sascha   96 2005-05-24 23:07 .garbage
abandoned source files are put here
drwxr-xr-x   4 sascha sascha   96 2005-05-24 23:07 .include
include files used by more than one method
-rw-r--r--   1 sascha sascha  112 2005-07-20 10:34 .inherit
the list of superclasses
drwxr-xr-x   3 sascha sascha  592 2005-06-11 05:25 .methdsc
method documentation
drwxr-xr-x   3 sascha sascha 3,2K 2005-07-31 09:37 .methods
compiled methods
drwxr-xr-x   7 sascha sascha  168 2005-07-14 17:02 .methsrc
method source files
drwxr-xr-x   3 sascha sascha  104 2005-07-06 11:34 .varidsc
variables documentation

The prompt command

The prompt command is a way to make the methods of the current object accessible in the shell. These shell commands are executed every time the current directory is changed. For example:
$ prompt
export DATADIRS="/home/sascha/dispatch/dispatch/core/docbook:/home/sascha/dispatch/dispatch/core-classes/universal:/home/sascha/dispatch/dispatch/core-classes/Universal/variable:/home/sascha/dispatch/dispatch/core-classes/Universal/navigation:/home/sascha/dispatch/dispatch/core-classes/Universal/reflection:/home/sascha/dispatch/dispatch/core-classes/Universal/loader:/home/sascha/dispatch/dispatch/core-classes/Universal/abbrev:/home/sascha/dispatch/dispatch/core-classes/methsrc:/home/sascha/dispatch/dispatch/core-classes/Methsrc/abbrev:/home/sascha/dispatch/dispatch/core-classes/operator:/home/sascha/dispatch/dispatch/core-classes/documentation:/home/sascha/dispatch/dispatch/core-classes/Documentation/builder:/objects/autoconf";
export DISPATCHPATHS="/home/sascha/dispatch/dispatch/core-classes/universal/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/variable/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/navigation/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/reflection/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/loader/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/abbrev/.methods:/home/sascha/dispatch/dispatch/core-classes/methsrc/.methods:/home/sascha/dispatch/dispatch/core-classes/Methsrc/abbrev/.methods:/home/sascha/dispatch/dispatch/core-classes/documentation/.methods:/home/sascha/dispatch/dispatch/core-classes/Documentation/builder/.methods:/objects/autoconf/.methods";
export DISPATCH_CWD="/home/sascha/dispatch/dispatch/core/docbook";
export PATH="/home/sascha/dispatch/dispatch/core-classes/universal/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/variable/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/navigation/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/reflection/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/loader/.methods:/home/sascha/dispatch/dispatch/core-classes/Universal/abbrev/.methods:/home/sascha/dispatch/dispatch/core-classes/methsrc/.methods:/home/sascha/dispatch/dispatch/core-classes/Methsrc/abbrev/.methods:/home/sascha/dispatch/dispatch/core-classes/documentation/.methods:/home/sascha/dispatch/dispatch/core-classes/Documentation/builder/.methods:/objects/autoconf/.methods:/home/sascha/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games::/sbin:/usr/sbin:/usr/local/sbin";
if [ "$DISPATCHCOMPLETIONS" ]; then for c in $DISPATCHCOMPLETIONS; do complete -r $c; done; unset DISPATCHCOMPLETIONS; fi;
complete -C /home/sascha/dispatch/dispatch/core-classes/universal/.methods/complete-class @;
complete -C /home/sascha/dispatch/dispatch/core-classes/universal/.methods/complete-class cdo;
complete -C /home/sascha/dispatch/dispatch/core-classes/methsrc/.methods/complete-method-source cm;
complete -C /home/sascha/dispatch/dispatch/core-classes/methsrc/.methods/complete-method-source compile-method;
complete -C /home/sascha/dispatch/dispatch/core-classes/methsrc/.methods/complete-method-source source-cache-file;
complete -C /home/sascha/dispatch/dispatch/core-classes/methsrc/.methods/complete-method-source source-file-name;
complete -C /home/sascha/dispatch/dispatch/core-classes/documentation/.methods/complete-manpage oman;
complete -C /home/sascha/dispatch/dispatch/core-classes/documentation/.methods/complete-manpage edit-manpage;
export DISPATCHCOMPLETIONS="@ cdo cm compile-method source-cache-file source-file-name oman edit-manpage";

You can see a list of paths in the DATADIRS variable. These are the objects that add up to your current object. They are written in descending order, from subclass to superclass, with the current object being the first path in the list. The paths list is actually a flattened tree: multiple inheritance is supported.

DISPATCH_CWD is redundant and is still used but deprecated.

The PATH variable is important to understand the concept of the method dispatch. You can see paths in this list that have the same base name as those in DATADIRS, but with a .methods directory added. When there is no .methods directory, that object occurs in the DATADIRS, but not in the PATH.

DISPATCHVARS lists all modified variables again and is probably redundant

DISPATCHCOMPLETIONS lists the currently installed completions and is probably not redundant, because as you can see it is actually used to wipe out all old completions, before installing new ones.


Usage Scenarios

The method@ object method [ args ] is used to invoke a method of an object that is not the current directory. It is roughly equivalent to cd object; method [ args ]

Most examples are not implemented yet.

$ @ Apt/stable install foopackage # call apt-get -c=... install foopackage

$ @ grub timeout 23 # change the timeout value in the grub configuration file

$ @ grub/linux-2.6.17 root '(hd2,3)' # set the root option of a specific grub entry

$ @ apache/inet port 80

$ @ proftpd/inet port 80

$ @ tty noecho

$ @ /etc/inetd.conf/telnet user baruser

Related work


elektra.sf.net is a project with a narrower scope, because it only supports variables in its namespace, so it does not allow methods and it has no explicit classes. It is uncertain to which level namespaces are unified (whether there are abstractions), because there are no classes. Also, elektra uses a configuration file format of its own, which is windows .ini look-alike and must convert the system config before it can be used. Furthermore all applications that want to use the elektra configuration data must be patched.


config4gnu does not have many of the drawbacks of elektra. It parses the original configuration files and does not introduce a new file format. It is a proper 3 tier application framework, with a big virtual xml file at the middle layer, config file parsers at the bottom layer and different frontends (shell, gui). It does not support method calls and it also has no explicit classes, but some kind of meta-data description.


Debconf is rather limited as it only provides a few "famous" configuration settings for a package and there is no way to read out those values when one does not parse the generated configuration himself.


Webmin is html only. There is no middle layer, no way to use functions of it in shell scripts other than including some perl parsing library and calling functions from it. There are no explicit classes. But there are _lots_ of config parsers written in perl that could be reused if licence permits.


Chapter 2.  Further reading

There is a paper i wrote for my upcoming talk at the Chaos Communication Congress. I also created some slides for the same talk. There are classes and methods that deal with documentation. To view the documentation of a given method or variable just call the method oman, which probably boils down to running the command oman clsname in the shell (to view the documentation for the clsname method, which is available in every object as it is from class universal). When you run oman without arguments, you get a man page for the current class. So you can run @ Universal/reflection oman to get a documentation for that class.

Chapter 3.  Links

Sourceforge Project Page - including forums, cvs, tarballs, news, etc.