Commit a7121d00 by Michael DeHaan

Merge pull request #4326 from angstwad/devel

Revamp of the rax.py inventory plugin
parents 4a3e828b f63a6faf
...@@ -46,7 +46,7 @@ description: ...@@ -46,7 +46,7 @@ description:
rax_name rax_name
rax_created rax_created
rax_tenant_id rax_tenant_id
rax__loaded rax_loaded
where some item can have nested structure. where some item can have nested structure.
- credentials are set in a credentials file - credentials are set in a credentials file
...@@ -57,28 +57,38 @@ options: ...@@ -57,28 +57,38 @@ options:
- File to find the Rackspace Public Cloud credentials in - File to find the Rackspace Public Cloud credentials in
required: true required: true
default: null default: null
region_name: region:
description: description:
- Region name to use in request - An optional value to narrow inventory scope, i.e. DFW, ORD, IAD, LON
required: false required: false
default: DFW default: null
author: Jesse Keating authors:
- Jesse Keating <jesse.keating@rackspace.com>
- Paul Durivage <paul.durivage@rackspace.com>
notes: notes:
- Two environment variables need to be set, RAX_CREDS and RAX_REGION. - RAX_CREDS_FILE is an optional environment variable that points to a pyrax-compatible credentials file.
- RAX_CREDS points to a credentials file appropriate for pyrax - If RAX_CREDS_FILE is not supplied, rax.py will look for a credentials file at ~/.rackspace_cloud_credentials.
- RAX_REGION defines a Rackspace Public Cloud region (DFW, ORD, LON, ...) - See https://github.com/rackspace/pyrax/blob/master/docs/getting_started.md#authenticating
- 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
requirements: [ "pyrax" ] requirements: [ "pyrax" ]
examples: examples:
- description: List server instances - description: List server instances
code: RAX_CREDS_FILE=~/.raxpub rax.py --list
- description: List servers in ORD datacenter only
code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --list code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --list
- description: List server instance properties - description: List servers in ORD and DFW datacenters
code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --host <HOST_IP> code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD,DFW rax.py --list
- description: Get server details for server named "server.example.com"
code: RAX_CREDS_FILE=~/.raxpub rax.py --host server.example.com
''' '''
import sys import sys
import re import re
import os import os
import argparse import argparse
import collections
try: try:
import json import json
...@@ -91,69 +101,129 @@ except ImportError: ...@@ -91,69 +101,129 @@ except ImportError:
print('pyrax required for this module') print('pyrax required for this module')
sys.exit(1) sys.exit(1)
# Setup the parser
parser = argparse.ArgumentParser(description='List active instances',
epilog='List by itself will list all the active \
instances. Listing a specific instance will show \
all the details about the instance.')
parser.add_argument('--list', action='store_true', default=True,
help='List active servers')
parser.add_argument('--host',
help='List details about the specific host (IP address)')
args = parser.parse_args()
# setup the auth
try:
creds_file = os.environ['RAX_CREDS_FILE']
region = os.environ['RAX_REGION']
except KeyError, e:
sys.stderr.write('Unable to load %s\n' % e.message)
sys.exit(1)
pyrax.set_setting('identity_type', 'rackspace')
try:
pyrax.set_setting("identity_type", "rackspace")
pyrax.set_credential_file(os.path.expanduser(creds_file),
region=region)
except Exception, e:
sys.stderr.write("%s: %s\n" % (e, e.message))
sys.exit(1)
# Execute the right stuff
if not args.host:
groups = {}
# Cycle on servers
for server in pyrax.cloudservers.list():
# Define group (or set to empty string)
try:
group = server.metadata['group']
except KeyError:
group = 'undefined'
# Create group if not exist and add the server
groups.setdefault(group, []).append(server.accessIPv4)
# Return server list def host(regions, hostname):
print(json.dumps(groups)) hostvars = {}
for region in regions:
# Connect to the region
cs = pyrax.connect_to_cloudservers(region=region)
for server in cs.servers.list():
if server.name == hostname:
keys = [key for key in vars(server) if key not in ('manager', '_info')]
for key in keys:
# Extract value
value = getattr(server, key)
# Generate sanitized key
key = 'rax_' + (re.sub("[^A-Za-z0-9\-]", "_", key)
.lower()
.lstrip("_"))
hostvars[key] = value
# And finally, add an IP address
hostvars['ansible_ssh_host'] = server.accessIPv4
print(json.dumps(hostvars, sort_keys=True, indent=4))
def _list(regions):
groups = collections.defaultdict(list)
hostvars = collections.defaultdict(dict)
# Go through all the regions looking for servers
for region in regions:
# Connect to the region
cs = pyrax.connect_to_cloudservers(region=region)
for server in cs.servers.list():
# Create a group on region
groups[region].append(server.name)
# Check if group metadata key in servers' metadata
try:
group = server.metadata['group']
except KeyError:
pass
else:
# Create group if not exist and add the server
groups[group].append(server.name)
# Add host metadata
keys = [key for key in vars(server) if key not in ('manager', '_info')]
for key in keys:
# Extract value
value = getattr(server, key)
# Generate sanitized key
key = 'rax_' + (re.sub("[^A-Za-z0-9\-]", "_", key)
.lower()
.lstrip('_'))
hostvars[server.name][key] = value
# And finally, add an IP address
hostvars[server.name]['ansible_ssh_host'] = server.accessIPv4
if hostvars:
groups['_meta'] = {'hostvars': hostvars}
print(json.dumps(groups, sort_keys=True, indent=4))
def parse_args():
parser = argparse.ArgumentParser(description='Ansible Rackspace Cloud '
'inventory module')
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--list', action='store_true',
help='List active servers')
group.add_argument('--host', help='List details about the specific host')
return parser.parse_args()
def setup():
default_creds_file = os.path.expanduser('~/.rackspace_cloud_credentials')
# Attempt to grab credentials from environment first
try:
creds_file = os.environ['RAX_CREDS_FILE']
except KeyError, e:
# But if that fails, use the default location of ~/.rackspace_cloud_credentials
if os.path.isfile(default_creds_file):
creds_file = default_creds_file
else:
sys.stderr.write('No value in environment variable %s and/or no '
'credentials file at %s\n'
% (e.message, default_creds_file))
sys.exit(1)
pyrax.set_setting('identity_type', 'rackspace')
try:
pyrax.set_credential_file(os.path.expanduser(creds_file))
except Exception, e:
sys.stderr.write("%s: %s\n" % (e, e.message))
sys.exit(1)
regions = []
for region in os.getenv('RAX_REGION', 'all').split(','):
region = region.strip().upper()
if region == 'ALL':
regions = pyrax.regions
break
elif region not in pyrax.regions:
sys.stderr.write('Unsupported region %s' % region)
sys.exit(1)
elif region not in regions:
regions.append(region)
return regions
def main():
args = parse_args()
regions = setup()
if args.list:
_list(regions)
elif args.host:
host(regions, args.host)
sys.exit(0) sys.exit(0)
# Get the deets for the instance asked for if __name__ == '__main__':
results = {} main()
# This should be only one, but loop anyway \ No newline at end of file
for server in pyrax.cloudservers.list():
if server.accessIPv4 == args.host:
for key in [key for key in vars(server) if
key not in ('manager', '_info')]:
# Extract value
value = getattr(server, key)
# Generate sanitized key
key = 'rax_' + re.sub("[^A-Za-z0-9\-]", "_", key).lower()
results[key] = value
print(json.dumps(results))
sys.exit(0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment