Merge remote-tracking branch 'upstream/devel' into locale

reviewable/pr18780/r1
Augustus Kling 11 years ago
commit eabc9cd775

@ -112,7 +112,7 @@ EXAMPLES = '''
- digital_ocean: >
state=present
command=droplet
name=my_new_droplet
name=mydroplet
client_id=XXX
api_key=XXX
size_id=1
@ -131,7 +131,7 @@ EXAMPLES = '''
state=present
command=droplet
id=123
name=my_new_droplet
name=mydroplet
client_id=XXX
api_key=XXX
size_id=1
@ -147,7 +147,7 @@ EXAMPLES = '''
- digital_ocean: >
state=present
ssh_key_ids=id1,id2
name=my_new_droplet
name=mydroplet
client_id=XXX
api_key=XXX
size_id=1
@ -221,7 +221,7 @@ class Droplet(JsonfyMixIn):
raise TimeoutError('Wait for droplet running timeout', self.id)
def destroy(self):
return self.manager.destroy_droplet(self.id)
return self.manager.destroy_droplet(self.id, scrub_data=True)
@classmethod
def setup(cls, client_id, api_key):

@ -1,5 +1,4 @@
#!/usr/bin/env python
#
#!/usr/bin/python
# (c) 2013, Cove Schneider
#

@ -294,15 +294,6 @@ local_action:
import sys
import time
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
try:
import boto.ec2
from boto.exception import EC2ResponseError
@ -653,24 +644,7 @@ def main():
)
)
# def get_ec2_creds(module):
# return ec2_url, ec2_access_key, ec2_secret_key, region
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
# If we specified an ec2_url then try connecting to it
elif ec2_url:
try:
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
else:
module.fail_json(msg="Either region or ec2_url must be specified")
ec2 = ec2_connect(module)
if module.params.get('state') == 'absent':
instance_ids = module.params.get('instance_ids')

@ -156,15 +156,6 @@ EXAMPLES = '''
import sys
import time
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
try:
import boto
import boto.ec2
@ -279,24 +270,7 @@ def main():
)
)
# def get_ec2_creds(module):
# return ec2_url, ec2_access_key, ec2_secret_key, region
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
# If we specified an ec2_url then try connecting to it
elif ec2_url:
try:
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
else:
module.fail_json(msg="Either region or ec2_url must be specified")
ec2 = ec2_connect(module)
if module.params.get('state') == 'absent':
if not module.params.get('image_id'):

@ -102,38 +102,6 @@ else:
boto_found = True
def connect(ec2_url, ec2_access_key, ec2_secret_key, region, module):
""" Return an ec2 connection"""
# allow environment variables to be used if ansible vars aren't set
if not ec2_url and 'EC2_URL' in os.environ:
ec2_url = os.environ['EC2_URL']
if not ec2_secret_key and 'EC2_SECRET_KEY' in os.environ:
ec2_secret_key = os.environ['EC2_SECRET_KEY']
if not ec2_access_key and 'EC2_ACCESS_KEY' in os.environ:
ec2_access_key = os.environ['EC2_ACCESS_KEY']
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region,
aws_access_key_id=ec2_access_key,
aws_secret_access_key=ec2_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(" %s %s %s " % (region, ec2_access_key,
ec2_secret_key)))
# Otherwise, no region so we fallback to the old connection method
else:
try:
if ec2_url: # if we have an URL set, connect to the specified endpoint
ec2 = boto.connect_ec2_endpoint(ec2_url, ec2_access_key, ec2_secret_key)
else: # otherwise it's Amazon.
ec2 = boto.connect_ec2(ec2_access_key, ec2_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
return ec2
def associate_ip_and_instance(ec2, address, instance_id, module):
if ip_is_associated_with_instance(ec2, address.public_ip, instance_id, module):
module.exit_json(changed=False, public_ip=address.public_ip)
@ -248,8 +216,8 @@ def main():
state = dict(required=False, default='present',
choices=['present', 'absent']),
ec2_url = dict(required=False, aliases=['EC2_URL']),
ec2_secret_key = dict(required=False, aliases=['EC2_SECRET_KEY'], no_log=True),
ec2_access_key = dict(required=False, aliases=['EC2_ACCESS_KEY']),
ec2_secret_key = dict(aliases=['aws_secret_key', 'secret_key'], no_log=True),
ec2_access_key = dict(aliases=['aws_access_key', 'access_key']),
region = dict(required=False, aliases=['ec2_region']),
in_vpc = dict(required=False, choices=BOOLEANS, default=False),
),
@ -259,13 +227,7 @@ def main():
if not boto_found:
module.fail_json(msg="boto is required")
ec2_url, ec2_access_key, ec2_secret_key, region = get_ec2_creds(module)
ec2 = connect(ec2_url,
ec2_access_key,
ec2_secret_key,
region,
module)
ec2 = ec2_connect(module)
instance_id = module.params.get('instance_id')
public_ip = module.params.get('public_ip')

@ -17,9 +17,9 @@
DOCUMENTATION = """
---
module: ec2_elb
short_description: De-registers or registers instances from EC2 ELB(s)
short_description: De-registers or registers instances from EC2 ELBs
description:
- This module de-registers or registers an AWS EC2 instance from the ELB(s)
- This module de-registers or registers an AWS EC2 instance from the ELBs
that it belongs to.
- Returns fact "ec2_elbs" which is a list of elbs attached to the instance
if state=absent is passed as an argument.
@ -32,6 +32,7 @@ options:
description:
- register or deregister the instance
required: true
choices: ['present', 'absent']
instance_id:
description:
@ -102,15 +103,6 @@ import time
import sys
import os
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
try:
import boto
import boto.ec2

@ -113,16 +113,12 @@ def main():
ec2_url=dict(aliases=['EC2_URL']),
ec2_secret_key=dict(aliases=['EC2_SECRET_KEY', 'aws_secret_key'], no_log=True),
ec2_access_key=dict(aliases=['EC2_ACCESS_KEY', 'aws_access_key']),
region=dict(choices=['eu-west-1', 'sa-east-1', 'us-east-1', 'ap-northeast-1', 'us-west-2', 'us-west-1', 'ap-southeast-1', 'ap-southeast-2']),
region=dict(choices=AWS_REGIONS),
state = dict(default='present', choices=['present', 'absent']),
),
supports_check_mode=True,
)
# def get_ec2_creds(module):
# return ec2_url, ec2_access_key, ec2_secret_key, region
ec2_url, ec2_access_key, ec2_secret_key, region = get_ec2_creds(module)
name = module.params['name']
description = module.params['description']
vpc_id = module.params['vpc_id']
@ -131,21 +127,7 @@ def main():
changed = False
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=ec2_access_key, aws_secret_access_key=ec2_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg=str(e))
# Otherwise, no region so we fallback to the old connection method
else:
try:
if ec2_url: # if we have an URL set, connect to the specified endpoint
ec2 = boto.connect_ec2_endpoint(ec2_url, ec2_access_key, ec2_secret_key)
else: # otherwise it's Amazon.
ec2 = boto.connect_ec2(ec2_access_key, ec2_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg=str(e))
ec2 = ec2_connect(module)
# find the group if present
group = None

@ -102,15 +102,6 @@ except ImportError:
print "failed=True msg='boto required for this module'"
sys.exit(1)
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
def main():
module = AnsibleModule(
argument_spec = dict(
@ -124,28 +115,11 @@ def main():
)
)
# def get_ec2_creds(module):
# return ec2_url, ec2_access_key, ec2_secret_key, region
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
resource = module.params.get('resource')
tags = module.params['tags']
state = module.params.get('state')
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
# Otherwise, no region so we fallback to the old connection method
elif ec2_url:
try:
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
else:
module.fail_json(msg="Either region or ec2_url must be specified")
ec2 = ec2_connect(module)
# We need a comparison here so that we can accurately report back changed status.
# Need to expand the gettags return format and compare with "tags" and then tag or detag as appropriate.

@ -127,15 +127,6 @@ except ImportError:
print "failed=True msg='boto required for this module'"
sys.exit(1)
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
def main():
module = AnsibleModule(
argument_spec = dict(
@ -151,30 +142,13 @@ def main():
)
)
# def get_ec2_creds(module):
# return ec2_url, ec2_access_key, ec2_secret_key, region
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
instance = module.params.get('instance')
volume_size = module.params.get('volume_size')
iops = module.params.get('iops')
device_name = module.params.get('device_name')
zone = module.params.get('zone')
# If we have a region specified, connect to its endpoint.
if region:
try:
ec2 = boto.ec2.connect_to_region(region, aws_access_key_id=aws_access_key, aws_secret_access_key=aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
# Otherwise, no region so we fallback to the old connection method
elif ec2_url:
try:
ec2 = boto.connect_ec2_endpoint(ec2_url, aws_access_key, aws_secret_key)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg = str(e))
else:
module.fail_json(msg="Either region or ec2_url must be specified")
ec2 = ec2_connect(module)
# Here we need to get the zone info for the instance. This covers situation where
# instance is specified but zone isn't.

@ -164,15 +164,6 @@ except ImportError:
print "failed=True msg='boto required for this module'"
sys.exit(1)
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
def get_vpc_info(vpc):
"""
Retrieves vpc information from an instance

@ -17,9 +17,9 @@
DOCUMENTATION = """
---
module: elasticache
short_description: Manage cache clusters in Amazon Elasticache.
description:
- Manage cache clusters in Amazon Elasticache.
short_description: Manage cache clusters in Amazon Elasticache.
- Returns information about the specified cache cluster.
version_added: "1.4"
requirements: [ "boto" ]
@ -137,15 +137,6 @@ import sys
import os
import time
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
try:
import boto
from boto.elasticache.layer1 import ElastiCacheConnection

@ -18,11 +18,14 @@
try:
from novaclient.v1_1 import client as nova_client
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
import time
except ImportError:
print("failed=True msg='glanceclient,keystoneclient and quantumclient client are required'")
print("failed=True msg='novaclient,keystoneclient and quantumclient (or neutronclient) are required'")
DOCUMENTATION = '''
---
@ -72,14 +75,19 @@ options:
- The name of the instance to which the IP address should be assigned
required: true
default: None
requirements: ["novaclient", "quantumclient", "keystoneclient"]
internal_network_name:
description:
- The name of the network of the port to associate with the floating ip. Necessary when VM multiple networks.
required: false
default: None
requirements: ["novaclient", "quantumclient", "neutronclient", "keystoneclient"]
'''
EXAMPLES = '''
# Assign a floating ip to the instance from an external network
- quantum_floating_ip: state=present login_username=admin login_password=admin
login_tenant_name=admin network_name=external_network
instance_name=vm1
instance_name=vm1 internal_network_name=internal_network
'''
def _get_ksclient(module, kwargs):
@ -99,10 +107,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -111,10 +119,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = "Error in connecting to quantum: %s " % e.message)
return quantum
module.fail_json(msg = "Error in connecting to neutron: %s " % e.message)
return neutron
def _get_server_state(module, nova):
server_info = None
@ -132,59 +140,72 @@ def _get_server_state(module, nova):
module.fail_json(msg = "Error in getting the server list: %s" % e.message)
return server_info, server
def _get_port_info(quantum, module, instance_id):
def _get_port_info(neutron, module, instance_id, internal_network_name=None):
if internal_network_name:
kwargs = {
'name': internal_network_name,
}
networks = neutron.list_networks(**kwargs)
subnet_id = networks['networks'][0]['subnets'][0]
kwargs = {
'device_id': instance_id,
}
try:
ports = quantum.list_ports(**kwargs)
ports = neutron.list_ports(**kwargs)
except Exception as e:
module.fail_json( msg = "Error in listing ports: %s" % e.message)
if subnet_id:
port = next(port for port in ports['ports'] if port['fixed_ips'][0]['subnet_id'] == subnet_id)
port_id = port['id']
fixed_ip_address = port['fixed_ips'][0]['ip_address']
else:
port_id = ports['ports'][0]['id']
fixed_ip_address = ports['ports'][0]['fixed_ips'][0]['ip_address']
if not ports['ports']:
return None, None
return ports['ports'][0]['fixed_ips'][0]['ip_address'], ports['ports'][0]['id']
return fixed_ip_address, port_id
def _get_floating_ip(module, quantum, fixed_ip_address):
def _get_floating_ip(module, neutron, fixed_ip_address):
kwargs = {
'fixed_ip_address': fixed_ip_address
}
try:
ips = quantum.list_floatingips(**kwargs)
ips = neutron.list_floatingips(**kwargs)
except Exception as e:
module.fail_json(msg = "error in fetching the floatingips's %s" % e.message)
if not ips['floatingips']:
return None, None
return ips['floatingips'][0]['id'], ips['floatingips'][0]['floating_ip_address']
def _create_floating_ip(quantum, module, port_id, net_id):
def _create_floating_ip(neutron, module, port_id, net_id):
kwargs = {
'port_id': port_id,
'floating_network_id': net_id
}
try:
result = quantum.create_floatingip({'floatingip': kwargs})
result = neutron.create_floatingip({'floatingip': kwargs})
except Exception as e:
module.fail_json(msg="There was an error in updating the floating ip address: %s" % e.message)
module.exit_json(changed=True, result=result, public_ip=result['floatingip']['floating_ip_address'])
def _get_net_id(quantum, module):
def _get_net_id(neutron, module):
kwargs = {
'name': module.params['network_name'],
}
try:
networks = quantum.list_networks(**kwargs)
networks = neutron.list_networks(**kwargs)
except Exception as e:
module.fail_json("Error in listing quantum networks: %s" % e.message)
module.fail_json("Error in listing neutron networks: %s" % e.message)
if not networks['networks']:
return None
return networks['networks'][0]['id']
def _update_floating_ip(quantum, module, port_id, floating_ip_id):
def _update_floating_ip(neutron, module, port_id, floating_ip_id):
kwargs = {
'port_id': port_id
}
try:
result = quantum.update_floatingip(floating_ip_id, {'floatingip': kwargs})
result = neutron.update_floatingip(floating_ip_id, {'floatingip': kwargs})
except Exception as e:
module.fail_json(msg="There was an error in updating the floating ip address: %s" % e.message)
module.exit_json(changed=True, result=result)
@ -201,14 +222,15 @@ def main():
region_name = dict(default=None),
network_name = dict(required=True),
instance_name = dict(required=True),
state = dict(default='present', choices=['absent', 'present'])
state = dict(default='present', choices=['absent', 'present']),
internal_network_name = dict(default=None),
),
)
try:
nova = nova_client.Client(module.params['login_username'], module.params['login_password'],
module.params['login_tenant_name'], module.params['auth_url'], service_type='compute')
quantum = _get_quantum_client(module, module.params)
neutron = _get_neutron_client(module, module.params)
except Exception as e:
module.fail_json(msg="Error in authenticating to nova: %s" % e.message)
@ -216,23 +238,23 @@ def main():
if not server_info:
module.fail_json(msg="The instance name provided cannot be found")
fixed_ip, port_id = _get_port_info(quantum, module, server_info['id'])
fixed_ip, port_id = _get_port_info(neutron, module, server_info['id'], module.params['internal_network_name'])
if not port_id:
module.fail_json(msg="Cannot find a port for this instance, maybe fixed ip is not assigned")
floating_id, floating_ip = _get_floating_ip(module, quantum, fixed_ip)
floating_id, floating_ip = _get_floating_ip(module, neutron, fixed_ip)
if module.params['state'] == 'present':
if floating_ip:
module.exit_json(changed = False, public_ip=floating_ip)
net_id = _get_net_id(quantum, module)
net_id = _get_net_id(neutron, module)
if not net_id:
module.fail_json(msg = "cannot find the network specified, please check")
_create_floating_ip(quantum, module, port_id, net_id)
_create_floating_ip(neutron, module, port_id, net_id)
if module.params['state'] == 'absent':
if floating_ip:
_update_floating_ip(quantum, module, None, floating_id)
_update_floating_ip(neutron, module, None, floating_id)
module.exit_json(changed=False)
# this is magic, see lib/ansible/module.params['common.py

@ -18,11 +18,14 @@
try:
from novaclient.v1_1 import client as nova_client
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
import time
except ImportError:
print "failed=True msg='glanceclient,novaclient and keystone client are required'"
print "failed=True msg='novaclient, keystone, and quantumclient (or neutronclient) client are required'"
DOCUMENTATION = '''
---
@ -72,7 +75,7 @@ options:
- floating ip that should be assigned to the instance
required: true
default: None
requirements: ["quantumclient", "keystoneclient"]
requirements: ["quantumclient", "neutronclient", "keystoneclient"]
'''
EXAMPLES = '''
@ -103,10 +106,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -115,10 +118,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = "Error in connecting to quantum: %s " % e.message)
return quantum
module.fail_json(msg = "Error in connecting to neutron: %s " % e.message)
return neutron
def _get_server_state(module, nova):
server_info = None
@ -136,22 +139,22 @@ def _get_server_state(module, nova):
module.fail_json(msg = "Error in getting the server list: %s" % e.message)
return server_info, server
def _get_port_id(quantum, module, instance_id):
def _get_port_id(neutron, module, instance_id):
kwargs = dict(device_id = instance_id)
try:
ports = quantum.list_ports(**kwargs)
ports = neutron.list_ports(**kwargs)
except Exception as e:
module.fail_json( msg = "Error in listing ports: %s" % e.message)
if not ports['ports']:
return None
return ports['ports'][0]['id']
def _get_floating_ip_id(module, quantum):
def _get_floating_ip_id(module, neutron):
kwargs = {
'floating_ip_address': module.params['ip_address']
}
try:
ips = quantum.list_floatingips(**kwargs)
ips = neutron.list_floatingips(**kwargs)
except Exception as e:
module.fail_json(msg = "error in fetching the floatingips's %s" % e.message)
if not ips['floatingips']:
@ -163,12 +166,12 @@ def _get_floating_ip_id(module, quantum):
state = "attached"
return state, ip
def _update_floating_ip(quantum, module, port_id, floating_ip_id):
def _update_floating_ip(neutron, module, port_id, floating_ip_id):
kwargs = {
'port_id': port_id
}
try:
result = quantum.update_floatingip(floating_ip_id, {'floatingip': kwargs})
result = neutron.update_floatingip(floating_ip_id, {'floatingip': kwargs})
except Exception as e:
module.fail_json(msg = "There was an error in updating the floating ip address: %s" % e.message)
module.exit_json(changed = True, result = result, public_ip=module.params['ip_address'])
@ -189,27 +192,28 @@ def main():
)
try:
nova = nova_client.Client(module.params['login_username'], module.params['login_password'], module.params['login_tenant_name'], module.params['auth_url'], service_type='compute')
nova = nova_client.Client(module.params['login_username'], module.params['login_password'],
module.params['login_tenant_name'], module.params['auth_url'], service_type='compute')
except Exception as e:
module.fail_json( msg = " Error in authenticating to nova: %s" % e.message)
quantum = _get_quantum_client(module, module.params)
state, floating_ip_id = _get_floating_ip_id(module, quantum)
neutron = _get_neutron_client(module, module.params)
state, floating_ip_id = _get_floating_ip_id(module, neutron)
if module.params['state'] == 'present':
if state == 'attached':
module.exit_json(changed = False, result = 'attached', public_ip=module.params['ip_address'])
server_info, server_obj = _get_server_state(module, nova)
if not server_info:
module.fail_json(msg = " The instance name provided cannot be found")
port_id = _get_port_id(quantum, module, server_info['id'])
port_id = _get_port_id(neutron, module, server_info['id'])
if not port_id:
module.fail_json(msg = "Cannot find a port for this instance, maybe fixed ip is not assigned")
_update_floating_ip(quantum, module, port_id, floating_ip_id)
_update_floating_ip(neutron, module, port_id, floating_ip_id)
if module.params['state'] == 'absent':
if state == 'detached':
module.exit_json(changed = False, result = 'detached')
if state == 'attached':
_update_floating_ip(quantum, module, None, floating_ip_id)
_update_floating_ip(neutron, module, None, floating_ip_id)
module.exit_json(changed = True, result = "detached")
# this is magic, see lib/ansible/module.params['common.py

@ -17,10 +17,13 @@
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
except ImportError:
print("failed=True msg='quantumclient and keystone client are required'")
print("failed=True msg='quantumclient (or neutronclient) and keystone client are required'")
DOCUMENTATION = '''
---
@ -100,7 +103,7 @@ options:
- Whether the state should be marked as up or down
required: false
default: true
requirements: ["quantumclient", "keystoneclient"]
requirements: ["quantumclient", "neutronclient", "keystoneclient"]
'''
@ -136,10 +139,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for Quantum: %s " %e.message)
module.fail_json(msg = "Error getting network endpoint: %s " %e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -148,10 +151,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = " Error in connecting to quantum: %s " %e.message)
return quantum
module.fail_json(msg = " Error in connecting to neutron: %s " %e.message)
return neutron
def _set_tenant_id(module):
global _os_tenant_id
@ -168,22 +171,22 @@ def _set_tenant_id(module):
module.fail_json(msg = "The tenant id cannot be found, please check the paramters")
def _get_net_id(quantum, module):
def _get_net_id(neutron, module):
kwargs = {
'tenant_id': _os_tenant_id,
'name': module.params['name'],
}
try:
networks = quantum.list_networks(**kwargs)
networks = neutron.list_networks(**kwargs)
except Exception as e:
module.fail_json(msg = "Error in listing quantum networks: %s" % e.message)
module.fail_json(msg = "Error in listing neutron networks: %s" % e.message)
if not networks['networks']:
return None
return networks['networks'][0]['id']
def _create_network(module, quantum):
def _create_network(module, neutron):
quantum.format = 'json'
neutron.format = 'json'
network = {
'name': module.params.get('name'),
@ -212,15 +215,15 @@ def _create_network(module, quantum):
network.pop('provider:segmentation_id', None)
try:
net = quantum.create_network({'network':network})
net = neutron.create_network({'network':network})
except Exception as e:
module.fail_json(msg = "Error in creating network: %s" % e.message)
return net['network']['id']
def _delete_network(module, net_id, quantum):
def _delete_network(module, net_id, neutron):
try:
id = quantum.delete_network(net_id)
id = neutron.delete_network(net_id)
except Exception as e:
module.fail_json(msg = "Error in deleting the network: %s" % e.message)
return True
@ -254,24 +257,24 @@ def main():
if not module.params['provider_segmentation_id']:
module.fail_json(msg = " for vlan & gre networks, variable provider_segmentation_id should be set.")
quantum = _get_quantum_client(module, module.params)
neutron = _get_neutron_client(module, module.params)
_set_tenant_id(module)
if module.params['state'] == 'present':
network_id = _get_net_id(quantum, module)
network_id = _get_net_id(neutron, module)
if not network_id:
network_id = _create_network(module, quantum)
network_id = _create_network(module, neutron)
module.exit_json(changed = True, result = "Created", id = network_id)
else:
module.exit_json(changed = False, result = "Success", id = network_id)
if module.params['state'] == 'absent':
network_id = _get_net_id(quantum, module)
network_id = _get_net_id(neutron, module)
if not network_id:
module.exit_json(changed = False, result = "Success")
else:
_delete_network(module, network_id, quantum)
_delete_network(module, network_id, neutron)
module.exit_json(changed = True, result = "Deleted")
# this is magic, see lib/ansible/module.params['common.py

@ -17,10 +17,13 @@
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
except ImportError:
print("failed=True msg='quantumclient and keystone client are required'")
print("failed=True msg='quantumclient (or neutronclient) and keystone client are required'")
DOCUMENTATION = '''
---
@ -75,7 +78,7 @@ options:
- desired admin state of the created router .
required: false
default: true
requirements: ["quantumclient", "keystoneclient"]
requirements: ["quantumclient", "neutronclient", "keystoneclient"]
'''
EXAMPLES = '''
@ -107,10 +110,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -119,10 +122,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = "Error in connecting to quantum: %s " % e.message)
return quantum
module.fail_json(msg = "Error in connecting to neutron: %s " % e.message)
return neutron
def _set_tenant_id(module):
global _os_tenant_id
@ -139,34 +142,34 @@ def _set_tenant_id(module):
module.fail_json(msg = "The tenant id cannot be found, please check the paramters")
def _get_router_id(module, quantum):
def _get_router_id(module, neutron):
kwargs = {
'name': module.params['name'],
'tenant_id': _os_tenant_id,
}
try:
routers = quantum.list_routers(**kwargs)
routers = neutron.list_routers(**kwargs)
except Exception as e:
module.fail_json(msg = "Error in getting the router list: %s " % e.message)
if not routers['routers']:
return None
return routers['routers'][0]['id']
def _create_router(module, quantum):
def _create_router(module, neutron):
router = {
'name': module.params['name'],
'tenant_id': _os_tenant_id,
'admin_state_up': module.params['admin_state_up'],
}
try:
new_router = quantum.create_router(dict(router=router))
new_router = neutron.create_router(dict(router=router))
except Exception as e:
module.fail_json( msg = "Error in creating router: %s" % e.message)
return new_router['router']['id']
def _delete_router(module, quantum, router_id):
def _delete_router(module, neutron, router_id):
try:
quantum.delete_router(router_id)
neutron.delete_router(router_id)
except:
module.fail_json("Error in deleting the router")
return True
@ -186,23 +189,23 @@ def main():
),
)
quantum = _get_quantum_client(module, module.params)
neutron = _get_neutron_client(module, module.params)
_set_tenant_id(module)
if module.params['state'] == 'present':
router_id = _get_router_id(module, quantum)
router_id = _get_router_id(module, neutron)
if not router_id:
router_id = _create_router(module, quantum)
router_id = _create_router(module, neutron)
module.exit_json(changed=True, result="Created", id=router_id)
else:
module.exit_json(changed=False, result="success" , id=router_id)
else:
router_id = _get_router_id(module, quantum)
router_id = _get_router_id(module, neutron)
if not router_id:
module.exit_json(changed=False, result="success")
else:
_delete_router(module, quantum, router_id)
_delete_router(module, neutron, router_id)
module.exit_json(changed=True, result="deleted")
# this is magic, see lib/ansible/module.params['common.py

@ -17,10 +17,13 @@
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
except ImportError:
print("failed=True msg='quantumclient and keystone client are required'")
print("failed=True msg='quantumclient (or neutronclient) and keystone client are required'")
DOCUMENTATION = '''
---
module: quantum_router_gateway
@ -69,7 +72,7 @@ options:
- Name of the external network which should be attached to the router.
required: true
default: None
requirements: ["quantumclient", "keystoneclient"]
requirements: ["quantumclient", "neutronclient", "keystoneclient"]
'''
EXAMPLES = '''
@ -97,10 +100,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -109,62 +112,62 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = "Error in connecting to quantum: %s " % e.message)
return quantum
module.fail_json(msg = "Error in connecting to neutron: %s " % e.message)
return neutron
def _get_router_id(module, quantum):
def _get_router_id(module, neutron):
kwargs = {
'name': module.params['router_name'],
}
try:
routers = quantum.list_routers(**kwargs)
routers = neutron.list_routers(**kwargs)
except Exception as e:
module.fail_json(msg = "Error in getting the router list: %s " % e.message)
if not routers['routers']:
return None
return routers['routers'][0]['id']
def _get_net_id(quantum, module):
def _get_net_id(neutron, module):
kwargs = {
'name': module.params['network_name'],
'router:external': True
}
try:
networks = quantum.list_networks(**kwargs)
networks = neutron.list_networks(**kwargs)
except Exception as e:
module.fail_json("Error in listing quantum networks: %s" % e.message)
module.fail_json("Error in listing neutron networks: %s" % e.message)
if not networks['networks']:
return None
return networks['networks'][0]['id']
def _get_port_id(quantum, module, router_id, network_id):
def _get_port_id(neutron, module, router_id, network_id):
kwargs = {
'device_id': router_id,
'network_id': network_id,
}
try:
ports = quantum.list_ports(**kwargs)
ports = neutron.list_ports(**kwargs)
except Exception as e:
module.fail_json( msg = "Error in listing ports: %s" % e.message)
if not ports['ports']:
return None
return ports['ports'][0]['id']
def _add_gateway_router(quantum, module, router_id, network_id):
def _add_gateway_router(neutron, module, router_id, network_id):
kwargs = {
'network_id': network_id
}
try:
quantum.add_gateway_router(router_id, kwargs)
neutron.add_gateway_router(router_id, kwargs)
except Exception as e:
module.fail_json(msg = "Error in adding gateway to router: %s" % e.message)
return True
def _remove_gateway_router(quantum, module, router_id):
def _remove_gateway_router(neutron, module, router_id):
try:
quantum.remove_gateway_router(router_id)
neutron.remove_gateway_router(router_id)
except Exception as e:
module.fail_json(msg = "Error in removing gateway to router: %s" % e.message)
return True
@ -184,28 +187,28 @@ def main():
),
)
quantum = _get_quantum_client(module, module.params)
router_id = _get_router_id(module, quantum)
neutron = _get_neutron_client(module, module.params)
router_id = _get_router_id(module, neutron)
if not router_id:
module.fail_json(msg="failed to get the router id, please check the router name")
network_id = _get_net_id(quantum, module)
network_id = _get_net_id(neutron, module)
if not network_id:
module.fail_json(msg="failed to get the network id, please check the network name and make sure it is external")
if module.params['state'] == 'present':
port_id = _get_port_id(quantum, module, router_id, network_id)
port_id = _get_port_id(neutron, module, router_id, network_id)
if not port_id:
_add_gateway_router(quantum, module, router_id, network_id)
_add_gateway_router(neutron, module, router_id, network_id)
module.exit_json(changed=True, result="created")
module.exit_json(changed=False, result="success")
if module.params['state'] == 'absent':
port_id = _get_port_id(quantum, module, router_id, network_id)
port_id = _get_port_id(neutron, module, router_id, network_id)
if not port_id:
module.exit_json(changed=False, result="Success")
_remove_gateway_router(quantum, module, router_id)
_remove_gateway_router(neutron, module, router_id)
module.exit_json(changed=True, result="Deleted")
# this is magic, see lib/ansible/module.params['common.py

@ -17,10 +17,13 @@
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
except ImportError:
print("failed=True msg='quantumclient and keystone client are required'")
print("failed=True msg='quantumclient (or neutronclient) and keystone client are required'")
DOCUMENTATION = '''
---
module: quantum_router_interface
@ -108,10 +111,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -120,10 +123,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = "Error in connecting to quantum: %s " % e.message)
return quantum
module.fail_json(msg = "Error in connecting to neutron: %s " % e.message)
return neutron
def _set_tenant_id(module):
global _os_tenant_id
@ -140,12 +143,12 @@ def _set_tenant_id(module):
module.fail_json(msg = "The tenant id cannot be found, please check the paramters")
def _get_router_id(module, quantum):
def _get_router_id(module, neutron):
kwargs = {
'name': module.params['router_name'],
}
try:
routers = quantum.list_routers(**kwargs)
routers = neutron.list_routers(**kwargs)
except Exception as e:
module.fail_json(msg = "Error in getting the router list: %s " % e.message)
if not routers['routers']:
@ -153,27 +156,27 @@ def _get_router_id(module, quantum):
return routers['routers'][0]['id']
def _get_subnet_id(module, quantum):
def _get_subnet_id(module, neutron):
subnet_id = None
kwargs = {
'tenant_id': _os_tenant_id,
'name': module.params['subnet_name'],
}
try:
subnets = quantum.list_subnets(**kwargs)
subnets = neutron.list_subnets(**kwargs)
except Exception as e:
module.fail_json( msg = " Error in getting the subnet list:%s " % e.message)
if not subnets['subnets']:
return None
return subnets['subnets'][0]['id']
def _get_port_id(quantum, module, router_id, subnet_id):
def _get_port_id(neutron, module, router_id, subnet_id):
kwargs = {
'tenant_id': _os_tenant_id,
'device_id': router_id,
}
try:
ports = quantum.list_ports(**kwargs)
ports = neutron.list_ports(**kwargs)
except Exception as e:
module.fail_json( msg = "Error in listing ports: %s" % e.message)
if not ports['ports']:
@ -184,22 +187,22 @@ def _get_port_id(quantum, module, router_id, subnet_id):
return port['id']
return None
def _add_interface_router(quantum, module, router_id, subnet_id):
def _add_interface_router(neutron, module, router_id, subnet_id):
kwargs = {
'subnet_id': subnet_id
}
try:
quantum.add_interface_router(router_id, kwargs)
neutron.add_interface_router(router_id, kwargs)
except Exception as e:
module.fail_json(msg = "Error in adding interface to router: %s" % e.message)
return True
def _remove_interface_router(quantum, module, router_id, subnet_id):
def _remove_interface_router(neutron, module, router_id, subnet_id):
kwargs = {
'subnet_id': subnet_id
}
try:
quantum.remove_interface_router(router_id, kwargs)
neutron.remove_interface_router(router_id, kwargs)
except Exception as e:
module.fail_json(msg="Error in removing interface from router: %s" % e.message)
return True
@ -219,29 +222,29 @@ def main():
),
)
quantum = _get_quantum_client(module, module.params)
neutron = _get_neutron_client(module, module.params)
_set_tenant_id(module)
router_id = _get_router_id(module, quantum)
router_id = _get_router_id(module, neutron)
if not router_id:
module.fail_json(msg="failed to get the router id, please check the router name")
subnet_id = _get_subnet_id(module, quantum)
subnet_id = _get_subnet_id(module, neutron)
if not subnet_id:
module.fail_json(msg="failed to get the subnet id, please check the subnet name")
if module.params['state'] == 'present':
port_id = _get_port_id(quantum, module, router_id, subnet_id)
port_id = _get_port_id(neutron, module, router_id, subnet_id)
if not port_id:
_add_interface_router(quantum, module, router_id, subnet_id)
_add_interface_router(neutron, module, router_id, subnet_id)
module.exit_json(changed=True, result="created", id=port_id)
module.exit_json(changed=False, result="success", id=port_id)
if module.params['state'] == 'absent':
port_id = _get_port_id(quantum, module, router_id, subnet_id)
port_id = _get_port_id(neutron, module, router_id, subnet_id)
if not port_id:
module.exit_json(changed = False, result = "Success")
_remove_interface_router(quantum, module, router_id, subnet_id)
_remove_interface_router(neutron, module, router_id, subnet_id)
module.exit_json(changed=True, result="Deleted")
# this is magic, see lib/ansible/module.params['common.py

@ -17,10 +17,13 @@
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
try:
from neutronclient.neutron import client
except ImportError:
from quantumclient.quantum import client
from keystoneclient.v2_0 import client as ksclient
except ImportError:
print("failed=True msg='quantum and keystone client are required'")
print("failed=True msg='quantumclient (or neutronclient) and keystoneclient are required'")
DOCUMENTATION = '''
---
@ -105,7 +108,7 @@ options:
- From the subnet pool the last IP that should be assigned to the virtual machines
required: false
default: None
requirements: ["quantum", "keystoneclient"]
requirements: ["quantumclient", "neutronclient", "keystoneclient"]
'''
EXAMPLES = '''
@ -136,10 +139,10 @@ def _get_endpoint(module, ksclient):
try:
endpoint = ksclient.service_catalog.url_for(service_type='network', endpoint_type='publicURL')
except Exception as e:
module.fail_json(msg = "Error getting endpoint for glance: %s" % e.message)
module.fail_json(msg = "Error getting network endpoint: %s" % e.message)
return endpoint
def _get_quantum_client(module, kwargs):
def _get_neutron_client(module, kwargs):
_ksclient = _get_ksclient(module, kwargs)
token = _ksclient.auth_token
endpoint = _get_endpoint(module, _ksclient)
@ -148,10 +151,10 @@ def _get_quantum_client(module, kwargs):
'endpoint_url': endpoint
}
try:
quantum = client.Client('2.0', **kwargs)
neutron = client.Client('2.0', **kwargs)
except Exception as e:
module.fail_json(msg = " Error in connecting to quantum: %s" % e.message)
return quantum
module.fail_json(msg = " Error in connecting to neutron: %s" % e.message)
return neutron
def _set_tenant_id(module):
global _os_tenant_id
@ -167,24 +170,24 @@ def _set_tenant_id(module):
if not _os_tenant_id:
module.fail_json(msg = "The tenant id cannot be found, please check the paramters")
def _get_net_id(quantum, module):
def _get_net_id(neutron, module):
kwargs = {
'tenant_id': _os_tenant_id,
'name': module.params['network_name'],
}
try:
networks = quantum.list_networks(**kwargs)
networks = neutron.list_networks(**kwargs)
except Exception as e:
module.fail_json("Error in listing quantum networks: %s" % e.message)
module.fail_json("Error in listing neutron networks: %s" % e.message)
if not networks['networks']:
return None
return networks['networks'][0]['id']
def _get_subnet_id(module, quantum):
def _get_subnet_id(module, neutron):
global _os_network_id
subnet_id = None
_os_network_id = _get_net_id(quantum, module)
_os_network_id = _get_net_id(neutron, module)
if not _os_network_id:
module.fail_json(msg = "network id of network not found.")
else:
@ -193,15 +196,15 @@ def _get_subnet_id(module, quantum):
'name': module.params['name'],
}
try:
subnets = quantum.list_subnets(**kwargs)
subnets = neutron.list_subnets(**kwargs)
except Exception as e:
module.fail_json( msg = " Error in getting the subnet list:%s " % e.message)
if not subnets['subnets']:
return None
return subnets['subnets'][0]['id']
def _create_subnet(module, quantum):
quantum.format = 'json'
def _create_subnet(module, neutron):
neutron.format = 'json'
subnet = {
'name': module.params['name'],
'ip_version': module.params['ip_version'],
@ -227,15 +230,15 @@ def _create_subnet(module, quantum):
else:
subnet.pop('dns_nameservers')
try:
new_subnet = quantum.create_subnet(dict(subnet=subnet))
new_subnet = neutron.create_subnet(dict(subnet=subnet))
except Exception, e:
module.fail_json(msg = "Failure in creating subnet: %s" % e.message)
return new_subnet['subnet']['id']
def _delete_subnet(module, quantum, subnet_id):
def _delete_subnet(module, neutron, subnet_id):
try:
quantum.delete_subnet(subnet_id)
neutron.delete_subnet(subnet_id)
except Exception as e:
module.fail_json( msg = "Error in deleting subnet: %s" % e.message)
return True
@ -263,21 +266,21 @@ def main():
allocation_pool_end = dict(default=None),
),
)
quantum = _get_quantum_client(module, module.params)
neutron = _get_neutron_client(module, module.params)
_set_tenant_id(module)
if module.params['state'] == 'present':
subnet_id = _get_subnet_id(module, quantum)
subnet_id = _get_subnet_id(module, neutron)
if not subnet_id:
subnet_id = _create_subnet(module, quantum)
subnet_id = _create_subnet(module, neutron)
module.exit_json(changed = True, result = "Created" , id = subnet_id)
else:
module.exit_json(changed = False, result = "success" , id = subnet_id)
else:
subnet_id = _get_subnet_id(module, quantum)
subnet_id = _get_subnet_id(module, neutron)
if not subnet_id:
module.exit_json(changed = False, result = "success")
else:
_delete_subnet(module, quantum, subnet_id)
_delete_subnet(module, neutron, subnet_id)
module.exit_json(changed = True, result = "deleted")
# this is magic, see lib/ansible/module.params['common.py

@ -26,6 +26,13 @@ options:
api_key:
description:
- Rackspace API key (overrides I(credentials))
auto_increment:
description:
- Whether or not to increment a single number with the name of the
created servers. Only applicable when used with the I(group) attribute
or meta key.
default: yes
version_added: 1.5
count:
description:
- number of instances to launch
@ -147,6 +154,26 @@ EXAMPLES = '''
networks:
- private
- public
register: rax
- name: Build an exact count of cloud servers with incremented names
hosts: local
gather_facts: False
tasks:
- name: Server build requests
local_action:
module: rax
credentials: ~/.raxpub
name: test%03d.example.org
flavor: performance1-1
image: ubuntu-1204-lts-precise-pangolin
state: present
count: 10
count_offset: 10
exact_count: yes
group: test
wait: yes
register: rax
'''
import sys
@ -199,7 +226,7 @@ def create(module, names, flavor, image, meta, key_name, files,
lpath = os.path.expanduser(files[rpath])
try:
fileobj = open(lpath, 'r')
files[rpath] = fileobj
files[rpath] = fileobj.read()
except Exception, e:
module.fail_json(msg='Failed to load %s' % lpath)
try:
@ -347,7 +374,8 @@ def delete(module, instance_ids, wait, wait_timeout):
def cloudservers(module, state, name, flavor, image, meta, key_name, files,
wait, wait_timeout, disk_config, count, group,
instance_ids, exact_count, networks, count_offset):
instance_ids, exact_count, networks, count_offset,
auto_increment):
cs = pyrax.cloudservers
cnw = pyrax.cloud_networks
servers = []
@ -358,6 +386,15 @@ def cloudservers(module, state, name, flavor, image, meta, key_name, files,
elif 'group' in meta and group is None:
group = meta['group']
# When using state=absent with group, the absent block won't match the
# names properly. Use the exact_count functionality to decrease the count
# to the desired level
was_absent = False
if group is not None and state == 'absent':
exact_count = True
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:
@ -416,6 +453,7 @@ def cloudservers(module, state, name, flavor, image, meta, key_name, files,
module.fail_json(msg='"group" must be provided when using '
'"exact_count"')
else:
if auto_increment:
numbers = set()
try:
@ -436,7 +474,22 @@ def cloudservers(module, state, name, flavor, image, meta, key_name, files,
numbers.add(number)
number_range = xrange(count_offset, count_offset + count)
available_numbers = list(set(number_range).difference(numbers))
available_numbers = list(set(number_range)
.difference(numbers))
else:
for server in cs.servers.list():
if server.metadata.get('group') == group:
servers.append(server)
# If state was absent but the count was changed,
# assume we only wanted to remove that number of instances
if was_absent:
diff = len(servers) - count
if diff < 0:
count = 0
else:
count = diff
if len(servers) > count:
state = 'absent'
del servers[:count]
@ -445,19 +498,23 @@ def cloudservers(module, state, name, flavor, image, meta, key_name, files,
instance_ids.append(server.id)
delete(module, instance_ids, wait, wait_timeout)
elif len(servers) < count:
if auto_increment:
names = []
numbers_to_use = available_numbers[:count - len(servers)]
name_slice = count - len(servers)
numbers_to_use = available_numbers[:name_slice]
for number in numbers_to_use:
names.append(name % number)
else:
names = [name] * (count - len(servers))
else:
module.exit_json(changed=False, action=None, instances=[],
success=[], error=[], timeout=[],
instance_ids={'instances': [],
'success': [], 'error': [],
'timeout': []})
else:
if group is not None:
if auto_increment:
numbers = set()
try:
@ -479,11 +536,14 @@ def cloudservers(module, state, name, flavor, image, meta, key_name, files,
number_range = xrange(count_offset,
count_offset + count + len(numbers))
available_numbers = list(set(number_range).difference(numbers))
available_numbers = list(set(number_range)
.difference(numbers))
names = []
numbers_to_use = available_numbers[:count]
for number in numbers_to_use:
names.append(name % number)
else:
names = [name] * count
else:
search_opts = {
'name': name,
@ -552,6 +612,7 @@ def main():
argument_spec = rax_argument_spec()
argument_spec.update(
dict(
auto_increment=dict(choices=BOOLEANS, default=True, type='bool'),
count=dict(default=1, type='int'),
count_offset=dict(default=1, type='int'),
disk_config=dict(default='auto', choices=['auto', 'manual']),
@ -584,6 +645,7 @@ def main():
'please remove "service: cloudservers" from your '
'playbook pertaining to the "rax" module')
auto_increment = module.params.get('auto_increment')
count = module.params.get('count')
count_offset = module.params.get('count_offset')
disk_config = module.params.get('disk_config').upper()
@ -605,7 +667,8 @@ def main():
cloudservers(module, state, name, flavor, image, meta, key_name, files,
wait, wait_timeout, disk_config, count, group,
instance_ids, exact_count, networks, count_offset)
instance_ids, exact_count, networks, count_offset,
auto_increment)
# import module snippets

@ -118,7 +118,6 @@ EXAMPLES = '''
'''
import sys
import os
from types import NoneType
@ -136,6 +135,12 @@ PROTOCOLS = ['DNS_TCP', 'DNS_UDP', 'FTP', 'HTTP', 'HTTPS', 'IMAPS', 'IMAPv4',
'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):
@ -151,7 +156,7 @@ def to_dict(obj):
elif key == 'nodes':
instance[key] = []
for node in value:
instance[key].append(node.to_dict())
instance[key].append(node_to_dict(node))
elif (isinstance(value, NON_CALLABLES) and
not key.startswith('_')):
instance[key] = value

@ -262,15 +262,6 @@ EXAMPLES = '''
import sys
import time
AWS_REGIONS = ['ap-northeast-1',
'ap-southeast-1',
'ap-southeast-2',
'eu-west-1',
'sa-east-1',
'us-east-1',
'us-west-1',
'us-west-2']
try:
import boto.rds
except ImportError:
@ -346,25 +337,7 @@ def main():
apply_immediately = module.params.get('apply_immediately')
new_instance_name = module.params.get('new_instance_name')
# allow environment variables to be used if ansible vars aren't set
if not region:
if 'AWS_REGION' in os.environ:
region = os.environ['AWS_REGION']
elif 'EC2_REGION' in os.environ:
region = os.environ['EC2_REGION']
if not aws_secret_key:
if 'AWS_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['AWS_SECRET_KEY']
elif 'EC2_SECRET_KEY' in os.environ:
aws_secret_key = os.environ['EC2_SECRET_KEY']
if not aws_access_key:
if 'AWS_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['AWS_ACCESS_KEY']
elif 'EC2_ACCESS_KEY' in os.environ:
aws_access_key = os.environ['EC2_ACCESS_KEY']
ec2_url, aws_access_key, aws_secret_key, region = get_ec2_creds(module)
if not region:
module.fail_json(msg = str("region not specified and unable to determine region from EC2_REGION."))
@ -577,5 +550,6 @@ def main():
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.ec2 import *
main()

@ -7,20 +7,26 @@ DOCUMENTATION = '''
module: shell
short_description: Execute commands in nodes.
description:
- The shell module takes the command name followed by a list of arguments,
space delimited. It is almost exactly like the M(command) module but runs
- The M(shell) module takes the command name followed by a list of space-delimited arguments.
It is almost exactly like the M(command) module but runs
the command through a shell (C(/bin/sh)) on the remote node.
version_added: "0.2"
options:
(free form):
free_form:
description:
- The command module takes a free form command to run
required: null
- The shell module takes a free form command to run
required: true
default: null
creates:
description:
- a filename, when it already exists, this step will NOT be run
required: false
- a filename, when it already exists, this step will B(not) be run.
required: no
default: null
removes:
description:
- a filename, when it does not exist, this step will B(not) be run.
version_added: "0.8"
required: no
default: null
chdir:
description:

@ -116,13 +116,13 @@ def db_delete(cursor, db):
cursor.execute(query)
return True
def db_dump(module, host, user, password, db_name, target, socket=None):
def db_dump(module, host, user, password, db_name, target, port, socket=None):
cmd = module.get_bin_path('mysqldump', True)
cmd += " --quick --user=%s --password=%s" %(user, password)
cmd += " --quick --user=%s --password='%s'" %(user, password)
if socket is not None:
cmd += " --socket=%s" % socket
else:
cmd += " --host=%s" % host
cmd += " --host=%s --port=%s" % (host, port)
cmd += " %s" % db_name
if os.path.splitext(target)[-1] == '.gz':
cmd = cmd + ' | gzip > ' + target
@ -133,13 +133,13 @@ def db_dump(module, host, user, password, db_name, target, socket=None):
rc, stdout, stderr = module.run_command(cmd)
return rc, stdout, stderr
def db_import(module, host, user, password, db_name, target, socket=None):
def db_import(module, host, user, password, db_name, target, port, socket=None):
cmd = module.get_bin_path('mysql', True)
cmd += " --user=%s --password=%s" %(user, password)
cmd += " --user=%s --password='%s'" %(user, password)
if socket is not None:
cmd += " --socket=%s" % socket
else:
cmd += " --host=%s" % host
cmd += " --host=%s --port=%s" % (host, port)
cmd += " -D %s" % db_name
if os.path.splitext(target)[-1] == '.gz':
cmd = 'gunzip < ' + target + ' | ' + cmd
@ -282,6 +282,7 @@ def main():
elif state == "dump":
rc, stdout, stderr = db_dump(module, login_host, login_user,
login_password, db, target,
port=module.params['login_port'],
socket=module.params['login_unix_socket'])
if rc != 0:
module.fail_json(msg="%s" % stderr)
@ -290,6 +291,7 @@ def main():
elif state == "import":
rc, stdout, stderr = db_import(module, login_host, login_user,
login_password, db, target,
port=module.params['login_port'],
socket=module.params['login_unix_socket'])
if rc != 0:
module.fail_json(msg="%s" % stderr)

@ -114,6 +114,9 @@ EXAMPLES = """
# Create database user with name 'bob' and password '12345' with all database privileges
- mysql_user: name=bob password=12345 priv=*.*:ALL state=present
# Creates database user 'bob' and password '12345' with all database privileges and 'WITH GRANT OPTION'
- mysql_user: name=bob password=12345 priv=*.*:ALL,GRANT state=present
# Ensure no user named 'sally' exists, also passing in the auth credentials.
- mysql_user: login_user=root login_password=123456 name=sally state=absent

@ -124,7 +124,7 @@ options:
choices: [ "yes", "no" ]
description:
- 'force the creation of the symlinks in two cases: the source file does
not exist (but will appear later); the destination exists and a file (so, we need to unlink the
not exist (but will appear later); the destination exists and is a file (so, we need to unlink the
"path" file and create symlink to the "src" file in place of it).'
notes:
- See also M(copy), M(template), M(assemble)
@ -245,7 +245,7 @@ def main():
module.exit_json(path=path, changed=True)
if prev_state != 'absent' and prev_state != state:
if not (force and (prev_state == 'file' or prev_state == 'directory') and state == 'link') and state != 'touch':
if not (force and (prev_state == 'file' or prev_state == 'hard' or prev_state == 'directory') and state == 'link') and state != 'touch':
module.fail_json(path=path, msg='refusing to convert between %s and %s for %s' % (prev_state, state, src))
if prev_state == 'absent' and state == 'absent':
@ -307,6 +307,10 @@ def main():
if not force:
module.fail_json(dest=path, src=src, msg='Cannot link, file exists at destination')
changed = True
elif prev_state == 'directory':
if not force:
module.fail_json(dest=path, src=src, msg='Cannot link, directory exists at destination')
changed = True
else:
module.fail_json(dest=path, src=src, msg='unexpected position reached')

@ -47,9 +47,12 @@ options:
- all arguments accepted by the M(file) module also work here
required: false
notes:
- Since Ansible version 0.9, templates are loaded with C(trim_blocks=True).
- 'You can override jinja2 settings by adding a special header to template file.
i.e. C(#jinja2: trim_blocks: False)'
- "Since Ansible version 0.9, templates are loaded with C(trim_blocks=True)."
- "Also, you can override jinja2 settings by adding a special header to template file.
i.e. C(#jinja2:variable_start_string:'[%' , variable_end_string:'%]')
which changes the variable interpolation markers to [% var %] instead of {{ var }}. This is the best way to prevent evaluation of things that look like, but should not be Jinja2. raw/endraw in Jinja2 will not work as you expect because templates in Ansible are recursively evaluated."
requirements: []
author: Michael DeHaan
'''

@ -394,7 +394,7 @@ def main():
{'type': 'ITYPE_TIMEOUT',
'value': timeout},
{'type': 'ITYPE_TIME_UNTIL_UP',
'value': interval}]
'value': time_until_up}]
# main logic, monitor generic
@ -425,11 +425,9 @@ def main():
# whether it already existed, or was just created, now update
# the update functions need to check for check mode but
# cannot update settings if it doesn't exist which happens in check mode
if monitor_exists and not module.check_mode:
result['changed'] |= update_monitor_properties(api, module, monitor,
template_string_properties,
template_integer_properties)
# else assume nothing changed
# we just have to update the ipport if monitor already exists and it's different
if monitor_exists and cur_ipport != ipport:

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/python
#coding: utf-8 -*-
# This module is free software: you can redistribute it and/or modify

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/python
#coding: utf-8 -*-
# This module is free software: you can redistribute it and/or modify

@ -324,9 +324,12 @@ def upgrade(m, mode="yes", force=False,
upgrade_command = "safe-upgrade"
if force:
if apt_cmd == APT_GET_CMD:
force_yes = '--force-yes'
else:
force_yes = ''
else:
force_yes = ''
apt_cmd_path = m.get_bin_path(apt_cmd, required=True)
cmd = '%s %s -y %s %s %s %s' % (APT_ENVVARS, apt_cmd_path, dpkg_options,

@ -124,7 +124,7 @@ def all_keys(module, keyring):
return results
def key_present(module, key_id):
(rc, out, err) = module.run_command("apt-key list | 2>&1 grep -q %s" % key_id)
(rc, out, err) = module.run_command("apt-key list | 2>&1 grep -i -q %s" % key_id)
return rc == 0
def download_key(module, url):

@ -3,6 +3,7 @@
# (c) 2012, Matt Wright <matt@nobien.net>
# (c) 2013, Alexander Saltanov <asd@mokote.com>
# (c) 2014, Rutger Spiertz <rutger@kumina.nl>
#
# This file is part of Ansible
#
@ -111,7 +112,8 @@ class SourcesList(object):
self.files = {} # group sources by file
self.default_file = apt_pkg.config.find_file('Dir::Etc::sourcelist')
# read sources.list
# read sources.list if it exists
if os.path.isfile(self.default_file):
self.load(self.default_file)
# read sources.list.d

@ -135,7 +135,6 @@ def main():
name = module.params['name']
env = module.params['virtualenv']
executable = module.params['executable']
easy_install = _get_easy_install(module, env, executable)
site_packages = module.params['virtualenv_site_packages']
virtualenv_command = module.params['virtualenv_command']
@ -159,6 +158,8 @@ def main():
out += out_venv
err += err_venv
easy_install = _get_easy_install(module, env, executable)
cmd = None
changed = False
installed = _is_package_installed(module, name, easy_install)

@ -71,7 +71,7 @@ def query_package(module, brew_path, name, state="present"):
""" Returns whether a package is installed or not. """
if state == "present":
rc, out, err = module.run_command("%s list -m1 | grep -q '^%s$'" % (brew_path, name))
rc, out, err = module.run_command("%s list %s" % (brew_path, name))
if rc == 0:
return True

@ -30,7 +30,7 @@ options:
name:
description:
- The name of a node.js library to install
requires: false
required: false
path:
description:
- The base path where to install the node.js libraries
@ -180,7 +180,7 @@ def main():
executable=dict(default=None),
state=dict(default='present', choices=['present', 'absent', 'latest'])
)
arg_spec['global']=dict(default='no', type='bool')
arg_spec['global'] = dict(default='no', type='bool')
module = AnsibleModule(
argument_spec=arg_spec,
supports_check_mode=True

@ -147,9 +147,8 @@ EXAMPLES = '''
def _get_cmd_options(module, cmd):
thiscmd = cmd + " --help"
rc, stdout, stderr = module.run_command(thiscmd)
#import epdb; epdb.serve()
if rc != 0:
module.fail_json(msg="Could not get --help output from %s" % virtualenv)
module.fail_json(msg="Could not get output from %s: %s" % (thiscmd, stdout + stderr))
words = stdout.strip().split()
cmd_options = [ x for x in words if x.startswith('--') ]
@ -275,6 +274,7 @@ def main():
pip = _get_pip(module, env, module.params['executable'])
cmd = '%s %s' % (pip, state_map[state])
cmd_opts = None
# If there's a virtualenv we want things we install to be able to use other
# installations that exist as binaries within this virtualenv. Example: we
@ -319,7 +319,11 @@ def main():
is_local_path = True
# for tarball or vcs source, applying --use-mirrors doesn't really make sense
is_package = is_vcs or is_tar or is_local_path # just a shortcut for bool
if not is_package and state != 'absent' and use_mirrors:
if cmd_opts is None:
cmd_opts = _get_cmd_options(module, '%s %s' % (pip, state_map[state]))
if not is_package and state != 'absent' and use_mirrors and '--use-mirrors' in cmd_opts:
cmd += ' --use-mirrors'
cmd += ' %s' % _get_full_name(name, version)
elif requirements:

@ -1,4 +1,4 @@
#!/usr/bin/python2
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""

@ -31,7 +31,7 @@ module: yum
version_added: historical
short_description: Manages packages with the I(yum) package manager
description:
- Will install, upgrade, remove, and list packages with the I(yum) package manager.
- Installs, upgrade, removes, and lists packages and groups with the I(yum) package manager.
options:
name:
description:
@ -41,7 +41,7 @@ options:
aliases: []
list:
description:
- Various non-idempotent commands for usage with C(/usr/bin/ansible) and I(not) playbooks. See examples.
- Various (non-idempotent) commands for usage with C(/usr/bin/ansible) and I(not) playbooks. See examples.
required: false
default: null
state:
@ -94,13 +94,26 @@ author: Seth Vidal
'''
EXAMPLES = '''
- yum: name=httpd state=latest
- yum: name=httpd state=removed
- yum: name=httpd enablerepo=testing state=installed
- yum: name=* state=latest
- yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- yum: name=/usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- yum: name="@Development tools" state=present
- name: install the latest version of Apache
yum: name=httpd state=latest
- name: remove the Apache package
yum: name=httpd state=removed
- name: install the latest version of Apche from the testing repo
yum: name=httpd enablerepo=testing state=installed
- name: upgrade all packages
yum: name=* state=latest
- name: install the nginx rpm from a remote repo
yum: name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- name: install nginx rpm from a local file
yum: name=/usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present
- name: install the 'Development tools' package group
yum: name="@Development tools" state=present
'''
def_qf = "%{name}-%{version}-%{release}.%{arch}"

@ -120,7 +120,7 @@ def main():
description=dict(required=False),
disable_gpg_check = dict(required=False, default='no', type='bool'),
),
supports_check_mode=True,
supports_check_mode=False,
)
repo = module.params['repo']

@ -43,6 +43,12 @@ options:
- What version of the repository to check out. This can be the
full 40-character I(SHA-1) hash, the literal string C(HEAD), a
branch name, or a tag name.
accept_hostkey:
required: false
default: false
version_added: "1.5"
description:
- Add the hostkey for the repo url if not already added.
reference:
required: false
default: null
@ -118,6 +124,7 @@ EXAMPLES = '''
import re
import tempfile
def get_version(git_path, dest, ref="HEAD"):
''' samples the version of the git repo '''
os.chdir(dest)
@ -352,6 +359,7 @@ def main():
force=dict(default='yes', type='bool'),
depth=dict(default=None, type='int'),
update=dict(default='yes', type='bool'),
accept_hostkey=dict(default='no', type='bool'),
executable=dict(default=None),
bare=dict(default='no', type='bool'),
),
@ -369,6 +377,10 @@ def main():
reference = module.params['reference']
git_path = module.params['executable'] or module.get_bin_path('git', True)
# add the git repo's hostkey
#if module.params['accept_hostkey']:
add_git_host_key(module, repo, accept_hostkey=module.params['accept_hostkey'])
if bare:
gitconfig = os.path.join(dest, 'config')
else:
@ -430,4 +442,6 @@ def main():
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.known_hosts import *
main()

@ -59,9 +59,7 @@ options:
choices: [ "yes", "no" ]
purge:
description:
- Deletes untracked files. Runs C(hg purge). Note this requires C(purge) extension to
be enabled if C(purge=yes). This module will modify hgrc file on behalf of the user
and undo the changes before exiting the task.
- Deletes untracked files. Runs C(hg purge).
required: false
default: "no"
choices: [ "yes", "no" ]
@ -85,36 +83,6 @@ EXAMPLES = '''
- hg: repo=https://bitbucket.org/user/repo1 dest=/home/user/repo1 revision=stable purge=yes
'''
def _set_hgrc(hgrc, vals):
parser = ConfigParser.SafeConfigParser()
parser.read(hgrc)
# val is a list of triple-tuple of the form [(section, option, value),...]
for each in vals:
(section, option, value) = each
if not parser.has_section(section):
parser.add_section(section)
parser.set(section, option, value)
f = open(hgrc, 'w')
parser.write(f)
f.close()
def _undo_hgrc(hgrc, vals):
parser = ConfigParser.SafeConfigParser()
parser.read(hgrc)
for each in vals:
(section, option, value) = each
if parser.has_section(section):
parser.remove_option(section, option)
f = open(hgrc, 'w')
parser.write(f)
f.close()
class Hg(object):
def __init__(self, module, dest, repo, revision, hg_path):
@ -129,7 +97,8 @@ class Hg(object):
return (rc, out, err)
def _list_untracked(self):
return self._command(['purge', '-R', self.dest, '--print'])
args = ['purge', '--config', 'extensions.purge=', '-R', self.dest, '--print']
return self._command(args)
def get_revision(self):
"""
@ -168,10 +137,6 @@ class Hg(object):
return True
def purge(self):
hgrc = os.path.join(self.dest, '.hg/hgrc')
purge_option = [('extensions', 'purge', '')]
_set_hgrc(hgrc, purge_option) # enable purge extension
# before purge, find out if there are any untracked files
(rc1, out1, err1) = self._list_untracked()
if rc1 != 0:
@ -179,10 +144,9 @@ class Hg(object):
# there are some untrackd files
if out1 != '':
(rc2, out2, err2) = self._command(['purge', '-R', self.dest])
if rc2 == 0:
_undo_hgrc(hgrc, purge_option)
else:
args = ['purge', '--config', 'extensions.purge=', '-R', self.dest]
(rc2, out2, err2) = self._command(args)
if rc2 != 0:
self.module.fail_json(msg=err2)
return True
else:

@ -94,6 +94,7 @@ class Subversion(object):
def _exec(self, args):
bits = [
'LANG=C',
self.svn_path,
'--non-interactive',
'--trust-server-cert',

@ -114,6 +114,27 @@ import tempfile
import re
import shlex
class keydict(dict):
""" a dictionary that maintains the order of keys as they are added """
# http://stackoverflow.com/questions/2328235/pythonextend-the-dict-class
def __init__(self, *args, **kw):
super(keydict,self).__init__(*args, **kw)
self.itemlist = super(keydict,self).keys()
def __setitem__(self, key, value):
self.itemlist.append(key)
super(keydict,self).__setitem__(key, value)
def __iter__(self):
return iter(self.itemlist)
def keys(self):
return self.itemlist
def values(self):
return [self[key] for key in self]
def itervalues(self):
return (self[key] for key in self)
def keyfile(module, user, write=False, path=None, manage_dir=True):
"""
Calculate name of authorized keys file, optionally creating the
@ -176,7 +197,7 @@ def parseoptions(module, options):
reads a string containing ssh-key options
and returns a dictionary of those options
'''
options_dict = {}
options_dict = keydict() #ordered dict
if options:
token_exp = [
# matches separator
@ -246,9 +267,8 @@ def parsekey(module, raw_key):
# check for options
if type_index is None:
return None
elif type_index == 1:
# parse the options and store them
options = key_parts[0]
elif type_index > 0:
options = " ".join(key_parts[:type_index])
# parse the options (if any)
options = parseoptions(module, options)
@ -292,7 +312,7 @@ def writekeys(module, filename, keys):
option_str = ""
if options:
option_strings = []
for option_key in sorted(options.keys()):
for option_key in options.keys():
if options[option_key]:
option_strings.append("%s=\"%s\"" % (option_key, options[option_key]))
else:
@ -321,7 +341,9 @@ def enforce_state(module, params):
state = params.get("state", "present")
key_options = params.get("key_options", None)
key = key.split('\n')
# extract indivial keys into an array, skipping blank lines and comments
key = [s for s in key.splitlines() if s and not s.startswith('#')]
# check current state -- just get the filename, don't create file
do_write = False
@ -330,10 +352,11 @@ def enforce_state(module, params):
# Check our new keys, if any of them exist we'll continue.
for new_key in key:
parsed_new_key = parsekey(module, new_key)
if key_options is not None:
new_key = "%s %s" % (key_options, new_key)
parsed_options = parseoptions(module, key_options)
parsed_new_key = (parsed_new_key[0], parsed_new_key[1], parsed_options, parsed_new_key[3])
parsed_new_key = parsekey(module, new_key)
if not parsed_new_key:
module.fail_json(msg="invalid key specified: %s" % new_key)

@ -146,6 +146,12 @@ class DebianStrategy(GenericStrategy):
HOSTNAME_FILE = '/etc/hostname'
def get_permanent_hostname(self):
if not os.path.isfile(self.HOSTNAME_FILE):
try:
open(self.HOSTNAME_FILE, "a").write("")
except IOError, err:
self.module.fail_json(msg="failed to write file: %s" %
str(err))
try:
f = open(self.HOSTNAME_FILE)
try:
@ -250,6 +256,11 @@ class AmazonLinuxHostname(Hostname):
distribution = 'Amazon'
strategy_class = RedHatStrategy
class ScientificLinuxHostname(Hostname):
platform = 'Linux'
distribution = 'Scientific'
strategy_class = RedHatStrategy
# ===========================================
class FedoraStrategy(GenericStrategy):

@ -1,4 +1,4 @@
#!/usr/bin/env python2
#!/usr/bin/python
#coding: utf-8 -*-
# This module is free software: you can redistribute it and/or modify

@ -431,10 +431,10 @@ class LinuxService(Service):
if check_systemd(self.name):
# service is managed by systemd
self.enable_cmd = location['systemctl']
elif os.path.exists("/etc/init/%s.conf" % self.name):
elif location['initctl'] and os.path.exists("/etc/init/%s.conf" % self.name):
# service is managed by upstart
self.enable_cmd = location['initctl']
elif os.path.exists("/etc/init.d/%s" % self.name):
elif location['update-rc.d'] and os.path.exists("/etc/init.d/%s" % self.name):
# service is managed by with SysV init scripts, but with update-rc.d
self.enable_cmd = location['update-rc.d']
else:

@ -83,7 +83,7 @@ ansible all -m setup -a 'filter=ansible_*_mb'
# Display only facts returned by facter.
ansible all -m setup -a 'filter=facter_*'
# Display only facts returned by facter.
# Display only facts about certain interfaces.
ansible all -m setup -a 'filter=ansible_eth[0-2]'
"""
@ -118,7 +118,8 @@ class Facts(object):
'/etc/alpine-release': 'Alpine',
'/etc/release': 'Solaris',
'/etc/arch-release': 'Archlinux',
'/etc/SuSE-release': 'SuSE' }
'/etc/SuSE-release': 'SuSE',
'/etc/os-release': 'Debian' }
SELINUX_MODE_DICT = { 1: 'enforcing', 0: 'permissive', -1: 'disabled' }
# A list of dicts. If there is a platform with more than one
@ -328,6 +329,11 @@ class Facts(object):
elif name == 'SuSE':
data = get_file_content(path).splitlines()
self.facts['distribution_release'] = data[2].split('=')[1].strip()
elif name == 'Debian':
data = get_file_content(path).split('\n')[0]
release = re.search("PRETTY_NAME.+ \(?([^ ]+?)\)?\"", data)
if release:
self.facts['distribution_release'] = release.groups()[0]
else:
self.facts['distribution'] = name
@ -1540,8 +1546,7 @@ class LinuxNetwork(Network):
iface = words[-1]
if iface != device:
interfaces[iface] = {}
interfaces[iface].update(interfaces[device])
if "ipv4_secondaries" not in interfaces[iface]:
if not secondary and "ipv4_secondaries" not in interfaces[iface]:
interfaces[iface]["ipv4_secondaries"] = []
if not secondary or "ipv4" not in interfaces[iface]:
interfaces[iface]['ipv4'] = {'address': address,
@ -1553,6 +1558,15 @@ class LinuxNetwork(Network):
'netmask': netmask,
'network': network,
})
# add this secondary IP to the main device
if secondary:
interfaces[device]["ipv4_secondaries"].append({
'address': address,
'netmask': netmask,
'network': network,
})
# If this is the default address, update default_ipv4
if 'address' in default_ipv4 and default_ipv4['address'] == address:
default_ipv4['netmask'] = netmask
@ -2072,6 +2086,11 @@ class LinuxVirtual(Virtual):
self.facts['virtualization_role'] = 'guest'
return
if product_name == 'RHEV Hypervisor':
self.facts['virtualization_type'] = 'RHEV'
self.facts['virtualization_role'] = 'guest'
return
if product_name == 'VMware Virtual Platform':
self.facts['virtualization_type'] = 'VMware'
self.facts['virtualization_role'] = 'guest'

@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
# (c) 2012, David "DaviXX" CHANIAL <david.chanial@gmail.com>
# (c) 2014, James Tanner <tanner.jc@gmail.com>
#
# This file is part of Ansible
#
@ -41,19 +42,9 @@ options:
aliases: [ 'val' ]
state:
description:
- Whether the entry should be present or absent.
- Whether the entry should be present or absent in the sysctl file.
choices: [ "present", "absent" ]
default: present
checks:
description:
- If C(none), no smart/facultative checks will be made. If
C(before), some checks are performed before any update (i.e. is
the sysctl key writable?). If C(after), some checks are performed
after an update (i.e. does kernel return the set value?). If
C(both), all of the smart checks (C(before) and C(after)) are
performed.
choices: [ "none", "before", "after", "both" ]
default: both
reload:
description:
- If C(yes), performs a I(/sbin/sysctl -p) if the C(sysctl_file) is
@ -66,6 +57,13 @@ options:
- Specifies the absolute path to C(sysctl.conf), if not C(/etc/sysctl.conf).
required: false
default: /etc/sysctl.conf
sysctl_set:
description:
- Verify token value with the sysctl command and set with -w if necessary
choices: [ "yes", "no" ]
required: false
version_added: 1.5
default: False
notes: []
requirements: []
author: David "DaviXX" CHANIAL <david.chanial@gmail.com>
@ -78,10 +76,14 @@ EXAMPLES = '''
# Remove kernel.panic entry from /etc/sysctl.conf
- sysctl: name=kernel.panic state=absent sysctl_file=/etc/sysctl.conf
# Set kernel.panic to 3 in /tmp/test_sysctl.conf, check if the sysctl key
# seems writable, but do not reload sysctl, and do not check kernel value
# after (not needed, because the real /etc/sysctl.conf was not updated)
- sysctl: name=kernel.panic value=3 sysctl_file=/tmp/test_sysctl.conf check=before reload=no
# Set kernel.panic to 3 in /tmp/test_sysctl.conf
- sysctl: name=kernel.panic value=3 sysctl_file=/tmp/test_sysctl.conf reload=no
# Set ip fowarding on in /proc and do not reload the sysctl file
- sysctl: name="net.ipv4.ip_forward" value=1 sysctl_set=yes
# Set ip forwarding on in /proc and in the sysctl file and reload if necessary
- sysctl: name="net.ipv4.ip_forward" value=1 sysctl_set=yes state=present reload=yes
'''
# ==============================================================
@ -90,137 +92,174 @@ import os
import tempfile
import re
# ==============================================================
class SysctlModule(object):
def reload_sysctl(module, **sysctl_args):
# update needed ?
if not sysctl_args['reload']:
return 0, ''
def __init__(self, module):
self.module = module
self.args = self.module.params
# do it
if get_platform().lower() == 'freebsd':
# freebsd doesn't support -p, so reload the sysctl service
rc,out,err = module.run_command('/etc/rc.d/sysctl reload')
else:
# system supports reloading via the -p flag to sysctl, so we'll use that
sysctl_cmd = module.get_bin_path('sysctl', required=True)
rc,out,err = module.run_command([sysctl_cmd, '-p', sysctl_args['sysctl_file']])
self.sysctl_cmd = self.module.get_bin_path('sysctl', required=True)
self.sysctl_file = self.args['sysctl_file']
return rc,out+err
self.proc_value = None # current token value in proc fs
self.file_value = None # current token value in file
self.file_lines = [] # all lines in the file
self.file_values = {} # dict of token values
# ==============================================================
self.changed = False # will change occur
self.set_proc = False # does sysctl need to set value
self.write_file = False # does the sysctl file need to be reloaded
def write_sysctl(module, lines, **sysctl_args):
# open a tmp file
fd, tmp_path = tempfile.mkstemp('.conf', '.ansible_m_sysctl_', os.path.dirname(sysctl_args['sysctl_file']))
f = open(tmp_path,"w")
try:
for l in lines:
f.write(l)
except IOError, e:
module.fail_json(msg="Failed to write to file %s: %s" % (tmp_path, str(e)))
f.flush()
f.close()
self.process()
# replace the real one
module.atomic_move(tmp_path, sysctl_args['sysctl_file'])
# ==============================================================
# LOGIC
# ==============================================================
# end
return sysctl_args
def process(self):
# ==============================================================
# Whitespace is bad
self.args['name'] = self.args['name'].strip()
if self.args['value'] is not None:
self.args['value'] = self.args['value'].strip()
else:
self.args['value'] = ""
thisname = self.args['name']
# get the current proc fs value
self.proc_value = self.get_token_curr_value(thisname)
# get the currect sysctl file value
self.read_sysctl_file()
if thisname not in self.file_values:
self.file_values[thisname] = None
# update file contents with desired token/value
self.fix_lines()
# what do we need to do now?
if self.file_values[thisname] is None and self.args['state'] == "present":
self.changed = True
self.write_file = True
elif self.file_values[thisname] != self.args['value']:
self.changed = True
self.write_file = True
if self.args['sysctl_set']:
if self.proc_value is None:
self.changed = True
elif self.proc_value != self.args['value']:
self.changed = True
self.set_proc = True
# Do the work
if not self.module.check_mode:
if self.write_file:
self.write_sysctl()
if self.write_file and self.args['reload']:
self.reload_sysctl()
if self.set_proc:
self.set_token_value(self.args['name'], self.args['value'])
# ==============================================================
# SYSCTL COMMAND MANAGEMENT
# ==============================================================
# Use the sysctl command to find the current value
def get_token_curr_value(self, token):
thiscmd = "%s -e -n %s" % (self.sysctl_cmd, token)
rc,out,err = self.module.run_command(thiscmd)
if rc != 0:
return None
else:
return out
# Use the sysctl command to set the current value
def set_token_value(self, token, value):
if len(value.split()) > 0:
value = '"' + value + '"'
thiscmd = "%s -w %s=%s" % (self.sysctl_cmd, token, value)
rc,out,err = self.module.run_command(thiscmd)
if rc != 0:
self.module.fail_json(msg='setting %s failed: %s' % (token, out + err))
else:
return rc
def sysctl_args_expand(**sysctl_args):
# Run sysctl -p
def reload_sysctl(self):
# do it
if get_platform().lower() == 'freebsd':
# FreeBSD does not use the /proc file system, and instead
# just uses the sysctl command to set the values
sysctl_args['key_path'] = None
# freebsd doesn't support -p, so reload the sysctl service
rc,out,err = self.module.run_command('/etc/rc.d/sysctl reload')
else:
sysctl_args['key_path'] = sysctl_args['name'].replace('.' ,'/')
sysctl_args['key_path'] = '/proc/sys/' + sysctl_args['key_path']
return sysctl_args
# system supports reloading via the -p flag to sysctl, so we'll use that
rc,out,err = self.module.run_command([self.sysctl_cmd, '-p', self.sysctl_file])
# ==============================================================
if rc != 0:
self.module.fail_json(msg="Failed to reload sysctl: %s" % str(out) + str(err))
def sysctl_args_collapse(**sysctl_args):
# go ahead
if sysctl_args.get('key_path') is not None:
del sysctl_args['key_path']
if sysctl_args['state'] == 'absent' and 'value' in sysctl_args:
del sysctl_args['value']
# ==============================================================
# SYSCTL FILE MANAGEMENT
# ==============================================================
# end
return sysctl_args
# Get the token value from the sysctl file
def read_sysctl_file(self):
lines = open(self.sysctl_file, "r").readlines()
for line in lines:
line = line.strip()
self.file_lines.append(line)
# ==============================================================
# don't split empty lines or comments
if not line or line.startswith("#"):
continue
def sysctl_check(module, current_step, **sysctl_args):
# no smart checks at this step ?
if sysctl_args['checks'] == 'none':
return 0, ''
if current_step == 'before' and sysctl_args['checks'] not in ['before', 'both']:
return 0, ''
if current_step == 'after' and sysctl_args['checks'] not in ['after', 'both']:
return 0, ''
# checking coherence
if sysctl_args['state'] == 'absent' and sysctl_args['value'] is not None:
return 1, 'value=x must not be supplied when state=absent'
if sysctl_args['state'] == 'present' and sysctl_args['value'] is None:
return 1, 'value=x must be supplied when state=present'
if not sysctl_args['reload'] and sysctl_args['checks'] in ['after', 'both']:
return 1, 'checks cannot be set to after or both if reload=no'
if sysctl_args['key_path'] is not None:
# getting file stat
if not os.access(sysctl_args['key_path'], os.F_OK):
return 1, 'key_path is not an existing file, key %s seems invalid' % sysctl_args['key_path']
if not os.access(sysctl_args['key_path'], os.R_OK):
return 1, 'key_path is not a readable file, key seems to be uncheckable'
# checks before
if current_step == 'before' and sysctl_args['checks'] in ['before', 'both']:
if sysctl_args['key_path'] is not None and not os.access(sysctl_args['key_path'], os.W_OK):
return 1, 'key_path is not a writable file, key seems to be read only'
return 0, ''
# checks after
if current_step == 'after' and sysctl_args['checks'] in ['after', 'both']:
if sysctl_args['value'] is not None:
if sysctl_args['key_path'] is not None:
# reading the virtual file
f = open(sysctl_args['key_path'],'r')
output = f.read()
f.close()
k, v = line.split('=',1)
k = k.strip()
v = v.strip()
self.file_values[k] = v.strip()
# Fix the value in the sysctl file content
def fix_lines(self):
checked = []
self.fixed_lines = []
for line in self.file_lines:
if not line.strip() or line.strip().startswith("#"):
self.fixed_lines.append(line)
continue
tmpline = line.strip()
k, v = line.split('=',1)
k = k.strip()
v = v.strip()
if k not in checked:
checked.append(k)
if k == self.args['name']:
if self.args['state'] == "present":
new_line = "%s = %s\n" % (k, self.args['value'])
self.fixed_lines.append(new_line)
else:
# we're on a system without /proc (ie. freebsd), so just
# use the sysctl command to get the currently set value
sysctl_cmd = module.get_bin_path('sysctl', required=True)
rc,output,stderr = module.run_command("%s -n %s" % (sysctl_cmd, sysctl_args['name']))
if rc != 0:
return 1, 'failed to lookup the value via the sysctl command'
new_line = "%s = %s\n" % (k, v)
self.fixed_lines.append(new_line)
output = output.strip(' \t\n\r')
output = re.sub(r'\s+', ' ', output)
if self.args['name'] not in checked and self.args['state'] == "present":
new_line = "%s = %s\n" % (self.args['name'], self.args['value'])
self.fixed_lines.append(new_line)
# normal case, found value must be equal to the submitted value, and
# we compare the exploded values to handle any whitepsace differences
if output.split() != sysctl_args['value'].split():
return 1, 'key seems not set to value even after update/sysctl, founded : <%s>, wanted : <%s>' % (output, sysctl_args['value'])
# Completely rewrite the sysctl file
def write_sysctl(self):
# open a tmp file
fd, tmp_path = tempfile.mkstemp('.conf', '.ansible_m_sysctl_', os.path.dirname(self.sysctl_file))
f = open(tmp_path,"w")
try:
for l in self.fixed_lines:
f.write(l.strip() + "\n")
except IOError, e:
self.module.fail_json(msg="Failed to write to file %s: %s" % (tmp_path, str(e)))
f.flush()
f.close()
return 0, ''
else:
# no value was supplied, so we're checking to make sure
# the associated name is absent. We just fudge this since
# the sysctl isn't really gone, just removed from the conf
# file meaning it will be whatever the system default is
return 0, ''
# replace the real one
self.module.atomic_move(tmp_path, self.sysctl_file)
# weird end
return 1, 'unexpected position reached'
# ==============================================================
# main
@ -233,110 +272,16 @@ def main():
name = dict(aliases=['key'], required=True),
value = dict(aliases=['val'], required=False),
state = dict(default='present', choices=['present', 'absent']),
checks = dict(default='both', choices=['none', 'before', 'after', 'both']),
reload = dict(default=True, type='bool'),
sysctl_set = dict(default=False, type='bool'),
sysctl_file = dict(default='/etc/sysctl.conf')
),
supports_check_mode=True
)
)
# defaults
sysctl_args = {
'changed': False,
'name': module.params['name'],
'state': module.params['state'],
'checks': module.params['checks'],
'reload': module.params['reload'],
'value': module.params.get('value'),
'sysctl_file': module.params['sysctl_file']
}
# prepare vars
sysctl_args = sysctl_args_expand(**sysctl_args)
if get_platform().lower() == 'freebsd':
# freebsd does not like spaces around the equal sign
pattern = "%s=%s\n"
else:
pattern = "%s = %s\n"
new_line = pattern % (sysctl_args['name'], sysctl_args['value'])
to_write = []
founded = False
# make checks before act
res,msg = sysctl_check(module, 'before', **sysctl_args)
if res != 0:
module.fail_json(msg='checks_before failed with: ' + msg)
if not os.access(sysctl_args['sysctl_file'], os.W_OK):
try:
f = open(sysctl_args['sysctl_file'],'w')
f.close()
except IOError, e:
module.fail_json(msg='unable to create supplied sysctl file (destination directory probably missing)')
# reading the file
for line in open(sysctl_args['sysctl_file'], 'r').readlines():
if not line.strip():
to_write.append(line)
continue
if line.strip().startswith('#'):
to_write.append(line)
continue
# write line if not the one searched
ld = {}
ld['name'], ld['val'] = line.split('=',1)
ld['name'] = ld['name'].strip()
if ld['name'] != sysctl_args['name']:
to_write.append(line)
continue
# should be absent ?
if sysctl_args['state'] == 'absent':
# not writing the founded line
# mark as changed
sysctl_args['changed'] = True
# should be present
if sysctl_args['state'] == 'present':
# is the founded line equal to the wanted one ?
ld['val'] = ld['val'].strip()
if ld['val'] == sysctl_args['value']:
# line is equal, writing it without update (but cancel repeats)
if sysctl_args['changed'] == False and founded == False:
to_write.append(line)
founded = True
else:
# update the line (but cancel repeats)
if sysctl_args['changed'] == False and founded == False:
to_write.append(new_line)
sysctl_args['changed'] = True
continue
result = SysctlModule(module)
# if not changed, but should be present, so we have to add it
if sysctl_args['state'] == 'present' and sysctl_args['changed'] == False and founded == False:
to_write.append(new_line)
sysctl_args['changed'] = True
# has changed ?
res = 0
if sysctl_args['changed'] == True:
sysctl_args = write_sysctl(module, to_write, **sysctl_args)
res,msg = reload_sysctl(module, **sysctl_args)
# make checks after act
res,msg = sysctl_check(module, 'after', **sysctl_args)
if res != 0:
module.fail_json(msg='checks_after failed with: ' + msg)
# look at the next link to avoid this workaround
# https://groups.google.com/forum/?fromgroups=#!topic/ansible-project/LMY-dwF6SQk
changed = sysctl_args['changed']
del sysctl_args['changed']
# end
sysctl_args = sysctl_args_collapse(**sysctl_args)
module.exit_json(changed=changed, **sysctl_args)
module.exit_json(changed=result.changed)
sys.exit(0)
# import module snippets

@ -77,8 +77,8 @@ options:
description:
- Optionally set the user's password to this crypted value. See
the user example in the github examples directory for what this looks
like in a playbook.
- Passwords values can be generated with "openssl passwd -salt <salt> -1 <plaintext>"
like in a playbook. The `FAQ <http://docs.ansible.com/faq.html#how-do-i-generate-crypted-passwords-for-the-user-module>`_
contains details on various ways to generate these password values.
state:
required: false
default: "present"
@ -901,6 +901,19 @@ class OpenBSDUser(User):
cmd.append(self.shell)
if self.login_class is not None:
# find current login class
user_login_class = None
userinfo_cmd = [self.module.get_bin_path('userinfo', True), self.name]
(rc, out, err) = self.execute_command(userinfo_cmd)
for line in out.splitlines():
tokens = line.split()
if tokens[0] == 'class' and len(tokens) == 2:
user_login_class = tokens[1]
# act only if login_class change
if self.login_class != user_login_class:
cmd.append('-L')
cmd.append(self.login_class)

@ -40,5 +40,5 @@ author: Dag Wieers
EXAMPLES = '''
# Example playbook using fail and when together
- fail: msg="The system may not be provisioned according to the CMDB status."
when: "{{ cmdb_status }} != 'to-be-staged'"
when: cmdb_status != "to-be-staged"
'''

@ -129,12 +129,11 @@ def _ensure_virtualenv(module):
if venv_param is None:
return
virtualenv = module.get_bin_path('virtualenv', True)
vbin = os.path.join(os.path.expanduser(venv_param), 'bin')
activate = os.path.join(vbin, 'activate')
if not os.path.exists(activate):
virtualenv = module.get_bin_path('virtualenv', True)
vcmd = '%s %s' % (virtualenv, venv_param)
vcmd = [virtualenv, venv_param]
rc, out_venv, err_venv = module.run_command(vcmd)

Loading…
Cancel
Save