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 Steve Baker
parent 4e549c3ae6
commit 16a6afc80b
6 changed files with 207 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-script \

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))

View File

@ -0,0 +1,11 @@
---
- name: Hello Ansible - quick start
connection: local
hosts: localhost
tasks:
- name: Hello touch_file
shell: echo {{ foo }} >> /tmp/{{ bar }}
- name: Hello echo
shell: echo "The file /tmp/{{ bar }} contains {{ foo }}" >> {{ heat_outputs_path }}.result

View File

@ -0,0 +1,89 @@
heat_template_version: 2013-05-23
parameters:
key_name:
type: string
default: test_key
flavor:
type: string
default: m1.heat
image:
type: string
default: fedora-software-config
resources:
the_sg:
type: OS::Neutron::SecurityGroup
properties:
name: the_sg
description: Ping and SSH
rules:
- protocol: icmp
- protocol: tcp
port_range_min: 22
port_range_max: 22
config:
type: OS::Heat::SoftwareConfig
properties:
group: ansible
inputs:
- name: foo
- name: bar
outputs:
- name: result
config:
get_file: config-scripts/example-ansible-template.ansible
deployment:
type: OS::Heat::SoftwareDeployment
properties:
config:
get_resource: config
server:
get_resource: server
input_values:
foo: fooooo
bar: baaaaa
other_deployment:
type: OS::Heat::SoftwareDeployment
properties:
config:
get_resource: config
server:
get_resource: server
input_values:
foo: fu
bar: barmy
actions:
- CREATE
- UPDATE
- SUSPEND
- RESUME
server:
type: OS::Nova::Server
properties:
image: {get_param: image}
flavor: {get_param: flavor}
key_name: {get_param: key_name}
security_groups:
- {get_resource: the_sg}
user_data_format: SOFTWARE_CONFIG
outputs:
result:
value:
get_attr: [deployment, result]
stdout:
value:
get_attr: [deployment, deploy_stdout]
stderr:
value:
get_attr: [deployment, deploy_stderr]
status_code:
value:
get_attr: [deployment, deploy_status_code]
other_result:
value:
get_attr: [other_deployment, result]