@@ -2,11 +2,11 @@ package virtualbox
2
2
3
3
import (
4
4
"bufio"
5
+ "context"
5
6
"fmt"
6
7
"path/filepath"
7
8
"strconv"
8
9
"strings"
9
- "sync"
10
10
"time"
11
11
)
12
12
@@ -201,18 +201,16 @@ func (m *Machine) Delete() error {
201
201
return Manage ().run ("unregistervm" , m .Name , "--delete" )
202
202
}
203
203
204
- var mutex sync.Mutex
205
-
206
- // GetMachine finds a machine by its name or UUID.
207
- func GetMachine (id string ) (* Machine , error ) {
204
+ // Machine returns the current machine state based on the current state.
205
+ func (m * manager ) Machine (ctx context.Context , id string ) (* Machine , error ) {
208
206
/* There is a strage behavior where running multiple instances of
209
207
'VBoxManage showvminfo' on same VM simultaneously can return an error of
210
208
'object is not ready (E_ACCESSDENIED)', so we sequential the operation with a mutex.
211
209
Note if you are running multiple process of go-virtualbox or 'showvminfo'
212
210
in the command line side by side, this not gonna work. */
213
- mutex .Lock ()
214
- stdout , stderr , err := Manage (). runOutErr ( "showvminfo" , id , "--machinereadable" )
215
- mutex .Unlock ()
211
+ m . lock .Lock ()
212
+ stdout , stderr , err := m . run ( ctx , "showvminfo" , id , "--machinereadable" )
213
+ m . lock .Unlock ()
216
214
if err != nil {
217
215
if reMachineNotFound .FindString (stderr ) != "" {
218
216
return nil , ErrMachineNotExist
@@ -240,27 +238,27 @@ func GetMachine(id string) (*Machine, error) {
240
238
}
241
239
242
240
/* Extract basic info */
243
- m := New ()
244
- m .Name = propMap ["name" ]
245
- m .UUID = propMap ["UUID" ]
246
- m .State = MachineState (propMap ["VMState" ])
241
+ vm := New ()
242
+ vm .Name = propMap ["name" ]
243
+ vm .UUID = propMap ["UUID" ]
244
+ vm .State = MachineState (propMap ["VMState" ])
247
245
n , err := strconv .ParseUint (propMap ["memory" ], 10 , 32 )
248
246
if err != nil {
249
247
return nil , err
250
248
}
251
- m .Memory = uint (n )
249
+ vm .Memory = uint (n )
252
250
n , err = strconv .ParseUint (propMap ["cpus" ], 10 , 32 )
253
251
if err != nil {
254
252
return nil , err
255
253
}
256
- m .CPUs = uint (n )
254
+ vm .CPUs = uint (n )
257
255
n , err = strconv .ParseUint (propMap ["vram" ], 10 , 32 )
258
256
if err != nil {
259
257
return nil , err
260
258
}
261
- m .VRAM = uint (n )
262
- m .CfgFile = propMap ["CfgFile" ]
263
- m .BaseFolder = filepath .Dir (m .CfgFile )
259
+ vm .VRAM = uint (n )
260
+ vm .CfgFile = propMap ["CfgFile" ]
261
+ vm .BaseFolder = filepath .Dir (vm .CfgFile )
264
262
265
263
/* Extract NIC info */
266
264
for i := 1 ; i <= 4 ; i ++ {
@@ -283,29 +281,46 @@ func GetMachine(id string) (*Machine, error) {
283
281
} else if nic .Network == NICNetBridged {
284
282
nic .HostInterface = propMap [fmt .Sprintf ("bridgeadapter%d" , i )]
285
283
}
286
- m .NICs = append (m .NICs , nic )
284
+ vm .NICs = append (vm .NICs , nic )
287
285
}
288
286
289
287
if err := s .Err (); err != nil {
290
288
return nil , err
291
289
}
292
- return m , nil
290
+ return vm , nil
291
+ }
292
+
293
+ // GetMachine finds a machine by its name or UUID.
294
+ //
295
+ // Deprecated: Use Manager.Machine()
296
+ func GetMachine (id string ) (* Machine , error ) {
297
+ return defaultManager .Machine (context .Background (), id )
293
298
}
294
299
295
300
// ListMachines lists all registered machines.
301
+ //
302
+ // Deprecated: Use Manager.ListMachines()
296
303
func ListMachines () ([]* Machine , error ) {
297
- out , err := Manage ().runOut ("list" , "vms" )
304
+ return defaultManager .ListMachines (context .Background ())
305
+ }
306
+
307
+ // ListMachines lists all registered machines.
308
+ func (m * manager ) ListMachines (ctx context.Context ) ([]* Machine , error ) {
309
+ m .lock .Lock ()
310
+ out , _ , err := m .run (ctx , "list" , "vms" )
311
+ m .lock .Unlock ()
298
312
if err != nil {
299
313
return nil , err
300
314
}
315
+
301
316
ms := []* Machine {}
302
317
s := bufio .NewScanner (strings .NewReader (out ))
303
318
for s .Scan () {
304
319
res := reVMNameUUID .FindStringSubmatch (s .Text ())
305
320
if res == nil {
306
321
continue
307
322
}
308
- m , err := GetMachine ( res [1 ])
323
+ m , err := m . Machine ( ctx , res [1 ])
309
324
if err != nil {
310
325
// Sometimes a VM is listed but not available, so we need to handle this.
311
326
if err == ErrMachineNotExist {
@@ -356,44 +371,44 @@ func CreateMachine(name, basefolder string) (*Machine, error) {
356
371
return m , nil
357
372
}
358
373
359
- // Modify changes the settings of the machine .
360
- func (m * Machine ) Modify ( ) error {
361
- args := []string {"modifyvm" , m .Name ,
374
+ // UpdateMachine updates the machine details based on the struct fields .
375
+ func (m * manager ) UpdateMachine ( ctx context. Context , vm * Machine ) error {
376
+ args := []string {"modifyvm" , vm .Name ,
362
377
"--firmware" , "bios" ,
363
378
"--bioslogofadein" , "off" ,
364
379
"--bioslogofadeout" , "off" ,
365
380
"--bioslogodisplaytime" , "0" ,
366
381
"--biosbootmenu" , "disabled" ,
367
382
368
- "--ostype" , m .OSType ,
369
- "--cpus" , fmt .Sprintf ("%d" , m .CPUs ),
370
- "--memory" , fmt .Sprintf ("%d" , m .Memory ),
371
- "--vram" , fmt .Sprintf ("%d" , m .VRAM ),
372
-
373
- "--acpi" , m .Flag .Get (ACPI ),
374
- "--ioapic" , m .Flag .Get (IOAPIC ),
375
- "--rtcuseutc" , m .Flag .Get (RTCUSEUTC ),
376
- "--cpuhotplug" , m .Flag .Get (CPUHOTPLUG ),
377
- "--pae" , m .Flag .Get (PAE ),
378
- "--longmode" , m .Flag .Get (LONGMODE ),
379
- "--hpet" , m .Flag .Get (HPET ),
380
- "--hwvirtex" , m .Flag .Get (HWVIRTEX ),
381
- "--triplefaultreset" , m .Flag .Get (TRIPLEFAULTRESET ),
382
- "--nestedpaging" , m .Flag .Get (NESTEDPAGING ),
383
- "--largepages" , m .Flag .Get (LARGEPAGES ),
384
- "--vtxvpid" , m .Flag .Get (VTXVPID ),
385
- "--vtxux" , m .Flag .Get (VTXUX ),
386
- "--accelerate3d" , m .Flag .Get (ACCELERATE3D ),
387
- }
388
-
389
- for i , dev := range m .BootOrder {
383
+ "--ostype" , vm .OSType ,
384
+ "--cpus" , fmt .Sprintf ("%d" , vm .CPUs ),
385
+ "--memory" , fmt .Sprintf ("%d" , vm .Memory ),
386
+ "--vram" , fmt .Sprintf ("%d" , vm .VRAM ),
387
+
388
+ "--acpi" , vm .Flag .Get (ACPI ),
389
+ "--ioapic" , vm .Flag .Get (IOAPIC ),
390
+ "--rtcuseutc" , vm .Flag .Get (RTCUSEUTC ),
391
+ "--cpuhotplug" , vm .Flag .Get (CPUHOTPLUG ),
392
+ "--pae" , vm .Flag .Get (PAE ),
393
+ "--longmode" , vm .Flag .Get (LONGMODE ),
394
+ "--hpet" , vm .Flag .Get (HPET ),
395
+ "--hwvirtex" , vm .Flag .Get (HWVIRTEX ),
396
+ "--triplefaultreset" , vm .Flag .Get (TRIPLEFAULTRESET ),
397
+ "--nestedpaging" , vm .Flag .Get (NESTEDPAGING ),
398
+ "--largepages" , vm .Flag .Get (LARGEPAGES ),
399
+ "--vtxvpid" , vm .Flag .Get (VTXVPID ),
400
+ "--vtxux" , vm .Flag .Get (VTXUX ),
401
+ "--accelerate3d" , vm .Flag .Get (ACCELERATE3D ),
402
+ }
403
+
404
+ for i , dev := range vm .BootOrder {
390
405
if i > 3 {
391
406
break // Only four slots `--boot{1,2,3,4}`. Ignore the rest.
392
407
}
393
408
args = append (args , fmt .Sprintf ("--boot%d" , i + 1 ), dev )
394
409
}
395
410
396
- for i , nic := range m .NICs {
411
+ for i , nic := range vm .NICs {
397
412
n := i + 1
398
413
args = append (args ,
399
414
fmt .Sprintf ("--nic%d" , n ), string (nic .Network ),
@@ -406,10 +421,14 @@ func (m *Machine) Modify() error {
406
421
}
407
422
}
408
423
409
- if err := Manage () .run (args ... ); err != nil {
424
+ if _ , _ , err := m .run (ctx , args ... ); err != nil {
410
425
return err
411
426
}
412
- return m .Refresh ()
427
+ return vm .Refresh ()
428
+ }
429
+
430
+ func (m * Machine ) Modify () error {
431
+ return defaultManager .UpdateMachine (context .Background (), m )
413
432
}
414
433
415
434
// AddNATPF adds a NAT port forarding rule to the n-th NIC with the given name.
@@ -463,22 +482,27 @@ func (m *Machine) DelStorageCtl(name string) error {
463
482
464
483
// AttachStorage attaches a storage medium to the named storage controller.
465
484
func (m * Machine ) AttachStorage (ctlName string , medium StorageMedium ) error {
466
- return Manage ().run ("storageattach" , m .Name , "--storagectl" , ctlName ,
485
+ _ , _ , err := defaultManager .run (context .Background (),
486
+ "storageattach" , m .Name , "--storagectl" , ctlName ,
467
487
"--port" , fmt .Sprintf ("%d" , medium .Port ),
468
488
"--device" , fmt .Sprintf ("%d" , medium .Device ),
469
489
"--type" , string (medium .DriveType ),
470
490
"--medium" , medium .Medium ,
471
491
)
492
+ return err
472
493
}
473
494
474
495
// SetExtraData attaches custom string to the VM.
475
496
func (m * Machine ) SetExtraData (key , val string ) error {
476
- return Manage ().run ("setextradata" , m .Name , key , val )
497
+ _ , _ , err := defaultManager .run (context .Background (),
498
+ "setextradata" , m .Name , key , val )
499
+ return err
477
500
}
478
501
479
502
// GetExtraData retrieves custom string from the VM.
480
503
func (m * Machine ) GetExtraData (key string ) (* string , error ) {
481
- value , err := Manage ().runOut ("getextradata" , m .Name , key )
504
+ value , _ , err := defaultManager .run (context .Background (),
505
+ "getextradata" , m .Name , key )
482
506
if err != nil {
483
507
return nil , err
484
508
}
@@ -494,13 +518,19 @@ func (m *Machine) GetExtraData(key string) (*string, error) {
494
518
495
519
// DeleteExtraData removes custom string from the VM.
496
520
func (m * Machine ) DeleteExtraData (key string ) error {
497
- return Manage ().run ("setextradata" , m .Name , key )
521
+ _ , _ , err := defaultManager .run (context .Background (),
522
+ "setextradata" , m .Name , key )
523
+ return err
498
524
}
499
525
500
526
// CloneMachine clones the given machine name into a new one.
501
527
func CloneMachine (baseImageName string , newImageName string , register bool ) error {
502
528
if register {
503
- return Manage ().run ("clonevm" , baseImageName , "--name" , newImageName , "--register" )
529
+ _ , _ , err := defaultManager .run (context .Background (),
530
+ "clonevm" , baseImageName , "--name" , newImageName , "--register" )
531
+ return err
504
532
}
505
- return Manage ().run ("clonevm" , baseImageName , "--name" , newImageName )
533
+ _ , _ , err := defaultManager .run (context .Background (),
534
+ "clonevm" , baseImageName , "--name" , newImageName )
535
+ return err
506
536
}
0 commit comments