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.
Pick a name for the driver. In this case, we picked the name RPM.
Create a file in
src/lib/Bcfg2/Client/Tools
with the same name (RPM.py)Create a class in this file with the same name (
class RPM
)- If it handles Package entries, subclass
Bcfg2.Client.Tools.PkgTool
- If it handles Service entries, subclass
Bcfg2.Client.Tools.SvcTool
- Otherwise, subclass
Bcfg2.Client.Tools.Tool
.
- If it handles Package entries, subclass
Add any required executable programs to
Bcfg2.Client.Tools.Tool.__execs__
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')]
.Add verification support by defining a method named
Verify<tag>
. SeeBcfg2.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)Add installation support by defining a method named
Install<tag
. SeeBcfg2.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.Optionally, add support for removing extra entries by defining a
Bcfg2.Client.Tools.Tool.Remove()
method.Optionally, add a
Bcfg2.Client.Tools.Tool.FindExtra()
method that locates entries not included in the configuration.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 thetype
attribute of the entry. If this tool handles entries with notype
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 thattype
attribute. In that case, thetype
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 aInstall<tag>
method to install each entry, where<tag>
is the entry tag. E.g., a Path entry would be installed by callingInstallPath()
.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:
- Call the appropriate entry-specific Verify method for each entry this tool verifies;
- Call
Bcfg2.Client.Tools.Tool.FindExtra()
to populateBcfg2.Client.Tools.Tool.extra
with extra entries.
This implementation of
Bcfg2.Client.Tools.Tool.Inventory()
calls aVerify<tag>
method to verify each entry, where<tag>
is the entry tag. E.g., a Path entry would be verified by callingVerifyPath()
.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:
- The entry is handled by this tool (as reported by
Bcfg2.Client.Tools.Tool.handlesEntry()
; - The entry does not report a bind failure;
- The entry is not missing any attributes (as reported by
Bcfg2.Client.Tools.Tool.missing_attrs()
).
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.
- The entry is handled by this tool (as reported by
-
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.
-
-
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 aInstall<tag>
method to install each entry, where<tag>
is the entry tag. E.g., a Path entry would be installed by callingInstallPath()
.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.