Merge pull request #1008 from privateip/vca_vapp

cleaned up vca_vapp module to focus on managing vapps
reviewable/pr18780/r1
Greg DeKoenigsberg 9 years ago
commit 9447bf9c6f

@ -21,20 +21,82 @@
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: vca_vapp module: vca_vapp
short_description: create, terminate, start or stop a vm in vca short_description: Manages vCloud Air vApp instances.
description: description:
- Creates or terminates vca vms. - This module will actively managed vCloud Air vApp instances. Instances
can be created and deleted as well as both deployed and undeployed.
version_added: "2.0" version_added: "2.0"
author: Peter Sprygada (@privateip) author: Peter Sprygada (@privateip)
options: options:
vapp_name:
description:
- The name of the vCloud Air vApp instance
required: yes
vdc_name:
description:
- The name of the virtual data center (VDC) that contains the vAPP
required: yes
template_name:
description:
- The name of the vApp template to use to create the vApp instance. If
the I(state) is not `absent` then the I(template_name) value must be
provided. The I(template_name) must be previously uploaded to the
catalog specified by I(catalog_name)
required: no
default: None
network_name:
description:
- The name of the network that should be attached to the virtual machine
in the vApp. The virtual network specified must already be created in
the vCloud Air VDC. If the I(state) is not 'absent' then the
I(network_name) argument must be provided.
required: no
default: None
network_mode:
description:
- Configures the mode of the network connection.
required: no
default: pool
choices: ['pool', 'dhcp', 'static']
vm_name:
description:
- The name of the virtual machine instance in the vApp to manage.
required: no
default: None
vm_cpus:
description:
- The number of vCPUs to configure for the VM in the vApp. If the
I(vm_name) argument is provided, then this becomes a per VM setting
otherwise it is applied to all VMs in the vApp.
required: no
default: None
vm_memory:
description:
- The amount of memory in MB to allocate to VMs in the vApp. If the
I(vm_name) argument is provided, then this becomes a per VM setting
otherise it is applied to all VMs in the vApp.
required: no
default: None
operation:
description:
- Specifies an operation to be performed on the vApp.
required: no
default: noop
choices: ['noop', 'poweron', 'poweroff', 'suspend', 'shutdown', 'reboot', 'reset']
state:
description:
- Configures the state of the vApp.
required: no
default: present
choices: ['present', 'absent', 'deployed', 'undeployed']
username: username:
description: description:
- The vca username or email address, if not set the environment variable VCA_USER is checked for the username. - The vCloud Air username to use during authentication
required: false required: false
default: None default: None
password: password:
description: description:
- The vca password, if not set the environment variable VCA_PASS is checked for the password - The vCloud Air password to use during authentication
required: false required: false
default: None default: None
org: org:
@ -47,6 +109,11 @@ options:
- The service id in a vchs environment to be used for creating the vapp - The service id in a vchs environment to be used for creating the vapp
required: false required: false
default: None default: None
instance_id:
description:
- The vCloud Air instance ID
required: no
default: None
host: host:
description: description:
- The authentication host to be used when service type is vcd. - The authentication host to be used when service type is vcd.
@ -63,176 +130,54 @@ options:
required: false required: false
default: vca default: vca
choices: [ "vca", "vchs", "vcd" ] choices: [ "vca", "vchs", "vcd" ]
state:
description:
- if the object should be added or removed
required: false
default: present
choices: [ "present", "absent" ]
catalog_name:
description:
- The catalog from which the vm template is used.
required: false
default: "Public Catalog"
script:
description:
- The path to script that gets injected to vm during creation.
required: false
default: "Public Catalog"
template_name:
description:
- The template name from which the vm should be created.
required: True
network_name:
description:
- The network name to which the vm should be attached.
required: false
default: 'None'
network_mode:
description:
- The network mode in which the ip should be allocated.
required: false
default: pool
choices: [ "pool", "dhcp", 'static' ]
instance_id::
description:
- The instance id of the region in vca flavour where the vm should be created
required: false
default: None
vdc_name: vdc_name:
description: description:
- The name of the vdc where the vm should be created. - The name of the vdc where the vm should be created.
required: false required: false
default: None default: None
vm_name:
description:
- The name of the vm to be created, the vapp is named the same as the vapp name
required: false
default: 'default_ansible_vm1'
vm_cpus:
description:
- The number if cpus to be added to the vm
required: false
default: None
vm_memory:
description:
- The amount of memory to be added to vm in megabytes
required: false
default: None
''' '''
EXAMPLES = ''' EXAMPLES = '''
#Create a vm in an vca environment. The username password is not set as they are set in environment - name: Creates a new vApp in a VCA instance
vca_vapp:
- hosts: localhost vapp_name: tower
connection: local state=present
tasks: template_name='Ubuntu Server 12.04 LTS (amd64 20150127)'
- vca_vapp: vdc_name=VDC1
operation: poweroff instance_id=<your instance id here>
instance_id: 'b15ff1e5-1024-4f55-889f-ea0209726282' username=<your username here>
vdc_name: 'benz_ansible' password=<your password here>
vm_name: benz
vm_cpus: 2
vm_memory: 1024
network_mode: pool
template_name: "CentOS63-32BIT"
admin_password: "Password!123"
network_name: "default-routed-network"
#Create a vm in a vchs environment.
- hosts: localhost
connection: local
tasks:
- vca_app:
operation: poweron
service_id: '9-69'
vdc_name: 'Marketing'
service_type: 'vchs'
vm_name: benz
vm_cpus: 1
script: "/tmp/configure_vm.sh"
catalog_name: "Marketing-Catalog"
template_name: "Marketing-Ubuntu-1204x64"
vm_memory: 512
network_name: "M49-default-isolated"
#create a vm in a vdc environment
- hosts: localhost
connection: local
tasks:
- vca_vapp:
operation: poweron
org: IT20
host: "mycloud.vmware.net"
api_version: "5.5"
service_type: vcd
vdc_name: 'IT20 Data Center (Beta)'
vm_name: benz
vm_cpus: 1
catalog_name: "OS Templates"
template_name: "CentOS 6.5 64Bit CLI"
network_mode: pool
''' '''
try: DEFAULT_VAPP_OPERATION = 'noop'
from pyvcloud.vcloudair import VCA
HAS_PYVCLOUD = True
except ImportError:
HAS_PYVCLOUD = False
VAPP_STATE_MAP = {
'poweron': 'Powered on',
'poweroff': 'Powered off',
'reboot': None,
'reset': None,
'shutdown': 'Powered off',
'suspend': 'Suspended',
'absent': None
}
def modify_vapp(vapp, module):
vm_name = module.params['vm_name']
vm_cpus = module.params['vm_cpus']
vm_memory = module.params['vm_memory']
changed = False
try:
vm = vapp.get_vms_details()[0]
except IndexError:
raise VcaError('No VM provisioned for vapp')
if vm['status'] != 'Powered off': VAPP_STATUS = {
raise VcaError('vApp must be powered off to modify') 'Powered off': 'poweroff',
'Powered on': 'poweron',
if vm_cpus != vm['cpus'] and vm_cpus is not None: 'Suspended': 'suspend'
if not module.check_mode: }
task = vapp.modify_vm_cpu(vm_name, vm_cpus)
changed = True
if vm_memory != vm['memory_mb'] and vm_memory is not None:
if not module.check_mode:
task = vca.modify_vm_memory(vm_name, vm_memory)
changed = True
return changed VAPP_STATES = ['present', 'absent', 'deployed', 'undeployed']
VAPP_OPERATIONS = ['poweron', 'poweroff', 'suspend', 'shutdown',
'reboot', 'reset', 'noop']
def set_vapp_state(vapp, state): def get_instance(module):
vm = vapp.get_vms_details()[0] vapp_name = module.params['vapp_name']
inst = dict(vapp_name=vapp_name, state='absent')
try: try:
if vm['status'] != VAPP_STATE_MAP[state]: vapp = module.get_vapp(vapp_name)
func = getattr(vm, state) if vapp:
func() status = module.vca.get_status(vapp.me.get_status())
except KeyError: inst['status'] = VAPP_STATUS.get(status, 'unknown')
raise VcaError('unknown vapp state', state=str(state), vm=str(vm)) inst['state'] = 'deployed' if vapp.me.deployed else 'undeployed'
return inst
except VcaError:
def create_vapp(vca, module): return inst
def create(module):
vdc_name = module.params['vdc_name'] vdc_name = module.params['vdc_name']
vapp_name = module.params['vapp_name'] vapp_name = module.params['vapp_name']
template_name = module.params['template_name'] template_name = module.params['template_name']
@ -242,85 +187,105 @@ def create_vapp(vca, module):
vm_name = module.params['vm_name'] vm_name = module.params['vm_name']
vm_cpus = module.params['vm_cpus'] vm_cpus = module.params['vm_cpus']
vm_memory = module.params['vm_memory'] vm_memory = module.params['vm_memory']
deploy = module.params['deploy'] deploy = module.params['state'] == 'deploy'
poweron = module.params['operation'] == 'poweron'
task = vca.create_vapp(vdc_name, vapp_name, template_name, catalog_name,
network_name, network_mode, vm_name, vm_cpus,
vm_memory, deploy, False)
vca.block_until_completed(task) task = module.vca.create_vapp(vdc_name, vapp_name, template_name,
catalog_name, network_name, network_mode,
vm_name, vm_cpus, vm_memory, deploy, poweron)
return vca.get_vapp(vca.get_vdc(vdc_name), vapp_name) module.vca.block_until_completed(task)
def remove_vapp(vca, module): def delete(module):
vdc_name = module.params['vdc_name'] vdc_name = module.params['vdc_name']
vapp_name = module.params['vapp_name'] vapp_name = module.params['vapp_name']
if not vca.delete_vapp(vdc_name, vapp_name): module.vca.delete_vapp(vdc_name, vapp_name)
raise VcaError('unable to delete %s from %s' % (vapp_name, vdc_name))
def do_operation(module):
vapp_name = module.params['vapp_name']
operation = module.params['operation']
vm_name = module.params.get('vm_name')
vm = None
if vm_name:
vm = module.get_vm(vapp_name, vm_name)
if operation == 'poweron':
operation = 'powerOn'
elif operation == 'poweroff':
operation = 'powerOff'
cmd = 'power:%s' % operation
module.get_vapp(vapp_name).execute(cmd, 'post', targetVM=vm)
def set_state(module):
state = module.params['state']
vapp = module.get_vapp(module.params['vapp_name'])
if state == 'deployed':
action = module.params['operation'] == 'poweron'
if not vapp.deploy(action):
module.fail('unable to deploy vapp')
elif state == 'undeployed':
action = module.params['operation']
if action == 'poweroff':
action = 'powerOff'
elif action != 'suspend':
action = None
if not vapp.undeploy(action):
module.fail('unable to undeploy vapp')
def main(): def main():
argument_spec = vca_argument_spec()
argument_spec.update( argument_spec = dict(
dict(
vdc_name=dict(requred=True),
vapp_name=dict(required=True), vapp_name=dict(required=True),
template_name=dict(required=True), vdc_name=dict(required=True),
template_name=dict(),
catalog_name=dict(default='Public Catalog'), catalog_name=dict(default='Public Catalog'),
network_name=dict(), network_name=dict(),
network_mode=dict(default='pool', choices=['dhcp', 'static', 'pool']), network_mode=dict(default='pool', choices=['dhcp', 'static', 'pool']),
vm_name=dict(), vm_name=dict(),
vm_memory=dict(),
vm_cpus=dict(), vm_cpus=dict(),
deploy=dict(default=False), vm_memory=dict(),
state=dict(default='poweron', choices=VAPP_STATE_MAP.keys()) operation=dict(default=DEFAULT_VAPP_OPERATION, choices=VAPP_OPERATIONS),
) state=dict(default='present', choices=VAPP_STATES)
) )
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True) module = VcaAnsibleModule(argument_spec=argument_spec,
supports_check_mode=True)
vdc_name = module.params['vdc_name']
vapp_name = module.params['vapp_name']
state = module.params['state'] state = module.params['state']
operation = module.params['operation']
if not HAS_PYVCLOUD: instance = get_instance(module)
module.fail_json(msg="python module pyvcloud is needed for this module")
vca = vca_login(module)
vdc = vca.get_vdc(vdc_name)
if not vdc:
module.fail_json(msg="Error getting the vdc, Please check the vdc name")
result = dict(changed=False) result = dict(changed=False)
vapp = vca.get_vapp(vdc, vapp_name) if instance and state == 'absent':
if not module.check_mode:
delete(module)
result['changed'] = True
try: elif state != 'absent':
if not vapp and state != 'absent': if instance['state'] == 'absent':
if not module.check_mode: if not module.check_mode:
vapp = create_vapp(vca, module) create(module)
set_vapp_state(vapp, state)
result['changed'] = True result['changed'] = True
elif vapp and state == 'absent':
elif instance['state'] != state and state != 'present':
if not module.check_mode: if not module.check_mode:
remove_vapp(vca, module) set_state(module)
result['changed'] = True result['changed'] = True
elif vapp:
if operation != instance.get('status') and operation != 'noop':
if not module.check_mode: if not module.check_mode:
changed = modify_vapp(vapp, module) do_operation(module)
set_vapp_state(vapp, state)
result['changed'] = True result['changed'] = True
except VcaError, e:
module.fail_json(msg=e.message, **e.kwargs)
except Exception, e:
module.fail_json(msg=e.message)
module.exit_json(**result) return module.exit(**result)
# import module snippets # import module snippets
from ansible.module_utils.basic import * from ansible.module_utils.basic import *
from ansible.module_utils.vca import * from ansible.module_utils.vca import *
if __name__ == '__main__': if __name__ == '__main__':
main() main()

Loading…
Cancel
Save