#!/usr/bin/python -tt # 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 . DOCUMENTATION = ''' --- module: rax_clb short_description: create / delete a load balancer in Rackspace Public Cloud description: - creates / deletes a Rackspace Public Cloud load balancer. version_added: "1.4" options: state: description: - Indicate desired state of the resource choices: ['present', 'absent'] default: present credentials: description: - File to find the Rackspace credentials in (ignored if C(api_key) and C(username) are provided) default: null aliases: ['creds_file'] api_key: description: - Rackspace API key (overrides C(credentials)) username: description: - Rackspace username (overrides C(credentials)) name: description: - Name to give the load balancer default: null algorithm: description: - algorithm for the balancer being created choices: ['RANDOM', 'LEAST_CONNECTIONS', 'ROUND_ROBIN', 'WEIGHTED_LEAST_CONNECTIONS', 'WEIGHTED_ROUND_ROBIN'] default: LEAST_CONNECTIONS port: description: - Port for the balancer being created default: 80 protocol: description: - Protocol for the balancer being created choices: ['DNS_TCP', 'DNS_UDP' ,'FTP', 'HTTP', 'HTTPS', 'IMAPS', 'IMAPv4', 'LDAP', 'LDAPS', 'MYSQL', 'POP3', 'POP3S', 'SMTP', 'TCP', 'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP'] default: HTTP timeout: description: - timeout for communication between the balancer and the node default: 30 type: description: - type of interface for the balancer being created choices: ['PUBLIC', 'SERVICENET'] default: PUBLIC region: description: - Region to create the load balancer in default: DFW wait: description: - wait for the balancer to be in state 'running' before returning default: "no" choices: [ "yes", "no" ] wait_timeout: description: - how long before wait gives up, in seconds default: 300 requirements: [ "pyrax" ] author: Christopher H. Laco, Jesse Keating notes: - The following environment variables can be used, C(RAX_USERNAME), C(RAX_API_KEY), C(RAX_CREDS), C(RAX_CREDENTIALS), C(RAX_REGION). - C(RAX_CREDENTIALS) and C(RAX_CREDS) points to a credentials file appropriate for pyrax - C(RAX_USERNAME) and C(RAX_API_KEY) obviate the use of a credentials file - C(RAX_REGION) defines a Rackspace Public Cloud region (DFW, ORD, LON, ...) ''' EXAMPLES = ''' - name: Build a Load Balancer gather_facts: False tasks: - name: Provision Load Balancer rax_lb: credentials: ~/.raxpub name: my-lb port: 9000 protocol: HTTP type: SERVICENET timeout: 30 region: DFW wait: yes state: present register: my_lb ''' import sys import os import time try: import pyrax import pyrax.utils from pyrax import exc except ImportError: print("failed=True msg='pyrax required for this module'") sys.exit(1) def cloud_load_balancer(module, state, name, meta, algorithm, port, protocol, type, timeout, wait, wait_timeout): for arg in (state, name, port, protocol, type): if not arg: module.fail_json(msg='%s is required for cloud_loadbalancers' % arg) changed = False balancer = None balancers = [] instances = [] for balancer in pyrax.cloud_loadbalancers.list(): if name != balancer.name: continue balancers.append(balancer) if state == 'present': if not balancers: try: balancers=[pyrax.cloud_loadbalancers.create( name, metadata=meta, algorithm=algorithm, port=port, protocol=protocol, timeout=timeout, virtual_ips=[pyrax.cloud_loadbalancers.VirtualIP(type=type)] )] changed = True except Exception, e: module.fail_json(msg='%s' % e.message) for balancer in balancers: if wait: pyrax.utils.wait_for_build(balancer, interval=5, attempts=5) if balancer.status == 'ACTIVE': instance = dict( id=balancer.id, algorithm=balancer.algorithm, cluster=balancer.cluster, connectionLogging=balancer.connectionLogging, contentCaching=balancer.contentCaching, halfClosed=balancer.halfClosed, port=balancer.port, protocol=balancer.protocol, sourceAddresses=balancer.sourceAddresses, name=balancer.name, timeout=balancer.timeout, status=balancer.status ) instances.append(instance) elif balancer.status == 'ERROR': module.fail_json(msg='%s failed to build' % balancer.id) elif wait: module.fail_json(msg='Timeout waiting on %s' % balancer.id) elif state == 'absent': if balancer: try: balancer.delete() changed = True except Exception, e: module.fail_json(msg='%s' % e.message) instance = dict( id=balancer.id, algorithm=balancer.algorithm, cluster=None, connectionLogging=None, contentCaching=None, halfClosed=None, port=balancer.port, protocol=balancer.protocol, sourceAddresses=None, name=balancer.name, timeout=balancer.timeout, status=balancer.status ) instances.append(instance) module.exit_json(changed=changed, balancers=instances) def main(): module = AnsibleModule( argument_spec=dict( state=dict(default='present', choices=['present', 'absent']), credentials=dict(aliases=['creds_file']), api_key=dict(), username=dict(), region=dict(), name=dict(), meta=dict(type='dict', default={}), algorithm=dict(choices=['RANDOM', 'LEAST_CONNECTIONS', 'ROUND_ROBIN', 'WEIGHTED_LEAST_CONNECTIONS', 'WEIGHTED_ROUND_ROBIN'], default='LEAST_CONNECTIONS'), port=dict(type='int', default=80), protocol=dict(choices=['DNS_TCP', 'DNS_UDP' ,'FTP', 'HTTP', 'HTTPS', 'IMAPS', 'IMAPv4', 'LDAP', 'LDAPS', 'MYSQL', 'POP3', 'POP3S', 'SMTP', 'TCP', 'TCP_CLIENT_FIRST', 'UDP', 'UDP_STREAM', 'SFTP'], default='HTTP'), type=dict(choices=['PUBLIC', 'SERVICENET'], default='PUBLIC'), timeout=dict(type='int', default=30), wait=dict(type='bool'), wait_timeout=dict(default=300) ) ) credentials = module.params.get('credentials') api_key = module.params.get('api_key') username = module.params.get('username') region = module.params.get('region') state = module.params.get('state') name = module.params.get('name') meta = module.params.get('meta') algorithm = module.params.get('algorithm') port = module.params.get('port') protocol = module.params.get('protocol') type = module.params.get('type') timeout = int(module.params.get('timeout')) wait = module.params.get('wait') wait_timeout = int(module.params.get('wait_timeout')) try: username = username or os.environ.get('RAX_USERNAME') api_key = api_key or os.environ.get('RAX_API_KEY') credentials = (credentials or os.environ.get('RAX_CREDENTIALS') or os.environ.get('RAX_CREDS_FILE')) region = region or os.environ.get('RAX_REGION') except KeyError, e: module.fail_json(msg='Unable to load %s' % e.message) try: pyrax.set_setting("identity_type", "rackspace") if api_key and username: pyrax.set_credentials(username, api_key=api_key, region=region) elif credentials: credentials = os.path.expanduser(credentials) pyrax.set_credential_file(credentials, region=region) else: raise Exception('No credentials supplied!') except Exception, e: module.fail_json(msg='%s' % e.message) cloud_load_balancer(module, state, name, meta, algorithm, port, protocol, type, timeout, wait, wait_timeout) # this is magic, see lib/ansible/module_common.py #<> main()