Software-config hook for ansible

Added ansible to the software-config README

Created a new folder elements/heat-config-ansible that will be
pre-installed by diskimage-builder on any images wishing to use the
ansible hook.

Created an example ansible heat template with an example ansible
script as a starting point.

Updated README.rst to reflect how heat-config-ansible interacts with the HOT template.

Change-Id: I861e96186e2f5d5b65ea5100edf1b82e753c425c
This commit is contained in:
Steve Gregory 2014-05-27 15:03:05 -07:00 committed by Thomas Herve
parent 0fd927af21
commit 0d204109c5
4 changed files with 107 additions and 0 deletions

View File

@ -33,6 +33,7 @@ with the following:
os-collect-config \
os-refresh-config \
os-apply-config \
heat-config-ansible \
heat-config-cfn-init \
heat-config-puppet \
heat-config-salt \

View File

@ -0,0 +1,4 @@
A hook which invokes ``ansible-playbook -i "localhost,"`` on the provided
configuration. Config inputs are written to a 'variables.json' file and
then passed to ansible via the '--extra-vars @json_file' parameter.
Config output values are read from written-out files.

View File

@ -0,0 +1,7 @@
#!/bin/bash
set -x
SCRIPTDIR=$(dirname $0)
install-packages ansible
install -D -g root -o root -m 0755 ${SCRIPTDIR}/hook-ansible.py /var/lib/heat-config/hooks/ansible

View File

@ -0,0 +1,95 @@
#!/usr/bin/env python
import json
import logging
import os
import subprocess
import sys
WORKING_DIR = os.environ.get('HEAT_ANSIBLE_WORKING',
'/var/lib/heat-config/heat-config-ansible')
OUTPUTS_DIR = os.environ.get('HEAT_ANSIBLE_OUTPUTS',
'/var/run/heat-config/heat-config-ansible')
def prepare_dir(path):
if not os.path.isdir(path):
os.makedirs(path, 0o700)
def main(argv=sys.argv):
log = logging.getLogger('heat-config')
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(
logging.Formatter(
'[%(asctime)s] (%(name)s) [%(levelname)s] %(message)s'))
log.addHandler(handler)
log.setLevel('DEBUG')
prepare_dir(OUTPUTS_DIR)
prepare_dir(WORKING_DIR)
os.chdir(WORKING_DIR)
c = json.load(sys.stdin)
variables = {}
for input in c['inputs']:
variables[input['name']] = input.get('value','')
fn = os.path.join(WORKING_DIR, '%s_playbook.yaml' % c['id'])
vars_filename = os.path.join(WORKING_DIR, '%s_variables.json' % c['id'])
heat_outputs_path = os.path.join(OUTPUTS_DIR, c['id'])
variables['heat_outputs_path'] = heat_outputs_path
config_text = c.get('config','')
if not config_text:
log.warn("No 'config' input found, nothing to do.")
return
#Write 'variables' to file
with os.fdopen(os.open(vars_filename, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as var_file:
json.dump(variables, var_file)
#Write the executable, 'config', to file
with os.fdopen(os.open(fn, os.O_CREAT | os.O_WRONLY, 0o600), 'w') as f:
f.write(c.get('config',''))
cmd = ['ansible-playbook','-i','localhost,', fn, '--extra-vars','@%s' % vars_filename]
log.debug('Running %s' % (' '.join(cmd),))
try:
subproc = subprocess.Popen([cmd], stdout=subprocess.PIPE,
stderr=subprocess.PIPE, env=env)
except OSError:
log.warn("ansible not installed yet")
return
stdout, stderr = subproc.communicate()
log.info('Return code %s' % subproc.returncode)
if stdout:
log.info(stdout)
if stderr:
log.info(stderr)
#TODO: Test if ansible returns any non-zero return codes in success.
if subproc.returncode:
log.error("Error running %s. [%s]\n" % (fn, subproc.returncode))
else:
log.info('Completed %s' % fn)
response = {}
for output in c.get('outputs') or []:
output_name = output['name']
try:
with open('%s.%s' % (heat_outputs_path, output_name)) as out:
response[output_name] = out.read()
except IOError:
pass
response.update({
'deploy_stdout': stdout,
'deploy_stderr': stderr,
'deploy_status_code': subproc.returncode,
})
json.dump(response, sys.stdout)
if __name__ == '__main__':
sys.exit(main(sys.argv))