Merge branch 'nova-compute-enhancements' of git://github.com/emonty/ansible into devel
Conflicts: lib/ansible/module_utils/openstack.py library/cloud/nova_compute
This commit is contained in:
commit
66eddfd491
4 changed files with 359 additions and 31 deletions
|
@ -54,3 +54,16 @@ def openstack_argument_spec():
|
||||||
else:
|
else:
|
||||||
spec['login_tenant_name'] = dict(required=True)
|
spec['login_tenant_name'] = dict(required=True)
|
||||||
return spec
|
return spec
|
||||||
|
|
||||||
|
def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
for (k, v) in addresses.iteritems():
|
||||||
|
if key_name and k == key_name:
|
||||||
|
ret.extend([addrs['addr'] for addrs in v])
|
||||||
|
else:
|
||||||
|
for interface_spec in v:
|
||||||
|
if 'OS-EXT-IPS:type' in interface_spec and interface_spec['OS-EXT-IPS:type'] == ext_tag:
|
||||||
|
ret.append(interface_spec['addr'])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,14 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this software. If not, see <http://www.gnu.org/licenses/>.
|
# along with this software. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import operator
|
||||||
import os
|
import os
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from novaclient.v1_1 import client as nova_client
|
from novaclient.v1_1 import client as nova_client
|
||||||
|
from novaclient.v1_1 import floating_ips
|
||||||
from novaclient import exceptions
|
from novaclient import exceptions
|
||||||
|
from novaclient import utils
|
||||||
import time
|
import time
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("failed=True msg='novaclient is required for this module'")
|
print("failed=True msg='novaclient is required for this module'")
|
||||||
|
@ -71,14 +74,34 @@ options:
|
||||||
default: None
|
default: None
|
||||||
image_id:
|
image_id:
|
||||||
description:
|
description:
|
||||||
- The id of the image that has to be cloned
|
- The id of the base image to boot. Mutually exclusive with image_name
|
||||||
required: true
|
required: true
|
||||||
default: None
|
default: None
|
||||||
|
image_name:
|
||||||
|
description:
|
||||||
|
- The name of the base image to boot. Mutually exclusive with image_id
|
||||||
|
required: true
|
||||||
|
default: None
|
||||||
|
version_added: "1.7"
|
||||||
|
image_exclude:
|
||||||
|
description:
|
||||||
|
- Text to use to filter image names, for the case, such as HP, where there are multiple image names matching the common identifying portions. image_exclude is a negative match filter - it is text that may not exist in the image name. Defaults to "(deprecated)"
|
||||||
|
version_added: "1.7"
|
||||||
flavor_id:
|
flavor_id:
|
||||||
description:
|
description:
|
||||||
- The id of the flavor in which the new VM has to be created
|
- The id of the flavor in which the new VM has to be created. Mutually exclusive with flavor_ram
|
||||||
required: false
|
required: false
|
||||||
default: 1
|
default: 1
|
||||||
|
flavor_ram:
|
||||||
|
description:
|
||||||
|
- The minimum amount of ram in MB that the flavor in which the new VM has to be created must have. Mutually exclusive with flavor_id
|
||||||
|
required: false
|
||||||
|
default: 1
|
||||||
|
version_added: "1.7"
|
||||||
|
flavor_include:
|
||||||
|
description:
|
||||||
|
- Text to use to filter flavor names, for the case, such as Rackspace, where there are multiple flavors that have the same ram count. flavor_include is a positive match filter - it must exist in the flavor name.
|
||||||
|
version_added: "1.7"
|
||||||
key_name:
|
key_name:
|
||||||
description:
|
description:
|
||||||
- The key pair name to be used when creating a VM
|
- The key pair name to be used when creating a VM
|
||||||
|
@ -94,6 +117,30 @@ options:
|
||||||
- A list of network id's to which the VM's interface should be attached
|
- A list of network id's to which the VM's interface should be attached
|
||||||
required: false
|
required: false
|
||||||
default: None
|
default: None
|
||||||
|
auto_floating_ip:
|
||||||
|
description:
|
||||||
|
- Should a floating ip be auto created and assigned
|
||||||
|
required: false
|
||||||
|
default: 'yes'
|
||||||
|
version_added: "1.7"
|
||||||
|
floating_ips:
|
||||||
|
decription:
|
||||||
|
- list of valid floating IPs that pre-exist to assign to this node
|
||||||
|
required: false
|
||||||
|
default: None
|
||||||
|
version_added: "1.7"
|
||||||
|
floating_ip_pools:
|
||||||
|
description:
|
||||||
|
- list of floating IP pools from which to choose a floating IP
|
||||||
|
required: false
|
||||||
|
default: None
|
||||||
|
version_added: "1.7"
|
||||||
|
availability_zone:
|
||||||
|
description:
|
||||||
|
- Name of the availability zone
|
||||||
|
required: false
|
||||||
|
default: None
|
||||||
|
version_added: "1.7"
|
||||||
meta:
|
meta:
|
||||||
description:
|
description:
|
||||||
- A list of key value pairs that should be provided as a metadata to the new VM
|
- A list of key value pairs that should be provided as a metadata to the new VM
|
||||||
|
@ -109,6 +156,11 @@ options:
|
||||||
- The amount of time the module should wait for the VM to get into active state
|
- The amount of time the module should wait for the VM to get into active state
|
||||||
required: false
|
required: false
|
||||||
default: 180
|
default: 180
|
||||||
|
config_drive:
|
||||||
|
description:
|
||||||
|
- Whether to boot the server with config drive enabled
|
||||||
|
required: false
|
||||||
|
default: 'no'
|
||||||
user_data:
|
user_data:
|
||||||
description:
|
description:
|
||||||
- Opaque blob of data which is made available to the instance
|
- Opaque blob of data which is made available to the instance
|
||||||
|
@ -135,8 +187,86 @@ EXAMPLES = '''
|
||||||
meta:
|
meta:
|
||||||
hostname: test1
|
hostname: test1
|
||||||
group: uge_master
|
group: uge_master
|
||||||
|
|
||||||
|
# Creates a new VM in HP Cloud AE1 region availability zone az2 and automatically assigns a floating IP
|
||||||
|
- name: launch a nova instance
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: launch an instance
|
||||||
|
nova_compute:
|
||||||
|
state: present
|
||||||
|
login_username: username
|
||||||
|
login_password: Equality7-2521
|
||||||
|
login_tenant_name: username-project1
|
||||||
|
name: vm1
|
||||||
|
auth_url: https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
|
||||||
|
region_name: region-b.geo-1
|
||||||
|
availability_zone: az2
|
||||||
|
image_id: 9302692b-b787-4b52-a3a6-daebb79cb498
|
||||||
|
key_name: test
|
||||||
|
wait_for: 200
|
||||||
|
flavor_id: 101
|
||||||
|
security_groups: default
|
||||||
|
auto_floating_ip: yes
|
||||||
|
|
||||||
|
# Creates a new VM in HP Cloud AE1 region availability zone az2 and assigns a pre-known floating IP
|
||||||
|
- name: launch a nova instance
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: launch an instance
|
||||||
|
nova_compute:
|
||||||
|
state: present
|
||||||
|
login_username: username
|
||||||
|
login_password: Equality7-2521
|
||||||
|
login_tenant_name: username-project1
|
||||||
|
name: vm1
|
||||||
|
auth_url: https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
|
||||||
|
region_name: region-b.geo-1
|
||||||
|
availability_zone: az2
|
||||||
|
image_id: 9302692b-b787-4b52-a3a6-daebb79cb498
|
||||||
|
key_name: test
|
||||||
|
wait_for: 200
|
||||||
|
flavor_id: 101
|
||||||
|
floating-ips:
|
||||||
|
- 12.34.56.79
|
||||||
|
|
||||||
|
# Creates a new VM with 4G of RAM on Ubuntu Trusty, ignoring deprecated images
|
||||||
|
- name: launch a nova instance
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: launch an instance
|
||||||
|
nova_compute:
|
||||||
|
name: vm1
|
||||||
|
state: present
|
||||||
|
login_username: username
|
||||||
|
login_password: Equality7-2521
|
||||||
|
login_tenant_name: username-project1
|
||||||
|
auth_url: https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
|
||||||
|
region_name: region-b.geo-1
|
||||||
|
image_name: Ubuntu Server 14.04
|
||||||
|
image_exclude: deprecated
|
||||||
|
flavor_ram: 4096
|
||||||
|
|
||||||
|
# Creates a new VM with 4G of RAM on Ubuntu Trusty on a Rackspace Performance node in DFW
|
||||||
|
- name: launch a nova instance
|
||||||
|
hosts: localhost
|
||||||
|
tasks:
|
||||||
|
- name: launch an instance
|
||||||
|
nova_compute:
|
||||||
|
name: vm1
|
||||||
|
state: present
|
||||||
|
login_username: username
|
||||||
|
login_password: Equality7-2521
|
||||||
|
login_tenant_name: username-project1
|
||||||
|
auth_url: https://identity.api.rackspacecloud.com/v2.0/
|
||||||
|
region_name: DFW
|
||||||
|
image_name: Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)
|
||||||
|
flavor_ram: 4096
|
||||||
|
flavor_include: Performance
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _delete_server(module, nova):
|
def _delete_server(module, nova):
|
||||||
name = None
|
name = None
|
||||||
server_list = None
|
server_list = None
|
||||||
|
@ -158,18 +288,142 @@ def _delete_server(module, nova):
|
||||||
module.fail_json(msg = "Timed out waiting for server to get deleted, please check manually")
|
module.fail_json(msg = "Timed out waiting for server to get deleted, please check manually")
|
||||||
|
|
||||||
|
|
||||||
|
def _add_floating_ip_from_pool(module, nova, server):
|
||||||
|
|
||||||
|
# instantiate FloatingIPManager object
|
||||||
|
floating_ip_obj = floating_ips.FloatingIPManager(nova)
|
||||||
|
|
||||||
|
# empty dict and list
|
||||||
|
usable_floating_ips = {}
|
||||||
|
pools = []
|
||||||
|
|
||||||
|
# user specified
|
||||||
|
pools = module.params['floating_ip_pools']
|
||||||
|
|
||||||
|
# get the list of all floating IPs. Mileage may
|
||||||
|
# vary according to Nova Compute configuration
|
||||||
|
# per cloud provider
|
||||||
|
all_floating_ips = floating_ip_obj.list()
|
||||||
|
|
||||||
|
# iterate through all pools of IP address. Empty
|
||||||
|
# string means all and is the default value
|
||||||
|
for pool in pools:
|
||||||
|
# temporary list per pool
|
||||||
|
pool_ips = []
|
||||||
|
# loop through all floating IPs
|
||||||
|
for f_ip in all_floating_ips:
|
||||||
|
# if not reserved and the correct pool, add
|
||||||
|
if f_ip.instance_id is None and (f_ip.pool == pool):
|
||||||
|
pool_ips.append(f_ip.ip)
|
||||||
|
# only need one
|
||||||
|
break
|
||||||
|
|
||||||
|
# if the list is empty, add for this pool
|
||||||
|
if not pool_ips:
|
||||||
|
try:
|
||||||
|
new_ip = nova.floating_ips.create(pool)
|
||||||
|
except Exception, e:
|
||||||
|
module.fail_json(msg = "Unable to create floating ip")
|
||||||
|
pool_ips.append(new_ip.ip)
|
||||||
|
# Add to the main list
|
||||||
|
usable_floating_ips[pool] = pool_ips
|
||||||
|
|
||||||
|
# finally, add ip(s) to instance for each pool
|
||||||
|
for pool in usable_floating_ips:
|
||||||
|
for ip in usable_floating_ips[pool]:
|
||||||
|
try:
|
||||||
|
server.add_floating_ip(ip)
|
||||||
|
# We only need to assign one ip - but there is an inherent
|
||||||
|
# race condition and some other cloud operation may have
|
||||||
|
# stolen an available floating ip
|
||||||
|
break
|
||||||
|
except Exception, e:
|
||||||
|
module.fail_json(msg = "Error attaching IP %s to instance %s: %s " % (ip, server.id, e.message))
|
||||||
|
|
||||||
|
|
||||||
|
def _add_floating_ip_list(module, server, ips):
|
||||||
|
# add ip(s) to instance
|
||||||
|
for ip in ips:
|
||||||
|
try:
|
||||||
|
server.add_floating_ip(ip)
|
||||||
|
except Exception, e:
|
||||||
|
module.fail_json(msg = "Error attaching IP %s to instance %s: %s " % (ip, server.id, e.message))
|
||||||
|
|
||||||
|
|
||||||
|
def _add_auto_floating_ip(module, nova, server):
|
||||||
|
|
||||||
|
try:
|
||||||
|
new_ip = nova.floating_ips.create()
|
||||||
|
except Exception as e:
|
||||||
|
module.fail_json(msg = "Unable to create floating ip: %s" % (e.message))
|
||||||
|
|
||||||
|
try:
|
||||||
|
server.add_floating_ip(new_ip)
|
||||||
|
except Exception as e:
|
||||||
|
# Clean up - we auto-created this ip, and it's not attached
|
||||||
|
# to the server, so the cloud will not know what to do with it
|
||||||
|
server.floating_ips.delete(new_ip)
|
||||||
|
module.fail_json(msg = "Error attaching IP %s to instance %s: %s " % (ip, server.id, e.message))
|
||||||
|
|
||||||
|
|
||||||
|
def _add_floating_ip(module, nova, server):
|
||||||
|
|
||||||
|
if module.params['floating_ip_pools']:
|
||||||
|
_add_floating_ip_from_pool(module, nova, server)
|
||||||
|
elif module.params['floating_ips']:
|
||||||
|
_add_floating_ip_list(module, server, module.params['floating_ips'])
|
||||||
|
elif module.params['auto_floating_ip']:
|
||||||
|
_add_auto_floating_ip(module, nova, server)
|
||||||
|
else:
|
||||||
|
return server
|
||||||
|
|
||||||
|
# this may look redundant, but if there is now a
|
||||||
|
# floating IP, then it needs to be obtained from
|
||||||
|
# a recent server object if the above code path exec'd
|
||||||
|
try:
|
||||||
|
server = nova.servers.get(server.id)
|
||||||
|
except Exception, e:
|
||||||
|
module.fail_json(msg = "Error in getting info from instance: %s " % e.message)
|
||||||
|
return server
|
||||||
|
|
||||||
|
|
||||||
|
def _get_image_id(module, nova):
|
||||||
|
if module.params['image_name']:
|
||||||
|
for image in nova.images.list():
|
||||||
|
if (module.params['image_name'] in image.name and (
|
||||||
|
not module.params['image_exclude']
|
||||||
|
or module.params['image_exclude'] not in image.name)):
|
||||||
|
return image.id
|
||||||
|
module.fail_json(msg = "Error finding image id from name(%s)" % module.params['image_name'])
|
||||||
|
return module.params['image_id']
|
||||||
|
|
||||||
|
|
||||||
|
def _get_flavor_id(module, nova):
|
||||||
|
if module.params['flavor_ram']:
|
||||||
|
for flavor in sorted(nova.flavors.list(), key=operator.attrgetter('ram')):
|
||||||
|
if (flavor.ram >= module.params['flavor_ram'] and
|
||||||
|
(not module.params['flavor_include'] or module.params['flavor_include'] in flavor.name)):
|
||||||
|
return flavor.id
|
||||||
|
module.fail_json(msg = "Error finding flavor with %sMB of RAM" % module.params['flavor_ram'])
|
||||||
|
return module.params['flavor_id']
|
||||||
|
|
||||||
|
|
||||||
def _create_server(module, nova):
|
def _create_server(module, nova):
|
||||||
bootargs = [module.params['name'], module.params['image_id'], module.params['flavor_id']]
|
image_id = _get_image_id(module, nova)
|
||||||
|
flavor_id = _get_flavor_id(module, nova)
|
||||||
|
bootargs = [module.params['name'], image_id, flavor_id]
|
||||||
bootkwargs = {
|
bootkwargs = {
|
||||||
'nics' : module.params['nics'],
|
'nics' : module.params['nics'],
|
||||||
'meta' : module.params['meta'],
|
'meta' : module.params['meta'],
|
||||||
'key_name': module.params['key_name'],
|
|
||||||
'security_groups': module.params['security_groups'].split(','),
|
'security_groups': module.params['security_groups'].split(','),
|
||||||
#userdata is unhyphenated in novaclient, but hyphenated here for consistency with the ec2 module:
|
#userdata is unhyphenated in novaclient, but hyphenated here for consistency with the ec2 module:
|
||||||
'userdata': module.params['user_data'],
|
'userdata': module.params['user_data'],
|
||||||
|
'config_drive': module.params['config_drive'],
|
||||||
}
|
}
|
||||||
if not module.params['key_name']:
|
|
||||||
del bootkwargs['key_name']
|
for optional_param in ('region_name', 'key_name', 'availability_zone'):
|
||||||
|
if module.params[optional_param]:
|
||||||
|
bootkwargs[optional_param] = module.params[optional_param]
|
||||||
try:
|
try:
|
||||||
server = nova.servers.create(*bootargs, **bootkwargs)
|
server = nova.servers.create(*bootargs, **bootkwargs)
|
||||||
server = nova.servers.get(server.id)
|
server = nova.servers.get(server.id)
|
||||||
|
@ -181,11 +435,16 @@ def _create_server(module, nova):
|
||||||
try:
|
try:
|
||||||
server = nova.servers.get(server.id)
|
server = nova.servers.get(server.id)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
module.fail_json( msg = "Error in getting info from instance: %s " % e.message)
|
module.fail_json( msg = "Error in getting info from instance: %s" % e.message)
|
||||||
if server.status == 'ACTIVE':
|
if server.status == 'ACTIVE':
|
||||||
private = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if 'OS-EXT-IPS:type' in x and x['OS-EXT-IPS:type'] == 'fixed']
|
server = _add_floating_ip(module, nova, server)
|
||||||
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if 'OS-EXT-IPS:type' in x and x['OS-EXT-IPS:type'] == 'floating']
|
|
||||||
|
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
|
||||||
|
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
|
||||||
|
|
||||||
|
# now exit with info
|
||||||
module.exit_json(changed = True, id = server.id, private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
|
module.exit_json(changed = True, id = server.id, private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
|
||||||
|
|
||||||
if server.status == 'ERROR':
|
if server.status == 'ERROR':
|
||||||
module.fail_json(msg = "Error in creating the server, please check logs")
|
module.fail_json(msg = "Error in creating the server, please check logs")
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
|
@ -193,11 +452,46 @@ def _create_server(module, nova):
|
||||||
module.fail_json(msg = "Timeout waiting for the server to come up.. Please check manually")
|
module.fail_json(msg = "Timeout waiting for the server to come up.. Please check manually")
|
||||||
if server.status == 'ERROR':
|
if server.status == 'ERROR':
|
||||||
module.fail_json(msg = "Error in creating the server.. Please check manually")
|
module.fail_json(msg = "Error in creating the server.. Please check manually")
|
||||||
private = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'fixed']
|
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
|
||||||
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
|
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
|
||||||
|
|
||||||
module.exit_json(changed = True, id = info['id'], private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
|
module.exit_json(changed = True, id = info['id'], private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_floating_ip_list(module, nova, server, extra_ips):
|
||||||
|
for ip in extra_ips:
|
||||||
|
nova.servers.remove_floating_ip(server=server.id, address=ip)
|
||||||
|
|
||||||
|
|
||||||
|
def _check_floating_ips(module, nova, server):
|
||||||
|
changed = False
|
||||||
|
if module.params['floating_ip_pools'] or module.params['floating_ips'] or module.params['auto_floating_ip']:
|
||||||
|
ips = openstack_find_nova_addresses(server.addresses, 'floating')
|
||||||
|
if not ips:
|
||||||
|
# If we're configured to have a floating but we don't have one,
|
||||||
|
# let's add one
|
||||||
|
server = _add_floating_ip(module, nova, server)
|
||||||
|
changed = True
|
||||||
|
elif module.params['floating_ips']:
|
||||||
|
# we were configured to have specific ips, let's make sure we have
|
||||||
|
# those
|
||||||
|
missing_ips = []
|
||||||
|
for ip in module.params['floating_ips']:
|
||||||
|
if ip not in ips:
|
||||||
|
missing_ips.append(ip)
|
||||||
|
if missing_ips:
|
||||||
|
server = _add_floating_ip_list(module, server, missing_ips)
|
||||||
|
changed = True
|
||||||
|
extra_ips = []
|
||||||
|
for ip in ips:
|
||||||
|
if ip not in module.params['floating_ips']:
|
||||||
|
extra_ips.append(ip)
|
||||||
|
if extra_ips:
|
||||||
|
_delete_floating_ip_list(module, server, extra_ips)
|
||||||
|
changed = True
|
||||||
|
return (changed, server)
|
||||||
|
|
||||||
|
|
||||||
def _get_server_state(module, nova):
|
def _get_server_state(module, nova):
|
||||||
server = None
|
server = None
|
||||||
try:
|
try:
|
||||||
|
@ -214,9 +508,10 @@ def _get_server_state(module, nova):
|
||||||
if server and module.params['state'] == 'present':
|
if server and module.params['state'] == 'present':
|
||||||
if server.status != 'ACTIVE':
|
if server.status != 'ACTIVE':
|
||||||
module.fail_json( msg="The VM is available but not Active. state:" + server.status)
|
module.fail_json( msg="The VM is available but not Active. state:" + server.status)
|
||||||
private = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if 'OS-EXT-IPS:type' in x and x['OS-EXT-IPS:type'] == 'fixed']
|
(ip_changed, server) = _check_floating_ips(module, nova, server)
|
||||||
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if 'OS-EXT-IPS:type' in x and x['OS-EXT-IPS:type'] == 'floating']
|
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
|
||||||
module.exit_json(changed = False, id = server.id, public_ip = ''.join(public), private_ip = ''.join(private), info = server._info)
|
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
|
||||||
|
module.exit_json(changed = ip_changed, id = server.id, public_ip = ''.join(public), private_ip = ''.join(private), info = server._info)
|
||||||
if server and module.params['state'] == 'absent':
|
if server and module.params['state'] == 'absent':
|
||||||
return True
|
return True
|
||||||
if module.params['state'] == 'absent':
|
if module.params['state'] == 'absent':
|
||||||
|
@ -230,7 +525,11 @@ def main():
|
||||||
argument_spec.update(dict(
|
argument_spec.update(dict(
|
||||||
name = dict(required=True),
|
name = dict(required=True),
|
||||||
image_id = dict(default=None),
|
image_id = dict(default=None),
|
||||||
|
image_name = dict(default=None),
|
||||||
|
image_exclude = dict(default='(deprecated)'),
|
||||||
flavor_id = dict(default=1),
|
flavor_id = dict(default=1),
|
||||||
|
flavor_ram = dict(default=None, type='int'),
|
||||||
|
flavor_include = dict(default=None),
|
||||||
key_name = dict(default=None),
|
key_name = dict(default=None),
|
||||||
security_groups = dict(default='default'),
|
security_groups = dict(default='default'),
|
||||||
nics = dict(default=None),
|
nics = dict(default=None),
|
||||||
|
@ -239,8 +538,21 @@ def main():
|
||||||
wait_for = dict(default=180),
|
wait_for = dict(default=180),
|
||||||
state = dict(default='present', choices=['absent', 'present']),
|
state = dict(default='present', choices=['absent', 'present']),
|
||||||
user_data = dict(default=None),
|
user_data = dict(default=None),
|
||||||
|
config_drive = dict(default=False, type='bool'),
|
||||||
|
auto_floating_ip = dict(default=False, type='bool'),
|
||||||
|
floating_ips = dict(default=None),
|
||||||
|
floating_ip_pools = dict(default=None),
|
||||||
))
|
))
|
||||||
module = AnsibleModule(argument_spec=argument_spec)
|
module = AnsibleModule(
|
||||||
|
argument_spec=argument_spec,
|
||||||
|
mutually_exclusive=[
|
||||||
|
['auto_floating_ip','floating_ips'],
|
||||||
|
['auto_floating_ip','floating_ip_pools'],
|
||||||
|
['floating_ips','floating_ip_pools'],
|
||||||
|
['image_id','image_name'],
|
||||||
|
['flavor_id','flavor_ram'],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
nova = nova_client.Client(module.params['login_username'],
|
nova = nova_client.Client(module.params['login_username'],
|
||||||
module.params['login_password'],
|
module.params['login_password'],
|
||||||
|
@ -256,8 +568,8 @@ def main():
|
||||||
module.fail_json(msg = "Unable to authorize user: %s" % e.message)
|
module.fail_json(msg = "Unable to authorize user: %s" % e.message)
|
||||||
|
|
||||||
if module.params['state'] == 'present':
|
if module.params['state'] == 'present':
|
||||||
if not module.params['image_id']:
|
if not module.params['image_id'] and not module.params['image_name']:
|
||||||
module.fail_json( msg = "Parameter 'image_id' is required if state == 'present'")
|
module.fail_json( msg = "Parameter 'image_id' or `image_name` is required if state == 'present'")
|
||||||
else:
|
else:
|
||||||
_get_server_state(module, nova)
|
_get_server_state(module, nova)
|
||||||
_create_server(module, nova)
|
_create_server(module, nova)
|
||||||
|
@ -265,7 +577,7 @@ def main():
|
||||||
_get_server_state(module, nova)
|
_get_server_state(module, nova)
|
||||||
_delete_server(module, nova)
|
_delete_server(module, nova)
|
||||||
|
|
||||||
# this is magic, see lib/ansible/module.params['common.py
|
# this is magic, see lib/ansible/module_common.py
|
||||||
from ansible.module_utils.basic import *
|
from ansible.module_utils.basic import *
|
||||||
from ansible.module_utils.openstack import *
|
from ansible.module_utils.openstack import *
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -99,6 +99,7 @@ def main():
|
||||||
module.params['login_password'],
|
module.params['login_password'],
|
||||||
module.params['login_tenant_name'],
|
module.params['login_tenant_name'],
|
||||||
module.params['auth_url'],
|
module.params['auth_url'],
|
||||||
|
region_name=module.params['region_name'],
|
||||||
service_type='compute')
|
service_type='compute')
|
||||||
try:
|
try:
|
||||||
nova.authenticate()
|
nova.authenticate()
|
||||||
|
|
|
@ -28,6 +28,8 @@ try:
|
||||||
except:
|
except:
|
||||||
import simplejson as json
|
import simplejson as json
|
||||||
|
|
||||||
|
from ansible.module_utils.openstack import *
|
||||||
|
|
||||||
###################################################
|
###################################################
|
||||||
# executed with no parameters, return the list of
|
# executed with no parameters, return the list of
|
||||||
# all groups and hosts
|
# all groups and hosts
|
||||||
|
@ -57,12 +59,12 @@ if not config:
|
||||||
sys.exit('Unable to find configfile in %s' % ', '.join(NOVA_CONFIG_FILES))
|
sys.exit('Unable to find configfile in %s' % ', '.join(NOVA_CONFIG_FILES))
|
||||||
|
|
||||||
client = nova_client.Client(
|
client = nova_client.Client(
|
||||||
version = config.get('openstack', 'version'),
|
config.get('openstack', 'version'),
|
||||||
username = config.get('openstack', 'username'),
|
config.get('openstack', 'username'),
|
||||||
api_key = config.get('openstack', 'api_key'),
|
config.get('openstack', 'api_key'),
|
||||||
auth_url = config.get('openstack', 'auth_url'),
|
config.get('openstack', 'project_id'),
|
||||||
|
config.get('openstack', 'auth_url'),
|
||||||
region_name = config.get('openstack', 'region_name'),
|
region_name = config.get('openstack', 'region_name'),
|
||||||
project_id = config.get('openstack', 'project_id'),
|
|
||||||
auth_system = config.get('openstack', 'auth_system')
|
auth_system = config.get('openstack', 'auth_system')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -70,20 +72,20 @@ if len(sys.argv) == 2 and (sys.argv[1] == '--list'):
|
||||||
groups = {}
|
groups = {}
|
||||||
|
|
||||||
# Cycle on servers
|
# Cycle on servers
|
||||||
for f in client.servers.list():
|
for server in client.servers.list():
|
||||||
private = [ x['addr'] for x in getattr(f, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'fixed']
|
private = openstack_find_nova_addresses(getattr(server, 'addresses'), 'fixed', 'private')
|
||||||
public = [ x['addr'] for x in getattr(f, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
|
public = openstack_find_nova_addresses(getattr(server, 'addresses'), 'floating', 'public')
|
||||||
|
|
||||||
# Define group (or set to empty string)
|
# Define group (or set to empty string)
|
||||||
group = f.metadata['group'] if f.metadata.has_key('group') else 'undefined'
|
group = server.metadata['group'] if server.metadata.has_key('group') else 'undefined'
|
||||||
|
|
||||||
# Create group if not exist
|
# Create group if not exist
|
||||||
if group not in groups:
|
if group not in groups:
|
||||||
groups[group] = []
|
groups[group] = []
|
||||||
|
|
||||||
# Append group to list
|
# Append group to list
|
||||||
if f.accessIPv4:
|
if server.accessIPv4:
|
||||||
groups[group].append(f.accessIPv4)
|
groups[group].append(server.accessIPv4)
|
||||||
continue
|
continue
|
||||||
if public:
|
if public:
|
||||||
groups[group].append(''.join(public))
|
groups[group].append(''.join(public))
|
||||||
|
@ -104,8 +106,8 @@ elif len(sys.argv) == 3 and (sys.argv[1] == '--host'):
|
||||||
results = {}
|
results = {}
|
||||||
ips = []
|
ips = []
|
||||||
for instance in client.servers.list():
|
for instance in client.servers.list():
|
||||||
private = [ x['addr'] for x in getattr(instance, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'fixed']
|
private = openstack_find_nova_addresses(getattr(instance, 'addresses'), 'fixed', 'private')
|
||||||
public = [ x['addr'] for x in getattr(instance, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
|
public = openstack_find_nova_addresses(getattr(instance, 'addresses'), 'floating', 'public')
|
||||||
ips.append( instance.accessIPv4)
|
ips.append( instance.accessIPv4)
|
||||||
ips.append(''.join(private))
|
ips.append(''.join(private))
|
||||||
ips.append(''.join(public))
|
ips.append(''.join(public))
|
||||||
|
|
Loading…
Reference in a new issue