Cobbler has the ability to run triggers at specific times. Two of those times include before installing a new machine ("pre-install triggers") and after installing a new machine ("post-install triggers").
"Old-style" triggers involve running executable binaries or scripts (e.g. shell scripts) in specific locations. Pre-install triggers are placed in the directory /var/lib/cobbler/triggers/install/pre/
and post-install triggers are placed in the directory /var/lib/cobbler/triggers/install/post/
. The trigger will be passed three pieces of information: the object type, e.g. "system," the name of the object, and the object's IP. (A comment in the run_install_triggers
method in remote.py
says this passes the name, MAC, and IP but this does not appear to match the name of the variables.) If the trigger requires more information, it will need to pull it from elsewhere or parse cobbler's output. For all but simple tasks, this is probably not a convenient way to go.
Note: There is a bug in cobbler 2.0.3.1 which prevents running "old-style" triggers. See ticket #530 for more information and a possible fix.
"New-style" triggers are written in Python as modules. They reside in cobbler's module directory. (On my system, this is /usr/lib/python2.4/site-packages/cobbler/modules/
.) Each module is required to define at least the functions register
and run
.
The register
function takes no arguments and returns a string corresponding to the directory the module would reside in if it were an "old-style" trigger. For a pre-install trigger, it would be:
-
def register():
-
return "/var/lib/cobbler/triggers/install/post/*"
For a post-install trigger, it would be:
-
def register():
-
return "/var/lib/cobbler/triggers/install/post/*"
The run
function is where the actual code for the trigger should reside. It takes three arguments: A cobbler API reference, an array containing arguments, and a logger reference. The argument array contains the same three values as for "old-style" triggers, i.e. the object type, the name, and the IP address. The logger reference may be set to None
and the code should handle that. (In cobbler 2.0.3.1, this will be set to None
. This may be fixed when the issue for "old-style" install triggers is.)
For an example of a run
function, let's look at one I wrote (based on the trigger in install_post_report.py
that is included with cobbler) to automatically sign Puppet certificates:
-
def run(api, args, logger):
This starts the method. Note the signature.
-
settings = api.settings()
-
-
if not str(settings.sign_puppet_certs_automatically).lower() in [ "1", "yes", "y", "true"]:
-
return 0
This retrieves the settings from /etc/cobbler/settings
. To control the trigger, I added another option there named sign_puppet_certs_automatically
. If this value either does not exist or is not set to one of the required values showing its enabled, the trigger returns a success code (since it's not supposed to run, it shouldn't return a failure code) and exits.
I also added another option to the cobbler settings called puppetca_path
which contains the path to the puppetca
command.
-
objtype = args[0] # "target" or "profile"
-
name = args[1] # name of target or profile
-
-
if objtype != "system":
-
return 0
This retrieves the object type and name from the argument array. If the object type is not a system, it returns a success code and exits.
-
system = api.find_system(name)
-
system = utils.blender(api, False, system)
-
-
hostname = system[ "hostname" ]
This finds the system in the cobbler API and then flattens it to a dictionary. I'm pretty sure this could be improved upon.
-
puppetca_path = settings.puppetca_path
-
cmd = [puppetca_path, '--sign', hostname]
This retrieves the path for puppetca
and sets up the command to be run to sign the certificate.
-
rc = 0
-
try:
-
rc = utils.subprocess_call(logger, cmd, shell=False)
-
except:
-
if logger is not None:
-
logger.warning("failed to execute %s", puppetca_path)
-
-
if rc != 0:
-
if logger is not None:
-
logger.warning("signing of puppet cert for %s failed", name)
-
-
return 0
This runs the command and logs a warning if either the command fails to be executed or does not succeed. Finally, at the end, it returns a success code.
According to the cobbler documentation, the return code of post-install triggers is ignored so there's no reason not to return anything other than value. Pre-install triggers apparently can halt the process if they return a non-zero value.
Note: The above code will not run correctly if logger
is set to None
. This is because utils.subprocess_call
tries to call logger
without verifying that it is not None
and throws an exception. To use this with cobbler 2.0.3.1, you must either edit change the call to utils.run_triggers
in remote.py
's run_install_triggers
method or you must change utils.subprocess_call
to properly check for logger
being set to None
.
Also note: Since the original code is under the GPL, the code above is also under the GPL.