Mount Linux Olympus - Remote File Interface README

Andy Kopciuch <akopciuch@mountlinux.com>

2000-11-19 v1.0


This document describes the public the design of the Remote File Interface for the Olympus open source administration system sponsored by Mount Linux.

1. Overview

2. Remote File Interface XML

3. The remoteFileInterface class


1. Overview

The goal of this README is to provide comprehensive documentation of the design and API used for the Remote File Interface provided by the Olympus client.

It is recommended that developers using the Remote File Interface:

The purpose of the Remote File Interface is to provide a system independant method for the Olympus client to be able to request a configuration file, modify it and commit the changes made. The retrieval and commitment of the system file is handled transparently by the Olympus network protocol. The system independant design is implemented using XML files to describe the information in a given type of file (for example all network interface configuration files). The modifcation of the information is accomplished using the remoteFileInterface class and its helper classes.

This document will describe the public interface to the remoteFileInterface class. Please see the other documentation for additional help on other important Olympus tools such as the plugin and commandXML classes.


2. Remote File Interface XML


2.1 Overview

The Remote File Interface uses XML descriptions of the information contained in the configuration files on a server. This section will describe the syntax of the XML, and the files used by the classes.

These XML description templates are used to maintain the platform independance of the Olympus software. With these description templates it is possible to outline what information is in a system file. If differences from system to system exist, this can be defined within the XML. The Remote File Interface will search for the informattion descibed in the XML template. If the information exists, it will wil be extracted.

The system independance comes from the use of an XML implementation (which is described in section 2.2) and by the Olympus database. This will make it possible for a client to request the information from a server, based on a generic XML template. The server will return the proper file from the database, and the information can be extracted based on this XML definition.

The abitilty to extract information based on a generic description will also allow us to make configuration changes to a system regardless of the platform being used. The client never needs to know what kind of server it is connected to.


2.2 XML Syntax

Please refer to the Config XML Syntax documentation for information pertaining to XML syntax.


2.3 .rfi files

The XML, as described in the Config XML Syntax documentation, needs to be located somewhere the Remote File Interface can access it. Each description of a system file will be stored in a .rfi file. The name of the file reflects what the XML describes. The example XML description is from the file "networkInterfaces.rfi". Another example would be the files: "services.rfi" and "inetd.rfi" used by the inetd plugin to determine the services.

All .rfi files are stored in the Olympus source tree in the directory: olympus/data/rfi/. Any changes to these files will only take affect when the source distribution is re-installed.

When a make install is completed, all .rfi files can be found in the directory: /usr/local/olympus/rfi/. This path is the default for all .rfi files. Any .rfi file can be overridden by one found in your home directory: ~/.olympus/rfi/. When the Remote File Interface is being used, it will use the .rfi in your home directory if it exists, and the distributed copy if none exists in the home directory.


3. The remoteFileInterface class


3.1 Overview

The remoteFileInterface class inherits from the plugin base class. This inheritance provides use of the network. RFI is not an actual "plugin", it just uses some of the functionality offered to plugins.

RFI makes use of the network by using the nmFetchFile netmessage, and the nmPutFile netmessage. These netmessages are used in the same way as they would be in a regular plugins, namely to handle in a system neutral manner which system file is used for a specific feature.


3.2 Creation

The remoteFileInterface object has only one constructor.

The users of RFI must create the object by passing a pointer to a host object, and the name of the .rfi file to be used. The path to the directory of .rfi files is already known. The home directory file is given preference over the distribution if it exists.

For example to create an RFI object for interface connections:

When a remoteFileInterface object is created. The XML template is opened and parsed. The parsing of the XML may cause several exceptions which are handled. A QMessageBox is displayed if any problem occurred during the XML parse. A signal called doneXML() is emitted when the parse is complete. This signal does not need to be connected to a slot. If extra processing is required when the XML desciption has beeen formed it may be useful to implement a slot for this signal, but is not mandatory.


3.3 Operation

After creation, the remoteFileInterface object is ready to do it's work. The tasks this class is repsonible for are:

  1. Parsing the XML template (networkInterfaces.rfi).
  2. Storing the XML description information. (xmlDefinition class)
  3. Requesting the relevant system file(s). (nmFetchFile class)
  4. Parsing the system file based on the XML description.
  5. Storing the system file data. (parsedElement class)
  6. Allowing access to the system file information. (viewing, modifying, removing)
  7. Requesting the modifcations of the system file to the server. (nmPutFile class)

Once the RFI object has been created, the start method can be called:

The start method will take four optional parameters: The mask used to retrieve files, whether the file should be expanded if it is a link, and the keys used to retrived files from the database.

The file mask is defaulted to *. This means all files matching will be returned. If any specific file is needed, it can be stated for this parameter. The default behaviour is to not expand links. You may have no idea what the link points to. The database keys a pre-defined within the XML template. If for any reason you want to override the default keys thay can be specified in the start command.

In a nutshell RFI will determine which keys to use in the nmFetchFile request. The COMMAND_FETCHFILE is created and sent to the server asking for the proper files matching the mask, and with proper link expansion. When the netmessage has returned success there are a few things that happen:

Plugins using the remoteFileInterface must create a slot to handle the signal of a file being returned from the server. If there is not slot implemented/connected to the fileRetrieved(), it will not be possible to know when/if you have a file to parse, or when you can parse it.

Now that the XML description is available, and when have a system file, we have two pieces of the puzzle and can make the third. We can now parse the system file based on the XML, and store all of the information.

This method is defined as virtual in the case that any subclass of remoteFileInterface can override the parse method to operate in another manner. This method will do some magic things.

The file is read into one large buffer. One pass is made through the buffer recording all points of a defined XML type from the .rfi. The XML template describes the types with regular expressions. The regular expressions are searched in the buffer and we can then cycle through each expression found and validate it's type and all XML description attributes.

The end result of the parse() method is that each XML element that is found in the system file is stored in a parsedElement * object. The remoteFileInterface class stores a linked list of all of the parsedElement objects created . This list retains the order of the elements as they were found in the system file.

Each parsedElement object is stored based on it's name and value. In an interface configuration, the DEVICE=lo for the loopback configuration, would probably be stored as a type "device" and has a value of "lo".

If there is data in the system file that cannot be reckognized as a valid defined type, it is stored in the list as a special type: "unparsed". All information from that point to the beginning of the next valid element would be stored in one parsedElement object with a name "unparsed".

The remoteFileInterface offers several methods to perform operations upon the linked list of parsedElement objects:

These methods are standard linked list operations. Adding an element to the end of the list, adding an element to the front of the list, inserting an element to one position after the current element, removing the current element from the list, getiing the element at the front of the list, and getting the element at the end of the list

The subscripting operator has been overloaded in the remoteFileInterface class twice. This will provide the functionality of direct element access to the list of parsed elements.

The subscript operator accepting a single const char * will search the list for a element which has a name that matches the request. Because the list is of parsedElement objects the remoteFileInterface subscript operator will return a refernce to a parsedElement. The subscript operator has also been overloaded for the parsedElement class. This allows direct element access to an elements sub-elements. The operators return a reference to an object so the subcripting can be streamed together like this:

The subscript operator will return the first occurance of a matching element. If the XML definition states that there can be multiple instance of an element (multi="true"), then the second overloaded subscript operator must be used.

In C++ subscripting operators can accpet only one parameter. In the case of multiple existing elements, we must match a name and a value. This is accomplished by using a pair object as the parameter. The operator can be given the values as follows:

This direct element access will allow users of RFI to manipulate the data in the list. For example you could change the order of the elements by using the setPrevious(), and setNext() methods from the parsedElement class. Accessors exist for all information, the name, data, beginning, and ending. Elements/sub-elements can be added or removed. The documentation for the parsedElement class will describe the actions in detail.

There are also a few convenience methods in the remoteFileInterface class for manipulation of elements:

The getCount() method will return the number of elements found matching a name. The getElements() method will return a vector of all elements matching a particular name, and the setUnparsed() will set a given element and all of it's sub elements to be unparsed.


3.4 Multiple Files