summaryrefslogtreecommitdiffstats
path: root/inventory
diff options
context:
space:
mode:
authorWesley Hearn <wesley.s.hearn@gmail.com>2015-04-24 14:06:02 -0400
committerWesley Hearn <wesley.s.hearn@gmail.com>2015-04-24 14:06:02 -0400
commit196d37e2ffa0d7f4221a857b143fd09f84a9d00b (patch)
tree4c5413c72a2dd2ec732730b6994a104cca6a9798 /inventory
parent7f7b582a7bc239e69c147b98c8c2512050f12851 (diff)
parent8ce5e1de898d2fd2c4aa4620f31b57b62ed0c5d6 (diff)
downloadopenshift-196d37e2ffa0d7f4221a857b143fd09f84a9d00b.tar.gz
openshift-196d37e2ffa0d7f4221a857b143fd09f84a9d00b.tar.bz2
openshift-196d37e2ffa0d7f4221a857b143fd09f84a9d00b.tar.xz
openshift-196d37e2ffa0d7f4221a857b143fd09f84a9d00b.zip
Merge pull request #187 from openshift/master
Merge master into INT
Diffstat (limited to 'inventory')
-rw-r--r--inventory/aws/group_vars/all2
-rw-r--r--inventory/aws/hosts/ec2.ini (renamed from inventory/aws/ec2.ini)0
-rwxr-xr-xinventory/aws/hosts/ec2.py (renamed from inventory/aws/ec2.py)0
-rw-r--r--inventory/aws/hosts/hosts1
-rw-r--r--inventory/byo/group_vars/all28
-rw-r--r--inventory/byo/hosts26
-rw-r--r--inventory/gce/group_vars/all2
-rwxr-xr-xinventory/gce/hosts/gce.py (renamed from inventory/gce/gce.py)0
-rw-r--r--inventory/gce/hosts/hosts1
-rw-r--r--inventory/libvirt/group_vars/all2
-rw-r--r--inventory/libvirt/hosts2
-rw-r--r--inventory/libvirt/hosts/hosts1
-rw-r--r--inventory/libvirt/hosts/libvirt.ini20
-rwxr-xr-xinventory/libvirt/hosts/libvirt_generic.py179
-rwxr-xr-xinventory/multi_ec2.py95
-rw-r--r--inventory/multi_ec2.yaml.example4
16 files changed, 280 insertions, 83 deletions
diff --git a/inventory/aws/group_vars/all b/inventory/aws/group_vars/all
deleted file mode 100644
index b22da00de..000000000
--- a/inventory/aws/group_vars/all
+++ /dev/null
@@ -1,2 +0,0 @@
----
-ansible_ssh_user: root
diff --git a/inventory/aws/ec2.ini b/inventory/aws/hosts/ec2.ini
index eaab0a410..eaab0a410 100644
--- a/inventory/aws/ec2.ini
+++ b/inventory/aws/hosts/ec2.ini
diff --git a/inventory/aws/ec2.py b/inventory/aws/hosts/ec2.py
index f231ff4c2..f231ff4c2 100755
--- a/inventory/aws/ec2.py
+++ b/inventory/aws/hosts/ec2.py
diff --git a/inventory/aws/hosts/hosts b/inventory/aws/hosts/hosts
new file mode 100644
index 000000000..34a4396bd
--- /dev/null
+++ b/inventory/aws/hosts/hosts
@@ -0,0 +1 @@
+localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2
diff --git a/inventory/byo/group_vars/all b/inventory/byo/group_vars/all
deleted file mode 100644
index d63e96668..000000000
--- a/inventory/byo/group_vars/all
+++ /dev/null
@@ -1,28 +0,0 @@
----
-# lets assume that we want to use the root as the ssh user for all hosts
-ansible_ssh_user: root
-
-# default debug level for all OpenShift hosts
-openshift_debug_level: 4
-
-# set the OpenShift deployment type for all hosts
-openshift_deployment_type: enterprise
-
-# Override the default registry for development
-openshift_registry_url: docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version}
-
-# Use latest Errata puddle as an additional repo:
-#openshift_additional_repos:
-#- id: ose-devel
-# name: ose-devel
-# baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterpriseErrata/3.0/latest/RH7-RHOSE-3.0/$basearch/os
-# enabled: 1
-# gpgcheck: 0
-
-# Use latest Whitelist puddle as an additional repo:
-openshift_additional_repos:
-- id: ose-devel
- name: ose-devel
- baseurl: http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os
- enabled: 1
- gpgcheck: 0
diff --git a/inventory/byo/hosts b/inventory/byo/hosts
index 2dd854778..98dbb4fd8 100644
--- a/inventory/byo/hosts
+++ b/inventory/byo/hosts
@@ -1,5 +1,30 @@
# This is an example of a bring your own (byo) host inventory
+# Create an OSEv3 group that contains the masters and nodes groups
+[OSEv3:children]
+masters
+nodes
+
+# Set variables common for all OSEv3 hosts
+[OSEv3:vars]
+# SSH user, this user should allow ssh based auth without requiring a password
+ansible_ssh_user=root
+
+# If ansible_ssh_user is not root, ansible_sudo must be set to true
+#ansible_sudo=true
+
+# To deploy origin, change deployment_type to origin
+deployment_type=enterprise
+
+# Pre-release registry URL
+openshift_registry_url=docker-buildvm-rhose.usersys.redhat.com:5000/openshift3_beta/ose-${component}:${version}
+
+# Pre-release additional repo
+openshift_additional_repos=[{'id': 'ose-devel', 'name': 'ose-devel', 'baseurl': 'http://buildvm-devops.usersys.redhat.com/puddle/build/OpenShiftEnterprise/3.0/latest/RH7-RHOSE-3.0/$basearch/os', 'enabled': 1, 'gpgcheck': 0}]
+
+# Origin copr repo
+#openshift_additional_repos=[{'id': 'openshift-origin-copr', 'name': 'OpenShift Origin COPR', 'baseurl': 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/epel-7-$basearch/', 'enabled': 1, 'gpgcheck': 1, gpgkey: 'https://copr-be.cloud.fedoraproject.org/results/maxamillion/origin-next/pubkey.gpg'}]
+
# host group for masters
[masters]
ose3-master-ansible.test.example.com
@@ -7,4 +32,3 @@ ose3-master-ansible.test.example.com
# host group for nodes
[nodes]
ose3-node[1:2]-ansible.test.example.com
-
diff --git a/inventory/gce/group_vars/all b/inventory/gce/group_vars/all
deleted file mode 100644
index b22da00de..000000000
--- a/inventory/gce/group_vars/all
+++ /dev/null
@@ -1,2 +0,0 @@
----
-ansible_ssh_user: root
diff --git a/inventory/gce/gce.py b/inventory/gce/hosts/gce.py
index 3403f735e..3403f735e 100755
--- a/inventory/gce/gce.py
+++ b/inventory/gce/hosts/gce.py
diff --git a/inventory/gce/hosts/hosts b/inventory/gce/hosts/hosts
new file mode 100644
index 000000000..34a4396bd
--- /dev/null
+++ b/inventory/gce/hosts/hosts
@@ -0,0 +1 @@
+localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2
diff --git a/inventory/libvirt/group_vars/all b/inventory/libvirt/group_vars/all
deleted file mode 100644
index b22da00de..000000000
--- a/inventory/libvirt/group_vars/all
+++ /dev/null
@@ -1,2 +0,0 @@
----
-ansible_ssh_user: root
diff --git a/inventory/libvirt/hosts b/inventory/libvirt/hosts
deleted file mode 100644
index 6a818f268..000000000
--- a/inventory/libvirt/hosts
+++ /dev/null
@@ -1,2 +0,0 @@
-# Eventually we'll add the GCE, AWS, etc dynamic inventories, but for now...
-localhost ansible_python_interpreter=/usr/bin/python2
diff --git a/inventory/libvirt/hosts/hosts b/inventory/libvirt/hosts/hosts
new file mode 100644
index 000000000..34a4396bd
--- /dev/null
+++ b/inventory/libvirt/hosts/hosts
@@ -0,0 +1 @@
+localhost ansible_connection=local ansible_sudo=no ansible_python_interpreter=/usr/bin/python2
diff --git a/inventory/libvirt/hosts/libvirt.ini b/inventory/libvirt/hosts/libvirt.ini
new file mode 100644
index 000000000..62ff204dd
--- /dev/null
+++ b/inventory/libvirt/hosts/libvirt.ini
@@ -0,0 +1,20 @@
+# Ansible libvirt external inventory script settings
+#
+
+[libvirt]
+
+uri = qemu:///system
+
+# API calls to libvirt can be slow. For this reason, we cache the results of an API
+# call. Set this to the path you want cache files to be written to. Two files
+# will be written to this directory:
+# - ansible-libvirt.cache
+# - ansible-libvirt.index
+cache_path = /tmp
+
+# The number of seconds a cache file is considered valid. After this many
+# seconds, a new API call will be made, and the cache file will be updated.
+cache_max_age = 900
+
+
+
diff --git a/inventory/libvirt/hosts/libvirt_generic.py b/inventory/libvirt/hosts/libvirt_generic.py
new file mode 100755
index 000000000..4652f112e
--- /dev/null
+++ b/inventory/libvirt/hosts/libvirt_generic.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python2
+
+"""
+libvirt external inventory script
+=================================
+
+Ansible has a feature where instead of reading from /etc/ansible/hosts
+as a text file, it can query external programs to obtain the list
+of hosts, groups the hosts are in, and even variables to assign to each host.
+
+To use this, copy this file over /etc/ansible/hosts and chmod +x the file.
+This, more or less, allows you to keep one central database containing
+info about all of your managed instances.
+
+"""
+
+# (c) 2015, Jason DeTiberus <jdetiber@redhat.com>
+#
+# This file is part of Ansible,
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+######################################################################
+
+import argparse
+import ConfigParser
+import os
+import re
+import sys
+from time import time
+import libvirt
+import xml.etree.ElementTree as ET
+
+try:
+ import json
+except ImportError:
+ import simplejson as json
+
+
+class LibvirtInventory(object):
+
+ def __init__(self):
+ self.inventory = dict() # A list of groups and the hosts in that group
+ self.cache = dict() # Details about hosts in the inventory
+
+ # Read settings and parse CLI arguments
+ self.read_settings()
+ self.parse_cli_args()
+
+ if self.args.host:
+ print self.json_format_dict(self.get_host_info(), self.args.pretty)
+ elif self.args.list:
+ print self.json_format_dict(self.get_inventory(), self.args.pretty)
+ else: # default action with no options
+ print self.json_format_dict(self.get_inventory(), self.args.pretty)
+
+ def read_settings(self):
+ config = ConfigParser.SafeConfigParser()
+ config.read(
+ os.path.dirname(os.path.realpath(__file__)) + '/libvirt.ini'
+ )
+ self.libvirt_uri = config.get('libvirt', 'uri')
+
+ def parse_cli_args(self):
+ parser = argparse.ArgumentParser(
+ description='Produce an Ansible Inventory file based on libvirt'
+ )
+ parser.add_argument(
+ '--list',
+ action='store_true',
+ default=True,
+ help='List instances (default: True)'
+ )
+ parser.add_argument(
+ '--host',
+ action='store',
+ help='Get all the variables about a specific instance'
+ )
+ parser.add_argument(
+ '--pretty',
+ action='store_true',
+ default=False,
+ help='Pretty format (default: False)'
+ )
+ self.args = parser.parse_args()
+
+ def get_host_info(self):
+ inventory = self.get_inventory()
+ if self.args.host in inventory['_meta']['hostvars']:
+ return inventory['_meta']['hostvars'][self.args.host]
+
+ def get_inventory(self):
+ inventory = dict(_meta=dict(hostvars=dict()))
+
+ conn = libvirt.openReadOnly(self.libvirt_uri)
+ if conn is None:
+ print "Failed to open connection to %s" % libvirt_uri
+ sys.exit(1)
+
+ domains = conn.listAllDomains()
+ if domains is None:
+ print "Failed to list domains for connection %s" % libvirt_uri
+ sys.exit(1)
+
+ arp_entries = self.parse_arp_entries()
+
+ for domain in domains:
+ hostvars = dict(libvirt_name=domain.name(),
+ libvirt_id=domain.ID(),
+ libvirt_uuid=domain.UUIDString())
+ domain_name = domain.name()
+
+ # TODO: add support for guests that are not in a running state
+ state, _ = domain.state()
+ # 2 is the state for a running guest
+ if state != 1:
+ continue
+
+ hostvars['libvirt_status'] = 'running'
+
+ root = ET.fromstring(domain.XMLDesc())
+ ns = {'ansible': 'https://github.com/ansible/ansible'}
+ for tag_elem in root.findall('./metadata/ansible:tags/ansible:tag', ns):
+ tag = tag_elem.text
+ self.push(inventory, "tag_%s" % tag, domain_name)
+ self.push(hostvars, 'libvirt_tags', tag)
+
+ # TODO: support more than one network interface, also support
+ # interface types other than 'network'
+ interface = root.find("./devices/interface[@type='network']")
+ if interface is not None:
+ mac_elem = interface.find('mac')
+ if mac_elem is not None:
+ mac = mac_elem.get('address')
+ if mac in arp_entries:
+ ip_address = arp_entries[mac]['ip_address']
+ hostvars['ansible_ssh_host'] = ip_address
+ hostvars['libvirt_ip_address'] = ip_address
+
+ inventory['_meta']['hostvars'][domain_name] = hostvars
+
+ return inventory
+
+ def parse_arp_entries(self):
+ arp_entries = dict()
+ with open('/proc/net/arp', 'r') as f:
+ # throw away the header
+ f.readline()
+
+ for line in f:
+ ip_address, _, _, mac, _, device = line.strip().split()
+ arp_entries[mac] = dict(ip_address=ip_address, device=device)
+
+ return arp_entries
+
+ def push(self, my_dict, key, element):
+ if key in my_dict:
+ my_dict[key].append(element)
+ else:
+ my_dict[key] = [element]
+
+ def json_format_dict(self, data, pretty=False):
+ if pretty:
+ return json.dumps(data, sort_keys=True, indent=2)
+ else:
+ return json.dumps(data)
+
+LibvirtInventory()
diff --git a/inventory/multi_ec2.py b/inventory/multi_ec2.py
index 26c09d712..b839a33ea 100755
--- a/inventory/multi_ec2.py
+++ b/inventory/multi_ec2.py
@@ -1,22 +1,29 @@
#!/usr/bin/env python2
+'''
+ Fetch and combine multiple ec2 account settings into a single
+ json hash.
+'''
# vim: expandtab:tabstop=4:shiftwidth=4
from time import time
import argparse
import yaml
import os
-import sys
-import pdb
import subprocess
import json
-import pprint
CONFIG_FILE_NAME = 'multi_ec2.yaml'
class MultiEc2(object):
+ '''
+ MultiEc2 class:
+ Opens a yaml config file and reads aws credentials.
+ Stores a json hash of resources in result.
+ '''
def __init__(self):
+ self.args = None
self.config = None
self.all_ec2_results = {}
self.result = {}
@@ -24,7 +31,7 @@ class MultiEc2(object):
self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))
same_dir_config_file = os.path.join(self.file_path, CONFIG_FILE_NAME)
- etc_dir_config_file = os.path.join(os.path.sep, 'etc','ansible', CONFIG_FILE_NAME)
+ etc_dir_config_file = os.path.join(os.path.sep, 'etc', 'ansible', CONFIG_FILE_NAME)
# Prefer a file in the same directory, fall back to a file in etc
if os.path.isfile(same_dir_config_file):
@@ -39,12 +46,13 @@ class MultiEc2(object):
# load yaml
if self.config_file and os.path.isfile(self.config_file):
self.config = self.load_yaml_config()
- elif os.environ.has_key("AWS_ACCESS_KEY_ID") and os.environ.has_key("AWS_SECRET_ACCESS_KEY"):
+ elif os.environ.has_key("AWS_ACCESS_KEY_ID") and \
+ os.environ.has_key("AWS_SECRET_ACCESS_KEY"):
self.config = {}
self.config['accounts'] = [
{
'name': 'default',
- 'provider': 'aws/ec2.py',
+ 'provider': 'aws/hosts/ec2.py',
'env_vars': {
'AWS_ACCESS_KEY_ID': os.environ["AWS_ACCESS_KEY_ID"],
'AWS_SECRET_ACCESS_KEY': os.environ["AWS_SECRET_ACCESS_KEY"],
@@ -56,13 +64,9 @@ class MultiEc2(object):
else:
raise RuntimeError("Could not find valid ec2 credentials in the environment.")
- if self.args.cache_only:
- # get data from disk
- result = self.get_inventory_from_cache()
-
- if not result:
- self.get_inventory()
- self.write_to_cache()
+ if self.args.refresh_cache:
+ self.get_inventory()
+ self.write_to_cache()
# if its a host query, fetch and do not cache
elif self.args.host:
self.get_inventory()
@@ -74,7 +78,7 @@ class MultiEc2(object):
# get data from disk
self.get_inventory_from_cache()
- def load_yaml_config(self,conf_file=None):
+ def load_yaml_config(self, conf_file=None):
"""Load a yaml config file with credentials to query the
respective cloud for inventory.
"""
@@ -88,7 +92,7 @@ class MultiEc2(object):
return config
- def get_provider_tags(self,provider, env={}):
+ def get_provider_tags(self, provider, env=None):
"""Call <provider> and query all of the tags that are usuable
by ansible. If environment is empty use the default env.
"""
@@ -153,7 +157,8 @@ class MultiEc2(object):
self.all_ec2_results[result['name']] = json.loads(result['out'])
values = self.all_ec2_results.values()
values.insert(0, self.result)
- [MultiEc2.merge_destructively(self.result, x) for x in values]
+ for result in values:
+ MultiEc2.merge_destructively(self.result, result)
else:
# For any 0 result, return it
count = 0
@@ -165,30 +170,30 @@ class MultiEc2(object):
raise RuntimeError("Found > 1 results for --host %s. \
This is an invalid state." % self.args.host)
@staticmethod
- def merge_destructively(a, b):
- "merges b into a"
- for key in b:
- if key in a:
- if isinstance(a[key], dict) and isinstance(b[key], dict):
- MultiEc2.merge_destructively(a[key], b[key])
- elif a[key] == b[key]:
+ def merge_destructively(input_a, input_b):
+ "merges b into input_a"
+ for key in input_b:
+ if key in input_a:
+ if isinstance(input_a[key], dict) and isinstance(input_b[key], dict):
+ MultiEc2.merge_destructively(input_a[key], input_b[key])
+ elif input_a[key] == input_b[key]:
pass # same leaf value
# both lists so add each element in b to a if it does ! exist
- elif isinstance(a[key], list) and isinstance(b[key],list):
- for x in b[key]:
- if x not in a[key]:
- a[key].append(x)
+ elif isinstance(input_a[key], list) and isinstance(input_b[key], list):
+ for result in input_b[key]:
+ if result not in input_a[key]:
+ input_a[key].input_append(result)
# a is a list and not b
- elif isinstance(a[key], list):
- if b[key] not in a[key]:
- a[key].append(b[key])
- elif isinstance(b[key], list):
- a[key] = [a[key]] + [k for k in b[key] if k != a[key]]
+ elif isinstance(input_a[key], list):
+ if input_b[key] not in input_a[key]:
+ input_a[key].append(input_b[key])
+ elif isinstance(input_b[key], list):
+ input_a[key] = [input_a[key]] + [k for k in input_b[key] if k != input_a[key]]
else:
- a[key] = [a[key],b[key]]
+ input_a[key] = [input_a[key], input_b[key]]
else:
- a[key] = b[key]
- return a
+ input_a[key] = input_b[key]
+ return input_a
def is_cache_valid(self):
''' Determines if the cache files have expired, or if it is still valid '''
@@ -204,19 +209,20 @@ class MultiEc2(object):
def parse_cli_args(self):
''' Command line argument processing '''
- parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on a provider')
- parser.add_argument('--cache-only', action='store_true', default=False,
- help='Fetch cached only instances (default: False)')
+ parser = argparse.ArgumentParser(
+ description='Produce an Ansible Inventory file based on a provider')
+ parser.add_argument('--refresh-cache', action='store_true', default=False,
+ help='Fetch cached only instances (default: False)')
parser.add_argument('--list', action='store_true', default=True,
- help='List instances (default: True)')
+ help='List instances (default: True)')
parser.add_argument('--host', action='store', default=False,
- help='Get all the variables about a specific instance')
+ help='Get all the variables about a specific instance')
self.args = parser.parse_args()
def write_to_cache(self):
''' Writes data in JSON format to a file '''
- json_data = self.json_format_dict(self.result, True)
+ json_data = MultiEc2.json_format_dict(self.result, True)
with open(self.cache_path, 'w') as cache:
cache.write(json_data)
@@ -232,7 +238,8 @@ class MultiEc2(object):
return True
- def json_format_dict(self, data, pretty=False):
+ @classmethod
+ def json_format_dict(cls, data, pretty=False):
''' Converts a dict to a JSON object and dumps it as a formatted
string '''
@@ -242,9 +249,9 @@ class MultiEc2(object):
return json.dumps(data)
def result_str(self):
+ '''Return cache string stored in self.result'''
return self.json_format_dict(self.result, True)
if __name__ == "__main__":
- mi = MultiEc2()
- print mi.result_str()
+ print MultiEc2().result_str()
diff --git a/inventory/multi_ec2.yaml.example b/inventory/multi_ec2.yaml.example
index 0bd505816..91e7c7970 100644
--- a/inventory/multi_ec2.yaml.example
+++ b/inventory/multi_ec2.yaml.example
@@ -1,13 +1,13 @@
# multi ec2 inventory configs
accounts:
- name: aws1
- provider: aws/ec2.py
+ provider: aws/hosts/ec2.py
env_vars:
AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
- name: aws2
- provider: aws/ec2.py
+ provider: aws/hosts/ec2.py
env_vars:
AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX