diff --git a/library/cloud/ovirt b/library/cloud/ovirt new file mode 100755 index 00000000000..f83bbb34b7f --- /dev/null +++ b/library/cloud/ovirt @@ -0,0 +1,420 @@ +#!/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 from scratch or image. delete / stop / start instances on the oVirt/RHEV platform +version_added: "1.3" +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: + - wether you want to deploy an image or create an instance from scratch. + default: null + required: false + aliases: [] + choices: [ 'new', 'template' ] + zone: + description: + - the name of the oVirt cluster you want to deploy the instance + 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 + + +''' +from ovirtsdk.api import API +from ovirtsdk.xml import params + +# ------------------------------------------------------------------- # +# 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': + 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) + + + + +# include magic from lib/ansible/module_common.py +#<> +main()