@@ -10,15 +10,18 @@ use vmsocket::VmSocket;
10
10
use super :: ProcessorTopology ;
11
11
use crate :: Firmware ;
12
12
use crate :: IsolationType ;
13
+ use crate :: NoPetriVmInspector ;
13
14
use crate :: OpenHclConfig ;
14
15
use crate :: OpenHclServicingFlags ;
15
16
use crate :: PetriVmConfig ;
17
+ use crate :: PetriVmFramebufferAccess ;
16
18
use crate :: PetriVmResources ;
17
19
use crate :: PetriVmRuntime ;
18
20
use crate :: PetriVmmBackend ;
19
21
use crate :: SecureBootTemplate ;
20
22
use crate :: ShutdownKind ;
21
23
use crate :: UefiConfig ;
24
+ use crate :: VmScreenshotMeta ;
22
25
use crate :: disk_image:: AgentImage ;
23
26
use crate :: hyperv:: powershell:: HyperVSecureBootTemplate ;
24
27
use crate :: openhcl_diag:: OpenHclDiagHandler ;
@@ -42,6 +45,8 @@ use pipette_client::PipetteClient;
42
45
use std:: fs;
43
46
use std:: io:: Write ;
44
47
use std:: path:: Path ;
48
+ use std:: sync:: Arc ;
49
+ use std:: sync:: Weak ;
45
50
use std:: time:: Duration ;
46
51
use vm:: HyperVVM ;
47
52
use vmm_core_defs:: HaltReason ;
@@ -51,10 +56,10 @@ pub struct HyperVPetriBackend {}
51
56
52
57
/// Resources needed at runtime for a Hyper-V Petri VM
53
58
pub struct HyperVPetriRuntime {
54
- vm : HyperVVM ,
59
+ vm : Arc < HyperVVM > ,
55
60
log_tasks : Vec < Task < anyhow:: Result < ( ) > > > ,
56
61
temp_dir : tempfile:: TempDir ,
57
- openhcl_diag_handler : Option < OpenHclDiagHandler > ,
62
+ is_openhcl : bool ,
58
63
driver : DefaultDriver ,
59
64
}
60
65
@@ -299,7 +304,7 @@ impl PetriVmmBackend for HyperVPetriBackend {
299
304
}
300
305
}
301
306
302
- let openhcl_diag_handler = if let Some ( (
307
+ if let Some ( (
303
308
src_igvm_file,
304
309
OpenHclConfig {
305
310
vtl2_nvme_boot : _, // TODO, see #1649.
@@ -365,13 +370,7 @@ impl PetriVmmBackend for HyperVPetriBackend {
365
370
}
366
371
}
367
372
} ) ) ;
368
-
369
- Some ( OpenHclDiagHandler :: new (
370
- diag_client:: DiagClient :: from_hyperv_id ( driver. clone ( ) , * vm. vmid ( ) ) ,
371
- ) )
372
- } else {
373
- None
374
- } ;
373
+ }
375
374
376
375
let serial_pipe_path = vm. set_vm_com_port ( 1 ) ?;
377
376
let serial_log_file = log_source. log_file ( "guest" ) ?;
@@ -390,22 +389,25 @@ impl PetriVmmBackend for HyperVPetriBackend {
390
389
vm. start ( ) ?;
391
390
392
391
Ok ( HyperVPetriRuntime {
393
- vm,
392
+ vm : Arc :: new ( vm ) ,
394
393
log_tasks,
395
394
temp_dir,
396
- openhcl_diag_handler ,
395
+ is_openhcl : openhcl_config . is_some ( ) ,
397
396
driver : driver. clone ( ) ,
398
397
} )
399
398
}
400
399
}
401
400
402
401
#[ async_trait]
403
402
impl PetriVmRuntime for HyperVPetriRuntime {
404
- async fn teardown ( self ) -> anyhow:: Result < ( ) > {
405
- for t in self . log_tasks {
406
- _ = t. cancel ( ) ;
407
- }
408
- self . vm . remove ( )
403
+ type VmInspector = NoPetriVmInspector ;
404
+ type VmFramebufferAccess = HyperVFramebufferAccess ;
405
+
406
+ async fn teardown ( mut self ) -> anyhow:: Result < ( ) > {
407
+ futures:: future:: join_all ( self . log_tasks . into_iter ( ) . map ( |t| t. cancel ( ) ) ) . await ;
408
+ Arc :: into_inner ( self . vm )
409
+ . context ( "all references to the Hyper-V VM object have not been closed" ) ?
410
+ . remove ( )
409
411
}
410
412
411
413
async fn wait_for_halt ( & mut self ) -> anyhow:: Result < HaltReason > {
@@ -450,8 +452,13 @@ impl PetriVmRuntime for HyperVPetriRuntime {
450
452
. context ( "failed to connect to pipette" )
451
453
}
452
454
453
- fn openhcl_diag ( & self ) -> Option < & OpenHclDiagHandler > {
454
- self . openhcl_diag_handler . as_ref ( )
455
+ fn openhcl_diag ( & self ) -> Option < OpenHclDiagHandler > {
456
+ self . is_openhcl . then ( || {
457
+ OpenHclDiagHandler :: new ( diag_client:: DiagClient :: from_hyperv_id (
458
+ self . driver . clone ( ) ,
459
+ * self . vm . vmid ( ) ,
460
+ ) )
461
+ } )
455
462
}
456
463
457
464
async fn wait_for_successful_boot_event ( & mut self ) -> anyhow:: Result < ( ) > {
@@ -483,6 +490,26 @@ impl PetriVmRuntime for HyperVPetriRuntime {
483
490
// TODO: Updating the file causes failure ... self.vm.set_openhcl_firmware(new_openhcl.get(), false)?;
484
491
self . vm . restart_openhcl ( flags) . await
485
492
}
493
+
494
+ fn take_framebuffer_access ( & mut self ) -> Option < HyperVFramebufferAccess > {
495
+ Some ( HyperVFramebufferAccess {
496
+ vm : Arc :: downgrade ( & self . vm ) ,
497
+ } )
498
+ }
499
+ }
500
+
501
+ /// Interface to the Hyper-V framebuffer
502
+ pub struct HyperVFramebufferAccess {
503
+ vm : Weak < HyperVVM > ,
504
+ }
505
+
506
+ impl PetriVmFramebufferAccess for HyperVFramebufferAccess {
507
+ fn screenshot ( & mut self , image : & mut Vec < u8 > ) -> anyhow:: Result < VmScreenshotMeta > {
508
+ self . vm
509
+ . upgrade ( )
510
+ . context ( "VM no longer exists" ) ?
511
+ . screenshot ( image)
512
+ }
486
513
}
487
514
488
515
fn acl_read_for_vm ( path : & Path , id : Option < guid:: Guid > ) -> anyhow:: Result < ( ) > {
0 commit comments