From 73438de862556064eb549c3c8a23ce7beab2ea46 Mon Sep 17 00:00:00 2001 From: Andrew Clarke Date: Mon, 27 Mar 2017 19:52:24 +0100 Subject: [PATCH] A basic lxd dynamic inventory script (#15848) * A basic start on an lxd dynamic inventory script The script is a fairly basic start on an lxd dynamic inventory script. Only tested on ubuntu 16.04 and currently only reports ipv4 container addresses. Improvements to come. * Updated formatting, indenting and python3 support Updated to work on python3 * Additional options read from the ini file Added options for connection and group to the ini file and modified to use these. Host returned is now the name by default. For non-lxd connection, the ansible_host var is populated with the ip address. * Additional options for group and connection * Minor change to re-run tests --- contrib/inventory/lxd.ini | 13 +++++ contrib/inventory/lxd.py | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 contrib/inventory/lxd.ini create mode 100644 contrib/inventory/lxd.py diff --git a/contrib/inventory/lxd.ini b/contrib/inventory/lxd.ini new file mode 100644 index 00000000000..5398e7d0219 --- /dev/null +++ b/contrib/inventory/lxd.ini @@ -0,0 +1,13 @@ +# LXD external inventory script settings + +[lxd] + +# The default resource +#resource = local: + +# The group name to add the hosts to +#group = lxd + +# The connection type to return for these hosts - lxd hasn't been tested yet +#connection = lxd +connection = smart diff --git a/contrib/inventory/lxd.py b/contrib/inventory/lxd.py new file mode 100644 index 00000000000..b0bb09ee819 --- /dev/null +++ b/contrib/inventory/lxd.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# (c) 2013, Michael Scherer +# (c) 2014, Hiroaki Nakamura +# (c) 2016, Andew Clarke +# +# This file is based on https://github.com/ansible/ansible/blob/devel/plugins/inventory/libvirt_lxc.py which is part of Ansible, +# and https://github.com/hnakamur/lxc-ansible-playbooks/blob/master/provisioning/inventory-lxc.py +# +# NOTE, this file has some obvious limitations, improvements welcome +# +# Ansible 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 3 of the License, or +# (at your option) any later version. +# +# Ansible 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 Ansible. If not, see . + +import os +from subprocess import Popen,PIPE +import distutils.spawn +import sys +import json +try: + import configparser +except: + from six.moves import configparser + +# Set up defaults +resource = 'local:' +group = 'lxd' +connection = 'lxd' +hosts = {} +result = {} + +# Read the settings from the lxd.ini file +config = configparser.SafeConfigParser() +config.read(os.path.dirname(os.path.realpath(__file__)) + '/lxd.ini') +if config.has_option('lxd', 'resource'): + resource = config.get('lxd', 'resource') +if config.has_option('lxd', 'group'): + group = config.get('lxd', 'group') +if config.has_option('lxd', 'connection'): + connection = config.get('lxd', 'connection') + +# Ensure executable exists +if distutils.spawn.find_executable('lxc'): + + # Set up containers result and hosts array + result[group] = {} + result[group]['hosts'] = [] + + # Run the command and load json result + pipe = Popen(['lxc', 'list', resource, '--format', 'json'], stdout=PIPE, universal_newlines=True) + lxdjson = json.load(pipe.stdout) + + # Iterate the json lxd output + for item in lxdjson: + + # Check state and network + if 'state' in item and item['state'] is not None and 'network' in item['state']: + network = item['state']['network'] + + # Check for eth0 and addresses + if 'eth0' in network and 'addresses' in network['eth0']: + addresses = network['eth0']['addresses'] + + # Iterate addresses + for address in addresses: + + # Only return inet family addresses + if 'family' in address and address['family'] == 'inet': + if 'address' in address: + ip = address['address'] + name = item['name'] + + # Add the host to the results and the host array + result[group]['hosts'].append(name) + hosts[name] = ip + + # Set the other containers result values + result[group]['vars'] = {} + result[group]['vars']['ansible_connection'] = connection + +# Process arguments +if len(sys.argv) == 2 and sys.argv[1] == '--list': + print(json.dumps(result)) +elif len(sys.argv) == 3 and sys.argv[1] == '--host': + if sys.argv[2] == 'localhost': + print(json.dumps({'ansible_connection': 'local'})) + else: + if connection == 'lxd': + print(json.dumps({'ansible_connection': connection})) + else: + print(json.dumps({'ansible_connection': connection, 'ansible_host': hosts[sys.argv[2]]})) +else: + print("Need an argument, either --list or --host ")