|
|
|
|
@ -46,7 +46,7 @@ description:
|
|
|
|
|
rax_name
|
|
|
|
|
rax_created
|
|
|
|
|
rax_tenant_id
|
|
|
|
|
rax__loaded
|
|
|
|
|
rax_loaded
|
|
|
|
|
|
|
|
|
|
where some item can have nested structure.
|
|
|
|
|
- credentials are set in a credentials file
|
|
|
|
|
@ -57,28 +57,38 @@ options:
|
|
|
|
|
- File to find the Rackspace Public Cloud credentials in
|
|
|
|
|
required: true
|
|
|
|
|
default: null
|
|
|
|
|
region_name:
|
|
|
|
|
region:
|
|
|
|
|
description:
|
|
|
|
|
- Region name to use in request
|
|
|
|
|
required: false
|
|
|
|
|
default: DFW
|
|
|
|
|
author: Jesse Keating
|
|
|
|
|
- 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>
|
|
|
|
|
notes:
|
|
|
|
|
- Two environment variables need to be set, RAX_CREDS and RAX_REGION.
|
|
|
|
|
- RAX_CREDS points to a credentials file appropriate for pyrax
|
|
|
|
|
- RAX_REGION defines a Rackspace Public Cloud region (DFW, ORD, LON, ...)
|
|
|
|
|
- RAX_CREDS_FILE is an optional environment variable that points to a pyrax-compatible credentials file.
|
|
|
|
|
- If RAX_CREDS_FILE is not supplied, rax.py will look for a credentials file at ~/.rackspace_cloud_credentials.
|
|
|
|
|
- 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" ]
|
|
|
|
|
examples:
|
|
|
|
|
- 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
|
|
|
|
|
- description: List server instance properties
|
|
|
|
|
code: RAX_CREDS_FILE=~/.raxpub RAX_REGION=ORD rax.py --host <HOST_IP>
|
|
|
|
|
- description: List servers in ORD and DFW datacenters
|
|
|
|
|
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 re
|
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import collections
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import json
|
|
|
|
|
@ -91,69 +101,129 @@ except ImportError:
|
|
|
|
|
print('pyrax required for this module')
|
|
|
|
|
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
|
|
|
|
|
print(json.dumps(groups))
|
|
|
|
|
def host(regions, hostname):
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
|
|
# Get the deets for the instance asked for
|
|
|
|
|
results = {}
|
|
|
|
|
# This should be only one, but loop anyway
|
|
|
|
|
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)
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|