Support RackConnect v3 by allowing a network to be specified for use in determining ansible_ssh_host

This commit is contained in:
Matt Martz 2014-10-22 14:40:20 -05:00
parent 7812c70d3b
commit 2bd927fd81

149
plugins/inventory/rax.py Executable file → Normal file
View file

@ -1,8 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python
# (c) 2013, Jesse Keating <jesse.keating@rackspace.com> # (c) 2013, Jesse Keating <jesse.keating@rackspace.com,
# Paul Durivage <paul.durivage@rackspace.com>,
# Matt Martz <matt@sivel.net>
# #
# This file is part of Ansible, # This file is part of Ansible.
# #
# Ansible is free software: you can redistribute it and/or modify # Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -17,16 +19,20 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>. # along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = ''' """
--- Rackspace Cloud Inventory
inventory: rax
short_description: Rackspace Public Cloud external inventory script Authors:
description: Jesse Keating <jesse.keating@rackspace.com,
- Generates inventory that Ansible can understand by making API request to Paul Durivage <paul.durivage@rackspace.com>,
Matt Martz <matt@sivel.net>
Description:
Generates inventory that Ansible can understand by making API request to
Rackspace Public Cloud API Rackspace Public Cloud API
- |
When run against a specific host, this script returns the following When run against a specific host, this script returns variables similar to:
variables:
rax_os-ext-sts_task_state rax_os-ext-sts_task_state
rax_addresses rax_addresses
rax_links rax_links
@ -50,63 +56,67 @@ description:
rax_tenant_id rax_tenant_id
rax_loaded rax_loaded
where some item can have nested structure. Notes:
- credentials are set in a credentials file RAX_CREDS_FILE is an optional environment variable that points to a
version_added: None
options:
creds_file:
description:
- File to find the Rackspace Public Cloud credentials in
required: true
default: null
region:
description:
- An optional value to narrow inventory scope, i.e. DFW, ORD, IAD, LON
required: false
default: null
authors:
- Jesse Keating <jesse.keating@rackspace.com>
- Paul Durivage <paul.durivage@rackspace.com>
- Matt Martz <matt@sivel.net>
notes:
- RAX_CREDS_FILE is an optional environment variable that points to a
pyrax-compatible credentials file. pyrax-compatible credentials file.
- If RAX_CREDS_FILE is not supplied, rax.py will look for a credentials file
at ~/.rackspace_cloud_credentials. If RAX_CREDS_FILE is not supplied, rax.py will look for a credentials file
- See https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md#authenticating at ~/.rackspace_cloud_credentials. It uses the Rackspace Python SDK, and
- RAX_REGION is an optional environment variable to narrow inventory search therefore requires a file formatted per the SDK's specifications. See
scope https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md
- RAX_REGION, if used, needs a value like ORD, DFW, SYD (a Rackspace #authenticating
datacenter) and optionally accepts a comma-separated list
- RAX_ENV is an environment variable that will use an environment as RAX_REGION is an optional environment variable to narrow inventory search
scope. RAX_REGION, if used, needs a value like ORD, DFW, SYD (a Rackspace
datacenter) and optionally accepts a comma-separated list.
RAX_ENV is an environment variable that will use an environment as
configured in ~/.pyrax.cfg, see configured in ~/.pyrax.cfg, see
https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md#pyrax-configuration https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md
- RAX_META_PREFIX is an environment variable that changes the prefix used
RAX_META_PREFIX is an environment variable that changes the prefix used
for meta key/value groups. For compatibility with ec2.py set to for meta key/value groups. For compatibility with ec2.py set to
RAX_META_PREFIX=tag RAX_META_PREFIX=tag
requirements: [ "pyrax" ]
examples: RAX_ACCESS_NETWORK is an environment variable that will tell the inventory
- description: List server instances script to use a specific server network to determine the ansible_ssh_host
code: RAX_CREDS_FILE=~/.raxpub rax.py --list value. If no address is found, ansible_ssh_host will not be set.
- description: List servers in ORD datacenter only
code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --list RAX_ACCESS_IP_VERSION is an environment variable related to
- description: List servers in ORD and DFW datacenters RAX_ACCESS_NETWORK that will attempt to determine the ansible_ssh_host
code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD,DFW rax.py --list value for either IPv4 or IPv6. If no address is found, ansible_ssh_host
- description: Get server details for server named "server.example.com" will not be set. Acceptable values are: 4 or 6. Values other than 4 or 6
code: RAX_CREDS_FILE=~/.raxpub rax.py --host server.example.com will be ignored, and 4 will be used.
'''
Examples:
List server instances
$ RAX_CREDS_FILE=~/.raxpub rax.py --list
List servers in ORD datacenter only
$ RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --list
List servers in ORD and DFW datacenters
$ RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD,DFW rax.py --list
Get server details for server named "server.example.com"
$ RAX_CREDS_FILE=~/.raxpub rax.py --host server.example.com
Use the instance private IP to connect (instead of public IP)
$ RAX_CREDS_FILE=~/.raxpub RAX_PRIVATE_IP=yes rax.py --list
"""
import os import os
import re import re
import sys import sys
import argparse import argparse
import warnings
import collections import collections
from types import NoneType from types import NoneType
try: try:
import json import json
except: except ImportError:
import simplejson as json import simplejson as json
try: try:
@ -126,7 +136,7 @@ def to_dict(obj):
instance = {} instance = {}
for key in dir(obj): for key in dir(obj):
value = getattr(obj, key) value = getattr(obj, key)
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')): if isinstance(value, NON_CALLABLES) and not key.startswith('_'):
key = rax_slugify(key) key = rax_slugify(key)
instance[key] = value instance[key] = value
@ -154,10 +164,25 @@ def _list(regions):
hostvars = collections.defaultdict(dict) hostvars = collections.defaultdict(dict)
images = {} images = {}
network = os.getenv('RAX_ACCESS_NETWORK', 'public')
try:
ip_version = int(os.getenv('RAX_ACCESS_IP_VERSION', 4))
except:
ip_version = 4
else:
if ip_version not in [4, 6]:
ip_version = 4
# Go through all the regions looking for servers # Go through all the regions looking for servers
for region in regions: for region in regions:
# Connect to the region # Connect to the region
cs = pyrax.connect_to_cloudservers(region=region) cs = pyrax.connect_to_cloudservers(region=region)
if isinstance(cs, NoneType):
warnings.warn(
'Connecting to Rackspace region "%s" has caused Pyrax to '
'return a NoneType. Is this a valid region?' % region,
RuntimeWarning)
continue
for server in cs.servers.list(): for server in cs.servers.list():
# Create a group on region # Create a group on region
groups[region].append(server.name) groups[region].append(server.name)
@ -198,7 +223,21 @@ def _list(regions):
groups['image-%s' % server.image['id']].append(server.name) groups['image-%s' % server.image['id']].append(server.name)
# And finally, add an IP address # And finally, add an IP address
hostvars[server.name]['ansible_ssh_host'] = server.accessIPv4 ansible_ssh_host = None
# use accessIPv[46] instead of looping address for 'public'
if network == 'public':
if ip_version == 6 and server.accessIPv6:
ansible_ssh_host = server.accessIPv6
elif server.accessIPv4:
ansible_ssh_host = server.accessIPv4
else:
addresses = server.addresses.get(network, [])
for address in addresses:
if address.get('version') == ip_version:
ansible_ssh_host = address.get('addr')
break
if ansible_ssh_host:
hostvars[server.name]['ansible_ssh_host'] = ansible_ssh_host
if hostvars: if hostvars:
groups['_meta'] = {'hostvars': hostvars} groups['_meta'] = {'hostvars': hostvars}