@ -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 ( > = 1280 x1024x16 ) 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 = '''
@ -660,7 +714,8 @@ try:
except ImportError :
HAS_PROXMOXER = False
VZ_TYPE = ' qemu '
VZ_TYPE = ' qemu '
def get_nextvmid ( proxmox ) :
try :
@ -669,14 +724,18 @@ def get_nextvmid(proxmox):
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
@ -689,7 +748,7 @@ def get_vminfo(module, proxmox, node, vmid, **kwargs):
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 )
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 ( ) :
@ -714,9 +773,26 @@ def get_vminfo(module, proxmox, node, vmid, **kwargs):
results [ ' devices ' ] = devices
results [ ' vmid ' ] = int ( vmid )
def create_vm ( module , proxmox , vmid , node , name , memory , cpu , cores , sockets , timeout , * * kwargs ) :
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 ' ]
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 )
@ -732,14 +808,33 @@ def create_vm(module, proxmox, vmid, node, name, memory, cpu, cores, sockets, ti
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 ' ]
@ -749,11 +844,23 @@ def create_vm(module, proxmox, vmid, node, name, memory, cpu, cores, sockets, ti
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 ' ) :
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 :
@ -762,10 +869,11 @@ def create_vm(module, proxmox, vmid, node, name, memory, cpu, cores, sockets, ti
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 '
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
@ -776,23 +884,24 @@ def start_vm(module, proxmox, vm, vmid, timeout):
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 ' ) :
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 (
@ -807,15 +916,18 @@ def main():
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 ' ) ,
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 ' ] ) ,
@ -830,14 +942,17 @@ def main():
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 ( ) ,
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 ' ] ) ,
@ -845,21 +960,28 @@ def main():
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 :
@ -868,14 +990,20 @@ def main():
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 ' ]
sockets = module . params [ ' sockets ' ] ,
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 ' ]
validate_certs = module . params [ ' validate_certs ' ]
# If password not set get it from PROXMOX_PASSWORD env
@ -893,28 +1021,68 @@ def main():
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 :
vmid = module . params [ ' vmid ' ]
elif state == ' present ' :
if not vmid :
if state == ' present ' and ( not update and not clone ) and ( not delete and not revert ) :
try :
vmid = get_nextvmid ( proxmox )
elif module . params [ ' name ' ] is not None :
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 module . params [ ' force ' ] :
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 module . params [ ' force ' ] :
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 , module . params [ ' name ' ] ) :
module . fail_json ( msg = ' node, name is mandatory for creating vm ' )
elif not ( node , name) :
module . fail_json ( msg = ' node, name is mandatory for cre ating/upd ating 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 ,
create_vm ( module , proxmox , vm id, new id, 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,15 +1135,26 @@ def main():
virtio = module . params [ ' virtio ' ] ,
watchdog = module . params [ ' watchdog ' ] )
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 :
module . fail_json ( msg = " creation of %s VM %s with vmid %s failed with exception: %s " % ( VZ_TYPE , name , vmid , 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 :
@ -986,7 +1167,7 @@ def main():
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 ) )
module . fail_json ( msg = " starting of VM %s failed with exception: %s " % ( vmid , e ) )
elif state == ' stopped ' :
try :
@ -1000,7 +1181,7 @@ def main():
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 ) )
module . fail_json ( msg = " stopping of VM %s failed with exception: %s " % ( vmid , e ) )
elif state == ' restarted ' :
try :
@ -1010,8 +1191,8 @@ def main():
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 ) ) :
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 ) )
@ -1027,7 +1208,7 @@ def main():
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 '
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
@ -1037,7 +1218,7 @@ def main():
time . sleep ( 1 )
except Exception as e :
module . fail_json ( msg = " deletion of VM %s failed with exception: %s " % ( vmid , e ) )
module . fail_json ( msg = " deletion of VM %s failed with exception: %s " % ( vmid , e ) )
elif state == ' current ' :
status = { }
@ -1052,6 +1233,7 @@ def main():
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 *
if __name__ == ' __main__ ' :