#!/usr/bin/python # (c) 2013, Vincent Van der Kussen # # This file is part of Ansible # # Ansible is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # Ansible is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Ansible. If not, see . DOCUMENTATION = ''' --- module: ovirt author: Vincent Van der Kussen short_description: oVirt/RHEV platform management description: - allows you to create new instances, either from scratch or an image, in addition to deleting or stopping instances on the oVirt/RHEV platform version_added: "1.4" options: user: description: - the user to authenticate with default: null required: true aliases: [] url: description: - the url of the oVirt instance default: null required: true aliases: [] instance_name: description: - the name of the instance to use default: null required: true aliases: [ vmname ] password: description: - password of the user to authenticate with default: null required: true aliases: [] image: description: - template to use for the instance default: null required: false aliases: [] resource_type: description: - whether you want to deploy an image or create an instance from scratch. default: null required: false aliases: [] choices: [ 'new', 'template' ] zone: description: - deploy the image to this oVirt cluster default: null required: false aliases: [] instance_disksize: description: - size of the instance's disk in GB default: null required: false aliases: [ vm_disksize] instance_cpus: description: - the instance's number of cpu's default: 1 required: false aliases: [ vmcpus ] instance_nic: description: - name of the network interface in oVirt/RHEV default: null required: false aliases: [ vmnic ] instance_network: description: - the logical network the machine should belong to default: rhevm required: false aliases: [ vmnetwork ] instance_mem: description: - the instance's amount of memory in MB default: null required: false aliases: [ vmmem ] instance_type: description: - define if the instance is a server or desktop default: server required: false aliases: [ vmtype ] choices: [ 'server', 'desktop' ] disk_alloc: description: - define if disk is thin or preallocated default: thin required: false aliases: [] choices: [ 'thin', 'preallocated' ] disk_int: description: - interface type of the disk default: virtio required: false aliases: [] choices: [ 'virtio', 'ide' ] instance_os: description: - type of Operating System default: null required: false aliases: [ vmos ] instance_cores: description: - define the instance's number of cores default: 1 required: false aliases: [ vmcores ] sdomain: description: - the Storage Domain where you want to create the instance's disk on. default: null required: false aliases: [] region: description: - the oVirt/RHEV datacenter where you want to deploy to default: null required: false aliases: [] state: description: - create, terminate or remove instances default: 'present' required: false aliases: [] choices: ['present', 'absent', 'shutdown', 'started', 'restarted'] requirements: [ "ovirt-engine-sdk" ] ''' EXAMPLES = ''' # Basic example provisioning from image. action: ovirt > user=admin@internal url=https://ovirt.example.com instance_name=ansiblevm04 password=secret image=centos_64 zone=cluster01 resource_type=template" # Full example to create new instance from scratch action: ovirt > instance_name=testansible resource_type=new instance_type=server user=admin@internal password=secret url=https://ovirt.example.com instance_disksize=10 zone=cluster01 region=datacenter1 instance_cpus=1 instance_nic=nic1 instance_network=rhevm instance_mem=1000 disk_alloc=thin sdomain=FIBER01 instance_cores=1 instance_os=rhel_6x64 disk_int=virtio" # stopping an instance action: ovirt > instance_name=testansible state=stopped user=admin@internal password=secret url=https://ovirt.example.com # starting an instance action: ovirt > instance_name=testansible state=started user=admin@internal password=secret url=https://ovirt.example.com ''' try: from ovirtsdk.api import API from ovirtsdk.xml import params except ImportError: print "failed=True msg='ovirtsdk required for this module'" sys.exit(1) # ------------------------------------------------------------------- # # create connection with API # def conn(url, user, password): api = API(url=url, username=user, password=password, insecure=True) try: value = api.test() except: print "error connecting to the oVirt API" sys.exit(1) return api # ------------------------------------------------------------------- # # Create VM from scratch def create_vm(conn, vmtype, vmname, zone, vmdisk_size, vmcpus, vmnic, vmnetwork, vmmem, vmdisk_alloc, sdomain, vmcores, vmos, vmdisk_int): if vmdisk_alloc == 'thin': # define VM params vmparams = params.VM(name=vmname,cluster=conn.clusters.get(name=zone),os=params.OperatingSystem(type_=vmos),template=conn.templates.get(name="Blank"),memory=1024 * 1024 * int(vmmem),cpu=params.CPU(topology=params.CpuTopology(cores=int(vmcores))), type_=vmtype) # define disk params vmdisk= params.Disk(size=1024 * 1024 * 1024 * int(vmdisk_size), wipe_after_delete=True, sparse=True, interface=vmdisk_int, type_="System", format='cow', storage_domains=params.StorageDomains(storage_domain=[conn.storagedomains.get(name=sdomain)])) # define network parameters network_net = params.Network(name=vmnetwork) nic_net1 = params.NIC(name='nic1', network=network_net, interface='virtio') elif vmdisk_alloc == 'preallocated': # define VM params vmparams = params.VM(name=vmname,cluster=conn.clusters.get(name=zone),os=params.OperatingSystem(type_=vmos),template=conn.templates.get(name="Blank"),memory=1024 * 1024 * int(vmmem),cpu=params.CPU(topology=params.CpuTopology(cores=int(vmcores))) ,type_=vmtype) # define disk params vmdisk= params.Disk(size=1024 * 1024 * 1024 * int(vmdisk_size), wipe_after_delete=True, sparse=False, interface=vmdisk_int, type_="System", format='raw', storage_domains=params.StorageDomains(storage_domain=[conn.storagedomains.get(name=sdomain)])) # define network parameters network_net = params.Network(name=vmnetwork) nic_net1 = params.NIC(name=vmnic, network=network_net, interface='virtio') try: conn.vms.add(vmparams) except: print "Error creating VM with specified parameters" sys.exit(1) vm = conn.vms.get(name=vmname) try: vm.disks.add(vmdisk) except: print "Error attaching disk" try: vm.nics.add(nic_net1) except: print "Error adding nic" # create an instance from a template def create_vm_template(conn, vmname, image, zone): vmparams = params.VM(name=vmname, cluster=conn.clusters.get(name=zone), template=conn.templates.get(name=image),disks=params.Disks(clone=True)) try: conn.vms.add(vmparams) except: print 'error adding template %s' % image sys.exit(1) # start instance def vm_start(conn, vmname): vm = conn.vms.get(name=vmname) vm.start() # Stop instance def vm_stop(conn, vmname): vm = conn.vms.get(name=vmname) vm.stop() # restart instance def vm_restart(conn, vmname): state = vm_status(conn, vmname) vm = conn.vms.get(name=vmname) vm.stop() while conn.vms.get(vmname).get_status().get_state() != 'down': time.sleep(5) vm.start() # remove an instance def vm_remove(conn, vmname): vm = conn.vms.get(name=vmname) vm.delete() # ------------------------------------------------------------------- # # VM statuses # # Get the VMs status def vm_status(conn, vmname): status = conn.vms.get(name=vmname).status.state print "vm status is : %s" % status return status # Get VM object and return it's name if object exists def get_vm(conn, vmname): vm = conn.vms.get(name=vmname) if vm == None: name = "empty" print "vmname: %s" % name else: name = vm.get_name() print "vmname: %s" % name return name # ------------------------------------------------------------------- # # Hypervisor operations # # not available yet # ------------------------------------------------------------------- # # Main def main(): module = AnsibleModule( argument_spec = dict( state = dict(default='present', choices=['present', 'absent', 'shutdown', 'started', 'restart']), #name = dict(required=True), user = dict(required=True), url = dict(required=True), instance_name = dict(required=True, aliases=['vmname']), password = dict(required=True), image = dict(), resource_type = dict(choices=['new', 'template']), zone = dict(), instance_disksize = dict(aliases=['vm_disksize']), instance_cpus = dict(default=1, aliases=['vmcpus']), instance_nic = dict(aliases=['vmnic']), instance_network = dict(default='rhevm', aliases=['vmnetwork']), instance_mem = dict(aliases=['vmmem']), instance_type = dict(default='server', aliases=['vmtype'], choices=['server', 'desktop']), disk_alloc = dict(default='thin', choices=['thin', 'preallocated']), disk_int = dict(default='virtio', choices=['virtio', 'ide']), instance_os = dict(aliases=['vmos']), instance_cores = dict(default=1, aliases=['vmcores']), sdomain = dict(), region = dict(), ) ) state = module.params['state'] user = module.params['user'] url = module.params['url'] vmname = module.params['instance_name'] password = module.params['password'] image = module.params['image'] # name of the image to deploy resource_type = module.params['resource_type'] # template or from scratch zone = module.params['zone'] # oVirt cluster vmdisk_size = module.params['instance_disksize'] # disksize vmcpus = module.params['instance_cpus'] # number of cpu vmnic = module.params['instance_nic'] # network interface vmnetwork = module.params['instance_network'] # logical network vmmem = module.params['instance_mem'] # mem size vmdisk_alloc = module.params['disk_alloc'] # thin, preallocated vmdisk_int = module.params['disk_int'] # disk interface virtio or ide vmos = module.params['instance_os'] # Operating System vmtype = module.params['instance_type'] # server or desktop vmcores = module.params['instance_cores'] # number of cores sdomain = module.params['sdomain'] # storage domain to store disk on region = module.params['region'] # oVirt Datacenter #initialize connection c = conn(url+"/api", user, password) if state == 'present': if get_vm(c, vmname) == "empty": if resource_type == 'template': create_vm_template(c, vmname, image, zone) module.exit_json(changed=True, msg="deployed VM %s from template %s" % (vmname,image)) elif resource_type == 'new': # FIXME: refactor, use keyword args. create_vm(c, vmtype, vmname, zone, vmdisk_size, vmcpus, vmnic, vmnetwork, vmmem, vmdisk_alloc, sdomain, vmcores, vmos, vmdisk_int) module.exit_json(changed=True, msg="deployed VM %s from scratch" % vmname) else: module.exit_json(changed=False, msg="You did not specify a resource type") else: module.exit_json(changed=False, msg="VM %s already exists" % vmname) if state == 'started': if vm_status(c, vmname) == 'up': module.exit_json(changed=False, msg="VM %s is already running" % vmname) else: vm_start(c, vmname) module.exit_json(changed=True, msg="VM %s started" % vmname) if state == 'shutdown': if vm_status(c, vmname) == 'down': module.exit_json(changed=False, msg="VM %s is already shutdown" % vmname) else: vm_stop(c, vmname) module.exit_json(changed=True, msg="VM %s is shutting down" % vmname) if state == 'restart': if vm_status(c, vmname) == 'up': vm_restart(c, vmname) module.exit_json(changed=True, msg="VM %s is restarted" % vmname) else: module.exit_json(changed=False, msg="VM %s is not running" % vmname) if state == 'absent': if get_vm(c, vmname) == "empty": module.exit_json(changed=False, msg="VM %s does not exist" % vmname) else: vm_remove(c, vmname) module.exit_json(changed=True, msg="VM %s removed" % vmname) # import module snippets from ansible.module_utils.basic import * main()