summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbdoul Bah <bahabdoul@gmail.com>2017-02-15 23:51:46 +0100
committerJohn R Barker <john@johnrbarker.com>2017-02-15 22:51:46 +0000
commitc22fbdc8314239ff9d5aa7f7bf65785c1a672add (patch)
tree239f11f2687cb6a0a35dfde2d5e0f1e6108490c7
parent7869b543fab304f06f70e20e2dd1f1ddeab33b74 (diff)
downloadansible-c22fbdc8314239ff9d5aa7f7bf65785c1a672add.tar.gz
resolve #21056 - Add support for full cloning a Qemu VM. Fix some issues. Update doc (#21225)
* resolve #21056 - Add support for full cloning. Fix some issues. Update doc * Fix condition and update doc. Fixes #28585 * Using built-in helper for argspec, revert ansible metadata, add more control and remove type in documentation * PEP8 style compliance
-rw-r--r--lib/ansible/modules/cloud/misc/proxmox_kvm.py914
1 files changed, 548 insertions, 366 deletions
diff --git a/lib/ansible/modules/cloud/misc/proxmox_kvm.py b/lib/ansible/modules/cloud/misc/proxmox_kvm.py
index 25d80fff69..f37a504c0f 100644
--- a/lib/ansible/modules/cloud/misc/proxmox_kvm.py
+++ b/lib/ansible/modules/cloud/misc/proxmox_kvm.py
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-# (c) 2016, Abdoul Bah (@helldorado) <abdoul.bah at alterway.fr>
+# (c) 2016, Abdoul Bah (@helldorado) <bahabdoul at gmail.com>
"""
Ansible module to manage Qemu(KVM) instance in Proxmox VE cluster.
@@ -28,7 +28,7 @@ short_description: Management of Qemu(KVM) Virtual Machines in Proxmox VE cluste
description:
- Allows you to create/delete/stop Qemu(KVM) Virtual Machines in Proxmox VE cluster.
version_added: "2.3"
-author: "Abdoul Bah (@helldorado) <abdoul.bah at alterway.fr>"
+author: "Abdoul Bah (@helldorado) <bahabdoul at gmail.com>"
options:
acpi:
description:
@@ -36,21 +36,18 @@ options:
required: false
default: "yes"
choices: [ "yes", "no" ]
- type: boolean
agent:
description:
- Specify if the QEMU GuestAgent should be enabled/disabled.
required: false
default: null
choices: [ "yes", "no" ]
- type: boolean
args:
description:
- Pass arbitrary arguments to kvm.
- This option is for experts only!
default: "-serial unix:/var/run/qemu-server/VMID.serial,server,nowait"
required: false
- type: string
api_host:
description:
- Specify the target host of the Proxmox VE cluster.
@@ -71,80 +68,73 @@ options:
required: false
default: "no"
choices: [ "yes", "no" ]
- type: boolean
balloon:
description:
- Specify the amount of RAM for the VM in MB.
- Using zero disables the balloon driver.
required: false
default: 0
- type: integer
bios:
description:
- Specify the BIOS implementation.
choices: ['seabios', 'ovmf']
required: false
default: null
- type: string
boot:
description:
- Specify the boot order -> boot on floppy C(a), hard disk C(c), CD-ROM C(d), or network C(n).
- You can combine to set order.
required: false
default: cnd
- type: string
bootdisk:
description:
- Enable booting from specified disk. C((ide|sata|scsi|virtio)\d+)
required: false
default: null
- type: string
+ clone:
+ description:
+ - Name of VM to be cloned. If C(vmid) is setted, C(clone) can take arbitrary value but required for intiating the clone.
+ required: false
+ default: null
cores:
description:
- Specify number of cores per socket.
required: false
default: 1
- type: integer
cpu:
description:
- Specify emulated CPU type.
required: false
default: kvm64
- type: string
cpulimit:
description:
- Specify if CPU usage will be limited. Value 0 indicates no CPU limit.
- If the computer has 2 CPUs, it has total of '2' CPU time
required: false
default: null
- type: integer
cpuunits:
description:
- Specify CPU weight for a VM.
- You can disable fair-scheduler configuration by setting this to 0
default: 1000
required: false
- type: integer
delete:
description:
- Specify a list of settings you want to delete.
required: false
default: null
- type: string
description:
description:
- Specify the description for the VM. Only used on the configuration web interface.
- This is saved as comment inside the configuration file.
required: false
default: null
- type: string
digest:
description:
- Specify if to prevent changes if current configuration file has different SHA1 digest.
- This can be used to prevent concurrent modifications.
required: false
default: null
- type: string
force:
description:
- Allow to force stop VM.
@@ -152,14 +142,27 @@ options:
default: null
choices: [ "yes", "no" ]
required: false
- type: boolean
+ format:
+ description:
+ - Target drive’s backing file’s data format.
+ - Used only with clone
+ default: qcow2
+ choices: [ "cloop", "cow", "qcow", "qcow2", "qed", "raw", "vmdk" ]
+ required: false
freeze:
description:
- Specify if PVE should freeze CPU at startup (use 'c' monitor command to start execution).
required: false
default: null
choices: [ "yes", "no" ]
- type: boolean
+ full:
+ description:
+ - Create a full copy of all disk. This is always done when you clone a normal VM.
+ - For VM templates, we try to create a linked clone by default.
+ - Used only with clone
+ default: yes
+ choices: [ "yes", "no"]
+ required: false
hostpci:
description:
- Specify a hash/dictionary of map host pci devices into guest. C(hostpci='{"key":"value", "key":"value"}').
@@ -172,7 +175,6 @@ options:
- /!\ This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
required: false
default: null
- type: A hash/dictionary defining host pci devices
hotplug:
description:
- Selectively enable hotplug features.
@@ -180,14 +182,12 @@ options:
- Value 0 disables hotplug completely and value 1 is an alias for the default C('network,disk,usb').
required: false
default: null
- type: string
hugepages:
description:
- Enable/disable hugepages memory.
choices: ['any', '2', '1024']
required: false
default: null
- type: string
ide:
description:
- A hash/dictionary of volume used as IDE hard disk or CD-ROM. C(ide='{"key":"value", "key":"value"}').
@@ -198,20 +198,17 @@ options:
- C(format) is the drive’s backing file’s data format. C(qcow2|raw|subvol).
required: false
default: null
- type: A hash/dictionary defining ide
keyboard:
description:
- Sets the keyboard layout for VNC server.
required: false
default: null
- type: string
kvm:
description:
- Enable/disable KVM hardware virtualization.
required: false
default: "yes"
choices: [ "yes", "no" ]
- type: boolean
localtime:
description:
- Sets the real time clock to local time.
@@ -219,40 +216,34 @@ options:
required: false
default: null
choices: [ "yes", "no" ]
- type: boolean
lock:
description:
- Lock/unlock the VM.
choices: ['migrate', 'backup', 'snapshot', 'rollback']
required: false
default: null
- type: string
machine:
description:
- Specifies the Qemu machine type.
- type => C((pc|pc(-i440fx)?-\d+\.\d+(\.pxe)?|q35|pc-q35-\d+\.\d+(\.pxe)?))
required: false
default: null
- type: string
memory:
description:
- Memory size in MB for instance.
required: false
default: 512
- type: integer
migrate_downtime:
description:
- Sets maximum tolerated downtime (in seconds) for migrations.
required: false
default: null
- type: integer
migrate_speed:
description:
- Sets maximum speed (in MB/s) for migrations.
- A value of 0 is no limit.
required: false
default: null
- type: integer
name:
description:
- Specifies the VM name. Only used on the configuration web interface.
@@ -271,7 +262,12 @@ options:
- If you specify no bridge, we create a kvm 'user' (NATed) network device, which provides DHCP and DNS services.
default: null
required: false
- type: A hash/dictionary defining interfaces
+ newid:
+ description:
+ - VMID for the clone. Used only with clone.
+ - If newid is not set, the next available VM ID will be fetched from ProxmoxAPI.
+ default: null
+ required: false
node:
description:
- Proxmox VE node, where the new VM will be created.
@@ -290,14 +286,12 @@ options:
- C(policy) NUMA allocation policy.
default: null
required: false
- type: A hash/dictionary defining NUMA topology
onboot:
description:
- Specifies whether a VM will be started during system bootup.
default: "yes"
choices: [ "yes", "no" ]
required: false
- type: boolean
ostype:
description:
- Specifies guest operating system. This is used to enable special optimization/features for specific operating systems.
@@ -305,7 +299,6 @@ options:
choices: ['other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7', 'win8', 'l24', 'l26', 'solaris']
default: l26
required: false
- type: string
parallel:
description:
- A hash/dictionary of map host parallel devices. C(parallel='{"key":"value", "key":"value"}').
@@ -313,27 +306,28 @@ options:
- Values allowed are - C("/dev/parport\d+|/dev/usb/lp\d+").
default: null
required: false
- type: A hash/dictionary defining host parallel devices
+ pool:
+ description:
+ - Add the new VM to the specified pool.
+ default: null
+ required: false
protection:
description:
- Enable/disable the protection flag of the VM. This will enable/disable the remove VM and remove disk operations.
default: null
choices: [ "yes", "no" ]
required: false
- type: boolean
reboot:
description:
- Allow reboot. If set to yes, the VM exit on reboot.
default: null
choices: [ "yes", "no" ]
required: false
- type: boolean
revert:
description:
- Revert a pending change.
default: null
required: false
- type: string
sata:
description:
- A hash/dictionary of volume used as sata hard disk or CD-ROM. C(sata='{"key":"value", "key":"value"}').
@@ -344,7 +338,6 @@ options:
- C(format) is the drive’s backing file’s data format. C(qcow2|raw|subvol).
default: null
required: false
- type: A hash/dictionary defining sata
scsi:
description:
- A hash/dictionary of volume used as SCSI hard disk or CD-ROM. C(scsi='{"key":"value", "key":"value"}').
@@ -355,14 +348,12 @@ options:
- C(format) is the drive’s backing file’s data format. C(qcow2|raw|subvol).
default: null
required: false
- type: A hash/dictionary defining scsi
scsihw:
description:
- Specifies the SCSI controller model.
choices: ['lsi', 'lsi53c810', 'virtio-scsi-pci', 'virtio-scsi-single', 'megasas', 'pvscsi']
required: false
default: null
- type: string
serial:
description:
- A hash/dictionary of serial device to create inside the VM. C('{"key":"value", "key":"value"}').
@@ -371,7 +362,6 @@ options:
- /!\ If you pass through a host serial device, it is no longer possible to migrate such machines - use with special care.
default: null
required: false
- type: A hash/dictionary defining serial
shares:
description:
- Rets amount of memory shares for auto-ballooning. (0 - 50000).
@@ -380,34 +370,33 @@ options:
- Using 0 disables auto-ballooning, this means no limit.
required: false
default: null
- type: integer
skiplock:
description:
- Ignore locks
- Only root is allowed to use this option.
required: false
default: null
- choices: [ "yes", "no" ]
- type: boolean
smbios:
description:
- Specifies SMBIOS type 1 fields.
required: false
default: null
- type: string
+ snapname:
+ description:
+ - The name of the snapshot. Used only with clone.
+ default: null
+ required: false
sockets:
description:
- Sets the number of CPU sockets. (1 - N).
required: false
default: 1
- type: integer
startdate:
description:
- Sets the initial date of the real time clock.
- Valid format for date are C('now') or C('2016-09-25T16:01:21') or C('2016-09-25').
required: false
default: null
- type: string
startup:
description:
- Startup and shutdown behavior. C([[order=]\d+] [,up=\d+] [,down=\d+]).
@@ -415,7 +404,6 @@ options:
- Shutdown in done with reverse ordering.
required: false
default: null
- type: string
state:
description:
- Indicates desired state of the instance.
@@ -423,46 +411,59 @@ options:
choices: ['present', 'started', 'absent', 'stopped', 'restarted','current']
required: false
default: present
+ storage:
+ description:
+ - Target storage for full clone.
+ default: null
+ required: false
tablet:
description:
- Enables/disables the USB tablet device.
required: false
choices: [ "yes", "no" ]
default: "no"
- type: boolean
+ target:
+ description:
+ - Target node. Only allowed if the original VM is on shared storage.
+ - Used only with clone
+ default: null
+ required: false
tdf:
description:
- Enables/disables time drift fix.
required: false
default: null
choices: [ "yes", "no" ]
- type: boolean
template:
description:
- Enables/disables the template.
required: false
default: "no"
choices: [ "yes", "no" ]
- type: boolean
timeout:
description:
- Timeout for operations.
default: 30
required: false
- type: integer
+ update:
+ description:
+ - If C(yes), the VM will be update with new value.
+ - Cause of the operations of the API and security reasons, I have disabled the update of the following parameters
+ - C(net, virtio, ide, sata, scsi). Per example updating C(net) update the MAC address and C(virtio) create always new disk...
+ default: "no"
+ choices: [ "yes", "no" ]
+ required: false
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used on personally controlled sites using self-signed certificates.
default: "no"
choices: [ "yes", "no" ]
required: false
- type: boolean
vcpus:
description:
- Sets number of hotplugged vcpus.
required: false
default: null
- type: integer
vga:
description:
- Select VGA type. If you want to use high resolution modes (>= 1280x1024x16) then you should use option 'std' or 'vmware'.
@@ -479,7 +480,6 @@ options:
- C(format) is the drive’s backing file’s data format. C(qcow2|raw|subvol).
required: false
default: null
- type: A hash/dictionary defining virtio
vmid:
description:
- Specifies the VM ID. Instead use I(name) parameter.
@@ -491,7 +491,6 @@ options:
- Creates a virtual hardware watchdog device.
required: false
default: null
- type: string
Notes:
- Requires proxmoxer and requests modules on host. This modules can be installed with pip.
requirements: [ "proxmoxer", "requests" ]
@@ -536,6 +535,32 @@ EXAMPLES = '''
cores : 4
vcpus : 2
+# Clone VM with only source VM name
+- proxmox_kvm:
+ api_user : root@pam
+ api_password: secret
+ api_host : helldorado
+ clone : spynal # The VM source
+ name : zavala # The target VM name
+ node : sabrewulf
+ storage : VMs
+ format : qcow2
+ timeout : 500 # Note: The task can take a while. Adapt
+
+# Clone VM with source vmid and target newid and raw format
+- proxmox_kvm:
+ api_user : root@pam
+ api_password: secret
+ api_host : helldorado
+ clone : arbitrary_name
+ vmid : 108
+ newid : 152
+ name : zavala # The target VM name
+ node : sabrewulf
+ storage : LVM_STO
+ format : raw
+ timeout : 300 # Note: The task can take a while. Adapt
+
# Create new VM and lock it for snapashot.
- proxmox_kvm:
api_user : root@pam
@@ -608,6 +633,35 @@ EXAMPLES = '''
name : spynal
node : sabrewulf
state : current
+
+# Update VM configuration
+- proxmox_kvm:
+ api_user : root@pam
+ api_password: secret
+ api_host : helldorado
+ name : spynal
+ node : sabrewulf
+ cpu : 8
+ memory : 16384
+ update : yes
+
+# Delete QEMU parameters
+- proxmox_kvm:
+ api_user : root@pam
+ api_password: secret
+ api_host : helldorado
+ name : spynal
+ node : sabrewulf
+ delete : 'args,template,cpulimit'
+
+# Revert a pending change
+- proxmox_kvm:
+ api_user : root@pam
+ api_password: secret
+ api_host : helldorado
+ name : spynal
+ node : sabrewulf
+ revert : 'template,cpulimit'
'''
RETURN = '''
@@ -655,266 +709,380 @@ import time
try:
- from proxmoxer import ProxmoxAPI
- HAS_PROXMOXER = True
+ from proxmoxer import ProxmoxAPI
+ HAS_PROXMOXER = True
except ImportError:
- HAS_PROXMOXER = False
+ HAS_PROXMOXER = False
+
+VZ_TYPE = 'qemu'
-VZ_TYPE='qemu'
def get_nextvmid(proxmox):
- try:
- vmid = proxmox.cluster.nextid.get()
- return vmid
- except Exception as e:
- module.fail_json(msg="Unable to get next vmid. Failed with exception: %s")
+ try:
+ vmid = proxmox.cluster.nextid.get()
+ return vmid
+ except Exception as e:
+ module.fail_json(msg="Unable to get next vmid. Failed with exception: %s")
+
def get_vmid(proxmox, name):
- return [ vm['vmid'] for vm in proxmox.cluster.resources.get(type='vm') if vm['name'] == name ]
+ return [vm['vmid'] for vm in proxmox.cluster.resources.get(type='vm') if vm['name'] == name]
+
def get_vm(proxmox, vmid):
- return [ vm for vm in proxmox.cluster.resources.get(type='vm') if vm['vmid'] == int(vmid) ]
+ return [vm for vm in proxmox.cluster.resources.get(type='vm') if vm['vmid'] == int(vmid)]
+
def node_check(proxmox, node):
- return [ True for nd in proxmox.nodes.get() if nd['node'] == node ]
+ return [True for nd in proxmox.nodes.get() if nd['node'] == node]
+
def get_vminfo(module, proxmox, node, vmid, **kwargs):
- global results
- results = {}
- mac = {}
- devices = {}
- try:
- vm = proxmox.nodes(node).qemu(vmid).config.get()
- except Exception as e:
- module.fail_json(msg='Getting information for VM with vmid = %s failed with exception: %s' % (vmid, e))
+ global results
+ results = {}
+ mac = {}
+ devices = {}
+ try:
+ vm = proxmox.nodes(node).qemu(vmid).config.get()
+ except Exception as e:
+ module.fail_json(msg='Getting information for VM with vmid = %s failed with exception: %s' % (vmid, e))
- # Sanitize kwargs. Remove not defined args and ensure True and False converted to int.
- kwargs = dict((k,v) for k, v in kwargs.items() if v is not None)
+ # Sanitize kwargs. Remove not defined args and ensure True and False converted to int.
+ kwargs = dict((k, v) for k, v in kwargs.items() if v is not None)
- # Convert all dict in kwargs to elements. For hostpci[n], ide[n], net[n], numa[n], parallel[n], sata[n], scsi[n], serial[n], virtio[n]
- for k in kwargs.keys():
- if isinstance(kwargs[k], dict):
- kwargs.update(kwargs[k])
- del kwargs[k]
+ # Convert all dict in kwargs to elements. For hostpci[n], ide[n], net[n], numa[n], parallel[n], sata[n], scsi[n], serial[n], virtio[n]
+ for k in kwargs.keys():
+ if isinstance(kwargs[k], dict):
+ kwargs.update(kwargs[k])
+ del kwargs[k]
- # Split information by type
- for k, v in kwargs.items():
- if re.match(r'net[0-9]', k) is not None:
+ # Split information by type
+ for k, v in kwargs.items():
+ if re.match(r'net[0-9]', k) is not None:
interface = k
k = vm[k]
k = re.search('=(.*?),', k).group(1)
mac[interface] = k
- if re.match(r'virtio[0-9]', k) is not None or re.match(r'ide[0-9]', k) is not None or re.match(r'scsi[0-9]', k) is not None or re.match(r'sata[0-9]', k) is not None:
+ if re.match(r'virtio[0-9]', k) is not None or re.match(r'ide[0-9]', k) is not None or re.match(r'scsi[0-9]', k) is not None or re.match(r'sata[0-9]', k) is not None:
device = k
k = vm[k]
k = re.search('(.*?),', k).group(1)
devices[device] = k
- results['mac'] = mac
- results['devices'] = devices
- results['vmid'] = int(vmid)
-
-def create_vm(module, proxmox, vmid, node, name, memory, cpu, cores, sockets, timeout, **kwargs):
- # Available only in PVE 4
- only_v4 = ['force','protection','skiplock']
- # Default args for vm. Note: -args option is for experts only. It allows you to pass arbitrary arguments to kvm.
- vm_args = "-serial unix:/var/run/qemu-server/{}.serial,server,nowait".format(vmid)
-
- proxmox_node = proxmox.nodes(node)
-
- # Sanitize kwargs. Remove not defined args and ensure True and False converted to int.
- kwargs = dict((k,v) for k, v in kwargs.items() if v is not None)
- kwargs.update(dict([k, int(v)] for k, v in kwargs.items() if isinstance(v, bool)))
-
- # The features work only on PVE 4
- if PVE_MAJOR_VERSION < 4:
- for p in only_v4:
- if p in kwargs:
- del kwargs[p]
-
- # Convert all dict in kwargs to elements. For hostpci[n], ide[n], net[n], numa[n], parallel[n], sata[n], scsi[n], serial[n], virtio[n]
- for k in kwargs.keys():
- if isinstance(kwargs[k], dict):
- kwargs.update(kwargs[k])
- del kwargs[k]
-
- # -args and skiplock require root@pam user
- if module.params['api_user'] == "root@pam" and module.params['args'] is None:
- kwargs['args'] = vm_args
- elif module.params['api_user'] == "root@pam" and module.params['args'] is not None:
- kwargs['args'] = module.params['args']
- elif module.params['api_user'] != "root@pam" and module.params['args'] is not None:
- module.fail_json(msg='args parameter require root@pam user. ')
-
- if module.params['api_user'] != "root@pam" and module.params['skiplock'] is not None:
- module.fail_json(msg='skiplock parameter require root@pam user. ')
-
- taskid = getattr(proxmox_node, VZ_TYPE).create(vmid=vmid, name=name, memory=memory, cpu=cpu, cores=cores, sockets=sockets, **kwargs)
-
- while timeout:
- if ( proxmox_node.tasks(taskid).status.get()['status'] == 'stopped'
- and proxmox_node.tasks(taskid).status.get()['exitstatus'] == 'OK' ):
- return True
- timeout = timeout - 1
- if timeout == 0:
- module.fail_json(msg='Reached timeout while waiting for creating VM. Last line in task before timeout: %s'
- % proxmox_node.tasks(taskid).log.get()[:1])
- time.sleep(1)
- return False
+ results['mac'] = mac
+ results['devices'] = devices
+ results['vmid'] = int(vmid)
+
+
+def settings(module, proxmox, vmid, node, name, timeout, **kwargs):
+ proxmox_node = proxmox.nodes(node)
+
+ # Sanitize kwargs. Remove not defined args and ensure True and False converted to int.
+ kwargs = dict((k, v) for k, v in kwargs.items() if v is not None)
+
+ if getattr(proxmox_node, VZ_TYPE)(vmid).config.set(**kwargs) is None:
+ return True
+ else:
+ return False
+
+
+def create_vm(module, proxmox, vmid, newid, node, name, memory, cpu, cores, sockets, timeout, update, **kwargs):
+ # Available only in PVE 4
+ only_v4 = ['force', 'protection', 'skiplock']
+
+ # valide clone parameters
+ valid_clone_params = ['format', 'full', 'pool', 'snapname', 'storage', 'target']
+ clone_params = {}
+ # Default args for vm. Note: -args option is for experts only. It allows you to pass arbitrary arguments to kvm.
+ vm_args = "-serial unix:/var/run/qemu-server/{}.serial,server,nowait".format(vmid)
+
+ proxmox_node = proxmox.nodes(node)
+
+ # Sanitize kwargs. Remove not defined args and ensure True and False converted to int.
+ kwargs = dict((k,v) for k, v in kwargs.items() if v is not None)
+ kwargs.update(dict([k, int(v)] for k, v in kwargs.items() if isinstance(v, bool)))
+
+ # The features work only on PVE 4
+ if PVE_MAJOR_VERSION < 4:
+ for p in only_v4:
+ if p in kwargs:
+ del kwargs[p]
+
+ # If update, don't update disk (virtio, ide, sata, scsi) and network interface
+ if update:
+ if 'virtio' in kwargs:
+ del kwargs['virtio']
+ if 'sata' in kwargs:
+ del kwargs['sata']
+ if 'scsi' in kwargs:
+ del kwargs['scsi']
+ if 'ide' in kwargs:
+ del kwargs['ide']
+ if 'net' in kwargs:
+ del kwargs['net']
+
+ # Convert all dict in kwargs to elements. For hostpci[n], ide[n], net[n], numa[n], parallel[n], sata[n], scsi[n], serial[n], virtio[n]
+ for k in kwargs.keys():
+ if isinstance(kwargs[k], dict):
+ kwargs.update(kwargs[k])
+ del kwargs[k]
+
+ # Rename numa_enabled to numa. According the API documentation
+ if 'numa_enabled' in kwargs:
+ kwargs['numa'] = kwargs['numa_enabled']
+ del kwargs['numa_enabled']
+
+ # -args and skiplock require root@pam user
+ if module.params['api_user'] == "root@pam" and module.params['args'] is None:
+ if not update:
+ kwargs['args'] = vm_args
+ elif module.params['api_user'] == "root@pam" and module.params['args'] is not None:
+ kwargs['args'] = module.params['args']
+ elif module.params['api_user'] != "root@pam" and module.params['args'] is not None:
+ module.fail_json(msg='args parameter require root@pam user. ')
+
+ if module.params['api_user'] != "root@pam" and module.params['skiplock'] is not None:
+ module.fail_json(msg='skiplock parameter require root@pam user. ')
+
+ if update:
+ if getattr(proxmox_node, VZ_TYPE)(vmid).config.set(name=name, memory=memory, cpu=cpu, cores=cores, sockets=sockets, **kwargs) is None:
+ return True
+ else:
+ return False
+ elif module.params['clone'] is not None:
+ for param in valid_clone_params:
+ if module.params[param] is not None:
+ clone_params[param] = module.params[param]
+ clone_params.update(dict([k, int(v)] for k, v in clone_params.items() if isinstance(v, bool)))
+ taskid = proxmox_node.qemu(vmid).clone.post(newid=newid, name=name, **clone_params)
+ else:
+ taskid = getattr(proxmox_node, VZ_TYPE).create(vmid=vmid, name=name, memory=memory, cpu=cpu, cores=cores, sockets=sockets, **kwargs)
+
+ while timeout:
+ if (proxmox_node.tasks(taskid).status.get()['status'] == 'stopped'
+ and proxmox_node.tasks(taskid).status.get()['exitstatus'] == 'OK'):
+ return True
+ timeout = timeout - 1
+ if timeout == 0:
+ module.fail_json(msg='Reached timeout while waiting for creating VM. Last line in task before timeout: %s'
+ % proxmox_node.tasks(taskid).log.get()[:1])
+ time.sleep(1)
+ return False
+
def start_vm(module, proxmox, vm, vmid, timeout):
- taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.start.post()
- while timeout:
- if ( proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
- and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK' ):
- return True
- timeout = timeout - 1
- if timeout == 0:
- module.fail_json(msg='Reached timeout while waiting for starting VM. Last line in task before timeout: %s'
- % proxmox.nodes(vm[0]['node']).tasks(taskid).log.get()[:1])
-
- time.sleep(1)
- return False
+ taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.start.post()
+ while timeout:
+ if (proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
+ and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK' ):
+ return True
+ timeout = timeout - 1
+ if timeout == 0:
+ module.fail_json(msg='Reached timeout while waiting for starting VM. Last line in task before timeout: %s'
+ % proxmox.nodes(vm[0]['node']).tasks(taskid).log.get()[:1])
+
+ time.sleep(1)
+ return False
+
def stop_vm(module, proxmox, vm, vmid, timeout, force):
- if force:
- taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.shutdown.post(forceStop=1)
- else:
- taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.shutdown.post()
- while timeout:
- if ( proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
- and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK' ):
- return True
- timeout = timeout - 1
- if timeout == 0:
- module.fail_json(msg='Reached timeout while waiting for stopping VM. Last line in task before timeout: %s'
- % proxmox.nodes(vm[0]['node']).tasks(taskid).log.get()[:1])
-
- time.sleep(1)
- return False
+ if force:
+ taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.shutdown.post(forceStop=1)
+ else:
+ taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.shutdown.post()
+ while timeout:
+ if (proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
+ and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK'):
+ return True
+ timeout = timeout - 1
+ if timeout == 0:
+ module.fail_json(msg='Reached timeout while waiting for stopping VM. Last line in task before timeout: %s'
+ % proxmox.nodes(vm[0]['node']).tasks(taskid).log.get()[:1])
+ time.sleep(1)
+ return False
+
def main():
- module = AnsibleModule(
- argument_spec = dict(
- acpi = dict(type='bool', default='yes'),
- agent = dict(type='bool'),
- args = dict(type='str', default=None),
- api_host = dict(required=True),
- api_user = dict(required=True),
- api_password = dict(no_log=True),
- autostart = dict(type='bool', default='no'),
- balloon = dict(type='int',default=0),
- bios = dict(choices=['seabios', 'ovmf']),
- boot = dict(type='str', default='cnd'),
- bootdisk = dict(type='str'),
- cores = dict(type='int', default=1),
- cpu = dict(type='str', default='kvm64'),
- cpulimit = dict(type='int'),
- cpuunits = dict(type='int', default=1000),
- delete = dict(type='str'),
- description = dict(type='str'),
- digest = dict(type='str'),
- force = dict(type='bool', default=None),
- freeze = dict(type='bool'),
- hostpci = dict(type='dict'),
- hotplug = dict(type='str'),
- hugepages = dict(choices=['any', '2', '1024']),
- ide = dict(type='dict', default=None),
- keyboard = dict(type='str'),
- kvm = dict(type='bool', default='yes'),
- localtime = dict(type='bool'),
- lock = dict(choices=['migrate', 'backup', 'snapshot', 'rollback']),
- machine = dict(type='str'),
- memory = dict(type='int', default=512),
- migrate_downtime = dict(type='int'),
- migrate_speed = dict(type='int'),
- name = dict(type='str'),
- net = dict(type='dict'),
- node = dict(),
- numa = dict(type='dict'),
- onboot = dict(type='bool', default='yes'),
- ostype = dict(default='l26', choices=['other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7', 'win8', 'l24', 'l26', 'solaris']),
- parallel = dict(type='dict'),
- protection = dict(type='bool'),
- reboot = dict(type='bool'),
- revert = dict(),
- sata = dict(type='dict'),
- scsi = dict(type='dict'),
- scsihw = dict(choices=['lsi', 'lsi53c810', 'virtio-scsi-pci', 'virtio-scsi-single', 'megasas', 'pvscsi']),
- serial = dict(type='dict'),
- shares = dict(type='int'),
- skiplock = dict(type='bool'),
- smbios = dict(type='str'),
- sockets = dict(type='int', default=1),
- startdate = dict(type='str'),
- startup = dict(),
- state = dict(default='present', choices=['present', 'absent', 'stopped', 'started', 'restarted', 'current']),
- tablet = dict(type='bool', default='no'),
- tdf = dict(type='bool'),
- template = dict(type='bool', default='no'),
- timeout = dict(type='int', default=30),
- validate_certs = dict(type='bool', default='no'),
- vcpus = dict(type='int', default=None),
- vga = dict(default='std', choices=['std', 'cirrus', 'vmware', 'qxl', 'serial0', 'serial1', 'serial2', 'serial3', 'qxl2', 'qxl3', 'qxl4']),
- virtio = dict(type='dict', default=None),
- vmid = dict(type='int', default=None),
- watchdog = dict(),
- )
- )
-
- if not HAS_PROXMOXER:
- module.fail_json(msg='proxmoxer required for this module')
-
- api_user = module.params['api_user']
- api_host = module.params['api_host']
- api_password = module.params['api_password']
- cpu = module.params['cpu']
- cores = module.params['cores']
- memory = module.params['memory']
- name = module.params['name']
- node = module.params['node']
- sockets = module.params['sockets'],
- state = module.params['state']
- timeout = module.params['timeout']
- validate_certs = module.params['validate_certs']
-
- # If password not set get it from PROXMOX_PASSWORD env
- if not api_password:
- try:
- api_password = os.environ['PROXMOX_PASSWORD']
- except KeyError as e:
- module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable')
-
- try:
- proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=validate_certs)
- global VZ_TYPE
- global PVE_MAJOR_VERSION
- PVE_MAJOR_VERSION = 3 if float(proxmox.version.get()['version']) < 4.0 else 4
- except Exception as e:
- module.fail_json(msg='authorization on proxmox cluster failed with exception: %s' % e)
-
-
- # If vmid not set get the Next VM id from ProxmoxAPI
- # If vm name is set get the VM id from ProxmoxAPI
- if module.params['vmid'] is not None:
+ module = AnsibleModule(
+ argument_spec = dict(
+ acpi = dict(type='bool', default='yes'),
+ agent = dict(type='bool'),
+ args = dict(type='str', default=None),
+ api_host = dict(required=True),
+ api_user = dict(required=True),
+ api_password = dict(no_log=True),
+ autostart = dict(type='bool', default='no'),
+ balloon = dict(type='int',default=0),
+ bios = dict(choices=['seabios', 'ovmf']),
+ boot = dict(type='str', default='cnd'),
+ bootdisk = dict(type='str'),
+ clone = dict(type='str', default=None),
+ cores = dict(type='int', default=1),
+ cpu = dict(type='str', default='kvm64'),
+ cpulimit = dict(type='int'),
+ cpuunits = dict(type='int', default=1000),
+ delete = dict(type='str', default=None),
+ description = dict(type='str'),
+ digest = dict(type='str'),
+ force = dict(type='bool', default=None),
+ format = dict(type='str', default='qcow2', choices=['cloop', 'cow', 'qcow', 'qcow2', 'qed', 'raw', 'vmdk' ]),
+ freeze = dict(type='bool'),
+ full = dict(type='bool', default='yes'),
+ hostpci = dict(type='dict'),
+ hotplug = dict(type='str'),
+ hugepages = dict(choices=['any', '2', '1024']),
+ ide = dict(type='dict', default=None),
+ keyboard = dict(type='str'),
+ kvm = dict(type='bool', default='yes'),
+ localtime = dict(type='bool'),
+ lock = dict(choices=['migrate', 'backup', 'snapshot', 'rollback']),
+ machine = dict(type='str'),
+ memory = dict(type='int', default=512),
+ migrate_downtime = dict(type='int'),
+ migrate_speed = dict(type='int'),
+ name = dict(type='str'),
+ net = dict(type='dict'),
+ newid = dict(type='int', default=None),
+ node = dict(),
+ numa = dict(type='dict'),
+ numa_enabled = dict(type='bool'),
+ onboot = dict(type='bool', default='yes'),
+ ostype = dict(default='l26', choices=['other', 'wxp', 'w2k', 'w2k3', 'w2k8', 'wvista', 'win7', 'win8', 'l24', 'l26', 'solaris']),
+ parallel = dict(type='dict'),
+ pool = dict(type='str'),
+ protection = dict(type='bool'),
+ reboot = dict(type='bool'),
+ revert = dict(type='str', default=None),
+ sata = dict(type='dict'),
+ scsi = dict(type='dict'),
+ scsihw = dict(choices=['lsi', 'lsi53c810', 'virtio-scsi-pci', 'virtio-scsi-single', 'megasas', 'pvscsi']),
+ serial = dict(type='dict'),
+ shares = dict(type='int'),
+ skiplock = dict(type='bool'),
+ smbios = dict(type='str'),
+ snapname = dict(type='str'),
+ sockets = dict(type='int', default=1),
+ startdate = dict(type='str'),
+ startup = dict(),
+ state = dict(default='present', choices=['present', 'absent', 'stopped', 'started', 'restarted', 'current']),
+ storage = dict(type='str'),
+ tablet = dict(type='bool', default='no'),
+ target = dict(type='str'),
+ tdf = dict(type='bool'),
+ template = dict(type='bool', default='no'),
+ timeout = dict(type='int', default=30),
+ update = dict(type='bool', default='no'),
+ validate_certs = dict(type='bool', default='no'),
+ vcpus = dict(type='int', default=None),
+ vga = dict(default='std', choices=['std', 'cirrus', 'vmware', 'qxl', 'serial0', 'serial1', 'serial2', 'serial3', 'qxl2', 'qxl3', 'qxl4']),
+ virtio = dict(type='dict', default=None),
+ vmid = dict(type='int', default=None),
+ watchdog = dict(),
+ ),
+ mutually_exclusive = [('delete', 'revert'), ('delete','update'), ('revert','update'), ('clone', 'update'), ('clone', 'delete'), ('clone','revert')],
+ required_one_of=[('name','vmid',)],
+ required_if=[('state', 'present', ['node'])]
+ )
+
+ if not HAS_PROXMOXER:
+ module.fail_json(msg='proxmoxer required for this module')
+
+ api_user = module.params['api_user']
+ api_host = module.params['api_host']
+ api_password = module.params['api_password']
+ clone = module.params['clone']
+ cpu = module.params['cpu']
+ cores = module.params['cores']
+ delete = module.params['delete']
+ memory = module.params['memory']
+ name = module.params['name']
+ newid = module.params['newid']
+ node = module.params['node']
+ revert = module.params['revert']
+ sockets = module.params['sockets']
+ state = module.params['state']
+ timeout = module.params['timeout']
+ update = bool(module.params['update'])
vmid = module.params['vmid']
- elif state == 'present':
- vmid = get_nextvmid(proxmox)
- elif module.params['name'] is not None:
- vmid = get_vmid(proxmox, name)[0]
+ validate_certs = module.params['validate_certs']
+
+ # If password not set get it from PROXMOX_PASSWORD env
+ if not api_password:
+ try:
+ api_password = os.environ['PROXMOX_PASSWORD']
+ except KeyError as e:
+ module.fail_json(msg='You should set api_password param or use PROXMOX_PASSWORD environment variable')
- if state == 'present':
try:
- if get_vm(proxmox, vmid) and not module.params['force']:
- module.exit_json(changed=False, msg="VM with vmid <%s> already exists" % vmid)
- elif get_vmid(proxmox, name) and not module.params['force']:
- module.exit_json(changed=False, msg="VM with name <%s> already exists" % name)
- elif not (node, module.params['name']):
- module.fail_json(msg='node, name is mandatory for creating vm')
- elif not node_check(proxmox, node):
- module.fail_json(msg="node '%s' does not exist in cluster" % node)
-
- create_vm(module, proxmox, vmid, node, name, memory, cpu, cores, sockets, timeout,
+ proxmox = ProxmoxAPI(api_host, user=api_user, password=api_password, verify_ssl=validate_certs)
+ global VZ_TYPE
+ global PVE_MAJOR_VERSION
+ PVE_MAJOR_VERSION = 3 if float(proxmox.version.get()['version']) < 4.0 else 4
+ except Exception as e:
+ module.fail_json(msg='authorization on proxmox cluster failed with exception: %s' % e)
+
+ # If vmid not set get the Next VM id from ProxmoxAPI
+ # If vm name is set get the VM id from ProxmoxAPI
+ if not vmid:
+ if state == 'present' and ( not update and not clone) and (not delete and not revert):
+ try:
+ vmid = get_nextvmid(proxmox)
+ except Exception as e:
+ module.fail_json(msg="Can't get the next vimd for VM {} automatically. Ensure your cluster state is good".format(name))
+ else:
+ try:
+ if not clone:
+ vmid = get_vmid(proxmox, name)[0]
+ else:
+ vmid = get_vmid(proxmox, clone)[0]
+ except Exception as e:
+ if not clone:
+ module.fail_json(msg="VM {} does not exist in cluster.".format(name))
+ else:
+ module.fail_json(msg="VM {} does not exist in cluster.".format(clone))
+
+ if clone is not None:
+ if get_vmid(proxmox, name):
+ module.exit_json(changed=False, msg="VM with name <%s> already exists" % name)
+ if vmid is not None:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
+ if not newid:
+ try:
+ newid = get_nextvmid(proxmox)
+ except Exception as e:
+ module.fail_json(msg="Can't get the next vimd for VM {} automatically. Ensure your cluster state is good".format(name))
+ else:
+ vm = get_vm(proxmox, newid)
+ if vm:
+ module.exit_json(changed=False, msg="vmid %s with VM name %s already exists" % (newid, name))
+
+ if delete is not None:
+ try:
+ settings(module, proxmox, vmid, node, name, timeout, delete=delete)
+ module.exit_json(changed=True, msg="Settings has deleted on VM {} with vmid {}".format(name, vmid))
+ except Exception as e:
+ module.fail_json(msg='Unable to delete settings on VM {} with vimd {}: '.format(name, vmid) + str(e))
+ elif revert is not None:
+ try:
+ settings(module, proxmox, vmid, node, name, timeout, revert=revert)
+ module.exit_json(changed=True, msg="Settings has reverted on VM {} with vmid {}".format(name, vmid))
+ except Exception as e:
+ module.fail_json(msg='Unable to revert settings on VM {} with vimd {}: Maybe is not a pending task... '.format(name, vmid) + str(e))
+
+ if state == 'present':
+ try:
+ if get_vm(proxmox, vmid) and not (update or clone):
+ module.exit_json(changed=False, msg="VM with vmid <%s> already exists" % vmid)
+ elif get_vmid(proxmox, name) and not (update or clone):
+ module.exit_json(changed=False, msg="VM with name <%s> already exists" % name)
+ elif not (node, name):
+ module.fail_json(msg='node, name is mandatory for creating/updating vm')
+ elif not node_check(proxmox, node):
+ module.fail_json(msg="node '%s' does not exist in cluster" % node)
+
+ create_vm(module, proxmox, vmid, newid, node, name, memory, cpu, cores, sockets, timeout, update,
acpi = module.params['acpi'],
agent = module.params['agent'],
autostart = module.params['autostart'],
@@ -924,7 +1092,6 @@ def main():
bootdisk = module.params['bootdisk'],
cpulimit = module.params['cpulimit'],
cpuunits = module.params['cpuunits'],
- delete = module.params['delete'],
description = module.params['description'],
digest = module.params['digest'],
force = module.params['force'],
@@ -942,12 +1109,13 @@ def main():
migrate_speed = module.params['migrate_speed'],
net = module.params['net'],
numa = module.params['numa'],
+ numa_enabled = module.params['numa_enabled'],
onboot = module.params['onboot'],
ostype = module.params['ostype'],
parallel = module.params['parallel'],
+ pool = module.params['pool'],
protection = module.params['protection'],
reboot = module.params['reboot'],
- revert = module.params['revert'],
sata = module.params['sata'],
scsi = module.params['scsi'],
scsihw = module.params['scsihw'],
@@ -955,9 +1123,11 @@ def main():
shares = module.params['shares'],
skiplock = module.params['skiplock'],
smbios1 = module.params['smbios'],
+ snapname = module.params['snapname'],
startdate = module.params['startdate'],
startup = module.params['startup'],
tablet = module.params['tablet'],
+ target = module.params['target'],
tdf = module.params['tdf'],
template = module.params['template'],
vcpus = module.params['vcpus'],
@@ -965,92 +1135,104 @@ def main():
virtio = module.params['virtio'],
watchdog = module.params['watchdog'])
- get_vminfo(module, proxmox, node, vmid,
- ide = module.params['ide'],
- net = module.params['net'],
- sata = module.params['sata'],
- scsi = module.params['scsi'],
- virtio = module.params['virtio'])
- module.exit_json(changed=True, msg="VM %s with vmid %s deployed" % (name, vmid), **results)
- except Exception as e:
- module.fail_json(msg="creation of %s VM %s with vmid %s failed with exception: %s" % ( VZ_TYPE, name, vmid, e ))
-
- elif state == 'started':
- try:
- vm = get_vm(proxmox, vmid)
- if not vm:
- module.fail_json(msg='VM with vmid <%s> does not exist in cluster' % vmid)
- if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'running':
- module.exit_json(changed=False, msg="VM %s is already running" % vmid)
-
- if start_vm(module, proxmox, vm, vmid, timeout):
- module.exit_json(changed=True, msg="VM %s started" % vmid)
- except Exception as e:
- module.fail_json(msg="starting of VM %s failed with exception: %s" % ( vmid, e ))
-
- elif state == 'stopped':
- try:
- vm = get_vm(proxmox, vmid)
- if not vm:
- module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
-
- if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'stopped':
- module.exit_json(changed=False, msg="VM %s is already stopped" % vmid)
+ if not clone:
+ get_vminfo(module, proxmox, node, vmid,
+ ide = module.params['ide'],
+ net = module.params['net'],
+ sata = module.params['sata'],
+ scsi = module.params['scsi'],
+ virtio = module.params['virtio'])
+ if update:
+ module.exit_json(changed=True, msg="VM %s with vmid %s updated" % (name, vmid))
+ elif clone is not None:
+ module.exit_json(changed=True, msg="VM %s with newid %s cloned from vm with vmid %s" % (name, newid, vmid))
+ else:
+ module.exit_json(changed=True, msg="VM %s with vmid %s deployed" % (name, vmid), **results)
+ except Exception as e:
+ if update:
+ module.fail_json(msg="Unable to update vm {} with vimd {}=".format(name, vmid) + str(e))
+ elif clone is not None:
+ module.fail_json(msg="Unable to clone vm {} from vimd {}=".format(name, vmid) + str(e))
+ else:
+ module.fail_json(msg="creation of %s VM %s with vmid %s failed with exception=%s" % (VZ_TYPE, name, vmid, e))
+
+ elif state == 'started':
+ try:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.fail_json(msg='VM with vmid <%s> does not exist in cluster' % vmid)
+ if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'running':
+ module.exit_json(changed=False, msg="VM %s is already running" % vmid)
+
+ if start_vm(module, proxmox, vm, vmid, timeout):
+ module.exit_json(changed=True, msg="VM %s started" % vmid)
+ except Exception as e:
+ module.fail_json(msg="starting of VM %s failed with exception: %s" % (vmid, e))
- if stop_vm(module, proxmox, vm, vmid, timeout, force = module.params['force']):
- module.exit_json(changed=True, msg="VM %s is shutting down" % vmid)
- except Exception as e:
- module.fail_json(msg="stopping of VM %s failed with exception: %s" % ( vmid, e ))
+ elif state == 'stopped':
+ try:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
- elif state == 'restarted':
- try:
- vm = get_vm(proxmox, vmid)
- if not vm:
- module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
- if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'stopped':
- module.exit_json(changed=False, msg="VM %s is not running" % vmid)
-
- if ( stop_vm(module, proxmox, vm, vmid, timeout, force = module.params['force']) and
- start_vm(module, proxmox, vm, vmid, timeout) ):
- module.exit_json(changed=True, msg="VM %s is restarted" % vmid)
- except Exception as e:
- module.fail_json(msg="restarting of VM %s failed with exception: %s" % ( vmid, e ))
+ if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'stopped':
+ module.exit_json(changed=False, msg="VM %s is already stopped" % vmid)
- elif state == 'absent':
- try:
- vm = get_vm(proxmox, vmid)
- if not vm:
- module.exit_json(changed=False, msg="VM %s does not exist" % vmid)
+ if stop_vm(module, proxmox, vm, vmid, timeout, force = module.params['force']):
+ module.exit_json(changed=True, msg="VM %s is shutting down" % vmid)
+ except Exception as e:
+ module.fail_json(msg="stopping of VM %s failed with exception: %s" % (vmid, e))
- if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'running':
- module.exit_json(changed=False, msg="VM %s is running. Stop it before deletion." % vmid)
+ elif state == 'restarted':
+ try:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
+ if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'stopped':
+ module.exit_json(changed=False, msg="VM %s is not running" % vmid)
+
+ if (stop_vm(module, proxmox, vm, vmid, timeout, force = module.params['force'])
+ and start_vm(module, proxmox, vm, vmid, timeout)):
+ module.exit_json(changed=True, msg="VM %s is restarted" % vmid)
+ except Exception as e:
+ module.fail_json(msg="restarting of VM %s failed with exception: %s" % ( vmid, e ))
- taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE).delete(vmid)
- while timeout:
- if ( proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
- and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK' ):
- module.exit_json(changed=True, msg="VM %s removed" % vmid)
- timeout = timeout - 1
- if timeout == 0:
- module.fail_json(msg='Reached timeout while waiting for removing VM. Last line in task before timeout: %s'
- % proxmox_node.tasks(taskid).log.get()[:1])
+ elif state == 'absent':
+ try:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.exit_json(changed=False, msg="VM %s does not exist" % vmid)
+
+ if getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status'] == 'running':
+ module.exit_json(changed=False, msg="VM %s is running. Stop it before deletion." % vmid)
+
+ taskid = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE).delete(vmid)
+ while timeout:
+ if (proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['status'] == 'stopped'
+ and proxmox.nodes(vm[0]['node']).tasks(taskid).status.get()['exitstatus'] == 'OK' ):
+ module.exit_json(changed=True, msg="VM %s removed" % vmid)
+ timeout = timeout - 1
+ if timeout == 0:
+ module.fail_json(msg='Reached timeout while waiting for removing VM. Last line in task before timeout: %s'
+ % proxmox_node.tasks(taskid).log.get()[:1])
+
+ time.sleep(1)
+ except Exception as e:
+ module.fail_json(msg="deletion of VM %s failed with exception: %s" % (vmid, e))
- time.sleep(1)
- except Exception as e:
- module.fail_json(msg="deletion of VM %s failed with exception: %s" % ( vmid, e ))
+ elif state == 'current':
+ status = {}
+ try:
+ vm = get_vm(proxmox, vmid)
+ if not vm:
+ module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
+ current = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status']
+ status['status'] = current
+ if status:
+ module.exit_json(changed=False, msg="VM %s with vmid = %s is %s" % (name, vmid, current), **status)
+ except Exception as e:
+ module.fail_json(msg="Unable to get vm {} with vmid = {} status: ".format(name, vmid) + str(e))
- elif state == 'current':
- status = {}
- try:
- vm = get_vm(proxmox, vmid)
- if not vm:
- module.fail_json(msg='VM with vmid = %s does not exist in cluster' % vmid)
- current = getattr(proxmox.nodes(vm[0]['node']), VZ_TYPE)(vmid).status.current.get()['status']
- status['status'] = current
- if status:
- module.exit_json(changed=False, msg="VM %s with vmid = %s is %s" % (name, vmid, current), **status)
- except Exception as e:
- module.fail_json(msg="Unable to get vm {} with vmid = {} status: ".format(name, vmid) + str(e))
# import module snippets
from ansible.module_utils.basic import *