diff --git a/examples/scripts/cobbler_external_inventory.py b/examples/scripts/cobbler_external_inventory.py deleted file mode 100755 index 223f8e37be4..00000000000 --- a/examples/scripts/cobbler_external_inventory.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/python - -""" -Cobbler 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. - -This script is an example of sourcing that data from Cobbler -(http://cobbler.github.com). With cobbler each --mgmt-class in cobbler -will correspond to a group in Ansible, and --ks-meta variables will be -passed down for use in templates or even in argument lines. - -NOTE: The cobbler system names will not be used. Make sure a -cobbler --dns-name is set for each cobbler system. If a system -appears with two DNS names we do not add it twice because we don't want -ansible talking to it twice. The first one found will be used. If no ---dns-name is set the system will NOT be visible to ansible. We do -not add cobbler system names because there is no requirement in cobbler -that those correspond to addresses. - -See http://ansible.github.com/api.html for more info - -Tested with Cobbler 2.0.11. -""" - -# (c) 2012, Michael DeHaan -# -# 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 . - -###################################################################### - - -import sys -import xmlrpclib -import shlex - -try: - import json -except: - import simplejson as json - -# NOTE -- this file assumes Ansible is being accessed FROM the cobbler -# server, so it does not attempt to login with a username and password. -# this will be addressed in a future version of this script. - -conn = xmlrpclib.Server("http://127.0.0.1/cobbler_api", allow_none=True) - -################################################### -# executed with no parameters, return the list of -# all groups and hosts - -if len(sys.argv) == 2 and (sys.argv[1] == '--list'): - - systems = conn.get_item_names('system') - groups = { 'ungrouped' : [] } - - for system in systems: - - data = conn.get_blended_data(None, system) - - dns_name = None - interfaces = data['interfaces'] - for (iname, ivalue) in interfaces.iteritems(): - this_dns_name = ivalue.get('dns_name', None) - if this_dns_name is not None: - dns_name = this_dns_name - - if dns_name is None: - continue - - classes = data['mgmt_classes'] - for cls in classes: - if cls not in groups: - groups[cls] = [] - # hostname is not really what we want to insert, really insert the - # first DNS name but no further DNS names - groups[cls].append(dns_name) - - print json.dumps(groups) - sys.exit(0) - -##################################################### -# executed with a hostname as a parameter, return the -# variables for that host - -elif len(sys.argv) == 3 and (sys.argv[1] == '--host'): - - # look up the system record for the given DNS name - result = conn.find_system_by_dns_name(sys.argv[2]) - system = result.get('name', None) - data = {} - if system is None: - print json.dumps({}) - sys.exit(1) - data = conn.get_system_for_koan(system) - - # return the ksmeta data for that system - metadata = data['ks_meta'] - tokens = shlex.split(metadata) - results = {} - for t in tokens: - if t.find("=") != -1: - (k,v) = t.split("=",1) - results[k]=v - print json.dumps(results) - sys.exit(0) - -else: - - print "usage: --list ..OR.. --host " - sys.exit(1) diff --git a/examples/scripts/ec2.ini b/examples/scripts/ec2.ini deleted file mode 100644 index cb4979df140..00000000000 --- a/examples/scripts/ec2.ini +++ /dev/null @@ -1,42 +0,0 @@ -# Ansible EC2 external inventory script settings -# - -[ec2] - -# AWS regions to make calls to. Set this to 'all' to make request to all regions -# in AWS and merge the results together. Alternatively, set this to a comma -# separated list of regions. E.g. 'us-east-1,us-west-1,us-west-2' -regions = all - -# When generating inventory, Ansible needs to know how to address a server. -# Each EC2 instance has a lot of variables associated with it. Here is the list: -# http://docs.pythonboto.org/en/latest/ref/ec2.html#module-boto.ec2.instance -# Below are 2 variables that are used as the address of a server: -# - destination_variable -# - vpc_destination_variable - -# This is the normal destination variable to use. If you are running Ansible -# from outside EC2, then 'public_dns_name' makes the most sense. If you are -# running Ansible from within EC2, then perhaps you want to use the internal -# address, and should set this to 'private_dns_name'. -destination_variable = public_dns_name - -# For server inside a VPC, using DNS names may not make sense. When an instance -# has 'subnet_id' set, this variable is used. If the subnet is public, setting -# this to 'ip_address' will return the public IP address. For instances in a -# private subnet, this should be set to 'private_ip_address', and Ansible must -# be run from with EC2. -vpc_destination_variable = ip_address - -# API calls to EC2 are 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-ec2.cache -# - ansible-ec2.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 = 300 - - diff --git a/examples/scripts/ec2_external_inventory.py b/examples/scripts/ec2_external_inventory.py deleted file mode 100755 index df5ce2c8395..00000000000 --- a/examples/scripts/ec2_external_inventory.py +++ /dev/null @@ -1,377 +0,0 @@ -#!/usr/bin/python -tt - -''' -EC2 external inventory script -================================= - -Generates inventory that Ansible can understand by making API request to -AWS EC2 using the Boto library. - -NOTE: This script assumes Ansible is being executed where the environment -variables needed for Boto have already been set: - export AWS_ACCESS_KEY_ID='AK123' - export AWS_SECRET_ACCESS_KEY='abc123' - -For more details, see: http://docs.pythonboto.org/en/latest/boto_config_tut.html - -When run against a specific host, this script returns the following variables: - - ec2_ami_launch_index - - ec2_architecture - - ec2_association - - ec2_attachTime - - ec2_attachment - - ec2_attachmentId - - ec2_client_token - - ec2_deleteOnTermination - - ec2_description - - ec2_deviceIndex - - ec2_dns_name - - ec2_eventsSet - - ec2_group_name - - ec2_hypervisor - - ec2_id - - ec2_image_id - - ec2_instanceState - - ec2_instance_type - - ec2_ipOwnerId - - ec2_ip_address - - ec2_item - - ec2_kernel - - ec2_key_name - - ec2_launch_time - - ec2_monitored - - ec2_monitoring - - ec2_networkInterfaceId - - ec2_ownerId - - ec2_persistent - - ec2_placement - - ec2_platform - - ec2_previous_state - - ec2_private_dns_name - - ec2_private_ip_address - - ec2_publicIp - - ec2_public_dns_name - - ec2_ramdisk - - ec2_reason - - ec2_region - - ec2_requester_id - - ec2_root_device_name - - ec2_root_device_type - - ec2_security_group_ids - - ec2_security_group_names - - ec2_shutdown_state - - ec2_sourceDestCheck - - ec2_spot_instance_request_id - - ec2_state - - ec2_state_code - - ec2_state_reason - - ec2_status - - ec2_subnet_id - - ec2_tenancy - - ec2_virtualization_type - - ec2_vpc_id - -These variables are pulled out of a boto.ec2.instance object. There is a lack of -consistency with variable spellings (camelCase and underscores) since this -just loops through all variables the object exposes. It is preferred to use the -ones with underscores when multiple exist. - -In addition, if an instance has AWS Tags associated with it, each tag is a new -variable named: - - ec2_tag_[Key] = [Value] - -Security groups are comma-separated in 'ec2_security_group_ids' and -'ec2_security_group_names'. -''' - -# (c) 2012, Peter Sankauskas -# -# 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 . - -###################################################################### - -import os -import argparse -import re -from time import time -from boto import ec2 -import ConfigParser - -try: - import json -except ImportError: - import simplejson as json - - -class Ec2Inventory(object): - def __init__(self): - ''' Main execution path ''' - - # Inventory grouped by instance IDs, tags, security groups, regions, - # and availability zones - self.inventory = {} - - # Index of hostname (address) to instance ID - self.index = {} - - # Read settings and parse CLI arguments - self.read_settings() - self.parse_cli_args() - - # Cache - if self.args.refresh_cache: - self.do_api_calls_update_cache() - elif not self.is_cache_valid(): - self.do_api_calls_update_cache() - - # Data to print - if self.args.host: - data_to_print = self.get_host_info() - - elif self.args.list: - # Display list of instances for inventory - if len(self.inventory) == 0: - data_to_print = self.get_inventory_from_cache() - else: - data_to_print = self.json_format_dict(self.inventory, True) - - print data_to_print - - - def is_cache_valid(self): - ''' Determines if the cache files have expired, or if it is still valid ''' - - if os.path.isfile(self.cache_path_cache): - mod_time = os.path.getmtime(self.cache_path_cache) - current_time = time() - if (mod_time + self.cache_max_age) > current_time: - if os.path.isfile(self.cache_path_index): - return True - - return False - - - def read_settings(self): - ''' Reads the settings from the ec2.ini file ''' - - config = ConfigParser.SafeConfigParser() - config.read(os.path.dirname(os.path.realpath(__file__)) + '/ec2.ini') - - # Regions - self.regions = [] - configRegions = config.get('ec2', 'regions') - if (configRegions == 'all'): - for regionInfo in ec2.regions(): - self.regions.append(regionInfo.name) - else: - self.regions = configRegions.split(",") - - # Destination addresses - self.destination_variable = config.get('ec2', 'destination_variable') - self.vpc_destination_variable = config.get('ec2', 'vpc_destination_variable') - - # Cache related - cache_path = config.get('ec2', 'cache_path') - self.cache_path_cache = cache_path + "/ansible-ec2.cache" - self.cache_path_index = cache_path + "/ansible-ec2.index" - self.cache_max_age = config.getint('ec2', 'cache_max_age') - - - def parse_cli_args(self): - ''' Command line argument processing ''' - - parser = argparse.ArgumentParser(description='Produce an Ansible Inventory file based on EC2') - 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('--refresh-cache', action='store_true', default=False, - help='Force refresh of cache by making API requests to EC2 (default: False - use cache files)') - self.args = parser.parse_args() - - - def do_api_calls_update_cache(self): - ''' Do API calls to each region, and save data in cache files ''' - - for region in self.regions: - self.get_instances_by_region(region) - - self.write_to_cache(self.inventory, self.cache_path_cache) - self.write_to_cache(self.index, self.cache_path_index) - - - def get_instances_by_region(self, region): - ''' Makes an AWS EC2 API call to the list of instances in a particular - region ''' - - conn = ec2.connect_to_region(region) - reservations = conn.get_all_instances() - for reservation in reservations: - for instance in reservation.instances: - self.add_instance(instance, region) - - - def get_instance(self, region, instance_id): - ''' Gets details about a specific instance ''' - conn = ec2.connect_to_region(region) - reservations = conn.get_all_instances([instance_id]) - for reservation in reservations: - for instance in reservation.instances: - return instance - - - def add_instance(self, instance, region): - ''' Adds an instance to the inventory and index, as long as it is - addressable ''' - - # Only want running instances - if instance.state == 'terminated': - return - - # Select the best destination address - if instance.subnet_id: - dest = getattr(instance, self.vpc_destination_variable) - else: - dest = getattr(instance, self.destination_variable) - - if dest == None: - # Skip instances we cannot address (e.g. private VPC subnet) - return - - # Add to index - self.index[dest] = [region, instance.id] - - # Inventory: Group by instance ID (always a group of 1) - self.inventory[instance.id] = [dest] - - # Inventory: Group by region - self.push(self.inventory, region, dest) - - # Inventory: Group by availability zone - self.push(self.inventory, instance.placement, dest) - - # Inventory: Group by security group - for group in instance.groups: - key = self.to_safe("security_group_" + group.name) - self.push(self.inventory, key, dest) - - # Inventory: Group by tag keys - for k, v in instance.tags.iteritems(): - key = self.to_safe("tag_" + k + "=" + v) - self.push(self.inventory, key, dest) - - - def get_host_info(self): - ''' Get variables about a specific host ''' - - if len(self.index) == 0: - # Need to load index from cache - self.load_index_from_cache() - - (region, instance_id) = self.index[self.args.host] - instance = self.get_instance(region, instance_id) - instance_vars = {} - for key in vars(instance): - value = getattr(instance, key) - key = self.to_safe('ec2_' + key) - - # Handle complex types - if type(value) in [int, bool]: - instance_vars[key] = value - elif type(value) in [str, unicode]: - instance_vars[key] = value.strip() - elif type(value) == type(None): - instance_vars[key] = '' - elif key == 'ec2_region': - instance_vars[key] = value.name - elif key == 'ec2_tags': - for k, v in value.iteritems(): - key = self.to_safe('ec2_tag_' + k) - instance_vars[key] = v - elif key == 'ec2_groups': - group_ids = [] - group_names = [] - for group in value: - group_ids.append(group.id) - group_names.append(group.name) - instance_vars["ec2_security_group_ids"] = ','.join(group_ids) - instance_vars["ec2_security_group_names"] = ','.join(group_names) - else: - pass - # TODO Product codes if someone finds them useful - #print key - #print type(value) - #print value - - return self.json_format_dict(instance_vars, True) - - - def push(self, my_dict, key, element): - ''' Pushed an element onto an array that may not have been defined in - the dict ''' - - if key in my_dict: - my_dict[key].append(element); - else: - my_dict[key] = [element] - - - def get_inventory_from_cache(self): - ''' Reads the inventory from the cache file and returns it as a JSON - object ''' - - cache = open(self.cache_path_cache, 'r') - json_inventory = cache.read() - return json_inventory - - - def load_index_from_cache(self): - ''' Reads the index from the cache file sets self.index ''' - - cache = open(self.cache_path_index, 'r') - json_index = cache.read() - self.index = json.loads(json_index) - - - def write_to_cache(self, data, filename): - ''' Writes data in JSON format to a file ''' - - json_data = self.json_format_dict(data, True) - cache = open(filename, 'w') - cache.write(json_data) - cache.close() - - - def to_safe(self, word): - ''' Converts 'bad' characters in a string to underscores so they can be - used as Ansible groups ''' - - return re.sub("[^A-Za-z0-9\-]", "_", word) - - - def json_format_dict(self, data, pretty=False): - ''' Converts a dict to a JSON object and dumps it as a formatted - string ''' - - if pretty: - return json.dumps(data, sort_keys=True, indent=2) - else: - return json.dumps(data) - - -# Run the script -Ec2Inventory() -