Merge pull request #8500 from sivel/rax-de-dupe
rax: Move additional shared code into module utils
This commit is contained in:
commit
d0205b2878
17 changed files with 232 additions and 400 deletions
|
@ -25,11 +25,13 @@ import shlex
|
|||
from ansible import errors
|
||||
from ansible import utils
|
||||
from ansible import constants as C
|
||||
from ansible import __version__
|
||||
|
||||
REPLACER = "#<<INCLUDE_ANSIBLE_MODULE_COMMON>>"
|
||||
REPLACER_ARGS = "\"<<INCLUDE_ANSIBLE_MODULE_ARGS>>\""
|
||||
REPLACER_COMPLEX = "\"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>\""
|
||||
REPLACER_WINDOWS = "# POWERSHELL_COMMON"
|
||||
REPLACER_VERSION = "\"<<ANSIBLE_VERSION>>\""
|
||||
|
||||
class ModuleReplacer(object):
|
||||
|
||||
|
@ -156,6 +158,7 @@ class ModuleReplacer(object):
|
|||
encoded_complex = repr(complex_args_json)
|
||||
|
||||
# these strings should be part of the 'basic' snippet which is required to be included
|
||||
module_data = module_data.replace(REPLACER_VERSION, repr(__version__))
|
||||
module_data = module_data.replace(REPLACER_ARGS, encoded_args)
|
||||
module_data = module_data.replace(REPLACER_COMPLEX, encoded_complex)
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
# == BEGIN DYNAMICALLY INSERTED CODE ==
|
||||
|
||||
ANSIBLE_VERSION = "<<ANSIBLE_VERSION>>"
|
||||
|
||||
MODULE_ARGS = "<<INCLUDE_ANSIBLE_MODULE_ARGS>>"
|
||||
MODULE_COMPLEX_ARGS = "<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>"
|
||||
|
||||
|
|
|
@ -1,32 +1,197 @@
|
|||
# This code is part of Ansible, but is an independent component.
|
||||
# This particular file snippet, and this file snippet only, is BSD licensed.
|
||||
# Modules you write using this snippet, which is embedded dynamically by Ansible
|
||||
# still belong to the author of the module, and may assign their own license
|
||||
# to the complete work.
|
||||
# Modules you write using this snippet, which is embedded dynamically by
|
||||
# Ansible still belong to the author of the module, and may assign their own
|
||||
# license to the complete work.
|
||||
#
|
||||
# Copyright (c), Michael DeHaan <michael.dehaan@gmail.com>, 2012-2013
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
|
||||
FINAL_STATUSES = ('ACTIVE', 'ERROR')
|
||||
VOLUME_STATUS = ('available', 'attaching', 'creating', 'deleting', 'in-use',
|
||||
'error', 'error_deleting')
|
||||
|
||||
CLB_ALGORITHMS = ['RANDOM', 'LEAST_CONNECTIONS', 'ROUND_ROBIN',
|
||||
'WEIGHTED_LEAST_CONNECTIONS', 'WEIGHTED_ROUND_ROBIN']
|
||||
CLB_PROTOCOLS = ['DNS_TCP', 'DNS_UDP', 'FTP', 'HTTP', 'HTTPS', 'IMAPS',
|
||||
'IMAPv4', 'LDAP', 'LDAPS', 'MYSQL', 'POP3', 'POP3S', 'SMTP',
|
||||
'TCP', 'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP']
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, type(None))
|
||||
PUBLIC_NET_ID = "00000000-0000-0000-0000-000000000000"
|
||||
SERVICE_NET_ID = "11111111-1111-1111-1111-111111111111"
|
||||
|
||||
|
||||
def rax_slugify(value):
|
||||
"""Prepend a key with rax_ and normalize the key name"""
|
||||
return 'rax_%s' % (re.sub('[^\w-]', '_', value).lower().lstrip('_'))
|
||||
|
||||
|
||||
def rax_clb_node_to_dict(obj):
|
||||
"""Function to convert a CLB Node object to a dict"""
|
||||
if not obj:
|
||||
return {}
|
||||
node = obj.to_dict()
|
||||
node['id'] = obj.id
|
||||
node['weight'] = obj.weight
|
||||
return node
|
||||
|
||||
|
||||
def rax_to_dict(obj, obj_type='standard'):
|
||||
"""Generic function to convert a pyrax object to a dict
|
||||
|
||||
obj_type values:
|
||||
standard
|
||||
clb
|
||||
server
|
||||
|
||||
"""
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if obj_type == 'clb' and key == 'nodes':
|
||||
instance[key] = []
|
||||
for node in value:
|
||||
instance[key].append(rax_clb_node_to_dict(node))
|
||||
elif (isinstance(value, list) and len(value) > 0 and
|
||||
not isinstance(value[0], NON_CALLABLES)):
|
||||
instance[key] = []
|
||||
for item in value:
|
||||
instance[key].append(rax_to_dict(item))
|
||||
elif (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
if obj_type == 'server':
|
||||
key = rax_slugify(key)
|
||||
instance[key] = value
|
||||
|
||||
if obj_type == 'server':
|
||||
for attr in ['id', 'accessIPv4', 'name', 'status']:
|
||||
instance[attr] = instance.get(rax_slugify(attr))
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def rax_find_image(module, rax_module, image):
|
||||
cs = rax_module.cloudservers
|
||||
try:
|
||||
UUID(image)
|
||||
except ValueError:
|
||||
try:
|
||||
image = cs.images.find(human_id=image)
|
||||
except(cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
try:
|
||||
image = cs.images.find(name=image)
|
||||
except (cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
module.fail_json(msg='No matching image found (%s)' %
|
||||
image)
|
||||
|
||||
return rax_module.utils.get_id(image)
|
||||
|
||||
|
||||
def rax_find_volume(module, rax_module, name):
|
||||
cbs = rax_module.cloud_blockstorage
|
||||
try:
|
||||
UUID(name)
|
||||
volume = cbs.get(name)
|
||||
except ValueError:
|
||||
try:
|
||||
volume = cbs.find(name=name)
|
||||
except rax_module.exc.NotFound:
|
||||
volume = None
|
||||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e)
|
||||
return volume
|
||||
|
||||
|
||||
def rax_find_network(module, rax_module, network):
|
||||
cnw = rax_module.cloud_networks
|
||||
try:
|
||||
UUID(network)
|
||||
except ValueError:
|
||||
if network.lower() == 'public':
|
||||
return cnw.get_server_networks(PUBLIC_NET_ID)
|
||||
elif network.lower() == 'private':
|
||||
return cnw.get_server_networks(SERVICE_NET_ID)
|
||||
else:
|
||||
try:
|
||||
network_obj = cnw.find_network_by_label(network)
|
||||
except (rax_module.exceptions.NetworkNotFound,
|
||||
rax_module.exceptions.NetworkLabelNotUnique):
|
||||
module.fail_json(msg='No matching network found (%s)' %
|
||||
network)
|
||||
else:
|
||||
return cnw.get_server_networks(network_obj)
|
||||
else:
|
||||
return cnw.get_server_networks(network)
|
||||
|
||||
|
||||
def rax_find_server(module, rax_module, server):
|
||||
cs = rax_module.cloudservers
|
||||
try:
|
||||
UUID(server)
|
||||
server = cs.servers.get(server)
|
||||
except ValueError:
|
||||
servers = cs.servers.list(search_opts=dict(name='^%s$' % server))
|
||||
if not servers:
|
||||
module.fail_json(msg='No Server was matched by name, '
|
||||
'try using the Server ID instead')
|
||||
if len(servers) > 1:
|
||||
module.fail_json(msg='Multiple servers matched by name, '
|
||||
'try using the Server ID instead')
|
||||
|
||||
# We made it this far, grab the first and hopefully only server
|
||||
# in the list
|
||||
server = servers[0]
|
||||
return server
|
||||
|
||||
|
||||
def rax_find_loadbalancer(module, rax_module, loadbalancer):
|
||||
clb = rax_module.cloud_loadbalancers
|
||||
try:
|
||||
UUID(loadbalancer)
|
||||
found = clb.get(loadbalancer)
|
||||
except:
|
||||
for lb in clb.list():
|
||||
if loadbalancer == lb.name:
|
||||
found.append(lb)
|
||||
|
||||
if not found:
|
||||
module.fail_json(msg='No loadbalancer was matched')
|
||||
|
||||
if len(found) > 1:
|
||||
module.fail_json(msg='Multiple loadbalancers matched')
|
||||
|
||||
# We made it this far, grab the first and hopefully only item
|
||||
# in the list
|
||||
found = found[0]
|
||||
|
||||
return found
|
||||
|
||||
import os
|
||||
|
||||
def rax_argument_spec():
|
||||
return dict(
|
||||
|
@ -48,6 +213,9 @@ def rax_required_together():
|
|||
|
||||
|
||||
def setup_rax_module(module, rax_module):
|
||||
rax_module.USER_AGENT = 'ansible/%s %s' % (ANSIBLE_VERSION,
|
||||
rax_module.USER_AGENT)
|
||||
|
||||
api_key = module.params.get('api_key')
|
||||
auth_endpoint = module.params.get('auth_endpoint')
|
||||
credentials = module.params.get('credentials')
|
||||
|
@ -102,4 +270,7 @@ def setup_rax_module(module, rax_module):
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
rax_module.USER_AGENT = 'ansible/%s %s' % (ANSIBLE_VERSION,
|
||||
rax_module.USER_AGENT)
|
||||
|
||||
return rax_module
|
||||
|
|
|
@ -194,44 +194,12 @@ EXAMPLES = '''
|
|||
register: rax
|
||||
'''
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
from uuid import UUID
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
ACTIVE_STATUSES = ('ACTIVE', 'BUILD', 'HARD_REBOOT', 'MIGRATING', 'PASSWORD',
|
||||
'REBOOT', 'REBUILD', 'RESCUE', 'RESIZE', 'REVERT_RESIZE')
|
||||
FINAL_STATUSES = ('ACTIVE', 'ERROR')
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
PUBLIC_NET_ID = "00000000-0000-0000-0000-000000000000"
|
||||
SERVICE_NET_ID = "11111111-1111-1111-1111-111111111111"
|
||||
|
||||
|
||||
def rax_slugify(value):
|
||||
return 'rax_%s' % (re.sub('[^\w-]', '_', value).lower().lstrip('_'))
|
||||
|
||||
|
||||
def server_to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
key = rax_slugify(key)
|
||||
instance[key] = value
|
||||
|
||||
for attr in ['id', 'accessIPv4', 'name', 'status']:
|
||||
instance[attr] = instance.get(rax_slugify(attr))
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def create(module, names=[], flavor=None, image=None, meta={}, key_name=None,
|
||||
files={}, wait=True, wait_timeout=300, disk_config=None,
|
||||
|
@ -251,7 +219,7 @@ def create(module, names=[], flavor=None, image=None, meta={}, key_name=None,
|
|||
except Exception, e:
|
||||
module.fail_json(msg='Failed to load %s' % user_data)
|
||||
|
||||
# Handle the file contents
|
||||
# Handle the file contents
|
||||
for rpath in files.keys():
|
||||
lpath = os.path.expanduser(files[rpath])
|
||||
try:
|
||||
|
@ -299,7 +267,7 @@ def create(module, names=[], flavor=None, image=None, meta={}, key_name=None,
|
|||
server.get()
|
||||
except:
|
||||
server.status == 'ERROR'
|
||||
instance = server_to_dict(server)
|
||||
instance = rax_to_dict(server, 'server')
|
||||
if server.status == 'ACTIVE' or not wait:
|
||||
success.append(instance)
|
||||
elif server.status == 'ERROR':
|
||||
|
@ -307,7 +275,7 @@ def create(module, names=[], flavor=None, image=None, meta={}, key_name=None,
|
|||
elif wait:
|
||||
timeout.append(instance)
|
||||
|
||||
untouched = [server_to_dict(s) for s in existing]
|
||||
untouched = [rax_to_dict(s, 'server') for s in existing]
|
||||
instances = success + untouched
|
||||
|
||||
results = {
|
||||
|
@ -354,7 +322,7 @@ def delete(module, instance_ids=[], wait=True, wait_timeout=300, kept=[]):
|
|||
else:
|
||||
changed = True
|
||||
|
||||
instance = server_to_dict(server)
|
||||
instance = rax_to_dict(server, 'server')
|
||||
instances[instance['id']] = instance
|
||||
|
||||
# If requested, wait for server deletion
|
||||
|
@ -384,7 +352,7 @@ def delete(module, instance_ids=[], wait=True, wait_timeout=300, kept=[]):
|
|||
success = filter(lambda s: s['status'] in ('', 'DELETED'),
|
||||
instances.values())
|
||||
|
||||
instances = [server_to_dict(s) for s in kept]
|
||||
instances = [rax_to_dict(s, 'server') for s in kept]
|
||||
|
||||
results = {
|
||||
'changed': changed,
|
||||
|
@ -451,48 +419,13 @@ def cloudservers(module, state=None, name=None, flavor=None, image=None,
|
|||
state = 'present'
|
||||
was_absent = True
|
||||
|
||||
# Check if the provided image is a UUID and if not, search for an
|
||||
# appropriate image using human_id and name
|
||||
if image:
|
||||
try:
|
||||
UUID(image)
|
||||
except ValueError:
|
||||
try:
|
||||
image = cs.images.find(human_id=image)
|
||||
except(cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
try:
|
||||
image = cs.images.find(name=image)
|
||||
except (cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
module.fail_json(msg='No matching image found (%s)' %
|
||||
image)
|
||||
image = rax_find_image(module, pyrax, image)
|
||||
|
||||
image = pyrax.utils.get_id(image)
|
||||
|
||||
# Check if the provided network is a UUID and if not, search for an
|
||||
# appropriate network using label
|
||||
nics = []
|
||||
if networks:
|
||||
for network in networks:
|
||||
try:
|
||||
UUID(network)
|
||||
except ValueError:
|
||||
if network.lower() == 'public':
|
||||
nics.extend(cnw.get_server_networks(PUBLIC_NET_ID))
|
||||
elif network.lower() == 'private':
|
||||
nics.extend(cnw.get_server_networks(SERVICE_NET_ID))
|
||||
else:
|
||||
try:
|
||||
network_obj = cnw.find_network_by_label(network)
|
||||
except (pyrax.exceptions.NetworkNotFound,
|
||||
pyrax.exceptions.NetworkLabelNotUnique):
|
||||
module.fail_json(msg='No matching network found (%s)' %
|
||||
network)
|
||||
else:
|
||||
nics.extend(cnw.get_server_networks(network_obj))
|
||||
else:
|
||||
nics.extend(cnw.get_server_networks(network))
|
||||
nics.extend(rax_find_network(module, pyrax, network))
|
||||
|
||||
# act on the state
|
||||
if state == 'present':
|
||||
|
@ -568,7 +501,7 @@ def cloudservers(module, state=None, name=None, flavor=None, image=None,
|
|||
instances = []
|
||||
instance_ids = []
|
||||
for server in servers:
|
||||
instances.append(server_to_dict(server))
|
||||
instances.append(rax_to_dict(server, 'server'))
|
||||
instance_ids.append(server.id)
|
||||
module.exit_json(changed=False, action=None,
|
||||
instances=instances,
|
||||
|
@ -623,7 +556,7 @@ def cloudservers(module, state=None, name=None, flavor=None, image=None,
|
|||
if len(servers) >= count:
|
||||
instances = []
|
||||
for server in servers:
|
||||
instances.append(server_to_dict(server))
|
||||
instances.append(rax_to_dict(server, 'server'))
|
||||
|
||||
instance_ids = [i['id'] for i in instances]
|
||||
module.exit_json(changed=False, action=None,
|
||||
|
@ -774,5 +707,5 @@ def main():
|
|||
from ansible.module_utils.basic import *
|
||||
from ansible.module_utils.rax import *
|
||||
|
||||
### invoke the module
|
||||
# invoke the module
|
||||
main()
|
||||
|
|
|
@ -99,21 +99,12 @@ EXAMPLES = '''
|
|||
register: my_volume
|
||||
'''
|
||||
|
||||
import sys
|
||||
|
||||
from uuid import UUID
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
VOLUME_STATUS = ('available', 'attaching', 'creating', 'deleting', 'in-use',
|
||||
'error', 'error_deleting')
|
||||
|
||||
|
||||
def cloud_block_storage(module, state, name, description, meta, size,
|
||||
snapshot_id, volume_type, wait, wait_timeout):
|
||||
|
@ -135,16 +126,7 @@ def cloud_block_storage(module, state, name, description, meta, size,
|
|||
'typically indicates an invalid region or an '
|
||||
'incorrectly capitalized region name.')
|
||||
|
||||
try:
|
||||
UUID(name)
|
||||
volume = cbs.get(name)
|
||||
except ValueError:
|
||||
try:
|
||||
volume = cbs.find(name=name)
|
||||
except pyrax.exc.NotFound:
|
||||
pass
|
||||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e)
|
||||
volume = rax_find_volume(module, pyrax, name)
|
||||
|
||||
if state == 'present':
|
||||
if not volume:
|
||||
|
|
|
@ -81,19 +81,12 @@ EXAMPLES = '''
|
|||
register: my_volume
|
||||
'''
|
||||
|
||||
import sys
|
||||
|
||||
from uuid import UUID
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
|
||||
|
||||
def cloud_block_storage_attachments(module, state, volume, server, device,
|
||||
wait, wait_timeout):
|
||||
|
@ -113,34 +106,13 @@ def cloud_block_storage_attachments(module, state, volume, server, device,
|
|||
changed = False
|
||||
instance = {}
|
||||
|
||||
try:
|
||||
UUID(volume)
|
||||
volume = cbs.get(volume)
|
||||
except ValueError:
|
||||
try:
|
||||
volume = cbs.find(name=volume)
|
||||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e)
|
||||
volume = rax_find_volume(module, pyrax, volume)
|
||||
|
||||
if not volume:
|
||||
module.fail_json(msg='No matching storage volumes were found')
|
||||
|
||||
if state == 'present':
|
||||
try:
|
||||
UUID(server)
|
||||
server = cs.servers.get(server)
|
||||
except ValueError:
|
||||
servers = cs.servers.list(search_opts=dict(name='^%s$' % server))
|
||||
if not servers:
|
||||
module.fail_json(msg='No Server was matched by name, '
|
||||
'try using the Server ID instead')
|
||||
if len(servers) > 1:
|
||||
module.fail_json(msg='Multiple servers matched by name, '
|
||||
'try using the Server ID instead')
|
||||
|
||||
# We made it this far, grab the first and hopefully only server
|
||||
# in the list
|
||||
server = servers[0]
|
||||
server = rax_find_server(module, pyrax, server)
|
||||
|
||||
if (volume.attachments and
|
||||
volume.attachments[0]['server_id'] == server.id):
|
||||
|
@ -176,21 +148,7 @@ def cloud_block_storage_attachments(module, state, volume, server, device,
|
|||
module.exit_json(**result)
|
||||
|
||||
elif state == 'absent':
|
||||
try:
|
||||
UUID(server)
|
||||
server = cs.servers.get(server)
|
||||
except ValueError:
|
||||
servers = cs.servers.list(search_opts=dict(name='^%s$' % server))
|
||||
if not servers:
|
||||
module.fail_json(msg='No Server was matched by name, '
|
||||
'try using the Server ID instead')
|
||||
if len(servers) > 1:
|
||||
module.fail_json(msg='Multiple servers matched by name, '
|
||||
'try using the Server ID instead')
|
||||
|
||||
# We made it this far, grab the first and hopefully only server
|
||||
# in the list
|
||||
server = servers[0]
|
||||
server = rax_find_server(module, pyrax, server)
|
||||
|
||||
if (volume.attachments and
|
||||
volume.attachments[0]['server_id'] == server.id):
|
||||
|
|
|
@ -130,7 +130,6 @@ EXAMPLES = '''
|
|||
register: my_lb
|
||||
'''
|
||||
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
|
@ -138,42 +137,6 @@ try:
|
|||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
ALGORITHMS = ['RANDOM', 'LEAST_CONNECTIONS', 'ROUND_ROBIN',
|
||||
'WEIGHTED_LEAST_CONNECTIONS', 'WEIGHTED_ROUND_ROBIN']
|
||||
PROTOCOLS = ['DNS_TCP', 'DNS_UDP', 'FTP', 'HTTP', 'HTTPS', 'IMAPS', 'IMAPv4',
|
||||
'LDAP', 'LDAPS', 'MYSQL', 'POP3', 'POP3S', 'SMTP', 'TCP',
|
||||
'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP']
|
||||
|
||||
|
||||
def node_to_dict(obj):
|
||||
node = obj.to_dict()
|
||||
node['id'] = obj.id
|
||||
return node
|
||||
|
||||
|
||||
def to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if key == 'virtual_ips':
|
||||
instance[key] = []
|
||||
for vip in value:
|
||||
vip_dict = {}
|
||||
for vip_key, vip_value in vars(vip).iteritems():
|
||||
if isinstance(vip_value, NON_CALLABLES):
|
||||
vip_dict[vip_key] = vip_value
|
||||
instance[key].append(vip_dict)
|
||||
elif key == 'nodes':
|
||||
instance[key] = []
|
||||
for node in value:
|
||||
instance[key].append(node_to_dict(node))
|
||||
elif (isinstance(value, NON_CALLABLES) and
|
||||
not key.startswith('_')):
|
||||
instance[key] = value
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol,
|
||||
vip_type, timeout, wait, wait_timeout, vip_id):
|
||||
|
@ -252,7 +215,7 @@ def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol,
|
|||
pyrax.utils.wait_for_build(balancer, interval=5, attempts=attempts)
|
||||
|
||||
balancer.get()
|
||||
instance = to_dict(balancer)
|
||||
instance = rax_to_dict(balancer, 'clb')
|
||||
|
||||
result = dict(changed=changed, balancer=instance)
|
||||
|
||||
|
@ -275,7 +238,7 @@ def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol,
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
instance = to_dict(balancer)
|
||||
instance = rax_to_dict(balancer, 'clb')
|
||||
|
||||
if wait:
|
||||
attempts = wait_timeout / 5
|
||||
|
@ -291,11 +254,12 @@ def main():
|
|||
argument_spec = rax_argument_spec()
|
||||
argument_spec.update(
|
||||
dict(
|
||||
algorithm=dict(choices=ALGORITHMS, default='LEAST_CONNECTIONS'),
|
||||
algorithm=dict(choices=CLB_ALGORITHMS,
|
||||
default='LEAST_CONNECTIONS'),
|
||||
meta=dict(type='dict', default={}),
|
||||
name=dict(),
|
||||
port=dict(type='int', default=80),
|
||||
protocol=dict(choices=PROTOCOLS, default='HTTP'),
|
||||
protocol=dict(choices=CLB_PROTOCOLS, default='HTTP'),
|
||||
state=dict(default='present', choices=['present', 'absent']),
|
||||
timeout=dict(type='int', default=30),
|
||||
type=dict(choices=['PUBLIC', 'SERVICENET'], default='PUBLIC'),
|
||||
|
|
|
@ -120,8 +120,6 @@ EXAMPLES = '''
|
|||
credentials: /path/to/credentials
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
|
@ -167,20 +165,6 @@ def _get_primary_nodes(lb):
|
|||
return nodes
|
||||
|
||||
|
||||
def _node_to_dict(node):
|
||||
"""Return a dictionary containing node details"""
|
||||
if not node:
|
||||
return {}
|
||||
return {
|
||||
'address': node.address,
|
||||
'condition': node.condition,
|
||||
'id': node.id,
|
||||
'port': node.port,
|
||||
'type': node.type,
|
||||
'weight': node.weight,
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = rax_argument_spec()
|
||||
argument_spec.update(
|
||||
|
@ -241,7 +225,7 @@ def main():
|
|||
|
||||
node = _get_node(lb, node_id, address, port)
|
||||
|
||||
result = _node_to_dict(node)
|
||||
result = rax_clb_node_to_dict(node)
|
||||
|
||||
if state == 'absent':
|
||||
if not node: # Removing a non-existent node
|
||||
|
|
|
@ -66,25 +66,12 @@ EXAMPLES = '''
|
|||
register: rax_dns
|
||||
'''
|
||||
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
|
||||
|
||||
def to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_dns(module, comment, email, name, state, ttl):
|
||||
changed = False
|
||||
|
@ -144,7 +131,7 @@ def rax_dns(module, comment, email, name, state, ttl):
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
module.exit_json(changed=changed, domain=to_dict(domain))
|
||||
module.exit_json(changed=changed, domain=rax_to_dict(domain))
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -113,65 +113,30 @@ EXAMPLES = '''
|
|||
register: ptr_record
|
||||
'''
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, type(None))
|
||||
|
||||
|
||||
def to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_dns_record_ptr(module, data=None, comment=None, loadbalancer=None,
|
||||
name=None, server=None, state='present', ttl=7200):
|
||||
"""Function for manipulating DNS PTR records"""
|
||||
|
||||
changed = False
|
||||
results = []
|
||||
|
||||
cs = pyrax.cloudservers
|
||||
clb = pyrax.cloud_loadbalancers
|
||||
dns = pyrax.cloud_dns
|
||||
|
||||
if not cs or not clb or not dns:
|
||||
if not dns:
|
||||
module.fail_json(msg='Failed to instantiate client. This '
|
||||
'typically indicates an invalid region or an '
|
||||
'incorrectly capitalized region name.')
|
||||
|
||||
if loadbalancer:
|
||||
try:
|
||||
UUID(loadbalancer)
|
||||
found = [clb.get(loadbalancer)]
|
||||
except:
|
||||
for lb in clb.list():
|
||||
if loadbalancer == lb.name:
|
||||
found.append(lb)
|
||||
|
||||
if len(found) != 1:
|
||||
module.fail_json(msg='Could not match a loadbalancer with %s' %
|
||||
loadbalancer)
|
||||
item = rax_find_loadbalancer(module, pyrax, loadbalancer)
|
||||
elif server:
|
||||
try:
|
||||
UUID(server)
|
||||
found = [cs.servers.get(server)]
|
||||
except:
|
||||
found = cs.servers.list(search_opts=dict(name='^%s$' % server))
|
||||
if len(found) != 1:
|
||||
module.fail_json(msg='Could not match a server with %s' %
|
||||
server)
|
||||
item = rax_find_server(module, pyrax, server)
|
||||
|
||||
item = found[0]
|
||||
if state == 'present':
|
||||
current = dns.list_ptr_records(item)
|
||||
for record in current:
|
||||
|
@ -184,10 +149,10 @@ def rax_dns_record_ptr(module, data=None, comment=None, loadbalancer=None,
|
|||
module.fail_json(msg='%s' % e.message)
|
||||
record.ttl = ttl
|
||||
record.name = name
|
||||
results.append(to_dict(record))
|
||||
results.append(rax_to_dict(record))
|
||||
break
|
||||
else:
|
||||
results.append(to_dict(record))
|
||||
results.append(rax_to_dict(record))
|
||||
break
|
||||
|
||||
if not results:
|
||||
|
@ -205,7 +170,7 @@ def rax_dns_record_ptr(module, data=None, comment=None, loadbalancer=None,
|
|||
current = dns.list_ptr_records(item)
|
||||
for record in current:
|
||||
if record.data == data:
|
||||
results.append(to_dict(record))
|
||||
results.append(rax_to_dict(record))
|
||||
break
|
||||
|
||||
if results:
|
||||
|
@ -301,7 +266,7 @@ def rax_dns_record(module, comment=None, data=None, domain=None, name=None,
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
module.exit_json(changed=changed, record=to_dict(record))
|
||||
module.exit_json(changed=changed, record=rax_to_dict(record))
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -55,30 +55,12 @@ EXAMPLES = '''
|
|||
ansible_ssh_host: "{{ rax_accessipv4 }}"
|
||||
'''
|
||||
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
|
||||
|
||||
def rax_slugify(value):
|
||||
return 'rax_%s' % (re.sub('[^\w-]', '_', value).lower().lstrip('_'))
|
||||
|
||||
|
||||
def pyrax_object_to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
key = rax_slugify(key)
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_facts(module, address, name, server_id):
|
||||
changed = False
|
||||
|
@ -120,7 +102,7 @@ def rax_facts(module, address, name, server_id):
|
|||
module.fail_json(msg='Multiple servers found matching provided '
|
||||
'search parameters')
|
||||
elif len(servers) == 1:
|
||||
ansible_facts = pyrax_object_to_dict(servers[0])
|
||||
ansible_facts = rax_to_dict(servers[0], 'server')
|
||||
|
||||
module.exit_json(changed=changed, ansible_facts=ansible_facts)
|
||||
|
||||
|
|
|
@ -139,8 +139,6 @@ EXAMPLES = '''
|
|||
file_for: ""
|
||||
'''
|
||||
|
||||
from ansible import __version__
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
|
@ -149,7 +147,6 @@ except ImportError, e:
|
|||
|
||||
EXIT_DICT = dict(success=True)
|
||||
META_PREFIX = 'x-container-meta-'
|
||||
USER_AGENT = "Ansible/%s via pyrax" % __version__
|
||||
|
||||
|
||||
def _get_container(module, cf, container):
|
||||
|
@ -321,8 +318,6 @@ def cloudfiles(module, container_, state, meta_, clear_meta, typ, ttl, public,
|
|||
'typically indicates an invalid region or an '
|
||||
'incorrectly capitalized region name.')
|
||||
|
||||
cf.user_agent = USER_AGENT
|
||||
|
||||
if typ == "container":
|
||||
container(cf, module, container_, state, meta_, clear_meta, ttl,
|
||||
public, private, web_index, web_error)
|
||||
|
|
|
@ -183,8 +183,6 @@ EXAMPLES = '''
|
|||
rax_files_objects: container=testcont type=meta
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
|
|
|
@ -47,8 +47,6 @@ EXAMPLES = '''
|
|||
register: rackspace_identity
|
||||
'''
|
||||
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
|
@ -56,9 +54,6 @@ except ImportError:
|
|||
HAS_PYRAX = False
|
||||
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
|
||||
|
||||
def cloud_identity(module, state, identity):
|
||||
for arg in (state, identity):
|
||||
if not arg:
|
||||
|
@ -70,10 +65,8 @@ def cloud_identity(module, state, identity):
|
|||
)
|
||||
changed = False
|
||||
|
||||
for key, value in vars(identity).iteritems():
|
||||
if (isinstance(value, NON_CALLABLES) and
|
||||
not key.startswith('_')):
|
||||
instance[key] = value
|
||||
instance.update(rax_to_dict(identity))
|
||||
instance['services'] = instance.get('services', {}).keys()
|
||||
|
||||
if state == 'present':
|
||||
if not identity.authenticated:
|
||||
|
|
|
@ -84,25 +84,12 @@ EXAMPLES = '''
|
|||
register: keypair
|
||||
'''
|
||||
|
||||
from types import NoneType
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
|
||||
|
||||
|
||||
def to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_keypair(module, name, public_key, state):
|
||||
changed = False
|
||||
|
@ -149,7 +136,7 @@ def rax_keypair(module, name, public_key, state):
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
module.exit_json(changed=changed, keypair=to_dict(keypair))
|
||||
module.exit_json(changed=changed, keypair=rax_to_dict(keypair))
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -118,34 +118,12 @@ EXAMPLES = '''
|
|||
register: asg
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, type(None))
|
||||
PUBLIC_NET_ID = "00000000-0000-0000-0000-000000000000"
|
||||
SERVICE_NET_ID = "11111111-1111-1111-1111-111111111111"
|
||||
|
||||
|
||||
def asg_to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if key == 'policies' and isinstance(value, list):
|
||||
policies = []
|
||||
for policy in value:
|
||||
policies.append(asg_to_dict(policy))
|
||||
instance[key] = policies
|
||||
elif (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None,
|
||||
image=None, key_name=None, loadbalancers=[], meta={},
|
||||
|
@ -172,48 +150,13 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None,
|
|||
elif not isinstance(v, basestring):
|
||||
meta[k] = '%s' % v
|
||||
|
||||
# Check if the provided image is a UUID and if not, search for an
|
||||
# appropriate image using human_id and name
|
||||
if image:
|
||||
try:
|
||||
UUID(image)
|
||||
except ValueError:
|
||||
try:
|
||||
image = cs.images.find(human_id=image)
|
||||
except(cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
try:
|
||||
image = cs.images.find(name=image)
|
||||
except (cs.exceptions.NotFound,
|
||||
cs.exceptions.NoUniqueMatch):
|
||||
module.fail_json(msg='No matching image found (%s)' %
|
||||
image)
|
||||
image = rax_find_image(module, pyrax, image)
|
||||
|
||||
image = pyrax.utils.get_id(image)
|
||||
|
||||
# Check if the provided network is a UUID and if not, search for an
|
||||
# appropriate network using label
|
||||
nics = []
|
||||
if networks:
|
||||
for network in networks:
|
||||
try:
|
||||
UUID(network)
|
||||
except ValueError:
|
||||
if network.lower() == 'public':
|
||||
nics.extend(cnw.get_server_networks(PUBLIC_NET_ID))
|
||||
elif network.lower() == 'private':
|
||||
nics.extend(cnw.get_server_networks(SERVICE_NET_ID))
|
||||
else:
|
||||
try:
|
||||
network_obj = cnw.find_network_by_label(network)
|
||||
except (pyrax.exceptions.NetworkNotFound,
|
||||
pyrax.exceptions.NetworkLabelNotUnique):
|
||||
module.fail_json(msg='No matching network found '
|
||||
'(%s)' % network)
|
||||
else:
|
||||
nics.extend(cnw.get_server_networks(network_obj))
|
||||
else:
|
||||
nics.extend(cnw.get_server_networks(network))
|
||||
nics.extend(rax_find_network(module, pyrax, network))
|
||||
|
||||
for nic in nics:
|
||||
# pyrax is currently returning net-id, but we need uuid
|
||||
|
@ -322,7 +265,7 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None,
|
|||
|
||||
sg.get()
|
||||
|
||||
module.exit_json(changed=changed, autoscale_group=asg_to_dict(sg))
|
||||
module.exit_json(changed=changed, autoscale_group=rax_to_dict(sg))
|
||||
|
||||
else:
|
||||
try:
|
||||
|
@ -334,7 +277,7 @@ def rax_asg(module, cooldown=300, disk_config=None, files={}, flavor=None,
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
module.exit_json(changed=changed, autoscale_group=asg_to_dict(sg))
|
||||
module.exit_json(changed=changed, autoscale_group=rax_to_dict(sg))
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -118,27 +118,12 @@ EXAMPLES = '''
|
|||
register: asp_webhook
|
||||
'''
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
try:
|
||||
import pyrax
|
||||
HAS_PYRAX = True
|
||||
except ImportError:
|
||||
HAS_PYRAX = False
|
||||
|
||||
NON_CALLABLES = (basestring, bool, dict, int, list, type(None))
|
||||
PUBLIC_NET_ID = "00000000-0000-0000-0000-000000000000"
|
||||
SERVICE_NET_ID = "11111111-1111-1111-1111-111111111111"
|
||||
|
||||
|
||||
def to_dict(obj):
|
||||
instance = {}
|
||||
for key in dir(obj):
|
||||
value = getattr(obj, key)
|
||||
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
|
||||
instance[key] = value
|
||||
return instance
|
||||
|
||||
|
||||
def rax_asp(module, at=None, change=0, cron=None, cooldown=300,
|
||||
desired_capacity=0, is_percent=False, name=None,
|
||||
|
@ -220,7 +205,7 @@ def rax_asp(module, at=None, change=0, cron=None, cooldown=300,
|
|||
|
||||
policy.get()
|
||||
|
||||
module.exit_json(changed=changed, autoscale_policy=to_dict(policy))
|
||||
module.exit_json(changed=changed, autoscale_policy=rax_to_dict(policy))
|
||||
|
||||
else:
|
||||
try:
|
||||
|
@ -235,7 +220,7 @@ def rax_asp(module, at=None, change=0, cron=None, cooldown=300,
|
|||
except Exception, e:
|
||||
module.fail_json(msg='%s' % e.message)
|
||||
|
||||
module.exit_json(changed=changed, autoscale_policy=to_dict(policy))
|
||||
module.exit_json(changed=changed, autoscale_policy=rax_to_dict(policy))
|
||||
|
||||
|
||||
def main():
|
||||
|
|
Loading…
Reference in a new issue