1+ import os
12import pynetbox
23import re
34import requests
@@ -173,7 +174,7 @@ def proxmox_clone_vm(self, json_in):
173174 try :
174175 for required_netbox_object in ['proxmox_vm_templates' , 'proxmox_vm_storage' ]:
175176 if not required_netbox_object in json_in ['data' ]['custom_fields' ]:
176- raise ValueError ( f"Missing { required_netbox_object } in VM configuration" )
177+ return 500 , { 'result' : f"Missing { required_netbox_object } in VM configuration" }
177178
178179 netbox_collected_vms = {}
179180
@@ -213,7 +214,8 @@ def proxmox_clone_vm(self, json_in):
213214 newid = new_vm_id ,
214215 full = 1 ,
215216 name = json_in ['data' ]['name' ],
216- storage = json_in ['data' ]['custom_fields' ]['proxmox_vm_storage' ]
217+ storage = json_in ['data' ]['custom_fields' ]['proxmox_vm_storage' ],
218+ target = json_in ['data' ]['custom_fields' ]['proxmox_node' ]
217219 )
218220
219221 self .proxmox_job_get_status (clone_data )
@@ -271,7 +273,7 @@ def proxmox_start_vm(self, json_in):
271273 try :
272274 self .json_data_check_proxmox_vmid_exists (json_in )
273275
274- start_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .start .post ()
276+ start_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .start .post ()
275277
276278 self .proxmox_job_get_status (start_data )
277279
@@ -284,7 +286,7 @@ def proxmox_stop_vm(self, json_in):
284286 try :
285287 self .json_data_check_proxmox_vmid_exists (json_in )
286288
287- stop_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .stop .post ()
289+ stop_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .stop .post ()
288290
289291 self .proxmox_job_get_status (stop_data )
290292
@@ -299,7 +301,7 @@ def proxmox_delete_vm(self, json_in):
299301
300302 self .proxmox_stop_vm (json_in )
301303
302- delete_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).delete ()
304+ delete_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).delete ()
303305
304306 self .proxmox_job_get_status (delete_data )
305307
@@ -315,7 +317,7 @@ def proxmox_set_ipconfig0(self, json_in):
315317 primary_ip = json_in ['data' ]['primary_ip' ]['address' ]
316318 gateway = self .generate_gateway_from_ip_address (primary_ip )
317319
318- create_ipconfig0 = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .post (
320+ create_ipconfig0 = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .post (
319321 ipconfig0 = f"ip={ primary_ip } ,gw={ gateway } "
320322 )
321323
@@ -332,7 +334,7 @@ def proxmox_set_ssh_public_key(self, json_in):
332334
333335 proxmox_public_ssh_key = urllib .parse .quote (json_in ['data' ]['custom_fields' ]['proxmox_public_ssh_key' ].rstrip (), safe = '' )
334336
335- create_ssh_public_key = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .post (
337+ create_ssh_public_key = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .post (
336338 sshkeys = f"{ proxmox_public_ssh_key } "
337339 )
338340
@@ -357,7 +359,7 @@ def proxmox_add_disk(self, json_in):
357359 f"{ json_in ['data' ]['name' ]} " : f"{ json_in ['data' ]['custom_fields' ]['proxmox_disk_storage_volume' ]} :{ int (json_in ['data' ]['size' ])/ 1000 } ,backup=0,ssd=0"
358360 }
359361
360- add_disk_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (proxmox_vmid ).config .post (
362+ add_disk_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (proxmox_vmid ).config .post (
361363 ** config_data
362364 )
363365
@@ -374,7 +376,7 @@ def proxmox_resize_disk(self, json_in):
374376 try :
375377 proxmox_vmid = self .netbox_get_proxmox_vmid (json_in ['data' ]['virtual_machine' ]['id' ])
376378
377- disk_resize_info = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (proxmox_vmid ).resize .put (
379+ disk_resize_info = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (proxmox_vmid ).resize .put (
378380 disk = json_in ['data' ]['name' ],
379381 size = f"{ int (json_in ['data' ]['size' ])/ 1000 } G"
380382 )
@@ -393,17 +395,17 @@ def proxmox_delete_disk(self, json_in):
393395
394396 proxmox_vmid = self .netbox_get_proxmox_vmid (json_in ['data' ]['virtual_machine' ]['id' ])
395397
396- self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (proxmox_vmid ).unlink .put (idlist = json_in ['data' ]['name' ], force = 1 )
398+ self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (proxmox_vmid ).unlink .put (idlist = json_in ['data' ]['name' ], force = 1 )
397399
398400 return 200 , {'result' : f"Disk { json_in ['data' ]['name' ]} for VM { json_in ['data' ]['virtual_machine' ]['id' ]} deleted successfully" }
399401 except ResourceException as e :
400402 return 500 , {'result' : e .content }
401403
402404
403405class NetBoxProxmoxHelperLXC (NetBoxProxmoxHelper ):
404- def __proxmox_update_lxc_vcpus_and_memory (self , vmid = 1 , vcpus = 1 , memory = 512 ):
406+ def __proxmox_update_lxc_vcpus_and_memory (self , proxmox_node = None , vmid = 1 , vcpus = 1 , memory = 512 ):
405407 try :
406- update_lxc_vcpus = self .proxmox_api .nodes (self . proxmox_api_config [ 'node' ] ).lxc (vmid ).config .put (
408+ update_lxc_vcpus = self .proxmox_api .nodes (proxmox_node ).lxc (vmid ).config .put (
407409 cores = int (float (vcpus )),
408410 memory = int (memory )
409411 )
@@ -424,7 +426,7 @@ def proxmox_create_lxc(self, json_in):
424426 print ("JSON IN" , json_in ['data' ])
425427
426428 if 'data' in json_in and 'custom_fields' in json_in ['data' ] and 'proxmox_vmid' in json_in ['data' ]['custom_fields' ] and json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]:
427- self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .get ()
429+ self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).qemu (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .get ()
428430 else :
429431 new_vm_id = self .proxmox_api .cluster .get ('nextid' )
430432 except ResourceException as e :
@@ -460,7 +462,7 @@ def proxmox_create_lxc(self, json_in):
460462 if self .debug :
461463 print ("LXC CREATE DATA" , lxc_create_data , new_vm_id )
462464
463- create_lxc_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc .create (** lxc_create_data )
465+ create_lxc_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc .create (** lxc_create_data )
464466
465467 self .proxmox_job_get_status (create_lxc_data )
466468
@@ -482,7 +484,7 @@ def proxmox_create_lxc(self, json_in):
482484 'rootfs': 'local-lvm:vm-104-disk-0,size=4G'}
483485 """
484486
485- lxc_config_info = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc (new_vm_id ).config .get ()
487+ lxc_config_info = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc (new_vm_id ).config .get ()
486488
487489 if self .debug :
488490 print ("LXC CONFIG INFO" , lxc_config_info )
@@ -506,7 +508,7 @@ def proxmox_update_lxc_vpus_and_memory(self, json_in):
506508
507509 # update VM vcpus and/or memory if defined
508510 if json_in ['data' ]['custom_fields' ]['proxmox_vmid' ] and json_in ['snapshots' ]['postchange' ]['vcpus' ] and json_in ['snapshots' ]['postchange' ]['memory' ]:
509- return self .__proxmox_update_lxc_vcpus_and_memory (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ], json_in ['snapshots' ]['postchange' ]['vcpus' ], json_in ['snapshots' ]['postchange' ]['memory' ])
511+ return self .__proxmox_update_lxc_vcpus_and_memory (json_in ['data' ]['custom_fields' ]['proxmox_node' ], json_in [ 'data' ][ 'custom_fields' ][ ' proxmox_vmid' ], json_in ['snapshots' ]['postchange' ]['vcpus' ], json_in ['snapshots' ]['postchange' ]['memory' ])
510512
511513 return 500 , {'result' : f"Unable to set vcpus ({ json_in ['data' ]['vcpus' ]} ) and/or memory ({ json_in ['data' ]['memory' ]} ) for LXC (vmid: { json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]} )" }
512514
@@ -518,7 +520,7 @@ def proxmox_lxc_set_net0(self, json_in):
518520 primary_ip = json_in ['data' ]['primary_ip' ]['address' ]
519521 gateway = self .generate_gateway_from_ip_address (primary_ip )
520522
521- self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .put (
523+ self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).config .put (
522524 net0 = f"name=net0,bridge=vmbr0,ip={ primary_ip } ,gw={ gateway } ,firewall=1"
523525 )
524526
@@ -542,7 +544,7 @@ def proxmox_lxc_resize_disk(self, json_in):
542544 'size' : disk_size
543545 }
544546
545- disk_resize_info = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc (proxmox_vmid ).resize .put (** lxc_disk_size_info )
547+ disk_resize_info = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc (proxmox_vmid ).resize .put (** lxc_disk_size_info )
546548
547549 self .proxmox_job_get_status (disk_resize_info )
548550
@@ -555,7 +557,7 @@ def proxmox_start_lxc(self, json_in):
555557 try :
556558 self .json_data_check_proxmox_vmid_exists (json_in )
557559
558- start_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .start .post ()
560+ start_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .start .post ()
559561
560562 self .proxmox_job_get_status (start_data )
561563
@@ -568,7 +570,7 @@ def proxmox_stop_lxc(self, json_in):
568570 try :
569571 self .json_data_check_proxmox_vmid_exists (json_in )
570572
571- stop_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .stop .post ()
573+ stop_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ]).status .stop .post ()
572574
573575 self .proxmox_job_get_status (stop_data )
574576
@@ -583,7 +585,7 @@ def proxmox_delete_lxc(self, json_in):
583585
584586 self .proxmox_stop_lxc (json_in )
585587
586- delete_data = self .proxmox_api .nodes (self . proxmox_api_config [ 'node ' ]).lxc .delete (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ])
588+ delete_data = self .proxmox_api .nodes (json_in [ 'data' ][ 'custom_fields' ][ 'proxmox_node ' ]).lxc .delete (json_in ['data' ]['custom_fields' ]['proxmox_vmid' ])
587589
588590 self .proxmox_job_get_status (delete_data )
589591
@@ -593,7 +595,9 @@ def proxmox_delete_lxc(self, json_in):
593595
594596
595597class NetBoxProxmoxHelperMigrate (NetBoxProxmoxHelper ):
596- def __init__ (self ):
598+ def __init__ (self , cfg_data , proxmox_node , debug = False ):
599+ super ().__init__ (cfg_data , proxmox_node , debug )
600+
597601 self .proxmox_cluster_name = 'default-proxmox-cluster-name'
598602 self .proxmox_nodes = {}
599603 self .proxmox_vms = {}
@@ -682,13 +686,13 @@ def __wait_for_migration_task(self, proxmox_node: str, proxmox_task_id: int):
682686 elapsed_seconds = current_time - start_time
683687
684688 if elapsed_seconds >= 600 : # 10 minutes
685- raise ValueError ( f"Unable to complete task { proxmox_task_id } in defined time" )
689+ return 500 , { 'content' : f"Unable to complete task { proxmox_task_id } in defined time" }
686690
687691 task_status = self .proxmox_api .nodes (proxmox_node ).tasks (proxmox_task_id ).status .get ()
688692
689693 if task_status ['status' ] == 'stopped' :
690694 if 'exitstatus' in task_status and task_status ['exitstatus' ] == 'OK' :
691- break
695+ return 200 , { 'result' : "Proxmox node migration successful" }
692696 else :
693697 return 500 , {'result' : f"Task { proxmox_task_id } is stopped but exit status does not appear to be successful: { task_status ['exit_status' ]} " }
694698 except ResourceException as e :
@@ -708,9 +712,7 @@ def migrate_vm(self, proxmox_vmid: int, proxmox_node: str, proxmox_target_node:
708712
709713 try :
710714 migrate_vm_task_id = self .proxmox_api .nodes (proxmox_node ).qemu (proxmox_vmid ).migrate .post (** migrate_vm_data )
711- self .__wait_for_migration_task (proxmox_node , migrate_vm_task_id )
712-
713- return 200 , {'result' : f"VM (vmid: { proxmox_vmid } ) has been migrated to node { proxmox_target_node } " }
715+ return self .__wait_for_migration_task (proxmox_node , migrate_vm_task_id )
714716 except ResourceException as e :
715717 return 500 , {'result' : f"Proxmox API error: { e } " }
716718 except requests .exceptions .ConnectionError :
0 commit comments