@@ -13,15 +13,14 @@ use crate::IsolationType;
13
13
use crate :: NoPetriVmInspector ;
14
14
use crate :: OpenHclConfig ;
15
15
use crate :: OpenHclServicingFlags ;
16
+ use crate :: PetriHaltReason ;
16
17
use crate :: PetriVmConfig ;
17
- use crate :: PetriVmFramebufferAccess ;
18
18
use crate :: PetriVmResources ;
19
19
use crate :: PetriVmRuntime ;
20
20
use crate :: PetriVmmBackend ;
21
21
use crate :: SecureBootTemplate ;
22
22
use crate :: ShutdownKind ;
23
23
use crate :: UefiConfig ;
24
- use crate :: VmScreenshotMeta ;
25
24
use crate :: disk_image:: AgentImage ;
26
25
use crate :: hyperv:: powershell:: HyperVSecureBootTemplate ;
27
26
use crate :: kmsg_log_task;
@@ -38,32 +37,31 @@ use pal_async::socket::PolledSocket;
38
37
use pal_async:: task:: Spawn ;
39
38
use pal_async:: task:: Task ;
40
39
use pal_async:: timer:: PolledTimer ;
40
+ use petri_artifacts_common:: tags:: GuestQuirks ;
41
+ use petri_artifacts_common:: tags:: GuestQuirksInner ;
41
42
use petri_artifacts_common:: tags:: MachineArch ;
42
43
use petri_artifacts_common:: tags:: OsFlavor ;
43
44
use petri_artifacts_core:: ArtifactResolver ;
44
45
use petri_artifacts_core:: ResolvedArtifact ;
45
46
use pipette_client:: PipetteClient ;
46
- use std:: fs;
47
47
use std:: io:: ErrorKind ;
48
48
use std:: io:: Write ;
49
49
use std:: path:: Path ;
50
- use std:: sync:: Arc ;
51
- use std:: sync:: Weak ;
52
50
use std:: time:: Duration ;
53
51
use vm:: HyperVVM ;
54
- use vmm_core_defs:: HaltReason ;
55
52
56
53
/// The Hyper-V Petri backend
57
54
pub struct HyperVPetriBackend { }
58
55
59
56
/// Resources needed at runtime for a Hyper-V Petri VM
60
57
pub struct HyperVPetriRuntime {
61
- vm : Arc < HyperVVM > ,
58
+ vm : HyperVVM ,
62
59
log_tasks : Vec < Task < anyhow:: Result < ( ) > > > ,
63
60
temp_dir : tempfile:: TempDir ,
61
+ driver : DefaultDriver ,
62
+
64
63
is_openhcl : bool ,
65
64
is_isolated : bool ,
66
- driver : DefaultDriver ,
67
65
}
68
66
69
67
#[ async_trait]
@@ -77,6 +75,10 @@ impl PetriVmmBackend for HyperVPetriBackend {
77
75
&& !( firmware. is_pcat ( ) && arch == MachineArch :: Aarch64 )
78
76
}
79
77
78
+ fn select_quirks ( quirks : GuestQuirks ) -> GuestQuirksInner {
79
+ quirks. hyperv
80
+ }
81
+
80
82
fn new ( _resolver : & ArtifactResolver < ' _ > ) -> Self {
81
83
HyperVPetriBackend { }
82
84
}
@@ -187,7 +189,6 @@ impl PetriVmmBackend for HyperVPetriBackend {
187
189
guest_state_isolation_type,
188
190
memory. startup_bytes ,
189
191
log_source. log_file ( "hyperv" ) ?,
190
- firmware. expected_boot_event ( ) ,
191
192
driver. clone ( ) ,
192
193
)
193
194
. await ?;
@@ -292,7 +293,7 @@ impl PetriVmmBackend for HyperVPetriBackend {
292
293
// location at runtime.
293
294
let imc_hive = temp_dir. path ( ) . join ( "imc.hiv" ) ;
294
295
{
295
- let mut imc_hive_file = fs :: File :: create_new ( & imc_hive) ?;
296
+ let mut imc_hive_file = fs_err :: File :: create_new ( & imc_hive) ?;
296
297
imc_hive_file
297
298
. write_all ( include_bytes ! ( "../../../guest-bootstrap/imc.hiv" ) )
298
299
. context ( "failed to write imc hive" ) ?;
@@ -427,32 +428,28 @@ impl PetriVmmBackend for HyperVPetriBackend {
427
428
vm. start ( ) . await ?;
428
429
429
430
Ok ( HyperVPetriRuntime {
430
- vm : Arc :: new ( vm ) ,
431
+ vm,
431
432
log_tasks,
432
433
temp_dir,
434
+ driver : driver. clone ( ) ,
433
435
is_openhcl : openhcl_config. is_some ( ) ,
434
436
is_isolated : firmware. isolation ( ) . is_some ( ) ,
435
- driver : driver. clone ( ) ,
436
437
} )
437
438
}
438
439
}
439
440
440
441
#[ async_trait]
441
442
impl PetriVmRuntime for HyperVPetriRuntime {
442
443
type VmInspector = NoPetriVmInspector ;
443
- type VmFramebufferAccess = HyperVFramebufferAccess ;
444
+ type VmFramebufferAccess = vm :: HyperVFramebufferAccess ;
444
445
445
446
async fn teardown ( mut self ) -> anyhow:: Result < ( ) > {
446
447
futures:: future:: join_all ( self . log_tasks . into_iter ( ) . map ( |t| t. cancel ( ) ) ) . await ;
447
- Arc :: into_inner ( self . vm )
448
- . context ( "all references to the Hyper-V VM object have not been closed" ) ?
449
- . remove ( )
450
- . await
448
+ self . vm . remove ( ) . await
451
449
}
452
450
453
- async fn wait_for_halt ( & mut self ) -> anyhow:: Result < HaltReason > {
454
- self . vm . wait_for_halt ( ) . await ?;
455
- Ok ( HaltReason :: PowerOff ) // TODO: Get actual halt reason
451
+ async fn wait_for_halt ( & mut self , allow_reset : bool ) -> anyhow:: Result < PetriHaltReason > {
452
+ self . vm . wait_for_halt ( allow_reset) . await
456
453
}
457
454
458
455
async fn wait_for_agent ( & mut self , set_high_vtl : bool ) -> anyhow:: Result < PipetteClient > {
@@ -501,10 +498,6 @@ impl PetriVmRuntime for HyperVPetriRuntime {
501
498
} )
502
499
}
503
500
504
- async fn wait_for_successful_boot_event ( & mut self ) -> anyhow:: Result < ( ) > {
505
- self . vm . wait_for_successful_boot_event ( ) . await
506
- }
507
-
508
501
async fn wait_for_boot_event ( & mut self ) -> anyhow:: Result < FirmwareEvent > {
509
502
self . vm . wait_for_boot_event ( ) . await
510
503
}
@@ -531,26 +524,8 @@ impl PetriVmRuntime for HyperVPetriRuntime {
531
524
self . vm . restart_openhcl ( flags) . await
532
525
}
533
526
534
- fn take_framebuffer_access ( & mut self ) -> Option < HyperVFramebufferAccess > {
535
- ( !self . is_isolated ) . then ( || HyperVFramebufferAccess {
536
- vm : Arc :: downgrade ( & self . vm ) ,
537
- } )
538
- }
539
- }
540
-
541
- /// Interface to the Hyper-V framebuffer
542
- pub struct HyperVFramebufferAccess {
543
- vm : Weak < HyperVVM > ,
544
- }
545
-
546
- #[ async_trait]
547
- impl PetriVmFramebufferAccess for HyperVFramebufferAccess {
548
- async fn screenshot ( & mut self , image : & mut Vec < u8 > ) -> anyhow:: Result < VmScreenshotMeta > {
549
- self . vm
550
- . upgrade ( )
551
- . context ( "VM no longer exists" ) ?
552
- . screenshot ( image)
553
- . await
527
+ fn take_framebuffer_access ( & mut self ) -> Option < vm:: HyperVFramebufferAccess > {
528
+ ( !self . is_isolated ) . then ( || self . vm . get_framebuffer_access ( ) )
554
529
}
555
530
}
556
531
@@ -644,13 +619,15 @@ async fn hyperv_serial_log_task(
644
619
) -> anyhow:: Result < ( ) > {
645
620
let mut timer = None ;
646
621
loop {
647
- match fs_err:: OpenOptions :: new ( )
622
+ // using `std::fs` here instead of `fs_err` since `raw_os_error` always
623
+ // returns `None` for `fs_err` errors.
624
+ match std:: fs:: OpenOptions :: new ( )
648
625
. read ( true )
649
626
. write ( true )
650
627
. open ( & serial_pipe_path)
651
628
{
652
629
Ok ( file) => {
653
- let pipe = PolledPipe :: new ( & driver, file. into ( ) ) . expect ( "failed to create pipe" ) ;
630
+ let pipe = PolledPipe :: new ( & driver, file) . expect ( "failed to create pipe" ) ;
654
631
// connect/disconnect messages logged internally
655
632
_ = crate :: log_task ( log_file. clone ( ) , pipe, & serial_pipe_path) . await ;
656
633
}
@@ -661,7 +638,7 @@ async fn hyperv_serial_log_task(
661
638
if !( err. kind ( ) == ErrorKind :: NotFound
662
639
|| matches ! ( err. raw_os_error( ) , Some ( ERROR_PIPE_BUSY ) ) )
663
640
{
664
- tracing:: warn!( "{ err:#}" )
641
+ tracing:: warn!( "failed to open {serial_pipe_path}: { err:#}" , )
665
642
}
666
643
// Wait a bit and try again.
667
644
timer
0 commit comments