mirror of
				https://github.com/ansible-collections/community.general.git
				synced 2025-10-26 05:50:36 -07:00 
			
		
		
		
	* Use semantic markup. * Use 'ignore:' for alias reference. * Ignore sanity errors for older ansible-core versions. * Improve markup for RHSM modules. Co-authored-by: Pino Toscano <ptoscano@redhat.com> * 'ignore:' is no longer needed. * E() now works better. --------- Co-authored-by: Pino Toscano <ptoscano@redhat.com>
		
			
				
	
	
		
			1506 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1506 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/python
 | |
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| # Copyright (c) 2016, Timothy Vandenbrande <timothy.vandenbrande@gmail.com>
 | |
| # GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
 | |
| # SPDX-License-Identifier: GPL-3.0-or-later
 | |
| 
 | |
| from __future__ import absolute_import, division, print_function
 | |
| __metaclass__ = type
 | |
| 
 | |
| DOCUMENTATION = r'''
 | |
| ---
 | |
| module: rhevm
 | |
| short_description: RHEV/oVirt automation
 | |
| description:
 | |
|     - This module only supports oVirt/RHEV version 3.
 | |
|     - A newer module M(ovirt.ovirt.ovirt_vm) supports oVirt/RHV version 4.
 | |
|     - Allows you to create/remove/update or powermanage virtual machines on a RHEV/oVirt platform.
 | |
| requirements:
 | |
|     - ovirtsdk
 | |
| author:
 | |
|     - Timothy Vandenbrande (@TimothyVandenbrande)
 | |
| extends_documentation_fragment:
 | |
|     - community.general.attributes
 | |
| attributes:
 | |
|     check_mode:
 | |
|         support: none
 | |
|     diff_mode:
 | |
|         support: none
 | |
| options:
 | |
|     user:
 | |
|         description:
 | |
|             - The user to authenticate with.
 | |
|         type: str
 | |
|         default: admin@internal
 | |
|     password:
 | |
|         description:
 | |
|             - The password for user authentication.
 | |
|         type: str
 | |
|         required: true
 | |
|     server:
 | |
|         description:
 | |
|             - The name/IP of your RHEV-m/oVirt instance.
 | |
|         type: str
 | |
|         default: 127.0.0.1
 | |
|     port:
 | |
|         description:
 | |
|             - The port on which the API is reachable.
 | |
|         type: int
 | |
|         default: 443
 | |
|     insecure_api:
 | |
|         description:
 | |
|             - A boolean switch to make a secure or insecure connection to the server.
 | |
|         type: bool
 | |
|         default: false
 | |
|     name:
 | |
|         description:
 | |
|             - The name of the VM.
 | |
|         type: str
 | |
|     cluster:
 | |
|         description:
 | |
|             - The RHEV/oVirt cluster in which you want you VM to start.
 | |
|         type: str
 | |
|         default: ''
 | |
|     datacenter:
 | |
|         description:
 | |
|             - The RHEV/oVirt datacenter in which you want you VM to start.
 | |
|         type: str
 | |
|         default: Default
 | |
|     state:
 | |
|         description:
 | |
|             - This serves to create/remove/update or powermanage your VM.
 | |
|         type: str
 | |
|         choices: [ absent, cd, down, info, ping, present, restarted, up ]
 | |
|         default: present
 | |
|     image:
 | |
|         description:
 | |
|             - The template to use for the VM.
 | |
|         type: str
 | |
|     type:
 | |
|         description:
 | |
|             - To define if the VM is a server or desktop.
 | |
|         type: str
 | |
|         choices: [ desktop, host, server ]
 | |
|         default: server
 | |
|     vmhost:
 | |
|         description:
 | |
|             - The host you wish your VM to run on.
 | |
|         type: str
 | |
|     vmcpu:
 | |
|         description:
 | |
|             - The number of CPUs you want in your VM.
 | |
|         type: int
 | |
|         default: 2
 | |
|     cpu_share:
 | |
|         description:
 | |
|             - This parameter is used to configure the CPU share.
 | |
|         type: int
 | |
|         default: 0
 | |
|     vmmem:
 | |
|         description:
 | |
|             - The amount of memory you want your VM to use (in GB).
 | |
|         type: int
 | |
|         default: 1
 | |
|     osver:
 | |
|         description:
 | |
|             - The operating system option in RHEV/oVirt.
 | |
|         type: str
 | |
|         default: rhel_6x64
 | |
|     mempol:
 | |
|         description:
 | |
|             - The minimum amount of memory you wish to reserve for this system.
 | |
|         type: int
 | |
|         default: 1
 | |
|     vm_ha:
 | |
|         description:
 | |
|             - To make your VM High Available.
 | |
|         type: bool
 | |
|         default: true
 | |
|     disks:
 | |
|         description:
 | |
|             - This option uses complex arguments and is a list of disks with the options name, size and domain.
 | |
|         type: list
 | |
|         elements: str
 | |
|     ifaces:
 | |
|         description:
 | |
|             - This option uses complex arguments and is a list of interfaces with the options name and vlan.
 | |
|         type: list
 | |
|         elements: str
 | |
|         aliases: [ interfaces, nics ]
 | |
|     boot_order:
 | |
|         description:
 | |
|             - This option uses complex arguments and is a list of items that specify the bootorder.
 | |
|         type: list
 | |
|         elements: str
 | |
|         default: [ hd, network ]
 | |
|     del_prot:
 | |
|         description:
 | |
|             - This option sets the delete protection checkbox.
 | |
|         type: bool
 | |
|         default: true
 | |
|     cd_drive:
 | |
|         description:
 | |
|             - The CD you wish to have mounted on the VM when O(state=cd).
 | |
|         type: str
 | |
|     timeout:
 | |
|         description:
 | |
|             - The timeout you wish to define for power actions.
 | |
|             - When O(state=up).
 | |
|             - When O(state=down).
 | |
|             - When O(state=restarted).
 | |
|         type: int
 | |
| '''
 | |
| 
 | |
| RETURN = r'''
 | |
| vm:
 | |
|     description: Returns all of the VMs variables and execution.
 | |
|     returned: always
 | |
|     type: dict
 | |
|     sample: {
 | |
|         "boot_order": [
 | |
|             "hd",
 | |
|             "network"
 | |
|         ],
 | |
|         "changed": true,
 | |
|         "changes": [
 | |
|             "Delete Protection"
 | |
|         ],
 | |
|         "cluster": "C1",
 | |
|         "cpu_share": "0",
 | |
|         "created": false,
 | |
|         "datacenter": "Default",
 | |
|         "del_prot": true,
 | |
|         "disks": [
 | |
|             {
 | |
|                 "domain": "ssd-san",
 | |
|                 "name": "OS",
 | |
|                 "size": 40
 | |
|             }
 | |
|         ],
 | |
|         "eth0": "00:00:5E:00:53:00",
 | |
|         "eth1": "00:00:5E:00:53:01",
 | |
|         "eth2": "00:00:5E:00:53:02",
 | |
|         "exists": true,
 | |
|         "failed": false,
 | |
|         "ifaces": [
 | |
|             {
 | |
|                 "name": "eth0",
 | |
|                 "vlan": "Management"
 | |
|             },
 | |
|             {
 | |
|                 "name": "eth1",
 | |
|                 "vlan": "Internal"
 | |
|             },
 | |
|             {
 | |
|                 "name": "eth2",
 | |
|                 "vlan": "External"
 | |
|             }
 | |
|         ],
 | |
|         "image": false,
 | |
|         "mempol": "0",
 | |
|         "msg": [
 | |
|             "VM exists",
 | |
|             "cpu_share was already set to 0",
 | |
|             "VM high availability was already set to True",
 | |
|             "The boot order has already been set",
 | |
|             "VM delete protection has been set to True",
 | |
|             "Disk web2_Disk0_OS already exists",
 | |
|             "The VM starting host was already set to host416"
 | |
|         ],
 | |
|         "name": "web2",
 | |
|         "type": "server",
 | |
|         "uuid": "4ba5a1be-e60b-4368-9533-920f156c817b",
 | |
|         "vm_ha": true,
 | |
|         "vmcpu": "4",
 | |
|         "vmhost": "host416",
 | |
|         "vmmem": "16"
 | |
|     }
 | |
| '''
 | |
| 
 | |
| EXAMPLES = r'''
 | |
| - name: Basic get info from VM
 | |
|   community.general.rhevm:
 | |
|     server: rhevm01
 | |
|     user: '{{ rhev.admin.name }}'
 | |
|     password: '{{ rhev.admin.pass }}'
 | |
|     name: demo
 | |
|     state: info
 | |
| 
 | |
| - name: Basic create example from image
 | |
|   community.general.rhevm:
 | |
|     server: rhevm01
 | |
|     user: '{{ rhev.admin.name }}'
 | |
|     password: '{{ rhev.admin.pass }}'
 | |
|     name: demo
 | |
|     cluster: centos
 | |
|     image: centos7_x64
 | |
|     state: present
 | |
| 
 | |
| - name: Power management
 | |
|   community.general.rhevm:
 | |
|     server: rhevm01
 | |
|     user: '{{ rhev.admin.name }}'
 | |
|     password: '{{ rhev.admin.pass }}'
 | |
|     cluster: RH
 | |
|     name: uptime_server
 | |
|     image: centos7_x64
 | |
|     state: down
 | |
| 
 | |
| - name: Multi disk, multi nic create example
 | |
|   community.general.rhevm:
 | |
|     server: rhevm01
 | |
|     user: '{{ rhev.admin.name }}'
 | |
|     password: '{{ rhev.admin.pass }}'
 | |
|     cluster: RH
 | |
|     name: server007
 | |
|     type: server
 | |
|     vmcpu: 4
 | |
|     vmmem: 2
 | |
|     ifaces:
 | |
|     - name: eth0
 | |
|       vlan: vlan2202
 | |
|     - name: eth1
 | |
|       vlan: vlan36
 | |
|     - name: eth2
 | |
|       vlan: vlan38
 | |
|     - name: eth3
 | |
|       vlan: vlan2202
 | |
|     disks:
 | |
|     - name: root
 | |
|       size: 10
 | |
|       domain: ssd-san
 | |
|     - name: swap
 | |
|       size: 10
 | |
|       domain: 15kiscsi-san
 | |
|     - name: opt
 | |
|       size: 10
 | |
|       domain: 15kiscsi-san
 | |
|     - name: var
 | |
|       size: 10
 | |
|       domain: 10kiscsi-san
 | |
|     - name: home
 | |
|       size: 10
 | |
|       domain: sata-san
 | |
|     boot_order:
 | |
|     - network
 | |
|     - hd
 | |
|     state: present
 | |
| 
 | |
| - name: Add a CD to the disk cd_drive
 | |
|   community.general.rhevm:
 | |
|     user: '{{ rhev.admin.name }}'
 | |
|     password: '{{ rhev.admin.pass }}'
 | |
|     name: server007
 | |
|     cd_drive: rhev-tools-setup.iso
 | |
|     state: cd
 | |
| 
 | |
| - name: New host deployment + host network configuration
 | |
|   community.general.rhevm:
 | |
|     password: '{{ rhevm.admin.pass }}'
 | |
|     name: ovirt_node007
 | |
|     type: host
 | |
|     cluster: rhevm01
 | |
|     ifaces:
 | |
|     - name: em1
 | |
|     - name: em2
 | |
|     - name: p3p1
 | |
|       ip: 172.31.224.200
 | |
|       netmask: 255.255.254.0
 | |
|     - name: p3p2
 | |
|       ip: 172.31.225.200
 | |
|       netmask: 255.255.254.0
 | |
|     - name: bond0
 | |
|       bond:
 | |
|       - em1
 | |
|       - em2
 | |
|       network: rhevm
 | |
|       ip: 172.31.222.200
 | |
|       netmask: 255.255.255.0
 | |
|       management: true
 | |
|     - name: bond0.36
 | |
|       network: vlan36
 | |
|       ip: 10.2.36.200
 | |
|       netmask: 255.255.254.0
 | |
|       gateway: 10.2.36.254
 | |
|     - name: bond0.2202
 | |
|       network: vlan2202
 | |
|     - name: bond0.38
 | |
|       network: vlan38
 | |
|     state: present
 | |
| '''
 | |
| 
 | |
| import time
 | |
| 
 | |
| try:
 | |
|     from ovirtsdk.api import API
 | |
|     from ovirtsdk.xml import params
 | |
|     HAS_SDK = True
 | |
| except ImportError:
 | |
|     HAS_SDK = False
 | |
| 
 | |
| from ansible.module_utils.basic import AnsibleModule
 | |
| 
 | |
| 
 | |
| RHEV_FAILED = 1
 | |
| RHEV_SUCCESS = 0
 | |
| RHEV_UNAVAILABLE = 2
 | |
| 
 | |
| RHEV_TYPE_OPTS = ['desktop', 'host', 'server']
 | |
| STATE_OPTS = ['absent', 'cd', 'down', 'info', 'ping', 'present', 'restart', 'up']
 | |
| 
 | |
| msg = []
 | |
| changed = False
 | |
| failed = False
 | |
| 
 | |
| 
 | |
| class RHEVConn(object):
 | |
|     'Connection to RHEV-M'
 | |
| 
 | |
|     def __init__(self, module):
 | |
|         self.module = module
 | |
| 
 | |
|         user = module.params.get('user')
 | |
|         password = module.params.get('password')
 | |
|         server = module.params.get('server')
 | |
|         port = module.params.get('port')
 | |
|         insecure_api = module.params.get('insecure_api')
 | |
| 
 | |
|         url = "https://%s:%s" % (server, port)
 | |
| 
 | |
|         try:
 | |
|             api = API(url=url, username=user, password=password, insecure=str(insecure_api))
 | |
|             api.test()
 | |
|             self.conn = api
 | |
|         except Exception:
 | |
|             raise Exception("Failed to connect to RHEV-M.")
 | |
| 
 | |
|     def __del__(self):
 | |
|         self.conn.disconnect()
 | |
| 
 | |
|     def createVMimage(self, name, cluster, template):
 | |
|         try:
 | |
|             vmparams = params.VM(
 | |
|                 name=name,
 | |
|                 cluster=self.conn.clusters.get(name=cluster),
 | |
|                 template=self.conn.templates.get(name=template),
 | |
|                 disks=params.Disks(clone=True)
 | |
|             )
 | |
|             self.conn.vms.add(vmparams)
 | |
|             setMsg("VM is created")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to create VM")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def createVM(self, name, cluster, os, actiontype):
 | |
|         try:
 | |
|             vmparams = params.VM(
 | |
|                 name=name,
 | |
|                 cluster=self.conn.clusters.get(name=cluster),
 | |
|                 os=params.OperatingSystem(type_=os),
 | |
|                 template=self.conn.templates.get(name="Blank"),
 | |
|                 type_=actiontype
 | |
|             )
 | |
|             self.conn.vms.add(vmparams)
 | |
|             setMsg("VM is created")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to create VM")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def createDisk(self, vmname, diskname, disksize, diskdomain, diskinterface, diskformat, diskallocationtype, diskboot):
 | |
|         VM = self.get_VM(vmname)
 | |
| 
 | |
|         newdisk = params.Disk(
 | |
|             name=diskname,
 | |
|             size=1024 * 1024 * 1024 * int(disksize),
 | |
|             wipe_after_delete=True,
 | |
|             sparse=diskallocationtype,
 | |
|             interface=diskinterface,
 | |
|             format=diskformat,
 | |
|             bootable=diskboot,
 | |
|             storage_domains=params.StorageDomains(
 | |
|                 storage_domain=[self.get_domain(diskdomain)]
 | |
|             )
 | |
|         )
 | |
| 
 | |
|         try:
 | |
|             VM.disks.add(newdisk)
 | |
|             VM.update()
 | |
|             setMsg("Successfully added disk " + diskname)
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setFailed()
 | |
|             setMsg("Error attaching " + diskname + "disk, please recheck and remove any leftover configuration.")
 | |
|             setMsg(str(e))
 | |
|             return False
 | |
| 
 | |
|         try:
 | |
|             currentdisk = VM.disks.get(name=diskname)
 | |
|             attempt = 1
 | |
|             while currentdisk.status.state != 'ok':
 | |
|                 currentdisk = VM.disks.get(name=diskname)
 | |
|                 if attempt == 100:
 | |
|                     setMsg("Error, disk %s, state %s" % (diskname, str(currentdisk.status.state)))
 | |
|                     raise Exception()
 | |
|                 else:
 | |
|                     attempt += 1
 | |
|                     time.sleep(2)
 | |
|             setMsg("The disk  " + diskname + " is ready.")
 | |
|         except Exception as e:
 | |
|             setFailed()
 | |
|             setMsg("Error getting the state of " + diskname + ".")
 | |
|             setMsg(str(e))
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def createNIC(self, vmname, nicname, vlan, interface):
 | |
|         VM = self.get_VM(vmname)
 | |
|         CLUSTER = self.get_cluster_byid(VM.cluster.id)
 | |
|         DC = self.get_DC_byid(CLUSTER.data_center.id)
 | |
|         newnic = params.NIC(
 | |
|             name=nicname,
 | |
|             network=DC.networks.get(name=vlan),
 | |
|             interface=interface
 | |
|         )
 | |
| 
 | |
|         try:
 | |
|             VM.nics.add(newnic)
 | |
|             VM.update()
 | |
|             setMsg("Successfully added iface " + nicname)
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setFailed()
 | |
|             setMsg("Error attaching " + nicname + " iface, please recheck and remove any leftover configuration.")
 | |
|             setMsg(str(e))
 | |
|             return False
 | |
| 
 | |
|         try:
 | |
|             currentnic = VM.nics.get(name=nicname)
 | |
|             attempt = 1
 | |
|             while currentnic.active is not True:
 | |
|                 currentnic = VM.nics.get(name=nicname)
 | |
|                 if attempt == 100:
 | |
|                     setMsg("Error, iface %s, state %s" % (nicname, str(currentnic.active)))
 | |
|                     raise Exception()
 | |
|                 else:
 | |
|                     attempt += 1
 | |
|                     time.sleep(2)
 | |
|             setMsg("The iface  " + nicname + " is ready.")
 | |
|         except Exception as e:
 | |
|             setFailed()
 | |
|             setMsg("Error getting the state of " + nicname + ".")
 | |
|             setMsg(str(e))
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def get_DC(self, dc_name):
 | |
|         return self.conn.datacenters.get(name=dc_name)
 | |
| 
 | |
|     def get_DC_byid(self, dc_id):
 | |
|         return self.conn.datacenters.get(id=dc_id)
 | |
| 
 | |
|     def get_VM(self, vm_name):
 | |
|         return self.conn.vms.get(name=vm_name)
 | |
| 
 | |
|     def get_cluster_byid(self, cluster_id):
 | |
|         return self.conn.clusters.get(id=cluster_id)
 | |
| 
 | |
|     def get_cluster(self, cluster_name):
 | |
|         return self.conn.clusters.get(name=cluster_name)
 | |
| 
 | |
|     def get_domain_byid(self, dom_id):
 | |
|         return self.conn.storagedomains.get(id=dom_id)
 | |
| 
 | |
|     def get_domain(self, domain_name):
 | |
|         return self.conn.storagedomains.get(name=domain_name)
 | |
| 
 | |
|     def get_disk(self, disk):
 | |
|         return self.conn.disks.get(disk)
 | |
| 
 | |
|     def get_network(self, dc_name, network_name):
 | |
|         return self.get_DC(dc_name).networks.get(network_name)
 | |
| 
 | |
|     def get_network_byid(self, network_id):
 | |
|         return self.conn.networks.get(id=network_id)
 | |
| 
 | |
|     def get_NIC(self, vm_name, nic_name):
 | |
|         return self.get_VM(vm_name).nics.get(nic_name)
 | |
| 
 | |
|     def get_Host(self, host_name):
 | |
|         return self.conn.hosts.get(name=host_name)
 | |
| 
 | |
|     def get_Host_byid(self, host_id):
 | |
|         return self.conn.hosts.get(id=host_id)
 | |
| 
 | |
|     def set_Memory(self, name, memory):
 | |
|         VM = self.get_VM(name)
 | |
|         VM.memory = int(int(memory) * 1024 * 1024 * 1024)
 | |
|         try:
 | |
|             VM.update()
 | |
|             setMsg("The Memory has been updated.")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update memory.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def set_Memory_Policy(self, name, memory_policy):
 | |
|         VM = self.get_VM(name)
 | |
|         VM.memory_policy.guaranteed = int(memory_policy) * 1024 * 1024 * 1024
 | |
|         try:
 | |
|             VM.update()
 | |
|             setMsg("The memory policy has been updated.")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update memory policy.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def set_CPU(self, name, cpu):
 | |
|         VM = self.get_VM(name)
 | |
|         VM.cpu.topology.cores = int(cpu)
 | |
|         try:
 | |
|             VM.update()
 | |
|             setMsg("The number of CPUs has been updated.")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update the number of CPUs.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def set_CPU_share(self, name, cpu_share):
 | |
|         VM = self.get_VM(name)
 | |
|         VM.cpu_shares = int(cpu_share)
 | |
|         try:
 | |
|             VM.update()
 | |
|             setMsg("The CPU share has been updated.")
 | |
|             setChanged()
 | |
|             return True
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update the CPU share.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|     def set_Disk(self, diskname, disksize, diskinterface, diskboot):
 | |
|         DISK = self.get_disk(diskname)
 | |
|         setMsg("Checking disk " + diskname)
 | |
|         if DISK.get_bootable() != diskboot:
 | |
|             try:
 | |
|                 DISK.set_bootable(diskboot)
 | |
|                 setMsg("Updated the boot option on the disk.")
 | |
|                 setChanged()
 | |
|             except Exception as e:
 | |
|                 setMsg("Failed to set the boot option on the disk.")
 | |
|                 setMsg(str(e))
 | |
|                 setFailed()
 | |
|                 return False
 | |
|         else:
 | |
|             setMsg("The boot option of the disk is correct")
 | |
|         if int(DISK.size) < (1024 * 1024 * 1024 * int(disksize)):
 | |
|             try:
 | |
|                 DISK.size = (1024 * 1024 * 1024 * int(disksize))
 | |
|                 setMsg("Updated the size of the disk.")
 | |
|                 setChanged()
 | |
|             except Exception as e:
 | |
|                 setMsg("Failed to update the size of the disk.")
 | |
|                 setMsg(str(e))
 | |
|                 setFailed()
 | |
|                 return False
 | |
|         elif int(DISK.size) > (1024 * 1024 * 1024 * int(disksize)):
 | |
|             setMsg("Shrinking disks is not supported")
 | |
|             setFailed()
 | |
|             return False
 | |
|         else:
 | |
|             setMsg("The size of the disk is correct")
 | |
|         if str(DISK.interface) != str(diskinterface):
 | |
|             try:
 | |
|                 DISK.interface = diskinterface
 | |
|                 setMsg("Updated the interface of the disk.")
 | |
|                 setChanged()
 | |
|             except Exception as e:
 | |
|                 setMsg("Failed to update the interface of the disk.")
 | |
|                 setMsg(str(e))
 | |
|                 setFailed()
 | |
|                 return False
 | |
|         else:
 | |
|             setMsg("The interface of the disk is correct")
 | |
|         return True
 | |
| 
 | |
|     def set_NIC(self, vmname, nicname, newname, vlan, interface):
 | |
|         NIC = self.get_NIC(vmname, nicname)
 | |
|         VM = self.get_VM(vmname)
 | |
|         CLUSTER = self.get_cluster_byid(VM.cluster.id)
 | |
|         DC = self.get_DC_byid(CLUSTER.data_center.id)
 | |
|         NETWORK = self.get_network(str(DC.name), vlan)
 | |
|         checkFail()
 | |
|         if NIC.name != newname:
 | |
|             NIC.name = newname
 | |
|             setMsg('Updating iface name to ' + newname)
 | |
|             setChanged()
 | |
|         if str(NIC.network.id) != str(NETWORK.id):
 | |
|             NIC.set_network(NETWORK)
 | |
|             setMsg('Updating iface network to ' + vlan)
 | |
|             setChanged()
 | |
|         if NIC.interface != interface:
 | |
|             NIC.interface = interface
 | |
|             setMsg('Updating iface interface to ' + interface)
 | |
|             setChanged()
 | |
|         try:
 | |
|             NIC.update()
 | |
|             setMsg('iface has successfully been updated.')
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update the iface.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def set_DeleteProtection(self, vmname, del_prot):
 | |
|         VM = self.get_VM(vmname)
 | |
|         VM.delete_protected = del_prot
 | |
|         try:
 | |
|             VM.update()
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update delete protection.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def set_BootOrder(self, vmname, boot_order):
 | |
|         VM = self.get_VM(vmname)
 | |
|         bootorder = []
 | |
|         for device in boot_order:
 | |
|             bootorder.append(params.Boot(dev=device))
 | |
|         VM.os.boot = bootorder
 | |
| 
 | |
|         try:
 | |
|             VM.update()
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to update the boot order.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def set_Host(self, host_name, cluster, ifaces):
 | |
|         HOST = self.get_Host(host_name)
 | |
|         CLUSTER = self.get_cluster(cluster)
 | |
| 
 | |
|         if HOST is None:
 | |
|             setMsg("Host does not exist.")
 | |
|             ifacelist = dict()
 | |
|             networklist = []
 | |
|             manageip = ''
 | |
| 
 | |
|             try:
 | |
|                 for iface in ifaces:
 | |
|                     try:
 | |
|                         setMsg('creating host interface ' + iface['name'])
 | |
|                         if 'management' in iface:
 | |
|                             manageip = iface['ip']
 | |
|                         if 'boot_protocol' not in iface:
 | |
|                             if 'ip' in iface:
 | |
|                                 iface['boot_protocol'] = 'static'
 | |
|                             else:
 | |
|                                 iface['boot_protocol'] = 'none'
 | |
|                         if 'ip' not in iface:
 | |
|                             iface['ip'] = ''
 | |
|                         if 'netmask' not in iface:
 | |
|                             iface['netmask'] = ''
 | |
|                         if 'gateway' not in iface:
 | |
|                             iface['gateway'] = ''
 | |
| 
 | |
|                         if 'network' in iface:
 | |
|                             if 'bond' in iface:
 | |
|                                 bond = []
 | |
|                                 for slave in iface['bond']:
 | |
|                                     bond.append(ifacelist[slave])
 | |
|                                 try:
 | |
|                                     tmpiface = params.Bonding(
 | |
|                                         slaves=params.Slaves(host_nic=bond),
 | |
|                                         options=params.Options(
 | |
|                                             option=[
 | |
|                                                 params.Option(name='miimon', value='100'),
 | |
|                                                 params.Option(name='mode', value='4')
 | |
|                                             ]
 | |
|                                         )
 | |
|                                     )
 | |
|                                 except Exception as e:
 | |
|                                     setMsg('Failed to create the bond for  ' + iface['name'])
 | |
|                                     setFailed()
 | |
|                                     setMsg(str(e))
 | |
|                                     return False
 | |
|                                 try:
 | |
|                                     tmpnetwork = params.HostNIC(
 | |
|                                         network=params.Network(name=iface['network']),
 | |
|                                         name=iface['name'],
 | |
|                                         boot_protocol=iface['boot_protocol'],
 | |
|                                         ip=params.IP(
 | |
|                                             address=iface['ip'],
 | |
|                                             netmask=iface['netmask'],
 | |
|                                             gateway=iface['gateway']
 | |
|                                         ),
 | |
|                                         override_configuration=True,
 | |
|                                         bonding=tmpiface)
 | |
|                                     networklist.append(tmpnetwork)
 | |
|                                     setMsg('Applying network ' + iface['name'])
 | |
|                                 except Exception as e:
 | |
|                                     setMsg('Failed to set' + iface['name'] + ' as network interface')
 | |
|                                     setFailed()
 | |
|                                     setMsg(str(e))
 | |
|                                     return False
 | |
|                             else:
 | |
|                                 tmpnetwork = params.HostNIC(
 | |
|                                     network=params.Network(name=iface['network']),
 | |
|                                     name=iface['name'],
 | |
|                                     boot_protocol=iface['boot_protocol'],
 | |
|                                     ip=params.IP(
 | |
|                                         address=iface['ip'],
 | |
|                                         netmask=iface['netmask'],
 | |
|                                         gateway=iface['gateway']
 | |
|                                     ))
 | |
|                                 networklist.append(tmpnetwork)
 | |
|                                 setMsg('Applying network ' + iface['name'])
 | |
|                         else:
 | |
|                             tmpiface = params.HostNIC(
 | |
|                                 name=iface['name'],
 | |
|                                 network=params.Network(),
 | |
|                                 boot_protocol=iface['boot_protocol'],
 | |
|                                 ip=params.IP(
 | |
|                                     address=iface['ip'],
 | |
|                                     netmask=iface['netmask'],
 | |
|                                     gateway=iface['gateway']
 | |
|                                 ))
 | |
|                         ifacelist[iface['name']] = tmpiface
 | |
|                     except Exception as e:
 | |
|                         setMsg('Failed to set ' + iface['name'])
 | |
|                         setFailed()
 | |
|                         setMsg(str(e))
 | |
|                         return False
 | |
|             except Exception as e:
 | |
|                 setMsg('Failed to set networks')
 | |
|                 setMsg(str(e))
 | |
|                 setFailed()
 | |
|                 return False
 | |
| 
 | |
|             if manageip == '':
 | |
|                 setMsg('No management network is defined')
 | |
|                 setFailed()
 | |
|                 return False
 | |
| 
 | |
|             try:
 | |
|                 HOST = params.Host(name=host_name, address=manageip, cluster=CLUSTER, ssh=params.SSH(authentication_method='publickey'))
 | |
|                 if self.conn.hosts.add(HOST):
 | |
|                     setChanged()
 | |
|                     HOST = self.get_Host(host_name)
 | |
|                     state = HOST.status.state
 | |
|                     while (state != 'non_operational' and state != 'up'):
 | |
|                         HOST = self.get_Host(host_name)
 | |
|                         state = HOST.status.state
 | |
|                         time.sleep(1)
 | |
|                         if state == 'non_responsive':
 | |
|                             setMsg('Failed to add host to RHEVM')
 | |
|                             setFailed()
 | |
|                             return False
 | |
| 
 | |
|                     setMsg('status host: up')
 | |
|                     time.sleep(5)
 | |
| 
 | |
|                     HOST = self.get_Host(host_name)
 | |
|                     state = HOST.status.state
 | |
|                     setMsg('State before setting to maintenance: ' + str(state))
 | |
|                     HOST.deactivate()
 | |
|                     while state != 'maintenance':
 | |
|                         HOST = self.get_Host(host_name)
 | |
|                         state = HOST.status.state
 | |
|                         time.sleep(1)
 | |
|                     setMsg('status host: maintenance')
 | |
| 
 | |
|                     try:
 | |
|                         HOST.nics.setupnetworks(params.Action(
 | |
|                             force=True,
 | |
|                             check_connectivity=False,
 | |
|                             host_nics=params.HostNics(host_nic=networklist)
 | |
|                         ))
 | |
|                         setMsg('nics are set')
 | |
|                     except Exception as e:
 | |
|                         setMsg('Failed to apply networkconfig')
 | |
|                         setFailed()
 | |
|                         setMsg(str(e))
 | |
|                         return False
 | |
| 
 | |
|                     try:
 | |
|                         HOST.commitnetconfig()
 | |
|                         setMsg('Network config is saved')
 | |
|                     except Exception as e:
 | |
|                         setMsg('Failed to save networkconfig')
 | |
|                         setFailed()
 | |
|                         setMsg(str(e))
 | |
|                         return False
 | |
|             except Exception as e:
 | |
|                 if 'The Host name is already in use' in str(e):
 | |
|                     setMsg("Host already exists")
 | |
|                 else:
 | |
|                     setMsg("Failed to add host")
 | |
|                     setFailed()
 | |
|                     setMsg(str(e))
 | |
|                 return False
 | |
| 
 | |
|             HOST.activate()
 | |
|             while state != 'up':
 | |
|                 HOST = self.get_Host(host_name)
 | |
|                 state = HOST.status.state
 | |
|                 time.sleep(1)
 | |
|                 if state == 'non_responsive':
 | |
|                     setMsg('Failed to apply networkconfig.')
 | |
|                     setFailed()
 | |
|                     return False
 | |
|             setMsg('status host: up')
 | |
|         else:
 | |
|             setMsg("Host exists.")
 | |
| 
 | |
|         return True
 | |
| 
 | |
|     def del_NIC(self, vmname, nicname):
 | |
|         return self.get_NIC(vmname, nicname).delete()
 | |
| 
 | |
|     def remove_VM(self, vmname):
 | |
|         VM = self.get_VM(vmname)
 | |
|         try:
 | |
|             VM.delete()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to remove VM.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def start_VM(self, vmname, timeout):
 | |
|         VM = self.get_VM(vmname)
 | |
|         try:
 | |
|             VM.start()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to start VM.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return self.wait_VM(vmname, "up", timeout)
 | |
| 
 | |
|     def wait_VM(self, vmname, state, timeout):
 | |
|         VM = self.get_VM(vmname)
 | |
|         while VM.status.state != state:
 | |
|             VM = self.get_VM(vmname)
 | |
|             time.sleep(10)
 | |
|             if timeout is not False:
 | |
|                 timeout -= 10
 | |
|                 if timeout <= 0:
 | |
|                     setMsg("Timeout expired")
 | |
|                     setFailed()
 | |
|                     return False
 | |
|         return True
 | |
| 
 | |
|     def stop_VM(self, vmname, timeout):
 | |
|         VM = self.get_VM(vmname)
 | |
|         try:
 | |
|             VM.stop()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to stop VM.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return self.wait_VM(vmname, "down", timeout)
 | |
| 
 | |
|     def set_CD(self, vmname, cd_drive):
 | |
|         VM = self.get_VM(vmname)
 | |
|         try:
 | |
|             if str(VM.status.state) == 'down':
 | |
|                 cdrom = params.CdRom(file=cd_drive)
 | |
|                 VM.cdroms.add(cdrom)
 | |
|                 setMsg("Attached the image.")
 | |
|                 setChanged()
 | |
|             else:
 | |
|                 cdrom = VM.cdroms.get(id="00000000-0000-0000-0000-000000000000")
 | |
|                 cdrom.set_file(cd_drive)
 | |
|                 cdrom.update(current=True)
 | |
|                 setMsg("Attached the image.")
 | |
|                 setChanged()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to attach image.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def set_VM_Host(self, vmname, vmhost):
 | |
|         VM = self.get_VM(vmname)
 | |
|         HOST = self.get_Host(vmhost)
 | |
|         try:
 | |
|             VM.placement_policy.host = HOST
 | |
|             VM.update()
 | |
|             setMsg("Set startup host to " + vmhost)
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to set startup host.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
|     def migrate_VM(self, vmname, vmhost):
 | |
|         VM = self.get_VM(vmname)
 | |
| 
 | |
|         HOST = self.get_Host_byid(VM.host.id)
 | |
|         if str(HOST.name) != vmhost:
 | |
|             try:
 | |
|                 VM.migrate(
 | |
|                     action=params.Action(
 | |
|                         host=params.Host(
 | |
|                             name=vmhost,
 | |
|                         )
 | |
|                     ),
 | |
|                 )
 | |
|                 setChanged()
 | |
|                 setMsg("VM migrated to " + vmhost)
 | |
|             except Exception as e:
 | |
|                 setMsg("Failed to set startup host.")
 | |
|                 setMsg(str(e))
 | |
|                 setFailed()
 | |
|                 return False
 | |
|         return True
 | |
| 
 | |
|     def remove_CD(self, vmname):
 | |
|         VM = self.get_VM(vmname)
 | |
|         try:
 | |
|             VM.cdroms.get(id="00000000-0000-0000-0000-000000000000").delete()
 | |
|             setMsg("Removed the image.")
 | |
|             setChanged()
 | |
|         except Exception as e:
 | |
|             setMsg("Failed to remove the image.")
 | |
|             setMsg(str(e))
 | |
|             setFailed()
 | |
|             return False
 | |
|         return True
 | |
| 
 | |
| 
 | |
| class RHEV(object):
 | |
|     def __init__(self, module):
 | |
|         self.module = module
 | |
| 
 | |
|     def __get_conn(self):
 | |
|         self.conn = RHEVConn(self.module)
 | |
|         return self.conn
 | |
| 
 | |
|     def test(self):
 | |
|         self.__get_conn()
 | |
|         return "OK"
 | |
| 
 | |
|     def getVM(self, name):
 | |
|         self.__get_conn()
 | |
|         VM = self.conn.get_VM(name)
 | |
|         if VM:
 | |
|             vminfo = dict()
 | |
|             vminfo['uuid'] = VM.id
 | |
|             vminfo['name'] = VM.name
 | |
|             vminfo['status'] = VM.status.state
 | |
|             vminfo['cpu_cores'] = VM.cpu.topology.cores
 | |
|             vminfo['cpu_sockets'] = VM.cpu.topology.sockets
 | |
|             vminfo['cpu_shares'] = VM.cpu_shares
 | |
|             vminfo['memory'] = (int(VM.memory) // 1024 // 1024 // 1024)
 | |
|             vminfo['mem_pol'] = (int(VM.memory_policy.guaranteed) // 1024 // 1024 // 1024)
 | |
|             vminfo['os'] = VM.get_os().type_
 | |
|             vminfo['del_prot'] = VM.delete_protected
 | |
|             try:
 | |
|                 vminfo['host'] = str(self.conn.get_Host_byid(str(VM.host.id)).name)
 | |
|             except Exception:
 | |
|                 vminfo['host'] = None
 | |
|             vminfo['boot_order'] = []
 | |
|             for boot_dev in VM.os.get_boot():
 | |
|                 vminfo['boot_order'].append(str(boot_dev.dev))
 | |
|             vminfo['disks'] = []
 | |
|             for DISK in VM.disks.list():
 | |
|                 disk = dict()
 | |
|                 disk['name'] = DISK.name
 | |
|                 disk['size'] = (int(DISK.size) // 1024 // 1024 // 1024)
 | |
|                 disk['domain'] = str((self.conn.get_domain_byid(DISK.get_storage_domains().get_storage_domain()[0].id)).name)
 | |
|                 disk['interface'] = DISK.interface
 | |
|                 vminfo['disks'].append(disk)
 | |
|             vminfo['ifaces'] = []
 | |
|             for NIC in VM.nics.list():
 | |
|                 iface = dict()
 | |
|                 iface['name'] = str(NIC.name)
 | |
|                 iface['vlan'] = str(self.conn.get_network_byid(NIC.get_network().id).name)
 | |
|                 iface['interface'] = NIC.interface
 | |
|                 iface['mac'] = NIC.mac.address
 | |
|                 vminfo['ifaces'].append(iface)
 | |
|                 vminfo[str(NIC.name)] = NIC.mac.address
 | |
|             CLUSTER = self.conn.get_cluster_byid(VM.cluster.id)
 | |
|             if CLUSTER:
 | |
|                 vminfo['cluster'] = CLUSTER.name
 | |
|         else:
 | |
|             vminfo = False
 | |
|         return vminfo
 | |
| 
 | |
|     def createVMimage(self, name, cluster, template, disks):
 | |
|         self.__get_conn()
 | |
|         return self.conn.createVMimage(name, cluster, template, disks)
 | |
| 
 | |
|     def createVM(self, name, cluster, os, actiontype):
 | |
|         self.__get_conn()
 | |
|         return self.conn.createVM(name, cluster, os, actiontype)
 | |
| 
 | |
|     def setMemory(self, name, memory):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_Memory(name, memory)
 | |
| 
 | |
|     def setMemoryPolicy(self, name, memory_policy):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_Memory_Policy(name, memory_policy)
 | |
| 
 | |
|     def setCPU(self, name, cpu):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_CPU(name, cpu)
 | |
| 
 | |
|     def setCPUShare(self, name, cpu_share):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_CPU_share(name, cpu_share)
 | |
| 
 | |
|     def setDisks(self, name, disks):
 | |
|         self.__get_conn()
 | |
|         counter = 0
 | |
|         bootselect = False
 | |
|         for disk in disks:
 | |
|             if 'bootable' in disk:
 | |
|                 if disk['bootable'] is True:
 | |
|                     bootselect = True
 | |
| 
 | |
|         for disk in disks:
 | |
|             diskname = name + "_Disk" + str(counter) + "_" + disk.get('name', '').replace('/', '_')
 | |
|             disksize = disk.get('size', 1)
 | |
|             diskdomain = disk.get('domain', None)
 | |
|             if diskdomain is None:
 | |
|                 setMsg("`domain` is a required disk key.")
 | |
|                 setFailed()
 | |
|                 return False
 | |
|             diskinterface = disk.get('interface', 'virtio')
 | |
|             diskformat = disk.get('format', 'raw')
 | |
|             diskallocationtype = disk.get('thin', False)
 | |
|             diskboot = disk.get('bootable', False)
 | |
| 
 | |
|             if bootselect is False and counter == 0:
 | |
|                 diskboot = True
 | |
| 
 | |
|             DISK = self.conn.get_disk(diskname)
 | |
| 
 | |
|             if DISK is None:
 | |
|                 self.conn.createDisk(name, diskname, disksize, diskdomain, diskinterface, diskformat, diskallocationtype, diskboot)
 | |
|             else:
 | |
|                 self.conn.set_Disk(diskname, disksize, diskinterface, diskboot)
 | |
|             checkFail()
 | |
|             counter += 1
 | |
| 
 | |
|         return True
 | |
| 
 | |
|     def setNetworks(self, vmname, ifaces):
 | |
|         self.__get_conn()
 | |
|         VM = self.conn.get_VM(vmname)
 | |
| 
 | |
|         counter = 0
 | |
|         length = len(ifaces)
 | |
| 
 | |
|         for NIC in VM.nics.list():
 | |
|             if counter < length:
 | |
|                 iface = ifaces[counter]
 | |
|                 name = iface.get('name', None)
 | |
|                 if name is None:
 | |
|                     setMsg("`name` is a required iface key.")
 | |
|                     setFailed()
 | |
|                 elif str(name) != str(NIC.name):
 | |
|                     setMsg("ifaces are in the wrong order, rebuilding everything.")
 | |
|                     for NIC in VM.nics.list():
 | |
|                         self.conn.del_NIC(vmname, NIC.name)
 | |
|                     self.setNetworks(vmname, ifaces)
 | |
|                     checkFail()
 | |
|                     return True
 | |
|                 vlan = iface.get('vlan', None)
 | |
|                 if vlan is None:
 | |
|                     setMsg("`vlan` is a required iface key.")
 | |
|                     setFailed()
 | |
|                 checkFail()
 | |
|                 interface = iface.get('interface', 'virtio')
 | |
|                 self.conn.set_NIC(vmname, str(NIC.name), name, vlan, interface)
 | |
|             else:
 | |
|                 self.conn.del_NIC(vmname, NIC.name)
 | |
|             counter += 1
 | |
|             checkFail()
 | |
| 
 | |
|         while counter < length:
 | |
|             iface = ifaces[counter]
 | |
|             name = iface.get('name', None)
 | |
|             if name is None:
 | |
|                 setMsg("`name` is a required iface key.")
 | |
|                 setFailed()
 | |
|             vlan = iface.get('vlan', None)
 | |
|             if vlan is None:
 | |
|                 setMsg("`vlan` is a required iface key.")
 | |
|                 setFailed()
 | |
|             if failed is True:
 | |
|                 return False
 | |
|             interface = iface.get('interface', 'virtio')
 | |
|             self.conn.createNIC(vmname, name, vlan, interface)
 | |
| 
 | |
|             counter += 1
 | |
|             checkFail()
 | |
|         return True
 | |
| 
 | |
|     def setDeleteProtection(self, vmname, del_prot):
 | |
|         self.__get_conn()
 | |
|         VM = self.conn.get_VM(vmname)
 | |
|         if bool(VM.delete_protected) != bool(del_prot):
 | |
|             self.conn.set_DeleteProtection(vmname, del_prot)
 | |
|             checkFail()
 | |
|             setMsg("`delete protection` has been updated.")
 | |
|         else:
 | |
|             setMsg("`delete protection` already has the right value.")
 | |
|         return True
 | |
| 
 | |
|     def setBootOrder(self, vmname, boot_order):
 | |
|         self.__get_conn()
 | |
|         VM = self.conn.get_VM(vmname)
 | |
|         bootorder = []
 | |
|         for boot_dev in VM.os.get_boot():
 | |
|             bootorder.append(str(boot_dev.dev))
 | |
| 
 | |
|         if boot_order != bootorder:
 | |
|             self.conn.set_BootOrder(vmname, boot_order)
 | |
|             setMsg('The boot order has been set')
 | |
|         else:
 | |
|             setMsg('The boot order has already been set')
 | |
|         return True
 | |
| 
 | |
|     def removeVM(self, vmname):
 | |
|         self.__get_conn()
 | |
|         self.setPower(vmname, "down", 300)
 | |
|         return self.conn.remove_VM(vmname)
 | |
| 
 | |
|     def setPower(self, vmname, state, timeout):
 | |
|         self.__get_conn()
 | |
|         VM = self.conn.get_VM(vmname)
 | |
|         if VM is None:
 | |
|             setMsg("VM does not exist.")
 | |
|             setFailed()
 | |
|             return False
 | |
| 
 | |
|         if state == VM.status.state:
 | |
|             setMsg("VM state was already " + state)
 | |
|         else:
 | |
|             if state == "up":
 | |
|                 setMsg("VM is going to start")
 | |
|                 self.conn.start_VM(vmname, timeout)
 | |
|                 setChanged()
 | |
|             elif state == "down":
 | |
|                 setMsg("VM is going to stop")
 | |
|                 self.conn.stop_VM(vmname, timeout)
 | |
|                 setChanged()
 | |
|             elif state == "restarted":
 | |
|                 self.setPower(vmname, "down", timeout)
 | |
|                 checkFail()
 | |
|                 self.setPower(vmname, "up", timeout)
 | |
|             checkFail()
 | |
|             setMsg("the vm state is set to " + state)
 | |
|         return True
 | |
| 
 | |
|     def setCD(self, vmname, cd_drive):
 | |
|         self.__get_conn()
 | |
|         if cd_drive:
 | |
|             return self.conn.set_CD(vmname, cd_drive)
 | |
|         else:
 | |
|             return self.conn.remove_CD(vmname)
 | |
| 
 | |
|     def setVMHost(self, vmname, vmhost):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_VM_Host(vmname, vmhost)
 | |
| 
 | |
|     def setHost(self, hostname, cluster, ifaces):
 | |
|         self.__get_conn()
 | |
|         return self.conn.set_Host(hostname, cluster, ifaces)
 | |
| 
 | |
| 
 | |
| def checkFail():
 | |
|     if failed:
 | |
|         module.fail_json(msg=msg)
 | |
|     else:
 | |
|         return True
 | |
| 
 | |
| 
 | |
| def setFailed():
 | |
|     global failed
 | |
|     failed = True
 | |
| 
 | |
| 
 | |
| def setChanged():
 | |
|     global changed
 | |
|     changed = True
 | |
| 
 | |
| 
 | |
| def setMsg(message):
 | |
|     msg.append(message)
 | |
| 
 | |
| 
 | |
| def core(module):
 | |
| 
 | |
|     r = RHEV(module)
 | |
| 
 | |
|     state = module.params.get('state')
 | |
| 
 | |
|     if state == 'ping':
 | |
|         r.test()
 | |
|         return RHEV_SUCCESS, {"ping": "pong"}
 | |
|     elif state == 'info':
 | |
|         name = module.params.get('name')
 | |
|         if not name:
 | |
|             setMsg("`name` is a required argument.")
 | |
|             return RHEV_FAILED, msg
 | |
|         vminfo = r.getVM(name)
 | |
|         return RHEV_SUCCESS, {'changed': changed, 'msg': msg, 'vm': vminfo}
 | |
|     elif state == 'present':
 | |
|         created = False
 | |
|         name = module.params.get('name')
 | |
|         if not name:
 | |
|             setMsg("`name` is a required argument.")
 | |
|             return RHEV_FAILED, msg
 | |
|         actiontype = module.params.get('type')
 | |
|         if actiontype == 'server' or actiontype == 'desktop':
 | |
|             vminfo = r.getVM(name)
 | |
|             if vminfo:
 | |
|                 setMsg('VM exists')
 | |
|             else:
 | |
|                 # Create VM
 | |
|                 cluster = module.params.get('cluster')
 | |
|                 if cluster is None:
 | |
|                     setMsg("cluster is a required argument.")
 | |
|                     setFailed()
 | |
|                 template = module.params.get('image')
 | |
|                 if template:
 | |
|                     disks = module.params.get('disks')
 | |
|                     if disks is None:
 | |
|                         setMsg("disks is a required argument.")
 | |
|                         setFailed()
 | |
|                     checkFail()
 | |
|                     if r.createVMimage(name, cluster, template, disks) is False:
 | |
|                         return RHEV_FAILED, vminfo
 | |
|                 else:
 | |
|                     os = module.params.get('osver')
 | |
|                     if os is None:
 | |
|                         setMsg("osver is a required argument.")
 | |
|                         setFailed()
 | |
|                     checkFail()
 | |
|                     if r.createVM(name, cluster, os, actiontype) is False:
 | |
|                         return RHEV_FAILED, vminfo
 | |
|                 created = True
 | |
| 
 | |
|             # Set MEMORY and MEMORY POLICY
 | |
|             vminfo = r.getVM(name)
 | |
|             memory = module.params.get('vmmem')
 | |
|             if memory is not None:
 | |
|                 memory_policy = module.params.get('mempol')
 | |
|                 if memory_policy == 0:
 | |
|                     memory_policy = memory
 | |
|                 mem_pol_nok = True
 | |
|                 if int(vminfo['mem_pol']) == memory_policy:
 | |
|                     setMsg("Memory is correct")
 | |
|                     mem_pol_nok = False
 | |
| 
 | |
|                 mem_nok = True
 | |
|                 if int(vminfo['memory']) == memory:
 | |
|                     setMsg("Memory is correct")
 | |
|                     mem_nok = False
 | |
| 
 | |
|                 if memory_policy > memory:
 | |
|                     setMsg('memory_policy cannot have a higher value than memory.')
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|                 if mem_nok and mem_pol_nok:
 | |
|                     if memory_policy > int(vminfo['memory']):
 | |
|                         r.setMemory(vminfo['name'], memory)
 | |
|                         r.setMemoryPolicy(vminfo['name'], memory_policy)
 | |
|                     else:
 | |
|                         r.setMemoryPolicy(vminfo['name'], memory_policy)
 | |
|                         r.setMemory(vminfo['name'], memory)
 | |
|                 elif mem_nok:
 | |
|                     r.setMemory(vminfo['name'], memory)
 | |
|                 elif mem_pol_nok:
 | |
|                     r.setMemoryPolicy(vminfo['name'], memory_policy)
 | |
|                 checkFail()
 | |
| 
 | |
|             # Set CPU
 | |
|             cpu = module.params.get('vmcpu')
 | |
|             if int(vminfo['cpu_cores']) == cpu:
 | |
|                 setMsg("Number of CPUs is correct")
 | |
|             else:
 | |
|                 if r.setCPU(vminfo['name'], cpu) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set CPU SHARE
 | |
|             cpu_share = module.params.get('cpu_share')
 | |
|             if cpu_share is not None:
 | |
|                 if int(vminfo['cpu_shares']) == cpu_share:
 | |
|                     setMsg("CPU share is correct.")
 | |
|                 else:
 | |
|                     if r.setCPUShare(vminfo['name'], cpu_share) is False:
 | |
|                         return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set DISKS
 | |
|             disks = module.params.get('disks')
 | |
|             if disks is not None:
 | |
|                 if r.setDisks(vminfo['name'], disks) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set NETWORKS
 | |
|             ifaces = module.params.get('ifaces', None)
 | |
|             if ifaces is not None:
 | |
|                 if r.setNetworks(vminfo['name'], ifaces) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set Delete Protection
 | |
|             del_prot = module.params.get('del_prot')
 | |
|             if r.setDeleteProtection(vminfo['name'], del_prot) is False:
 | |
|                 return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set Boot Order
 | |
|             boot_order = module.params.get('boot_order')
 | |
|             if r.setBootOrder(vminfo['name'], boot_order) is False:
 | |
|                 return RHEV_FAILED, msg
 | |
| 
 | |
|             # Set VM Host
 | |
|             vmhost = module.params.get('vmhost')
 | |
|             if vmhost:
 | |
|                 if r.setVMHost(vminfo['name'], vmhost) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|             vminfo = r.getVM(name)
 | |
|             vminfo['created'] = created
 | |
|             return RHEV_SUCCESS, {'changed': changed, 'msg': msg, 'vm': vminfo}
 | |
| 
 | |
|         if actiontype == 'host':
 | |
|             cluster = module.params.get('cluster')
 | |
|             if cluster is None:
 | |
|                 setMsg("cluster is a required argument.")
 | |
|                 setFailed()
 | |
|             ifaces = module.params.get('ifaces')
 | |
|             if ifaces is None:
 | |
|                 setMsg("ifaces is a required argument.")
 | |
|                 setFailed()
 | |
|             if r.setHost(name, cluster, ifaces) is False:
 | |
|                 return RHEV_FAILED, msg
 | |
|             return RHEV_SUCCESS, {'changed': changed, 'msg': msg}
 | |
| 
 | |
|     elif state == 'absent':
 | |
|         name = module.params.get('name')
 | |
|         if not name:
 | |
|             setMsg("`name` is a required argument.")
 | |
|             return RHEV_FAILED, msg
 | |
|         actiontype = module.params.get('type')
 | |
|         if actiontype == 'server' or actiontype == 'desktop':
 | |
|             vminfo = r.getVM(name)
 | |
|             if vminfo:
 | |
|                 setMsg('VM exists')
 | |
| 
 | |
|                 # Set Delete Protection
 | |
|                 del_prot = module.params.get('del_prot')
 | |
|                 if r.setDeleteProtection(vminfo['name'], del_prot) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
| 
 | |
|                 # Remove VM
 | |
|                 if r.removeVM(vminfo['name']) is False:
 | |
|                     return RHEV_FAILED, msg
 | |
|                 setMsg('VM has been removed.')
 | |
|                 vminfo['state'] = 'DELETED'
 | |
|             else:
 | |
|                 setMsg('VM was already removed.')
 | |
|             return RHEV_SUCCESS, {'changed': changed, 'msg': msg, 'vm': vminfo}
 | |
| 
 | |
|     elif state == 'up' or state == 'down' or state == 'restarted':
 | |
|         name = module.params.get('name')
 | |
|         if not name:
 | |
|             setMsg("`name` is a required argument.")
 | |
|             return RHEV_FAILED, msg
 | |
|         timeout = module.params.get('timeout')
 | |
|         if r.setPower(name, state, timeout) is False:
 | |
|             return RHEV_FAILED, msg
 | |
|         vminfo = r.getVM(name)
 | |
|         return RHEV_SUCCESS, {'changed': changed, 'msg': msg, 'vm': vminfo}
 | |
| 
 | |
|     elif state == 'cd':
 | |
|         name = module.params.get('name')
 | |
|         cd_drive = module.params.get('cd_drive')
 | |
|         if r.setCD(name, cd_drive) is False:
 | |
|             return RHEV_FAILED, msg
 | |
|         return RHEV_SUCCESS, {'changed': changed, 'msg': msg}
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     global module
 | |
|     module = AnsibleModule(
 | |
|         argument_spec=dict(
 | |
|             state=dict(type='str', default='present', choices=['absent', 'cd', 'down', 'info', 'ping', 'present', 'restarted', 'up']),
 | |
|             user=dict(type='str', default='admin@internal'),
 | |
|             password=dict(type='str', required=True, no_log=True),
 | |
|             server=dict(type='str', default='127.0.0.1'),
 | |
|             port=dict(type='int', default=443),
 | |
|             insecure_api=dict(type='bool', default=False),
 | |
|             name=dict(type='str'),
 | |
|             image=dict(type='str'),
 | |
|             datacenter=dict(type='str', default="Default"),
 | |
|             type=dict(type='str', default='server', choices=['desktop', 'host', 'server']),
 | |
|             cluster=dict(type='str', default=''),
 | |
|             vmhost=dict(type='str'),
 | |
|             vmcpu=dict(type='int', default=2),
 | |
|             vmmem=dict(type='int', default=1),
 | |
|             disks=dict(type='list', elements='str'),
 | |
|             osver=dict(type='str', default="rhel_6x64"),
 | |
|             ifaces=dict(type='list', elements='str', aliases=['interfaces', 'nics']),
 | |
|             timeout=dict(type='int'),
 | |
|             mempol=dict(type='int', default=1),
 | |
|             vm_ha=dict(type='bool', default=True),
 | |
|             cpu_share=dict(type='int', default=0),
 | |
|             boot_order=dict(type='list', elements='str', default=['hd', 'network']),
 | |
|             del_prot=dict(type='bool', default=True),
 | |
|             cd_drive=dict(type='str'),
 | |
|         ),
 | |
|     )
 | |
| 
 | |
|     if not HAS_SDK:
 | |
|         module.fail_json(msg="The 'ovirtsdk' module is not importable. Check the requirements.")
 | |
| 
 | |
|     rc = RHEV_SUCCESS
 | |
|     try:
 | |
|         rc, result = core(module)
 | |
|     except Exception as e:
 | |
|         module.fail_json(msg=str(e))
 | |
| 
 | |
|     if rc != 0:  # something went wrong emit the msg
 | |
|         module.fail_json(rc=rc, msg=result)
 | |
| 
 | |
|     module.exit_json(**result)
 | |
| 
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     main()
 |