Skip to main content

flowey_lib_hvlite/
run_prep_steps.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Raw bindings to `prep_steps`, used to prepare test images before running tests.
5
6use crate::build_prep_steps::PrepStepsOutput;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10flowey_request! {
11    pub struct Request {
12        /// Path to prep_steps bin to use
13        pub prep_steps: ReadVar<PrepStepsOutput>,
14        /// Environment variables to set when running prep_steps
15        pub env: ReadVar<BTreeMap<String, String>>,
16        /// Completion indicator
17        pub done: WriteVar<SideEffect>,
18    }
19}
20
21new_simple_flow_node!(struct Node);
22
23impl SimpleFlowNode for Node {
24    type Request = Request;
25
26    fn imports(_ctx: &mut ImportCtx<'_>) {}
27
28    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
29        let Request {
30            prep_steps,
31            env,
32            done,
33        } = request;
34
35        ctx.emit_rust_step("running vmm_test prep_steps", |ctx| {
36            let prep_steps = prep_steps.claim(ctx);
37            let env = env.claim(ctx);
38            done.claim(ctx);
39            move |rt| {
40                let prep_steps = rt.read(prep_steps);
41                let env = rt.read(env);
42
43                #[cfg(windows)]
44                if !matches!(rt.backend(), FlowBackend::Local) {
45                    // Shutdown and remove any running VMs that might be using the disk
46                    // generated during a previous test run. (CI only)
47                    let vms = powershell_builder::PowerShellBuilder::new()
48                        .cmdlet("Get-VM")
49                        .finish()
50                        .build()
51                        .output()?;
52                    log::info!(
53                        "removing any existing VMs: {}",
54                        String::from_utf8_lossy(&vms.stdout)
55                    );
56
57                    powershell_builder::PowerShellBuilder::new()
58                        .cmdlet("Get-VM")
59                        .pipeline()
60                        .cmdlet("Stop-VM")
61                        .flag("TurnOff")
62                        .finish()
63                        .build()
64                        .output()?;
65
66                    powershell_builder::PowerShellBuilder::new()
67                        .cmdlet("Get-VM")
68                        .pipeline()
69                        .cmdlet("Remove-VM")
70                        .flag("Force")
71                        .finish()
72                        .build()
73                        .output()?;
74                }
75
76                let binary_path = match &prep_steps {
77                    PrepStepsOutput::WindowsBin { exe, .. } => exe,
78                    PrepStepsOutput::LinuxBin { bin, .. } => bin,
79                };
80
81                // When running a Windows exe from WSL2, environment variables don't
82                // automatically propagate. We need to set WSLENV to tell WSL which
83                // env vars to share with Windows processes.
84                let is_windows_exe_via_wsl = flowey_lib_common::_util::running_in_wsl(rt)
85                    && matches!(prep_steps, PrepStepsOutput::WindowsBin { .. });
86
87                let mut env = env;
88                if is_windows_exe_via_wsl {
89                    // Inherit the existing WSLENV value if any and append any
90                    // new vars to add. No /p flag needed since paths are
91                    // already converted to Windows format.
92                    let old_wslenv = std::env::var("WSLENV");
93                    let new_wslenv = env.keys().cloned().collect::<Vec<_>>().join(":");
94                    env.insert(
95                        "WSLENV".into(),
96                        format!(
97                            "{}{}",
98                            old_wslenv.map(|s| s + ":").unwrap_or_default(),
99                            new_wslenv
100                        ),
101                    );
102                }
103
104                flowey::shell_cmd!(rt, "{binary_path}").envs(env).run()?;
105
106                Ok(())
107            }
108        });
109
110        Ok(())
111    }
112}