@@ -15,6 +15,12 @@ import (
1515 "time"
1616)
1717
18+ type ProxmoxJobStatus struct {
19+ Exitstatus string `json:"exitstatus,omitempty"`
20+ JobId string `json:"upid"`
21+ Status string `json:"status"`
22+ }
23+
1824type ProxmoxCreds struct {
1925 Username string `json:"username"`
2026 Password string `json:"password"`
@@ -47,6 +53,10 @@ type rawProxmoxInterfaces struct {
4753 Data []ProxmoxInterfaces `json:"data"`
4854}
4955
56+ type rawProxmoxJobStatus struct {
57+ Data ProxmoxJobStatus `json:"data"`
58+ }
59+
5060type ProxmoxInterfaces struct {
5161 Address string `json:"address"`
5262 Active int `json:"active"`
@@ -307,7 +317,7 @@ func getNodeAddresses(creds ProxmoxCreds, token ProxmoxAuth) ([]ProxmoxInterface
307317 return parsedResponse .Data , nil
308318}
309319
310- func cloneTemplate (creds ProxmoxCreds , token ProxmoxAuth , vm ProxmoxVm ) (ProxmoxVm , error ) {
320+ func cloneTemplate (creds ProxmoxCreds , token ProxmoxAuth , vm ProxmoxVm ) (ProxmoxVm , ProxmoxJobStatus , error ) {
311321 // Boilerplate create cookie
312322 authCookie := & http.Cookie {
313323 Name : "PVEAuthCookie" ,
@@ -331,7 +341,7 @@ func cloneTemplate(creds ProxmoxCreds, token ProxmoxAuth, vm ProxmoxVm) (Proxmox
331341 apiUrl := fmt .Sprintf ("https://%s:8006/api2/json/nodes/%s/qemu/%d/clone" , creds .Address , vm .Node , vm .VmNumber )
332342 cloneVmReq , err := http .NewRequest (http .MethodPost , apiUrl , bytes .NewBufferString (data .Encode ()))
333343 if err != nil {
334- return ProxmoxVm {}, fmt .Errorf ("error while creating request: %+v\n url: %s\n " , err , apiUrl )
344+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("error while creating request: %+v\n url: %s\n " , err , apiUrl )
335345 }
336346
337347 // Add the auth cookies to the request
@@ -341,26 +351,77 @@ func cloneTemplate(creds ProxmoxCreds, token ProxmoxAuth, vm ProxmoxVm) (Proxmox
341351 // Perform the request
342352 cloneVmResp , err := client .Do (cloneVmReq )
343353 if err != nil {
344- return ProxmoxVm {}, fmt .Errorf ("error while performing request: %+v\n " , err )
354+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("error while performing request: %+v\n " , err )
345355 }
346356
347357 if cloneVmResp .StatusCode != 200 {
348358 response , err := io .ReadAll (cloneVmResp .Body )
349359 if err != nil {
350- return ProxmoxVm {}, fmt .Errorf ("got unexpected status code %d: %s\n " , cloneVmResp .StatusCode , cloneVmResp .Status )
360+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("got unexpected status code %d: %s\n " , cloneVmResp .StatusCode , cloneVmResp .Status )
351361 }
352362
353363 // Bodge solution for generating an invalid VM ID
354364 if cloneVmResp .StatusCode == 400 && strings .Contains (fmt .Sprintf ("%s" , response ), "invalid format - value does not look like a valid VM ID\\ n" ) {
355- generatedVm , err := cloneTemplate (creds , token , vm )
356- return generatedVm , err
365+ generatedVm , jobStatus , err := cloneTemplate (creds , token , vm )
366+ return generatedVm , jobStatus , err
357367 } else {
358- return ProxmoxVm {}, fmt .Errorf ("got unexpected status code %d: %s: %s\n " , cloneVmResp .StatusCode , cloneVmResp .Status , response )
368+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("got unexpected status code %d: %s: %s\n " , cloneVmResp .StatusCode , cloneVmResp .Status , response )
359369 }
360370 }
361371
362- fmt .Printf ("Status Code: %d\n " , cloneVmResp .StatusCode )
363- fmt .Printf ("Status: %s\n " , cloneVmResp .Status )
372+ var resp struct {
373+ Data string `json:"data"`
374+ }
375+
376+ body , err := io .ReadAll (cloneVmResp .Body )
377+ if err != nil {
378+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("Error while reading body: %v\n " , err )
379+ }
380+
381+ err = json .Unmarshal (body , & resp )
382+ if err != nil {
383+ return ProxmoxVm {}, ProxmoxJobStatus {}, fmt .Errorf ("Error while unmarshalling body: %v\n " , err )
384+ }
385+
386+ return newVm , ProxmoxJobStatus {JobId : resp .Data }, nil
387+ }
388+
389+ func getJobStatus (creds ProxmoxCreds , token ProxmoxAuth , job ProxmoxJobStatus ) (ProxmoxJobStatus , error ) {
390+ authCookie := & http.Cookie {
391+ Name : "PVEAuthCookie" ,
392+ Value : token .Data .Ticket ,
393+ }
394+
395+ apiUrl := fmt .Sprintf ("https://%s:8006/api2/json/nodes/%s/tasks/%s/status" , creds .Address , creds .Server , job .JobId )
396+
397+ req , err := http .NewRequest (http .MethodPost , apiUrl , nil )
398+ if err != nil {
399+ return ProxmoxJobStatus {}, fmt .Errorf ("error while creating request: %+v\n url: %s\n " , err , apiUrl )
400+ }
401+
402+ req .AddCookie (authCookie )
403+ req .Header .Add ("CSRFPreventionToken" , token .Data .CSRF )
404+ req .Header .Add ("Content-Type" , "application/x-www-form-urlencoded" )
405+
406+ resp , err := client .Do (req )
407+ if err != nil {
408+ return ProxmoxJobStatus {}, fmt .Errorf ("error while performing request: %+v\n " , err )
409+ }
410+
411+ if resp .StatusCode != 200 {
412+ return ProxmoxJobStatus {}, fmt .Errorf ("unexpected status code %d returned from server: %s\n " , resp .StatusCode , resp .Status )
413+ }
414+
415+ body , err := io .ReadAll (resp .Body )
416+ if err != nil {
417+ return ProxmoxJobStatus {}, fmt .Errorf ("error while reading response from server: %v\n " , err )
418+ }
419+
420+ var jobStatus rawProxmoxJobStatus
421+ err = json .Unmarshal (body , & jobStatus )
422+ if err != nil {
423+ return ProxmoxJobStatus {}, fmt .Errorf ("error while unmarshalling json from server: %v\n " , err )
424+ }
364425
365- return newVm , nil
426+ return jobStatus . Data , nil
366427}
0 commit comments