Common Utilities

Some helper functions, classes, etc., are useful to both the client and server. Some of these are used to maintain Python Compatibility, and should go in Bcfg2.Compat. Those that aren’t strictly for Python compatibility go in Bcfg2.Utils, which is documented below.

Miscellaneous useful utility functions, classes, etc., that are used by both client and server. Stuff that doesn’t fit anywhere else.

class Bcfg2.Utils.ClassName[source]

Bases: object

This very simple descriptor class exists only to get the name of the owner class. This is used because, for historical reasons, we expect every server plugin and every client tool to have a name attribute that is in almost all cases the same as the __class__.__name__ attribute of the plugin object. This makes that more dynamic so that each plugin and tool isn’t repeating its own name.

class Bcfg2.Utils.Executor(timeout=None)[source]

Bases: object

A convenient way to run external commands with subprocess.Popen

Parameters:timeout (float) – Set a default timeout for all commands run by this Executor object
run(command, inputdata=None, timeout=None, **kwargs)[source]

Run a command, given as a list, optionally giving it the specified input data. All additional keyword arguments are passed through to subprocess.Popen.

Parameters:
  • command (list or string) – The command to run, as a list (preferred) or as a string. See subprocess.Popen for details.
  • inputdata (string) – Data to pass to the command on stdin
  • timeout (float) – Kill the command if it runs longer than this many seconds. Set to 0 or -1 to explicitly override a default timeout.
Returns:

Bcfg2.Utils.ExecutorResult

class Bcfg2.Utils.ExecutorResult(stdout, stderr, retval)[source]

Bases: object

Returned as the result of a call to Bcfg2.Utils.Executor.run(). The result can be accessed via the instance variables, documented below, as a boolean (which is equivalent to Bcfg2.Utils.ExecutorResult.success), or as a tuple, which, for backwards compatibility, is equivalent to (result.retval, result.stdout.splitlines()).

error = None

A friendly error message

retval = None

The return value of the command.

success = None

Whether or not the command was successful. If the ExecutorResult is used as a boolean, success is returned.

class Bcfg2.Utils.PackedDigitRange(*ranges)[source]

Bases: object

Representation of a set of integer ranges. A range is described by a comma-delimited string of integers and ranges, e.g.:

1,10-12,15-20

Ranges are inclusive on both bounds, and may include 0. Negative numbers are not supported.

May be instantiated in one of two ways:

PackedDigitRange(<comma-delimited list of ranges>)

Or:

PackedDigitRange(<int_or_range>[, <int_or_range>[, ...]])

E.g., both of the following are valid:

PackedDigitRange("1-5,7, 10-12")
PackedDigitRange("1-5", 7, "10-12")
includes(other)[source]

Return True if other is included in this range. Functionally equivalent to other in range, which should be used instead.

class Bcfg2.Utils.classproperty(getter)[source]

Bases: object

Decorator that can be used to create read-only class properties.

Bcfg2.Utils.hostnames2ranges(hostnames)[source]

convert a list of hostnames to a set of human-readable ranges. e.g.:

[“foo1.example.com”, “foo2.example.com”, “foo3.example.com”,
“foo6.example.com”] -> [“foo[1-3,6].example.com”]
Bcfg2.Utils.is_string(strng, encoding)[source]

Returns true if the string contains no ASCII control characters and can be decoded from the specified encoding.

Bcfg2.Utils.list2range(lst)[source]

convert a list of integers to a set of human-readable ranges. e.g.:

[1, 2, 3, 6, 9, 10, 11] -> “[1-3,6,9-11]”

Bcfg2.Utils.locked(fd)[source]

Acquire a lock on a file.

Parameters:fd (int) – The file descriptor to lock
Returns:bool - True if the file is already locked, False otherwise
Bcfg2.Utils.safe_input(msg)[source]

input() that flushes the input buffer before accepting input

Bcfg2.Utils.safe_module_name(prefix, module)[source]

Munge the name of a module with prefix to avoid collisions with other Python modules. E.g., if you want to import user defined helper modules and someone has a helper named ‘ldap.py’, it should not be added to sys.modules as ldap, but rather as something more obscure.