#!/usr/bin/env python

# Name:         vamp (VirtualBox/VBoxManage Ansible Module in Python)
# Version:      0.3.3
# Release:      1
# License:      CC-BA (Creative Commons By Attribution)
#               http://creativecommons.org/licenses/by/4.0/legalcode
# Group:        System
# Source:       N/A
# URL:          N/A
# Distribution: UNIX
# Vendor:       Lateral Blast
# Packager:     Richard Spindler <richard@lateralblast.com.au>
# Description:  VirtualBox/VBoxManage Ansible Module

from ansible.constants import mk_boolean
from ansible.module_utils.basic import *
import subprocess
import inspect
import os
import re

DOCUMENTATION = '''
---
module: vboxmanage
version_added: "post 2.8.0"
short_description: Automate VirtualBox command line
dewscription: 
  - Automate VirtualBox command line
options:
  dry-run:
    description:
      - Used with import to perform a dry run (don't import)
  options:
    description:
      - Used with clonevm, import, and export to provide more options to command line
  output:
    description:
      - Used with export to specifile the output file
  type:
    description:
      - Used with startvm to specify headles etc
  import:
    description:
      - Import VM
  export:
    description:
      - Export VM
  showvminfo:
    description:
      - Get VM information
  controlvm:
    description:
      - Control VM
  startvm:
    description:
      - Start VM
  modifyvm:
    description:
      - Modify VM parameters
  unregistervm:
    description:
      - Unregister VM
  registervm:
    description:
      - Register VM
  list:
    description:
      - List VMs and other resources
  param:
    description:
      - Used with get/set parameter function, e.g. modifyvm
  value:
    description:
      - Used with set parameter function, e.g. modifyvm
'''

EXAMPLES = '''
# Set VM memory
- vboxmanage: function=modify vmname=VM_NAME memory=4096 
# Start VM in headless mode
- vboxmanage: function=start vmname=VM_NAME type=headless
# Stop VM
- vboxmanage: function=control vmname=VM_NAME state=poweroff
# Export VM
- vboxmanage: function=export vmname=VMNAME output=VM_NAME-export.ova 
# Import VM
- vboxmanage: function=import filename=/path/to/VM_IMPORT.ova
'''

# Handle KVM list

def kvm_list(module):
  term = ""
  subroutine = inspect.stack()[0][3]
  if re.search("domain|vm", module.params['list']):
    term = "list"
  else:
    if re.search("domblk|domif", module.params['list']):
      term = "%slist" % (module.params['list'])
    else:
      term = "%s-list" % (module.params['list'])
  if module.params['search']:
    command = "virsh %s --all |grep %s" % (term, module.params['search'])
  else:
    command = "virsh %s --all" % (term)
  if module.params['search']:
    command = "virsh %s --all |grep '%s'" % (term, module.params['search'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle kvm control functions e.g. start, stop etc

def kvm_control(module):
  subroutine = inspect.stack()[0][3]
  if module.params['type'] == "pool":
    command = "virsh pool-%s %s" % (module.params['function'], module.params['poolname'])
  else:
    command = "virsh %s %s" % (module.params['function'], module.params['vmname'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle kvm detach

def kvm_detach(module):
  subroutine = inspect.stack()[0][3]
  command = "virsh %s --domain %s --type %s --mac %s" % (module.params['function'], module.params['vmname'], module.params['type'], module.params['mac'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)


# Handle kvm getproperty function, e.g. MAC address

def kvm_get_property(module):
  subroutine = inspect.stack()[0][3]
  if re.search("disk|block|blklist", module.params['type']):
    command = "virsh domblklist %s" % (module.params['vmname'])
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "target":
      command = "%s |grep -v Target |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "source":
      command = "%s |grep -v Target |awk '{print $2}'" % (command)
  if re.search("interface|iflist", module.params['type']) or module.params['getproperty'] == "mac":
    command = "virsh domiflist %s" % (module.params['vmname'])
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "interface":
      command = "%s |grep -v Interface |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "type":
      command = "%s |grep -v Interface |awk '{print $2}'" % (command)
    if module.params['getproperty'] == "source":
      command = "%s |grep -v Interface |awk '{print $3}'" % (command)
    if module.params['getproperty'] == "model":
      command = "%s |grep -v Interface |awk '{print $4}'" % (command)
    if module.params['getproperty'] == "mac":
      command = "%s |grep -v Interface |awk '{print $5}'" % (command)
  if re.search("vol", module.params['type']):
    command = "virsh vol-list %s" % module.params['poolname']
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "name":
      command = "%s |grep -v Target |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "path":
      command = "%s |grep -v Target |awk '{print $2}'" % (command)
  if re.search("pool", module.params['type']):
    command = "virsh pool-list"
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "name":
      command = "%s |grep -v State |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "state":
      command = "%s |grep -v State |awk '{print $2}'" % (command)
    if module.params['getproperty'] == "autostart":
      command = "%s |grep -v State |awk '{print $3}'" % (command)
  if re.search("snapshot", module.params['type']):
    command = "virsh snapshot-list %s" % (module.params['vmname'])
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "name":
      command = "%s |grep -v State |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "creation":
      command = "%s |grep -v State |awk '{print $2}'" % (command)
    if module.params['getproperty'] == "state":
      command = "%s |grep -v State |awk '{print $3}'" % (command)
  if re.search("secret", module.params['type']):
    command = "virsh secret-list"
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "uuid":
      command = "%s |grep -v UUID |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "creation":
      command = "%s |grep -v UUID |awk '{print $2}'" % (command)
  if re.search("checkpoint", module.params['type']):
    command = "virsh checkpoint-list %s" % (module.params['vmname'])
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "name":
      command = "%s |grep -v Creation |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "creation":
      command = "%s |grep -v Creation |awk '{print $2}'" % (command)
  if re.search("network", module.params['type']):
    command = ""
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "name":
      command = "%s |grep -v State |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "state":
      command = "%s |grep -v State |awk '{print $2}'" % (command)
    if module.params['getproperty'] == "autostart":
      command = "%s |grep -v State |awk '{print $3}'" % (command)
    if module.params['getproperty'] == "persistent":
      command = "%s |grep -v State |awk '{print $4}'" % (command)
  if re.search("nwfilter$", module.params['type']):
    command = "virsh nwfiler-list"
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "uuid":
      command = "%s |grep -v UUID |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "name":
      command = "%s |grep -v UUID |awk '{print $2}'" % (command)
  if re.search("nwfilter-binding", module.params['type']):
    command = "virsh nwfiler-binding-list"
    if module.params['search']:
      command = "%s |grep '%s'" % (command, module.params['search'])
    if module.params['getproperty'] == "port":
      command = "%s |grep -v UUID |awk '{print $1}'" % (command)
    if module.params['getproperty'] == "filter":
      command = "%s |grep -v UUID |awk '{print $2}'" % (command)
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle kvm modify functions e.g. setmem, setvcpus

def kvm_modify(module):
  subroutine = inspect.stack()[0][3] 
  if module.params['type'] == "pool":
    if re.search("define|create", module.params['function']):
      if module.params['print']:
        command = "virsh pool-define-as %s --print %s --type dir %s" % (module.params['poolname'], module.params['print'], module.params['target'])
      else:
        command = "virsh pool-define-as %s --type dir --target %s" % (module.params['poolname'], module.params['target'])
    else:
      command = "virsh pool-%s %s" % (module.params['function'], module.params['poolname'])
  else:
    if re.search("bridge",module.params['type']):
      if not module.params['mode']:
        module.params['mode'] = "bridge"
      if module.params['filename']:
        command = "virsh net-define %s" % (module.params['filename'])
        if not module.params['bridgename']:
          module.params['bridgename'] = module.params['bridge']
        if re.search("dump", module.params['function']):
          command = "virsh net-dumpxml %s > %s" % (module.params['bridgename'], module.params['filename'])
        else:
          if module.params['start'] == True:
            command = "%s ; virsh net-start %s" % (command, module.params['bridgename'])
          if module.params['autostart'] == True:
            command = "%s ; virsh net-autostart %s" % (command, module.params['bridgename'])
      else:
        if module.params['bridge'] or module.params['bridgename']:
          if not module.params['bridgename']:
            module.params['bridgename'] = module.params['bridge']
          filename = "/tmp/%s.xml" % (module.params['bridgename'])
          if re.search("delete|destroy|undefine", module.params['function']):
            command = "virsh net-undefine %s" % (module.params['bridgename'])
          else:
            filename = "/tmp/%s.xml" % (module.params['bridgename'])
            module.params['filename'] = filename
            bridge = "<network>\n"
            bridge = "%s  <name>%s</name>\n" % (bridge, module.params['bridgename'])
            if module.params['startport']:
              bridge = "%s    <nat>\n" % (bridge)
              bridge = "%s      <port start='%s' end='%s'/>\n" % (bridge, module.params['startport'], module.params['endport']) 
              bridge = "%s    </nat>\n"  % (bridge)
              bridge = "%s  </forward>\n" % (bridge) 
            else:
              bridge = "%s />\n" % (bridge)
            if module.params['uuid']:
              bridge = "%s  <uuid>%s</uuid>\n" % (bridge, module.params['uuid'])
            bridge = "%s  <forward mode='%s'/>\n" % (bridge, module.params['mode'])
            bridge = "%s  <bridge name='%s'" % (bridge, module.params['bridgename'])
            if module.params['macaddress']:
              bridge = "%s  <mac address='%s'/>\n" % (bridge, module.params['macaddress'])
            if module.params['ipaddress']:
              bridge = "%s  <ip address='%s' netmask='%s'/>\n" % (bridge, module.params['ipaddress'], module.params['netmask'])
            if module.params['stp']:
              bridge = "%s strp='%s'" % (bridge, module.params['stp'])
            if module.params['delay']:
              bridge = "%s delay='%s'" % (bridge, module.params['delay'])
            if module.params['bridgeip']:
              strings[counter] = "  <ip address='%s' netmask='%s'>\n" % (module.params['bridgeip'], module.params['bridgenetmask'])
            if module.params['dhcp'] == True:
                bridge = "%s    <dhcp>\n" % (bridge)
                if module.params['startip']:
                  bridge = "%s      <range start='%s' end='%s'/>\n" % (bridge, module.params['startip'], module.params['endip'])
                bridge = "%s    </dhcp>\n" % (bridge)
                bridge = "%s  </ip>\n" % (bridge)
            bridge  = "%s<network>\n" % (bridge)
            file = open(filename, "w")
            file.write(bridge)
            command = "virsh net-define %s" % (module.params['filename'])
            if module.params['start'] == True:
              command = "%s ; virsh net-start %s" % (command, module.params['bridgename'])
            if module.params['autostart'] == True:
              command = "%s ; virsh net-autostart %s" % (command, module.params['bridgename'])
    else:
      if re.search("rename",module.params['function']):
        command = "virsh %s %s %s" % (module.params['function'], module.params['vmname'], module.params['newname'])
      else:
        if module.params['filename']:
          command = "virsh %s %s" % (module.params['function'], module.params['filename'])
        else:
          if module.params['remove-all-storage'] == True:
            command = "virsh %s %s --remove-all-storage" % (module.params['function'], module.params['vmname'])
          else:
            command = "virsh %s %s" % (module.params['function'], module.params['vmname'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle kvm convert and other image functions

def kvm_image(module):
  subroutine = inspect.stack()[0][3]
  if module.params['function'] == "import":
    command = "virt-v2v -i %s %s -o libvirt -of %s -os %s -n %s" % (module.params['type'], module.params['filename'], module.params['format'], module.params['poolname'], module.params['network'])
  if module.params['function'] == "cloud-localds":
    if module.params['network-config']:
      if re.search("[a-z]|[A-Z]|[0-9]",module.params['network-config']):
        command = "%s --network-config %s %s %s" % (module.params['function'], module.params['network-config'], module.params['outputfile'], module.params['cloud-config'])
    else:
      command = "%s %s %s" % (module.params['function'], module.params['outputfile'], module.params['cloud-config'])
  if module.params['function'] == "convert":
    command = "qemu-img %s -f %s -O %s %s %s" % (module.params['function'], module.params['format'], module.params['format'], module.params['inputfile'], module.params['outputfile'])
  if module.params['function'] == "resize":
    command = "qemu-img %s %s %s" % (module.params['function'], module.params['inputfile'], module.params['size'])
  if module.params['function'] == "customize":
    command = "virt-customize %s %s" % (module.params['function'], module.params['intputfile'])
    if re.search("[a-z]|[A-Z]|[0-9]",module.params['root-password']):
      command = "%s --root-password password:%s" % (command, module.params['root-password'])
    if re.search("[a-z]|[A-Z]|[0-9]",module.params['uninstall']):
      command = "%s --uninstall%s" % (command, module.params['root-password'])
    if re.search("[a-z]",module.params['options']):
      command = "%s %s" % (command, module.params['options'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle KVM install

def kvm_install(module):
  subroutine = inspect.stack()[0][3]
  command = "virt-install"
  for option in [ "name", "vcpus", "memory", "cdrom", "cpu", "os-type", "os-variant", "host-device", "machine", "pxe", 
                  "import", "extra-args", "connect", "metadata", "initrd-inject", "unattended", "install", "boot", "idmap",
                  "disk", "network", "graphics", "controller", "input", "serial", "parallel", "channel", "console", "hostdev",
                  "filesystem", "sound", "watchdog", "video", "smartcard", "redirdev", "memballoon", "tpm", "rng", "panic",
                  "memdev", "vsock", "iothreads", "seclabel", "cputune", "memtune", "blkiotune", "memorybacking", "features",
                  "clock", "pm", "events", "resource", "sysinfo", "qemu-commandline", "launchSecurity", "hvm", "paravirt",
                  "container", "virt-type", "arch", "machine", "autostart", "transient", "destroy-on-exit", "wait",
                  "noautoconsole", "noreboot", "print-xml", "dry-run", "check", "virt-type" ]:
    if module.params[option]:
      if option == "disk":
        if re.search(" ", module.params[option]):
          if not re.search("--disk", module.params[option]):
            disks = module.params["disk"].replace(" ", " --disk ")
            module.params["disk"] = disks
      if re.search("[a-z]|[A-Z]|[0-9]", module.params[option]):
        if module.params[option] == True or re.search("True",module.params[option]):
          command = "%s --%s" % (command, option)
        else:
          command = "%s --%s %s" % (command, option, module.params[option])
  if module.params['options']:
    if re.search("[a-z]",module.params['options']):
      command = "%s %s" % (command, module.params['options'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle simple VirtualBox functions like version

def vbox_other(module):
  subroutine = inspect.stack()[0][3]
  command = "vboxmanage --%s" % (module.params['function'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Import VirtualBox VM

def vbox_image(module):
  subroutine = inspect.stack()[0][3]
  if module.params['dry-run'] == True and module.params['function'] == "import":
    dryrun = "--dry-run"
    command = "vboxmanage %s %s %s" % (module.params['function'], module.params['filename'], dryrun)
  else:
    if module.params['function'] == "import":
      command = "vboxmanage %s %s" % (module.params['function'], module.params['filename'])
    else:
      command = "vboxmanage %s %s --output %s" % (module.params['function'], module.params['vmname'], module.params['filename'])
  for param in module.params:
    if not re.search("vmname|function|list|machinereadable|filename|execute|dry-run|delete|import|export|engine", param):
      value = module.params[param]
      if value != None:
        command = "%s --%s %s" % (command, param, value)
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Get VirtualBox property

def vbox_get_property(module):
  subroutine = inspect.stack()[0][3]
  if not module.params['param'] == None:
    if module.params['function'] == "getproperty":
      command = 'vboxmanage showvminfo %s |grep -i "%s"' % (module.params['vmname'], module.params['param'])
    else:
      command = "vboxmanage %s %s %s" % (module.params['function'], module.params['vmname'], module.params['param'])
  else:
    command = "vboxmanage %s %s" % (module.params['function'], module.params['vmname'])
    for param in module.params:
      if not re.search("vmname|function|list|machinereadable|execute|dry-run|delete|engine", param):
        value = module.params[param]
        if value != None:
          if value == True:
            value = "yes"
          if value == False:
            value = "no"
          command = "%s %s" % (command, param)
  if module.params['search']:
    command = '%s |grep -i "%s"' % (command, module.params['search'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Set VirtualBox property

def vbox_set_property(module):
  subroutine = inspect.stack()[0][3]
  if not module.params['param'] == None:
    command = "vboxmanage %s %s %s %s" % (module.params['function'], module.params['vmname'], module.params['param'], module.params['value'])
  else:
    command = "vboxmanage %s %s" % (module.params['function'], module.params['vmname'])
    for param in module.params:
      if not re.search("vmname|function|list|machinereadable|execute|dry-run|delete|engine", param):
        value = module.params[param]
        if value != None:
          if value == True:
            value = "yes"
          if value == False:
            value = "no"
          command = "%s %s %s" % (command, param, value)
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Control VirtualBox VM

def vbox_control(module):
  subroutine = inspect.stack()[0][3]
  if module.params['state']:
    command = "vboxmanage %s %s %s" % (module.params['function'], module.params['vmname'], module.params['state'])
  else:
    if module.params['param']:
      command = "%s %s %s %s" % (module.params['function'], module.params['vmname'], module.params['param'], module.params['value'])
    else:
      command = "vboxmanage %s %s" % (module.params['function'], module.params['vmname'])
      for param in module.params:
        if not re.search("vmname|function|list|machinereadable|execute|dry-run|delete|engine", param):
          value = module.params[param]
          if value != None:
            if value == True:
              value = "yes"
            if value == False:
              value = "no"
            command = "%s %s %s" % (command, param, value)
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle VirtualBox list function

def vbox_list(module):
  command = "vboxmanage %s %s" % (module.params['function'], module.params['list'])
  subroutine = inspect.stack()[0][3]
  if module.params['search']:
    command = '%s |grep -i "%s"' % (command, module.params['search'])
  else:
    if module.params['param']:
      command = '%s |grep -i "%s"' % (command, module.params['param'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle VirtualBox mediumproperty function

def vbox_medium_property(module):
  subroutine = inspect.stack()[0][3]
  if module.params['function'] == "checkmediumpwd":
    command = "vboxmanage %s %s %s" % (module.params['function'], module.params['filename'], module.params['passwordfile'])
  else:
    if module.params['action'] == "set":
      command = "vboxmanage %s %s %s %s %s %s" % (module.params['function'], module.params['device'], module.params['action'], module.params['filename'], module.params['property'], module.params['value'])
    else:
      command = "vboxmanage %s %s %s %s %s" % (module.params['function'], module.params['device'], module.params['action'], module.params['filename'], module.params['property'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)


# Handle VirtualBox createmedium function

def vbox_modify_medium(module):
  subroutine = inspect.stack()[0][3]
  if module.params['function'] == "createmedium":
    command = "vboxmanage %s %s --filename %s" % (module.params['function'], module.params['device'], module.params['filename'])
  else:
    if module.params['function'] == "convertfromraw":
      command = "vboxmanage %s %s %s" % (module.params['function'], module.params['inputfile'], module.params['outputfile'])
    else:
      if module.params['function'] == "clonemedium":
        command = "vboxmanage %s %s %s %s" % (module.params['function'], module.params['device'], module.params['inputfile'], module.params['outputfile'])
      else:
        command = "vboxmanage %s %s %s" % (module.params['function'], module.params['device'], module.params['filename'])
  for param in module.params:
    if not re.search("vmname|function|list|machinereadable|execute|dry-run|delete|engine", param):
      value = module.params[param]
      if value != None and value != False:
        if module.params['function'] == "convertfromraw":
          command = "%s --%s %s" % (command, param, value)
        else:
          command = "%s %s %s" % (command, param, value)
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle VirtualBox closemedium function

def vbox_close_medium(module):
  subroutine = inspect.stack()[0][3]
  if module.params['uuid'] != None:
    module.params['filename'] = module.params['uuid']
  if module.params['delete'] == True:
    command = "vboxmanage %s %s %s --delete" % (module.params['function'], module.params['device'], module.params['filename'])
  else:
    command = "vboxmanage %s %s %s" % (module.params['function'], module.params['device'], module.params['filename'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle VirtualBox unregistervm function

def vbox_register(module):
  subroutine = inspect.stack()[0][3]
  if module.params['function'] == "unregistervm":
    command = "vboxmanage %s %s --delete" % (module.params['function'], module.params['filename'])
  else:
    if module.params['delete'] == True:
      command = "vboxmanage %s %s --delete" % (module.params['function'], module.params['vmname'])
    else:
      command = "vboxmanage %s %s" % (module.params['function'], module.params['vmname'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle other VirtualBox functions

def vbox_function(module):
  command = ""
  subroutine = inspect.stack()[0][3]
  if module.params['param'] != None:
    if module.params['function'] == "showvminfo":
      command = "vboxmanage %s %s |grep -i %s" % (module.params['function'], module.params['vmname'], module.params['param'])
    else:
      command = "vboxmanage %s %s --%s %s" % (module.params['function'], module.params['vmname'], module.params['param'], module.params['value'])
  else:
    if re.search("dhcpsever|extpack", module.params['function']):
      command = "vboxmanage %s %s" % (module.params['function'], module.params['action'])
    else:
      if re.search("snapshot|debugvm", module.params['function']):
        command = "vboxmanage %s %s %s" % (module.params['function'], module.params['vmname'], module.params['action'])
      else:
        if re.search("encryptmedium", module.params['function']):
          command = "vboxmanage %s %s" % (module.params['function'], module.params['filename'])
        else:
          command = "vboxmanage %s %s" % (module.params['function'], module.params['vmname'])
    for param in module.params:
      if not re.search("vmname|function|list|machinereadable|execute|dry-run|delete|export|filename|action|engine", param):
        value = module.params[param]
        if value != None:
          if re.search("removeonsuspend|active|remote|allowlocallogon", param):
            command = "%s --%s" % (command, param)
          else:
            if value == True:
              value = "yes"
            if value == False:
              value = "no"
            if param == "set" or param == "add":
              command = "%s %s %s" % (command, param, value)
            else:
              if re.search("dhcpserver|clonevm", module.params['function']):
                command = "%s --%s=%s" % (command, param, value)
              else:
                command = "%s --%s %s" % (command, param, value)
  if module.params['suffix']:
    command = "%s %s" % (command, module.params['suffix'])
  if module.params['search']:
    command = '%s |grep -i "%s"' % (command, module.params['search'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)

# Handle VirtualBox unregistervm function

def qemu_image(module):
  subroutine = inspect.stack()[0][3]
  if module.params['function'] == "info":
    command = "qemu-img %s %s" % (module.params['function'], module.params['filename'])
  else:
    if module.params['function'] == "resize":
      command = "qemu-img %s %s %s" % (module.params['function'], module.params['filename'], module.params['size'])
    else:
      if module.params['function'] == "convert":
        command = "qemu-img %s -f %s %s" % (module.params['function'], module.params['filename'], module.params['output'])
  if module.params['search']:
    command = '%s |grep -i "%s"' % (command, module.params['search'])
  if module.params['execute'] == True:
    process = subprocess.run(command, shell = True, universal_newlines = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
    return(process.stdout, process.stderr, process.returncode, command, subroutine)
  else:
    return("", "", 0, command, subroutine)


# Main routine - Get anisible module parameters, call functions and exit

def main():
  fields = {
    'engine':                     { 'default': None,   'type': 'str' },
    'accelerate2dvideo':          { 'default': None,   'type': 'str' },
    'accelerate3d':               { 'default': None,   'type': 'str' },
    'action':                     { 'default': None,   'type': 'str' },
    'active':                     { 'default': None,   'type': 'str' },
    'acpi':                       { 'default': None,   'type': 'str' },
    'add':                        { 'default': None,   'type': 'str' },
    'address':                    { 'default': None,   'type': 'str' },
    'allowlocallogon':            { 'default': None,   'type': 'str' },
    'apic':                       { 'default': None,   'type': 'str' },
    'arch':                       { 'default': None,   'type': 'str' },
    'arg0':                       { 'default': None,   'type': 'str' },
    'audio':                      { 'default': None,   'type': 'str' },
    'audioin':                    { 'default': None,   'type': 'str' },
    'audioout':                   { 'default': None,   'type': 'str' },
    'audiocontroller':            { 'default': None,   'type': 'str' },
    'audiocodec':                 { 'default': None,   'type': 'str' },
    'autostart':                  { 'default': True,   'type': 'bool' },
    'autostartdbpath':            { 'default': None,   'type': 'str' },
    'autostart-delay':            { 'default': None,   'type': 'str' },
    'autostart-enabled':          { 'default': None,   'type': 'str' },
    'backend':                    { 'default': None,   'type': 'str' },
    'basefolder':                 { 'default': None,   'type': 'str' },
    'bandwidthgroup':             { 'default': None,   'type': 'str' },
    'basefolder':                 { 'default': None,   'type': 'str' },
    'biosapic':                   { 'default': None,   'type': 'str' },
    'biosbootmenu':               { 'default': None,   'type': 'str' },
    'bioslogodisplaytime':        { 'default': None,   'type': 'str' },
    'bioslogofadein':             { 'default': None,   'type': 'str' },
    'biospxedebug':               { 'default': None,   'type': 'str' },
    'bioslogoimagepath':          { 'default': None,   'type': 'str' },
    'biossystemtimeoffset':       { 'default': None,   'type': 'str' },
    'blkiotune':                  { 'default': None,   'type': 'str' },
    'boot':                       { 'default': None,   'type': 'str' },
    'boot1':                      { 'default': None,   'type': 'str' },
    'boot2':                      { 'default': None,   'type': 'str' },
    'boot3':                      { 'default': None,   'type': 'str' },
    'boot4':                      { 'default': None,   'type': 'str' },
    'bootable':                   { 'default': None,   'type': 'str' },
    'bridge':                     { 'default': None,   'type': 'str' },
    'bridgeip':                   { 'default': None,   'type': 'str' },
    'bridgemac':                  { 'default': None,   'type': 'str' },
    'bridgename':                 { 'default': None,   'type': 'str' },
    'bridgenetmask':              { 'default': None,   'type': 'str' },
    'cableconnected1':            { 'default': None,   'type': 'str' },
    'cableconnected2':            { 'default': None,   'type': 'str' },
    'cableconnected3':            { 'default': None,   'type': 'str' },
    'cableconnected4':            { 'default': None,   'type': 'str' },
    'cdrom':                      { 'default': None,   'type': 'str' },
    'channel':                    { 'default': None,   'type': 'str' },
    'check':                      { 'default': None,   'type': 'str' },
    'chipset':                    { 'default': None,   'type': 'str' },
    'cipher':                     { 'default': None,   'type': 'str' },
    'clipboard-mode':             { 'default': None,   'type': 'str' },
    'closesession':               { 'default': None,   'type': 'str' },
    'clock':                      { 'default': None,   'type': 'str' },
    'cloud':                      { 'default': None,   'type': 'str' },
    'cloud-config':               { 'default': None,   'type': 'str' },
    'cloudinstanceid':            { 'default': None,   'type': 'str' },
    'cloudbucket':                { 'default': None,   'type': 'str' },
    'cloudkeepobject':            { 'default': None,   'type': 'str' },
    'clouddisksize':              { 'default': None,   'type': 'str' },
    'clouddomain':                { 'default': None,   'type': 'str' },
    'cloudlaunchinstance':        { 'default': None,   'type': 'str' },
    'cloudlaunchmode':            { 'default': None,   'type': 'str' },
    'cloudocivcn':                { 'default': None,   'type': 'str' },
    'cloudocisubnet':             { 'default': None,   'type': 'str' },
    'cloudprivateip':             { 'default': None,   'type': 'str' },
    'cloudpublicip':              { 'default': None,   'type': 'str' },
    'cloudshape':                 { 'default': None,   'type': 'str' },
    'comment':                    { 'default': None,   'type': 'str' },
    'connect':                    { 'default': None,   'type': 'str' },
    'console':                    { 'default': None,   'type': 'str' },
    'container':                  { 'default': None,   'type': 'str' },
    'controller':                 { 'default': None,   'type': 'str' },
    'copyfrom':                   { 'default': None,   'type': 'str' },
    'copyto':                     { 'default': None,   'type': 'str' },
    'cpu-profile':                { 'default': None,   'type': 'str' },
    'cpuexecutioncap':            { 'default': None,   'type': 'str' },
    'cpuhotplug':                 { 'default': None,   'type': 'str' },
    'cpuid':                      { 'default': None,   'type': 'str' },
    'cpu':                        { 'default': None,   'type': 'str' },
    'cpus':                       { 'default': None,   'type': 'str' },
    'cputune':                    { 'default': None,   'type': 'str' },
    'createdir':                  { 'default': None,   'type': 'str' },
    'createdirectory':            { 'default': None,   'type': 'str' },
    'createtemp':                 { 'default': None,   'type': 'str' },
    'createtemporary':            { 'default': None,   'type': 'str' },
    'default-lease-time':         { 'default': None,   'type': 'str' },
    'defaultfrontend':            { 'default': None,   'type': 'str' },
    'delay':                      { 'default': None,   'type': 'str' },
    'delete':                     { 'default': False,  'type': 'bool' },
    'description':                { 'default': None,   'type': 'str' },
    'destroy-on-exit':            { 'default': None,   'type': 'str' },
    'device':                     { 'default': None,   'type': 'str' },
    'dhcp':                       { 'default': False,  'type': 'bool' },
    'disable':                    { 'default': None,   'type': 'str' },
    'discard':                    { 'default': None,   'type': 'str' },
    'disk':                       { 'default': None,   'type': 'str' },
    'disk1':                      { 'default': None,   'type': 'str' },
    'disk2':                      { 'default': None,   'type': 'str' },
    'domain':                     { 'default': None,   'type': 'str' },
    'draganddrop':                { 'default': None,   'type': 'str' },
    'dry-run':                    { 'default': False,  'type': 'bool' },
    'enable':                     { 'default': None,   'type': 'str' },
    'encodedlun':                 { 'default': None,   'type': 'str' },
    'endip':                      { 'default': None,   'type': 'str' },
    'endport':                    { 'default': None,   'type': 'str' },
    'eula':                       { 'default': None,   'type': 'str' },
    'eulafile':                   { 'default': None,   'type': 'str' },
    'events':                     { 'default': None,   'type': 'str' },
    'excl-mac':                   { 'default': None,   'type': 'str' },
    'excl-mac-wild':              { 'default': None,   'type': 'str' },
    'exe':                        { 'default': None,   'type': 'str' },
    'execute':                    { 'default': True,   'type': 'bool' },
    'export':                     { 'default': True,   'type': 'str' },
    'extra-args':                 { 'default': None,   'type': 'str' },
    'extpack':                    { 'default': None,   'type': 'str' },
    'features':                   { 'default': None,   'type': 'str' },
    'filename':                   { 'default': None,   'type': 'str' },
    'filesystem':                 { 'default': None,   'type': 'str' },
    'firmware':                   { 'default': None,   'type': 'str' },
    'fixed-address':              { 'default': None,   'type': 'str' },
    'follow':                     { 'default': None,   'type': 'str' },
    'force-opt':                  { 'default': None,   'type': 'str' },
    'forceunmount':               { 'default': None,   'type': 'str' },
    'format':                     { 'default': None,   'type': 'str' },
    'from':                       { 'default': None,   'type': 'str' },
    'function':                   { 'default': 'list', 'type': 'str' },
    'get':                        { 'default': None,   'type': 'str' },
    'getproperty':                { 'default': None,   'type': 'str' },
    'global':                     { 'default': None,   'type': 'str' },
    'graphics':                   { 'default': None,   'type': 'str' },
    'graphicscontroller':         { 'default': None,   'type': 'str' },
    'group':                      { 'default': None,   'type': 'str' },
    'groups':                     { 'default': None,   'type': 'str' },
    'guestmemoryballoon':         { 'default': None,   'type': 'str' },
    'hardwareuuid':               { 'default': None,   'type': 'str' },
    'host-device':                { 'default': None,   'type': 'str' },
    'hostdev':                    { 'default': None,   'type': 'str' },
    'hostiocache':                { 'default': None,   'type': 'str' },
    'hotpluggable':               { 'default': None,   'type': 'str' },
    'hpet':                       { 'default': None,   'type': 'str' },
    'hvm':                        { 'default': None,   'type': 'str' },
    'hwvirtex':                   { 'default': None,   'type': 'str' },
    'hwvirtexclusive':            { 'default': None,   'type': 'str' },
    'idmap':                      { 'default': None,   'type': 'str' },
    'iconfile':                   { 'default': None,   'type': 'str' },
    'ignore-operhaned-processes': { 'default': None,   'type': 'str' },
    'import':                     { 'default': None,   'type': 'str' },
    'incl-mac':                   { 'default': None,   'type': 'str' },
    'incl-mac-wild':              { 'default': None,   'type': 'str' },
    'initiator':                  { 'default': None,   'type': 'str' },
    'initrd-inject':              { 'default': None,   'type': 'str' },
    'input':                      { 'default': None,   'type': 'str' },
    'inputfile':                  { 'default': None,   'type': 'str' },
    'install':                    { 'default': None,   'type': 'str' },
    'interface':                  { 'default': None,   'type': 'str' },
    'intnet':                     { 'default': None,   'type': 'str' },
    'intnet1':                    { 'default': None,   'type': 'str' },
    'intnet2':                    { 'default': None,   'type': 'str' },
    'intnet3':                    { 'default': None,   'type': 'str' },
    'intnet4':                    { 'default': None,   'type': 'str' },
    'iothreads':                  { 'default': None,   'type': 'str' },
    'ipaddress':                  { 'default': None,   'type': 'str' },
    'ipv4':                       { 'default': None,   'type': 'str' },
    'ipv6':                       { 'default': None,   'type': 'str' },
    'keyboard':                   { 'default': None,   'type': 'str' },
    'largepages':                 { 'default': None,   'type': 'str' },
    'launchSecurity':             { 'default': None,   'type': 'str' },
    'legacy09':                   { 'default': None,   'type': 'str' },
    'list':                       { 'default': 'vms',  'type': 'str' },
    'loghistorycount':            { 'default': None,   'type': 'str' },
    'logginglevel':               { 'default': None,   'type': 'str' },
    'longmode':                   { 'default': None,   'type': 'str' },
    'loopback-4':                 { 'default': None,   'type': 'str' },
    'loopback-6':                 { 'default': None,   'type': 'str' },
    'lower-ip':                   { 'default': None,   'type': 'str' },
    'lpt1':                       { 'default': None,   'type': 'str' },
    'lpt2':                       { 'default': None,   'type': 'str' },
    'lpt3':                       { 'default': None,   'type': 'str' },
    'lpt4':                       { 'default': None,   'type': 'str' },
    'lptmode1':                   { 'default': None,   'type': 'str' },
    'lptmode2':                   { 'default': None,   'type': 'str' },
    'lptmode3':                   { 'default': None,   'type': 'str' },
    'lptmode4':                   { 'default': None,   'type': 'str' },
    'lun':                        { 'default': None,   'type': 'str' },
    'macaddress':                 { 'default': None,   'type': 'str' },
    'macaddress1':                { 'default': None,   'type': 'str' },
    'macaddress2':                { 'default': None,   'type': 'str' },
    'macaddress3':                { 'default': None,   'type': 'str' },
    'macaddress4':                { 'default': None,   'type': 'str' },
    'machine':                    { 'default': None,   'type': 'str' },
    'machinefolder':              { 'default': None,   'type': 'str' },
    'machinereadable':            { 'default': False,  'type': 'bool' },
    'manufacturer':               { 'default': None,   'type': 'str' },
    'maskedinterfaces':           { 'default': None,   'type': 'str' },
    'max-lease-time':             { 'default': None,   'type': 'str' },
    'medium':                     { 'default': None,   'type': 'str' },
    'memballoon':                 { 'default': None,   'type': 'str' },
    'memdev':                     { 'default': None,   'type': 'str' },
    'memory':                     { 'default': None,   'type': 'str' },
    'memorybacking':              { 'default': None,   'type': 'str' },
    'memtune':                    { 'default': None,   'type': 'str' },
    'metadata':                   { 'default': None,   'type': 'str' },
    'min-lease-time':             { 'default': None,   'type': 'str' },
    'mkdir':                      { 'default': None,   'type': 'str' },
    'mktemp':                     { 'default': None,   'type': 'str' },
    'mouse':                      { 'default': None,   'type': 'str' },
    'mode':                       { 'default': None,   'type': 'str' },
    'move':                       { 'default': None,   'type': 'str' },
    'mtype':                      { 'default': None,   'type': 'str' },
    'mv':                         { 'default': None,   'type': 'str' },
    'name':                       { 'default': None,   'type': 'str' },
    'nataliasmode1':              { 'default': None,   'type': 'str' },
    'nataliasmode2':              { 'default': None,   'type': 'str' },
    'nataliasmode3':              { 'default': None,   'type': 'str' },
    'nataliasmode4':              { 'default': None,   'type': 'str' },
    'natbindip1':                 { 'default': None,   'type': 'str' },
    'natbindip2':                 { 'default': None,   'type': 'str' },
    'natbindip3':                 { 'default': None,   'type': 'str' },
    'natbindip4':                 { 'default': None,   'type': 'str' },
    'natdnshostresolver1':        { 'default': None,   'type': 'str' },
    'natdnshostresolver2':        { 'default': None,   'type': 'str' },
    'natdnshostresolver3':        { 'default': None,   'type': 'str' },
    'natdnshostresolver4':        { 'default': None,   'type': 'str' },
    'natdnspassdomain1':          { 'default': None,   'type': 'str' },
    'natdnspassdomain2':          { 'default': None,   'type': 'str' },
    'natdnspassdomain3':          { 'default': None,   'type': 'str' },
    'natdnspassdomain4':          { 'default': None,   'type': 'str' },
    'natproxy1':                  { 'default': None,   'type': 'str' },
    'natproxy2':                  { 'default': None,   'type': 'str' },
    'natproxy3':                  { 'default': None,   'type': 'str' },
    'natproxy4':                  { 'default': None,   'type': 'str' },
    'natnet1':                    { 'default': None,   'type': 'str' },
    'natnet2':                    { 'default': None,   'type': 'str' },
    'natnet3':                    { 'default': None,   'type': 'str' },
    'natnet4':                    { 'default': None,   'type': 'str' },
    'natpf1':                     { 'default': None,   'type': 'str' },
    'natpf2':                     { 'default': None,   'type': 'str' },
    'natpf3':                     { 'default': None,   'type': 'str' },
    'natpf4':                     { 'default': None,   'type': 'str' },
    'nattftpfile1':               { 'default': None,   'type': 'str' },
    'nattftpfile2':               { 'default': None,   'type': 'str' },
    'nattftpfile3':               { 'default': None,   'type': 'str' },
    'nattftpfile4':               { 'default': None,   'type': 'str' },
    'nattftpprefix1':             { 'default': None,   'type': 'str' },
    'nattftpprefix2':             { 'default': None,   'type': 'str' },
    'nattftpprefix3':             { 'default': None,   'type': 'str' },
    'nattftpprefix4':             { 'default': None,   'type': 'str' },
    'nattftpserver1':             { 'default': None,   'type': 'str' },
    'nattftpserver2':             { 'default': None,   'type': 'str' },
    'nattftpserver3':             { 'default': None,   'type': 'str' },
    'nattftpserver4':             { 'default': None,   'type': 'str' },
    'natsettings1':               { 'default': None,   'type': 'str' },
    'natsettings2':               { 'default': None,   'type': 'str' },
    'natsettings3':               { 'default': None,   'type': 'str' },
    'natsettings4':               { 'default': None,   'type': 'str' },
    'nested-hw-virt':             { 'default': None,   'type': 'str' },
    'nestedpaging':               { 'default': None,   'type': 'str' },
    'netmask':                    { 'default': None,   'type': 'str' },
    'netname':                    { 'default': None,   'type': 'str' },
    'network':                    { 'default': None,   'type': 'str' },
    'network-config':             { 'default': None,   'type': 'str' },
    'newname':                    { 'default': None,   'type': 'str' },
    'newpassword':                { 'default': None,   'type': 'str' },
    'newpasswordid':              { 'default': None,   'type': 'str' },
    'nic1':                       { 'default': None,   'type': 'str' },
    'nic2':                       { 'default': None,   'type': 'str' },
    'nic3':                       { 'default': None,   'type': 'str' },
    'nic4':                       { 'default': None,   'type': 'str' },
    'nicgenericdrv1':             { 'default': None,   'type': 'str' },
    'nicgenericdrv2':             { 'default': None,   'type': 'str' },
    'nicgenericdrv3':             { 'default': None,   'type': 'str' },
    'nicgenericdrv4':             { 'default': None,   'type': 'str' },
    'nictrace1':                  { 'default': None,   'type': 'str' },
    'nictrace2':                  { 'default': None,   'type': 'str' },
    'nictrace3':                  { 'default': None,   'type': 'str' },
    'nictrace4':                  { 'default': None,   'type': 'str' },
    'nictracefile1':              { 'default': None,   'type': 'str' },
    'nictracefile2':              { 'default': None,   'type': 'str' },
    'nictracefile3':              { 'default': None,   'type': 'str' },
    'nictracefile4':              { 'default': None,   'type': 'str' },
    'nictype1':                   { 'default': None,   'type': 'str' },
    'nictype2':                   { 'default': None,   'type': 'str' },
    'nictype3':                   { 'default': None,   'type': 'str' },
    'nictype4':                   { 'default': None,   'type': 'str' },
    'nonrotational':              { 'default': None,   'type': 'str' },
    'noautoconsole':              { 'default': None,   'type': 'str' },
    'noreboot':                   { 'default': None,   'type': 'str' },
    'numatune':                   { 'default': None,   'type': 'str' },
    'oldpassword':                { 'default': None,   'type': 'str' },
    'options':                    { 'default': None,   'type': 'str' },
    'ostype':                     { 'default': None,   'type': 'str' },
    'os-type':                    { 'default': None,   'type': 'str' },
    'os-variant':                 { 'default': None,   'type': 'str' },
    'output':                     { 'default': None,   'type': 'str' },
    'outputfile':                 { 'default': None,   'type': 'str' },
    'ovf09':                      { 'default': None,   'type': 'str' },
    'ovf10':                      { 'default': None,   'type': 'str' },
    'ovf20':                      { 'default': None,   'type': 'str' },
    'opc10':                      { 'default': None,   'type': 'str' },
    'pae':                        { 'default': None,   'type': 'str' },
    'pagefusion':                 { 'default': None,   'type': 'str' },
    'panic':                      { 'default': None,   'type': 'str' },
    'password':                   { 'default': None,   'type': 'str' },
    'passwordfile':               { 'default': None,   'type': 'str' },
    'parallel':                   { 'default': None,   'type': 'str' },
    'paravirt':                   { 'default': None,   'type': 'str' },
    'paravirtprovider':           { 'default': None,   'type': 'str' },
    'paravirtdebug':              { 'default': None,   'type': 'str' },
    'path':                       { 'default': None,   'type': 'str' },
    'param':                      { 'default': None,   'type': 'str' },
    'passthrough':                { 'default': None,   'type': 'str' },
    'pciattach':                  { 'default': None,   'type': 'str' },
    'pcidetach':                  { 'default': None,   'type': 'str' },
    'plugcpu':                    { 'default': None,   'type': 'str' },
    'pm':                         { 'default': None,   'type': 'str' },
    'pool':                       { 'default': None,   'type': 'str' },
    'poolname':                   { 'default': None,   'type': 'str' },
    'port-forward-4':             { 'default': None,   'type': 'str' },
    'port-forward-6':             { 'default': None,   'type': 'str' },
    'portcount':                  { 'default': None,   'type': 'str' },
    'print':                      { 'default': None,   'type': 'str' },
    'print-xml':                  { 'default': None,   'type': 'str' },
    'program':                    { 'default': None,   'type': 'str' },
    'product':                    { 'default': None,   'type': 'str' },
    'profile':                    { 'default': None,   'type': 'str' },
    'productid':                  { 'default': None,   'type': 'str' },
    'producturl':                 { 'default': None,   'type': 'str' },
    'property':                   { 'default': None,   'type': 'str' },
    'proxymode':                  { 'default': None,   'type': 'str' },
    'proxyurl':                   { 'default': None,   'type': 'str' },
    'putenv':                     { 'default': None,   'type': 'str' },
    'pxe':                        { 'default': None,   'type': 'str' },
    'qemu-commandline':           { 'default': None,   'type': 'str' },
    'unplugcpu':                  { 'default': None,   'type': 'str' },
    'recording':                  { 'default': None,   'type': 'str' },
    'recordingscreens':           { 'default': None,   'type': 'str' },
    'recordingfile':              { 'default': None,   'type': 'str' },
    'recordingmaxsize':           { 'default': None,   'type': 'str' },
    'recordingmaxtime':           { 'default': None,   'type': 'str' },
    'recordingopts':              { 'default': None,   'type': 'str' },
    'recordingvideofps':          { 'default': None,   'type': 'str' },
    'recordingvideorate':         { 'default': None,   'type': 'str' },
    'recordingvideores':          { 'default': None,   'type': 'str' },
    'recursive':                  { 'default': None,   'type': 'str' },
    'redirdev':                   { 'default': None,   'type': 'str' },
    'register':                   { 'default': None,   'type': 'str' },
    'remote':                     { 'default': None,   'type': 'str' },
    'remove':                     { 'default': None,   'type': 'str' },
    'remove-all-storage':         { 'default': True,   'type': 'bool' },
    'removedir':                  { 'default': None,   'type': 'str' },
    'removedirectory':            { 'default': None,   'type': 'str' },
    'removefile':                 { 'default': None,   'type': 'str' },
    'removeonsuspend':            { 'default': None,   'type': 'str' },
    'ren':                        { 'default': None,   'type': 'str' },
    'rename':                     { 'default': None,   'type': 'str' },
    'resource':                   { 'default': None,   'type': 'str' },
    'revision':                   { 'default': None,   'type': 'str' },
    'rm':                         { 'default': None,   'type': 'str' },
    'rmdir':                      { 'default': None,   'type': 'str' },
    'rng':                        { 'default': None,   'type': 'str' },
    'root-password':              { 'default': None,   'type': 'str' },
    'rtcuseutc':                  { 'default': None,   'type': 'str' },
    'run':                        { 'default': None,   'type': 'str' },
    'screenshotpng':              { 'default': None,   'type': 'str' },
    'search':                     { 'default': None,   'type': 'str' },
    'seclabel':                   { 'default': None,   'type': 'str' },
    'serial':                     { 'default': None,   'type': 'str' },
    'serialnumber':               { 'default': None,   'type': 'str' },
    'server':                     { 'default': None,   'type': 'str' },
    'server-ip':                  { 'default': None,   'type': 'str' },
    'session-id':                 { 'default': None,   'type': 'str' },
    'session-name':               { 'default': None,   'type': 'str' },
    'set-opt':                    { 'default': None,   'type': 'str' },
    'set-opt-hex':                { 'default': None,   'type': 'str' },
    'setscreenlayout':            { 'default': None,   'type': 'str' },
    'setparentuuid':              { 'default': None,   'type': 'str' },
    'settingspw':                 { 'default': None,   'type': 'str' },
    'settingspwfile':             { 'default': None,   'type': 'str' },
    'setup':                      { 'default': None,   'type': 'str' },
    'setuuid':                    { 'default': None,   'type': 'str' },
    'setvideomodehint':           { 'default': None,   'type': 'str' },
    'size':                       { 'default': None,   'type': 'str' },
    'smartcard':                  { 'default': None,   'type': 'str' },
    'snapshotfolder':             { 'default': None,   'type': 'str' },
    'sound':                      { 'default': None,   'type': 'str' },
    'source':                     { 'default': None,   'type': 'str' },
    'spec-ctrl':                  { 'default': None,   'type': 'str' },
    'start':                      { 'default': True,   'type': 'bool' },
    'statip':                     { 'default': None,   'type': 'str' },
    'startport':                  { 'default': None,   'type': 'str' },
    'stat':                       { 'default': None,   'type': 'str' },
    'state':                      { 'default': None,   'type': 'str' },
    'stp':                        { 'default': None,   'type': 'str' },
    'supress-opt':                { 'default': None,   'type': 'str' },
    'sysinfo':                    { 'default': None,   'type': 'str' },
    'system-uuid-le':             { 'default': None,   'type': 'str' },
    'target':                     { 'default': None,   'type': 'str' },
    'target-directory':           { 'default': None,   'type': 'str' },
    'teleporter':                 { 'default': None,   'type': 'str' },
    'teleporteaddress':           { 'default': None,   'type': 'str' },
    'teleporterassword':          { 'default': None,   'type': 'str' },
    'teleporterasswordfile':      { 'default': None,   'type': 'str' },
    'teleporterport':             { 'default': None,   'type': 'str' },
    'tempeject':                  { 'default': None,   'type': 'str' },
    'timeout':                    { 'default': None,   'type': 'str' },
    'tpm':                        { 'default': None,   'type': 'str' },
    'tport':                      { 'default': None,   'type': 'str' },
    'tracing-allow-vm-access':    { 'default': None,   'type': 'str' },
    'tracing-config':             { 'default': None,   'type': 'str' },
    'tracing-enabled':            { 'default': None,   'type': 'str' },
    'transient':                  { 'default': None,   'type': 'str' },
    'type':                       { 'default': None,   'type': 'str' },
    'uart1':                      { 'default': None,   'type': 'str' },
    'uart2':                      { 'default': None,   'type': 'str' },
    'uart3':                      { 'default': None,   'type': 'str' },
    'uart4':                      { 'default': None,   'type': 'str' },
    'uartmode1':                  { 'default': None,   'type': 'str' },
    'uartmode2':                  { 'default': None,   'type': 'str' },
    'uartmode3':                  { 'default': None,   'type': 'str' },
    'uartmode4':                  { 'default': None,   'type': 'str' },
    'uarttype1':                  { 'default': None,   'type': 'str' },
    'uarttype2':                  { 'default': None,   'type': 'str' },
    'uarttype3':                  { 'default': None,   'type': 'str' },
    'uarttype4':                  { 'default': None,   'type': 'str' },
    'unquoted-args':              { 'default': None,   'type': 'str' },
    'usbcardreader':              { 'default': None,   'type': 'str' },
    'unattended':                 { 'default': None,   'type': 'str' },
    'uninstall':                  { 'default': None,   'type': 'str' },
    'upper-ip':                   { 'default': None,   'type': 'str' },
    'username':                   { 'default': None,   'type': 'str' },
    'uuid':                       { 'default': None,   'type': 'str' },
    'value':                      { 'default': None,   'type': 'str' },
    'variant':                    { 'default': None,   'type': 'str' },
    'vcpus':                      { 'default': None,   'type': 'str' },
    'vendor':                     { 'default': None,   'type': 'str' },
    'vendorid':                   { 'default': None,   'type': 'str' },
    'vendorurl':                  { 'default': None,   'type': 'str' },
    'video':                      { 'default': None,   'type': 'str' },
    'virt-type':                  { 'default': "kvm",  'type': 'str' },
    'vm-process-priority':        { 'default': None,   'type': 'str' },
    'vm':                         { 'default': None,   'type': 'str' },
    'vmname':                     { 'default': None,   'type': 'str' },
    'vmram':                      { 'default': None,   'type': 'str' },
    'vrde':                       { 'default': None,   'type': 'str' },
    'vrdeextpack':                { 'default': None,   'type': 'str' },
    'vrdeaddress':                { 'default': None,   'type': 'str' },
    'vrdeauthtype':               { 'default': None,   'type': 'str' },
    'vrdeauthlibrary':            { 'default': None,   'type': 'str' },
    'vrdemulticon':               { 'default': None,   'type': 'str' },
    'vrdeport':                   { 'default': None,   'type': 'str' },
    'vrdeproperty':               { 'default': None,   'type': 'str' },
    'vrdereusecon':               { 'default': None,   'type': 'str' },
    'vrdevideochannel':           { 'default': None,   'type': 'str' },
    'vrdevideochannelquality':    { 'default': None,   'type': 'str' },
    'vsock':                      { 'default': None,   'type': 'str' },
    'vsys':                       { 'default': None,   'type': 'str' },
    'vtxux':                      { 'default': None,   'type': 'str' },
    'vtxvpid':                    { 'default': None,   'type': 'str' },
    'wait':                       { 'default': None,   'type': 'str' },
    'wait-start':                 { 'default': None,   'type': 'str' },
    'wait-stdout':                { 'default': None,   'type': 'str' },
    'no-wait-stdout':             { 'default': None,   'type': 'str' },
    'wait-stderr':                { 'default': None,   'type': 'str' },
    'no-wait-stderr':             { 'default': None,   'type': 'str' },
    'watch':                      { 'default': None,   'type': 'str' },
    'watchdog':                   { 'default': None,   'type': 'str' },
    'websrvauthlibrary':          { 'default': None,   'type': 'str' },
    'x2apic':                     { 'default': None,   'type': 'str' }, 
    'suffix':                     { 'default': None,   'type': 'str' }
  }
  module = AnsibleModule(argument_spec = fields)

  stdout  = ""
  stderr  = ""
  rc      = 1
  command = ""
  subroutine = ""

  if module.params['engine'] == None:
    if re.search("_", module._name):
      module.params['engine'] = module._name.split("_")[0] 
    else:
      module.params['engine'] = module._name

  if module.params['function'] == None:
    if re.search("_", module._name):
      module.params['function'] = module._name.split("_")[1] 

  function = module.params['function']

  if module.params['vm']:
    module.params['vmname'] = module.params['vm']

  if re.search("img|image",module.params['engine']):
    (stdout, stderr, rc, command, subroutine) = qemu_image(module)
  
  if module.params['engine'] == "kvm":

    function = re.sub("^startvm$", "start", function)
    function = re.sub("^stopvm$", "stop", function)
    function = re.sub("^modifyvm$", "modify", function)
    function = re.sub("^get$", "getproperty", function)
    module.params['function'] = function

    if re.search("get", function):
      if module.params['from']:
        module.params['type'] = module.params['from']

    if module.params['pool']:
      module.params['poolname'] = module.params['pool']

    if module.params['format'] == None:
      module.params['format'] = "qcow2"

    if module.params['network'] == None:
      module.params['network'] = "default"

    if re.search("start|stop|suspend|reboot|reset|resume", function):
      (stdout, stderr, rc, command, subroutine) = kvm_control(module)
    else:
      if re.search("modify|set|pool|create|define|build", function):
        (stdout, stderr, rc, command, subroutine) = kvm_modify(module)
      else:
        if re.search("list", function):
          module.params['list'] = re.sub("network", "net", module.params['list'])
          (stdout, stderr, rc, command, subroutine) = kvm_list(module)
        else:
          if re.search("import|resize|convert|customize|cloud-localds", function):
            (stdout, stderr, rc, command, subroutine) = kvm_image(module)
          else:
            if re.search("get", function):
              (stdout, stderr, rc, command, subroutine) = kvm_get_property(module)
            else:
              if re.search("install", function):
                (stdout, stderr, rc, command, subroutine) = kvm_install(module)

  if re.search("vbox", module.params['engine']):

    function = re.sub("^start$", "startvm", function)
    function = re.sub("^stop$", "stopvm", function)
    function = re.sub("^modify$", "modifyvm", function)
    function = re.sub("^control$", "controlvm", function)
    function = re.sub("^create$", "createvm", function)
    function = re.sub("^clone$", "clonevm", function)
    function = re.sub("^importvm$", "import", function)
    function = re.sub("^exportvm$", "export", function)
    function = re.sub("^register$", "registervm", function)
    function = re.sub("^unregister$","unregistervm", function)
    module.params['function'] = function

    if module.params['import']:
      module.params['filename'] = module.params['import']

    if module.params['export']:
      module.params['filename'] = module.params['export']

    if module.params['output']:
      module.params['filename'] = module.params['output']

    if re.search("mediumpropery|checkmediumpwd", function):
      if module.params['uuid']:
        module.params['filename'] = module.params['uuid']
      if module.params['param']:
        module.params['property'] = module.params['param']

    if function == "version":
      (stdout, stderr, rc, command, subroutine) = vbox_other(module)
    else:
      if function == "list":
        (stdout, stderr, rc, command, subroutine) = vbox_list(module)
      else:
        if function == "controlvm":
          (stdout, stderr, rc, command, subroutine) = vbox_control(module)
        else:
          if re.search("port", function):
            (stdout, stderr, rc, command, subroutine) = vbox_image(module)
          else:   
            if re.search("setproperty|setextrdata", function):
              (stdout, stderr, rc, command, subroutine) = vbox_set_property(module)
            else:
              if re.search("getproperty|getextrdata", function):
                (stdout, stderr, rc, command, subroutine) = vbox_get_property(module)
              else:
                if function == "closemedium":
                  (stdout, stderr, rc, command, subroutine) = vbox_close_medium(module)
                else:
                  if re.search("createmedium|modifymedium|convertfromraw", function):
                    (stdout, stderr, rc, command, subroutine) = vbox_modify_medium(module)
                  else:
                    if re.search("mediumpropery|checkmediumpwd", function):
                      (stdout, stderr, rc, command, subroutine) = vbox_medium_property(module)
                    else:
                      if re.search("register", function):
                        (stdout, stderr, rc, command, subroutine) = vbox_register(module)
                      else:
                        (stdout, stderr, rc, command, subroutine) = vbox_function(module)

  if len(stdout) == 0 and len(stderr) > 0:
    stdout = stderr

  module.exit_json(
    _name       = module._name,
    changed     = True,
    stdout      = stdout, 
    stderr      = stderr, 
    rc          = rc, 
    command     = command, 
    subroutine  = subroutine,
    meta        = module.params
  )

if __name__ == '__main__':
  main()
