ansible/cloud/nova_compute
2013-05-23 07:55:05 +05:30

243 lines
8.7 KiB
Python
Executable file

#!/usr/bin/python
#coding: utf-8 -*-
# (c) 2013, Benno Joy <benno@ansibleworks.com>
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software. If not, see <http://www.gnu.org/licenses/>.
try:
from novaclient.v1_1 import client as nova_client
import time
except ImportError:
print("failed=True msg='novaclient is required for this module'")
DOCUMENTATION = '''
---
module: nova_compute
short_description: Create/Delete VM's from OpenStack
description:
- Create or Remove virtual machines from Openstack.
options:
login_username:
description:
- login username to authenticate to keystone
required: true
default: admin
login_password:
description:
- Password of login user
required: true
default: True
login_tenant_name:
description:
- The tenant name of the login user
required: true
default: True
auth_url:
description:
- The keystone url for authentication
required: false
default: 'http://127.0.0.1:35357/v2.0/'
region_name:
description:
- Name of the region
required: false
default: None
state:
description:
- Indicate desired state of the resource
choices: ['present', 'absent']
default: present
name:
description:
- Name that has to be given to the image
required: true
default: None
image_id:
description:
- The id of the image that has to be cloned
required: true
default: None
flavor_id:
description:
- The id of the flavor in which the new vm has to be created
required: false
default: 1
key_name:
description:
- The keypair name to be used when creating a vm
required: false
default: None
security_groups:
description:
- The name of the security group to which the vm should be added
required: false
default: None
nics:
description:
- A list of network id's to which the vm's interface should be attached
required: false
default: None
meta:
description:
- A list of key value pairs that should be provided as a metadata to the new vm
required: false
default: None
wait:
description:
- If the module should wait for the vm to be created.
required: false
default: 'yes'
wait_for:
description:
- The amount of time the module should wait for the vm to get into active state
required: false
default: 180
examples:
- code: "nova_compute:
state: present
login_username: admin
login_password: admin
login_tenant_name: admin
name: vm1
image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
key_name: ansible_key
wait_for: 200
flavor_id: 4
nics:
- net-id: 34605f38-e52a-25d2-b6ec-754a13ffb723
meta:
hostname: test1
group: uge_master"
description: "Creates a new VM and attaches to a network and passes metadata to the instance"
requirements: ["novaclient"]
'''
def _delete_server(module, nova):
name = None
try:
server = nova.servers.list({'name': module.params['name']}).pop()
nova.servers.delete(server)
except Exception as e:
module.fail_json( msg = "Error in deleting vm: %s" % e.message)
if module.params['wait'] == 'no':
module.exit_json(changed = True, result = "deleted")
expire = time.time() + module.params['wait_for']
while time.time() < expire:
name = nova.servers.list({'name': module.params['name']})
if not name:
module.exit_json(changed = True, result = "deleted")
time.sleep(5)
module.fail_json(msg = "Timed out waiting for server to get deleted, please check manually")
def _create_server(module, nova):
bootargs = [module.params['name'], module.params['image_id'], module.params['flavor_id']]
bootkwargs = {
'nics' : module.params['nics'],
'meta' : module.params['meta'],
'key_name': module.params['key_name'],
'security_groups': module.params['security_groups'].split(','),
}
if not module.params['key_name']:
del bootkwargs['key_name']
try:
server = nova.servers.create(*bootargs, **bootkwargs )
server = nova.servers.get(server.id)
except Exception as e:
module.fail_json( msg = "Error in creating instance: %s " % e.message)
if module.params['wait'] == 'yes':
expire = time.time() + module.params['wait_for']
while time.time() < expire:
try:
server = nova.servers.get(server.id)
except Exception as e:
module.fail_json( msg = "Error in getting info from instance: %s " % e.message)
if server.status == 'ACTIVE':
private = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'fixed']
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
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':
module.fail_json(msg = "Error in creating the server, please check logs")
time.sleep(2)
module.fail_json(msg = "Timeout waiting for the server to come up.. Please check manually")
if server.status == 'ERROR':
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']
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
module.exit_json(changed = True, id = info['id'], private_ip=''.join(private), public_ip=''.join(public), status = server.status, info = server._info)
def _get_server_state(module, nova):
server = None
try:
servers = nova.servers.list({'name': module.params['name']})
if servers:
server = servers.pop()
except Exception as e:
module.fail_json(msg = "Error in getting the server list: %s" % e.message)
if server and module.params['state'] == 'present':
if server.status != 'ACTIVE':
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 x['OS-EXT-IPS:type'] == 'fixed']
public = [ x['addr'] for x in getattr(server, 'addresses').itervalues().next() if x['OS-EXT-IPS:type'] == 'floating']
module.exit_json(changed = False, id = server.id, public_ip = ''.join(public), private_ip = ''.join(private), info = server._info)
if server and module.params['state'] == 'absent':
return True
if module.params['state'] == 'absent':
module.exit_json(changed = False, result = "not present")
return True
def main():
module = AnsibleModule(
argument_spec = dict(
login_username = dict(default='admin'),
login_password = dict(required=True),
login_tenant_name = dict(required='True'),
auth_url = dict(default='http://127.0.0.1:35357/v2.0/'),
region_name = dict(default=None),
name = dict(required=True),
image_id = dict(required=True),
flavor_id = dict(default=1),
key_name = dict(default=None),
security_groups = dict(default='default'),
nics = dict(default=None),
meta = dict(default=None),
wait = dict(default='yes', choices=['yes', 'no']),
wait_for = dict(default=120),
state = dict(default='present', choices=['absent', 'present'])
),
)
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')
except Exception as e:
module.fail_json( msg = "Error in authenticating to nova: %s" % e.message)
if module.params['state'] == 'present':
_get_server_state(module, nova)
_create_server(module, nova)
if module.params['state'] == 'absent':
_get_server_state(module, nova)
_delete_server(module, nova)
# this is magic, see lib/ansible/module.params['common.py
#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()