#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright: (c) 2018, Bojan Vitnik <bvitnik@mainstream.rs>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type

ANSIBLE_METADATA = {'metadata_version': '1.1',
                    'status': ['preview'],
                    'supported_by': 'community'}

DOCUMENTATION = r'''
---
module: xenserver_guest
short_description: Manages virtual machines running on Citrix XenServer host or pool
description: >
   This module can be used to create new virtual machines from templates or other virtual machines,
   modify various virtual machine components like network and disk, rename a virtual machine and
   remove a virtual machine with associated components.
version_added: '2.8'
author:
- Bojan Vitnik (@bvitnik) <bvitnik@mainstream.rs>
notes:
- Minimal supported version of XenServer is 5.6.
- Module was tested with XenServer 6.5, 7.1 and 7.2.
- 'XenAPI Python library can be acquired from XenServer SDK (downloadable from Citrix website) or by running C(pip install XenAPI) (possibly very old
   version, not compatible with Python 3.x). Latest version can also be acquired from GitHub:
   https://raw.githubusercontent.com/xapi-project/xen-api/master/scripts/examples/python/XenAPI.py'
- 'If no scheme is specified in C(hostname), module defaults to C(http://) because C(https://) is problematic in most setups. Make sure you are
   accessing XenServer host in trusted environment or use C(https://) scheme explicitly.'
- 'To use C(https://) scheme for C(hostname) you have to either import host certificate to your OS certificate store or use C(validate_certs: no)
   which requires XenAPI library from XenServer 7.2 SDK or newer and Python 2.7.9 or newer.'
- 'Network configuration inside a guest OS, by using C(networks.type), C(networks.ip), C(networks.gateway) etc. parameters, is supported on
  XenServer 7.0 or newer for Windows guests by using official XenServer Guest agent support for network configuration. The module will try to
  detect if such support is available and utilize it, else it will use a custom method of configuration via xenstore. Since XenServer Guest
  agent only support None and Static types of network configuration, where None means DHCP configured interface, C(networks.type) and C(networks.type6)
  values C(none) and C(dhcp) have same effect.
  More info here: https://xenserver.org/blog/entry/set-windows-guest-vm-static-ip-address-in-xenserver.html'
- 'On platforms without official support for network configuration inside a guest OS, network parameters will be written to xenstore
  C(vm-data/networks/<vif_device>) key. Parameters can be inspected by using C(xenstore ls) and C(xenstore read) tools on \*nix guests or trough
  WMI interface on Windows guests. They can also be found in VM facts C(instance.xenstore_data) key as returned by the module. It is up to the user
  to implement a boot time scripts or custom agent that will read the parameters from xenstore and configure network with given parameters.
  Take note that for xenstore data to become available inside a guest, a VM restart is needed hence module will require VM restart if any
  parameter is changed. This is a limitation of XenAPI and xenstore. Considering these limitations, network configuration trough xenstore is most
  useful for bootstraping newly deployed VMs, much less for reconfiguring existing ones.
  More info here: https://support.citrix.com/article/CTX226713'
requirements:
- python >= 2.6
- XenAPI
options:
  state:
    description:
    - Specify the state VM should be in.
    - If C(state) is set to C(present) and VM exists, ensure the VM configuration conforms to given parameters.
    - If C(state) is set to C(present) and VM does not exist, then VM is deployed with given parameters.
    - If C(state) is set to C(absent) and VM exists, then VM is removed with its associated components.
    - If C(state) is set to C(poweredon) and VM does not exist, then VM is deployed with given parameters and powered on automatically.
    type: str
    default: present
    choices: [ present, absent, poweredon ]
  name:
    description:
    - Name of the VM to work with.
    - VMs running on XenServer do not necessarily have unique names. The module will fail if multiple VMs with same name are found.
    - In case of multiple VMs with same name, use C(uuid) to uniquely specify VM to manage.
    - This parameter is case sensitive.
    type: str
    required: yes
    aliases: [ name_label ]
  name_desc:
    description:
    - VM description.
    type: str
  uuid:
    description:
    - UUID of the VM to manage if known. This is XenServer's unique identifier.
    - It is required if name is not unique.
    - Please note that a supplied UUID will be ignored on VM creation, as XenServer creates the UUID internally.
    type: str
  template:
    description:
    - Name of a template, an existing VM (must be shut down) or a snapshot that should be used to create VM.
    - Templates/VMs/snapshots on XenServer do not necessarily have unique names. The module will fail if multiple templates with same name are found.
    - In case of multiple templates/VMs/snapshots with same name, use C(template_uuid) to uniquely specify source template.
    - If VM already exists, this setting will be ignored.
    - This parameter is case sensitive.
    type: str
    aliases: [ template_src ]
  template_uuid:
    description:
    - UUID of a template, an exist
ing VM or a snapshot that should be used to create VM.
    - It is required if template name is not unique.
    type: str
  is_template:
    description:
    - Convert VM to template.
    type: bool
    default: no
  folder:
    description:
    - Destination folder for VM.
    - This parameter is case sensitive.
    - 'Example:'

    - '  folder: /folder1/folder2'
    type: str
  hardware:
    description:
    - Manage VM's hardware parameters. VM needs to be shut down to reconfigure these parameters.
    - 'Valid parameters are:'
    - ' - C(num_cpus) (integer): Number of CPUs.'
    - ' - C(num_cpu_cores_per_socket) (integer): Number of Cores Per Socket. C(num_cpus) has to be a multiple of C(num_cpu_cores_per_socket).'
    - ' - C(memory_mb) (integer): Amount of memory in MB.'
    type: dict
  disks:
    description:
    - A list of disks to add to VM.
    - All parameters are case sensitive.
    - Removing or detaching existing disks of VM is not supported.
    - 'Required parameters per entry:'
    - ' - C(size_[tb,gb,mb,kb,b]) (integer): Disk storage size in specified unit. VM needs to be shut down to reconfigure this parameter.'
    - 'Optional parameters per entry:'
    - ' - C(name) (string): Disk name. You can also use C(name_label) as an alias.'
    - ' - C(name_desc) (string): Disk description.'
    - ' - C(sr) (string): Storage Repository to create disk on. If not specified, will use default SR. Cannot be used for moving disk to other SR.'
    - ' - C(sr_uuid) (string): UUID of a SR to create disk on. Use if SR name is not unique.'
    type: list
    aliases: [ disk ]
  cdrom:
    description:
    - A CD-ROM configuration for the VM.
    - All parameters are case sensitive.
    - 'Valid parameters are:'
    - ' - C(type) (string): The type of CD-ROM, valid options are C(none) or C(iso). With C(none) the CD-ROM device will be present but empty.'
    - ' - C(iso_name) (string): The file name of an ISO image from one of the XenServer ISO Libraries (implies C(type: iso)).
          Required if C(type) is set to C(iso).'
    type: dict
  networks:
    description:
    - A list of networks (in the order of the NICs).
    - All parameters are case sensitive.
    - 'Required parameters per entry:'
    - ' - C(name) (string): Name of a XenServer network to attach the network interface to. You can also use C(name_label) as an alias.'
    - 'Optional parameters per entry (used for VM hardware):'
    - ' - C(mac) (string): Customize MAC address of the interface.'
    - 'Optional parameters per entry (used for OS customization):'
    - ' - C(type) (string): Type of IPv4 a