Writing A Client Tool Driver

This page describes the step-by-step process of writing a client tool driver for a configuration element type. The included example describes an existing driver, and the process that was used to create it.

  1. Pick a name for the driver. In this case, we picked the name RPM.

  2. Create a file in src/lib/Bcfg2/Client/Tools with the same name (RPM.py)

  3. Create a class in this file with the same name (class RPM)

  4. Add any required executable programs to Bcfg2.Client.Tools.Tool.__execs__

  5. Set Bcfg2.Client.Tools.Tool.__handles__ to a list of (<tag>, <type>) tuples. This determines which entries the Tool module can be used on. In this case, we set __handles__ = [('Package', 'rpm')].

  6. Add verification support by defining a method named Verify<tag>. See Bcfg2.Client.Tools.Tool.Inventory() for details. This method should return True/False depending on current entry installation status. In the failure path, the current state of failing entry attributes should be set in the entry, to aid in auditing. (For example, if a file should be mode 644, and is currently mode 600, then set attribute current_mode=‘600’ in the input entry)

  7. Add installation support by defining a method named Install<tag. See Bcfg2.Client.Tools.Tool.Install() for details. This method should return True/False depending on the results of the installation process.

    If you are writing a tool to handle Package entries, PkgTool class has a generic mechanism for performing all-at-once installations, followed, in the case of failures, by single installations. See Bcfg2.Client.Tools.PkgTool.Install() for details.

  8. Optionally, add support for removing extra entries by defining a Bcfg2.Client.Tools.Tool.Remove() method.

  9. Optionally, add a Bcfg2.Client.Tools.Tool.FindExtra() method that locates entries not included in the configuration.

  10. Package drivers require a Bcfg2.Client.Tools.PkgTool.RefreshPackages() method that updates the internal representation of the package database.

Client Tool API

Base Classes

class Bcfg2.Client.Tools.Tool(config)[source]

Bases: object

The base tool class. All tools subclass this.

__execs__ = []

Full paths to all executables the tool uses. When the tool is instantiated it will check to ensure that all of these files exist and are executable.

__handles__ = []

A list of 2-tuples of entries handled by this tool. Each 2-tuple should contain (<tag>, <type>), where <type> is the type attribute of the entry. If this tool handles entries with no type attribute, specify None.

__req__ = {}

A dict that describes the required attributes for entries handled by this tool. The keys are the names of tags. The values may either be lists of attribute names (if the same attributes are required by all tags of that name), or dicts whose keys are the type attribute and whose values are lists of attributes required by tags with that type attribute. In that case, the type attribute will also be required.

__important__ = []

A list of entry names that will be treated as important and installed before other entries.

Parameters:config (lxml.etree._Element) – The XML configuration for this client
Raises:Bcfg2.Client.Tools.ToolInstantiationError
BundleNotUpdated(bundle)[source]

Callback that is invoked when a bundle has been updated.

Parameters:bundle (lxml.etree._Element) – The bundle that has been updated
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
BundleUpdated(bundle)[source]

Callback that is invoked when a bundle has been updated.

Parameters:bundle (lxml.etree._Element) – The bundle that has been updated
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
FindExtra()[source]

Return a list of extra entries, i.e., entries that exist on the client but are not in the configuration.

Returns:list of lxml.etree._Element
Install(entries)[source]

Install entries. ‘Install’ in this sense means either initially install, or update as necessary to match the specification.

This implementation of Bcfg2.Client.Tools.Tool.Install() calls a Install<tag> method to install each entry, where <tag> is the entry tag. E.g., a Path entry would be installed by calling InstallPath().

Parameters:entries (list of lxml.etree._Element) – The entries to install
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
Inventory(structures=None)[source]

Take an inventory of the system as it exists. This involves two steps:

This implementation of Bcfg2.Client.Tools.Tool.Inventory() calls a Verify<tag> method to verify each entry, where <tag> is the entry tag. E.g., a Path entry would be verified by calling VerifyPath().

Parameters:structures (list of lxml.etree._Element) – The list of structures (i.e., bundles) to get entries from. If this is not given, all children of Bcfg2.Client.Tools.Tool.config will be used.
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
Remove(entries)[source]

Remove specified extra entries.

Parameters:entries (list of lxml.etree._Element) – The entries to remove
Returns:None
_entry_is_complete(entry, action=None)[source]

Test if the entry is complete. This involves three things:

Parameters:
  • entry (lxml.etree._Element) – The entry to evaluate
  • action (string) – The action being performed on the entry (e.g., “install”, “verify”). This is used to produce error messages; if not provided, generic error messages will be used.
Returns:

bool - True if the entry can be verified, False otherwise.

buildModlist()[source]

Build a list of all Path entries in the configuration. (This can be used to determine which paths might be modified from their original state, useful for verifying packages)

Returns:list of lxml.etree._Element
canInstall(entry)[source]

Test if entry can be installed by calling Bcfg2.Client.Tools.Tool._entry_is_complete().

Parameters:entry (lxml.etree._Element) – The entry to evaluate
Returns:bool - True if the entry can be installed, False otherwise.
canVerify(entry)[source]

Test if entry can be verified by calling Bcfg2.Client.Tools.Tool._entry_is_complete().

Parameters:entry (lxml.etree._Element) – The entry to evaluate
Returns:bool - True if the entry can be verified, False otherwise.
cmd = None

An Bcfg2.Utils.Executor object for running external commands.

config = None

The XML configuration for this client

conflicts = []

List of other tools (by name) that this tool conflicts with. If any of the listed tools are loaded, they will be removed at runtime with a warning.

deprecated = False

This tool is deprecated, and a warning will be produced if it is used.

experimental = False

This tool is experimental, and a warning will be produced if it is used.

extra = None

A list of extra entries that are not listed in the configuration

getSupportedEntries()[source]

Get all entries that are handled by this tool.

Returns:list of lxml.etree._Element
handled = None

A list of all entries handled by this tool

handlesEntry(entry)[source]

Return True if the entry is handled by this tool.

Parameters:entry (lxml.etree._Element) – Determine if this entry is handled.
Returns:bool
logger = None

A logging.Logger object that will be used by this tool for logging

missing_attrs(entry)[source]

Return a list of attributes that were expected on an entry (from Bcfg2.Client.Tools.Tool.__req__), but not found.

Parameters:entry (lxml.etree._Element) – The entry to find missing attributes on
Returns:list of strings
modified = None

A list of entries that have been modified by this tool

name = 'Tool'

The name of the tool. By default this uses Bcfg2.Client.Tools.ClassName to ensure that it is the same as the name of the class.

primarykey(entry)[source]

Return a string that describes the entry uniquely amongst all entries in the configuration.

Parameters:entry (lxml.etree._Element) – The entry to describe
Returns:string
class Bcfg2.Client.Tools.PkgTool(config)[source]

Bases: Bcfg2.Client.Tools.Tool

PkgTool provides a one-pass install with fallback for use with packaging systems. PkgTool makes a number of assumptions that may need to be overridden by a subclass. For instance, it assumes that packages are installed by a shell command; that only one version of a given package can be installed; etc. Nonetheless, it offers a strong base for writing simple package tools.

FindExtra()[source]

Return a list of extra entries, i.e., entries that exist on the client but are not in the configuration.

Returns:list of lxml.etree._Element
Install(packages)[source]

Run a one-pass install where all required packages are installed with a single command, followed by single package installs in case of failure.

Parameters:entries (list of lxml.etree._Element) – The entries to install
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
RefreshPackages()[source]

Refresh the internal representation of the package database (Bcfg2.Client.Tools.PkgTool.installed).

Returns:None
VerifyPackage(entry, modlist)[source]

Verify the given Package entry.

Parameters:
  • entry (lxml.etree._Element) – The Package entry to verify
  • modlist (list of strings) – A list of all Path entries in the configuration, which may be considered when verifying a package. For instance, a package should verify successfully if paths in modlist have been modified outside the package.
Returns:

bool - True if the package verifies, false otherwise.

installed = None

A dict of installed packages; the keys should be package names and the values should be simple strings giving the installed version.

pkgtool = ('echo %s', ('%s', ['name']))

A tuple describing the format of the command to run to install a single package. The first element of the tuple is a string giving the format of the command, with a single ‘%s’ for the name of the package or packages to be installed. The second element is a tuple whose first element is the format of the name of the package, and whose second element is a list whose members are the names of attributes that will be used when formatting the package name format string.

pkgtype = 'echo'

The type attribute of Packages handled by this tool.

class Bcfg2.Client.Tools.SvcTool(config)[source]

Bases: Bcfg2.Client.Tools.Tool

Base class for tools that handle Service entries

Parameters:config (lxml.etree._Element) – The XML configuration for this client
Raises:Bcfg2.Client.Tools.ToolInstantiationError
BundleUpdated(bundle)[source]

Callback that is invoked when a bundle has been updated.

Parameters:bundle (lxml.etree._Element) – The bundle that has been updated
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
Install(entries)[source]

Install entries. ‘Install’ in this sense means either initially install, or update as necessary to match the specification.

This implementation of Bcfg2.Client.Tools.Tool.Install() calls a Install<tag> method to install each entry, where <tag> is the entry tag. E.g., a Path entry would be installed by calling InstallPath().

Parameters:entries (list of lxml.etree._Element) – The entries to install
Returns:dict - A dict of the state of entries suitable for updating Bcfg2.Client.Client.states
InstallService(entry)[source]

Install a single service entry. See Bcfg2.Client.Tools.Tool.Install().

Parameters:entry (lxml.etree._Element) – The Service entry to install
Returns:bool - True if installation was successful, False otherwise
Remove(services)[source]

Remove specified extra entries.

Parameters:entries (list of lxml.etree._Element) – The entries to remove
Returns:None
check_service(service)[source]

Check the status a service.

Parameters:service (lxml.etree._Element) – The service entry to modify
Returns:bool - True if the status command returned 0, False otherwise
get_bootstatus(service)[source]

Return the bootstatus attribute if it exists.

Parameters:service (lxml.etree._Element) – The service entry
Returns:string or None - Value of bootstatus if it exists. If bootstatus is unspecified and status is not ignore, return value of status. If bootstatus is unspecified and status is ignore, return None.
get_svc_command(service, action)[source]

Return a command that can be run to start or stop a service.

Parameters:
  • service (lxml.etree._Element) – The service entry to modify
  • action (string) – The action to take (e.g., “stop”, “start”)
Returns:

string - The command to run

restart_service(service)[source]

Restart a service.

Parameters:service (lxml.etree._Element) – The service entry to modify
Returns:Bcfg2.Utils.ExecutorResult - The return value from Bcfg2.Utils.Executor.run
restarted = None

List of services that have been restarted

start_service(service)[source]

Start a service.

Parameters:service (lxml.etree._Element) – The service entry to modify
Returns:Bcfg2.Utils.ExecutorResult - The return value from Bcfg2.Utils.Executor.run
stop_service(service)[source]

Stop a service.

Parameters:service (lxml.etree._Element) – The service entry to modify
Returns:Bcfg2.Utils.ExecutorResult - The return value from Bcfg2.Utils.Executor.run

Helper Classes

class Bcfg2.Client.Tools.ToolInstantiationError[source]

Bases: exceptions.Exception

This error is raised if the toolset cannot be instantiated.