|
#!/usr/bin/env python |
|
""" |
|
(C) 2010 Pragmatic Source |
|
Farzad FARID <ffarid@pragmatic-source.com> |
|
|
|
register_chef.py: Register the server being installed on the Chef server |
|
We assume that the 'knife' is installed locally on the Cobbler server. |
|
|
|
Check https://fedorahosted.org/cobbler/wiki/CobblerTriggers for |
|
documentation on Cobbler's triggers and API. |
|
|
|
This program is free software; you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation; either version 2 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program; if not, write to the Free Software |
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
|
02110-1301 USA |
|
""" |
|
|
|
from cobbler import utils |
|
import sys |
|
import os |
|
|
|
|
|
# Configuration settings |
|
# ---------------------- |
|
|
|
# * home: |
|
# The HOME environment variable is undefined in the cobblerd process, we |
|
# have to set it here for 'knife' to be able to find its configuration |
|
# file, '~/.chef/knife.rb'. |
|
# * knife_config_path: |
|
# If the 'knife.rb' configuration file is in an unusual place, define the |
|
# full path here. |
|
# * chef_roles: |
|
# List of compulsory Chef Roles to prepend to the management classes extracted |
|
# from the Cobbler configuration. |
|
# Only the 'home' setting is compulsory. |
|
CHEF_CONFIG = { |
|
#'home': '/root', |
|
'knife_config_path': '/root/.chef/knife.rb', |
|
'chef_roles': [ 'Base' ] |
|
} |
|
|
|
|
|
def register(): |
|
# this pure python trigger acts as if it were a legacy shell-trigger, but is much faster. |
|
# the return of this method indicates the trigger type |
|
return "/var/lib/cobbler/triggers/install/pre/*" |
|
|
|
def run(api, args, logger): |
|
objtype = args[0] # "system" or "profile" |
|
name = args[1] # name of system or profile |
|
boot_ip = args[2] # ip or "?" |
|
|
|
# Handle only systems, not profiles |
|
if objtype != "system": |
|
return 0 |
|
|
|
# Lookup the node in Cobbler's database |
|
node = api.find_system(name) |
|
|
|
# Find its fully qualified hostname and the management classes, to which we |
|
# add "Linux" unconditionnaly. We directly map cobbler's Management Classes to |
|
# Chef Roles' names. |
|
hostname = node.hostname |
|
roles = node.mgmt_classes |
|
roles = CHEF_CONFIG.get('chef_roles', []) + roles |
|
|
|
logger.info("Registering %s (%s) in Chef" % (name, hostname)) |
|
|
|
# Create the node in Chef, deleting it first if necessary, and |
|
# add roles one by one. |
|
# Note: "knife node delete" does not destroy the node's RSA key. We don't |
|
# need to delete it as it will be recreated by chef-client on the first |
|
# run. |
|
if CHEF_CONFIG.has_key('home'): |
|
os.environ['HOME'] = CHEF_CONFIG['home'] |
|
knife_opts = '' |
|
if CHEF_CONFIG.has_key('knife_config_path'): |
|
knife_opts = '--config ' + CHEF_CONFIG['knife_config_path'] |
|
|
|
# Delete the node |
|
# Ignore stderr too, as usually this command should fail. |
|
rc = utils.subprocess_call(logger, |
|
"knife node delete %(hostname)s --yes %(knife_opts)s >> /var/log/cobbler/knife.log" % { 'hostname': hostname, 'knife_opts': knife_opts }, |
|
shell=True) |
|
if rc != 0: |
|
logger.warning("Failed to delete node %s in Chef" % hostname) |
|
|
|
# Remove the client |
|
rc = utils.subprocess_call(logger, |
|
"knife client delete %(hostname)s --yes %(knife_opts)s >> /var/log/cobbler/knife.log" % { 'hostname': hostname, 'knife_opts': knife_opts }, |
|
shell=True) |
|
if rc != 0: |
|
logger.warning("Failed to delete client %s in Chef" % hostname) |
|
|
|
# Add the node |
|
logger.info("Setting environment to %s" % node.status.title()) |
|
rc = utils.subprocess_call(logger, "knife node create %(hostname)s --disable-editing %(knife_opts)s >> /var/log/cobbler/knife.log" % |
|
{ 'hostname': hostname, 'knife_opts': knife_opts}, |
|
shell=True) |
|
if rc != 0: |
|
logger.error("Failed to create node %s in Chef" % hostname) |
|
|
|
# Set the environment using the plugin from the README |
|
logger.info("Setting environment to %s" % node.status.title()) |
|
rc = utils.subprocess_call(logger, "knife node set_environment %(hostname)s environment %(environment)s %(knife_opts)s >> /var/log/cobbler/knife.log" % |
|
{ 'hostname': hostname, 'knife_opts': knife_opts, 'environment': node.status.title()}, |
|
shell=True) |
|
if rc != 0: |
|
logger.error("Failed to set environment for node %s in Chef" % hostname) |
|
|
|
# Add roles to the node |
|
for role in roles: |
|
rc = utils.subprocess_call(logger, |
|
"knife node run_list add %(hostname)s \"role[%(role)s]\" %(knife_opts)s >> /var/log/cobbler/knife.log" % { 'hostname': hostname, 'knife_opts': knife_opts, 'role': role }, |
|
shell=True) |
|
if rc != 0: |
|
logger.error("Failed to add role %(role)s to node %(hostname)s in Chef" % { 'hostname': hostname, 'role': role }) |
|
|
|
return 0 |