Skip to content

Commit 32f93bc

Browse files
committed
Add postinstall stuff
1 parent 7942be5 commit 32f93bc

18 files changed

Lines changed: 842 additions & 14 deletions

File tree

src/checkers/mod.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
1-
pub mod byo_kernel;
2-
pub mod iommu;
3-
pub mod kernel;
4-
pub mod numa;
5-
pub mod pvh;
6-
pub mod system;
1+
pub mod postinstall;
2+
pub mod preinstall;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use crate::helpers::{
2+
CheckGroup, CheckGroupCategory, CheckGroupResult, CheckResult,
3+
CheckResultValue::{Errored, Failed, Passed},
4+
host_executor::HostNamespaceExecutor,
5+
};
6+
use async_trait::async_trait;
7+
use futures::{FutureExt, future::join_all};
8+
use std::{fs, path::Path};
9+
10+
const GROUP_IDENTIFIER: &str = "guesttype";
11+
const NAME: &str = "Guest Support Checks";
12+
13+
pub struct GuestTypeChecks {
14+
host_executor: HostNamespaceExecutor,
15+
}
16+
17+
impl GuestTypeChecks {
18+
pub fn new(host_executor: HostNamespaceExecutor) -> Self {
19+
GuestTypeChecks { host_executor }
20+
}
21+
22+
/// Run all the checkers asynchronously, then
23+
/// join and collect the results.
24+
pub async fn run_all(&self) -> CheckGroupResult {
25+
let results = join_all([self.check_guest_support().boxed()]).await;
26+
27+
let mut group_result = Passed;
28+
for res in results.iter() {
29+
// Set group result to Failed if we failed and aren't already in an Errored state
30+
if !matches!(group_result, Errored(_)) && matches!(res.result, Failed(_)) {
31+
group_result = Failed("".into());
32+
}
33+
34+
if matches!(res.result, Errored(_)) {
35+
group_result = Errored("".into());
36+
}
37+
}
38+
39+
CheckGroupResult {
40+
name: NAME.to_string(),
41+
result: group_result,
42+
results,
43+
}
44+
}
45+
46+
async fn check_guest_support(&self) -> CheckResult {
47+
let name = String::from("Guest Type Support");
48+
match self
49+
.host_executor
50+
.spawn_in_host_ns(async {
51+
let xen = Path::new("/sys/hypervisor/guest_type");
52+
xen.exists() && fs::read_to_string(xen).unwrap_or_default().trim() == "PVH"
53+
})
54+
.await
55+
{
56+
Ok(true) => CheckResult::new(&name, Passed),
57+
Ok(false) => CheckResult::new(&name, Failed("PVH guests not supported".into())),
58+
Err(e) => CheckResult::new(&name, Errored(format!("Error: {}", e))),
59+
}
60+
}
61+
}
62+
63+
#[async_trait]
64+
impl CheckGroup for GuestTypeChecks {
65+
fn id(&self) -> &str {
66+
GROUP_IDENTIFIER
67+
}
68+
69+
fn name(&self) -> &str {
70+
NAME
71+
}
72+
73+
fn description(&self) -> &str {
74+
"Supported guest type checks"
75+
}
76+
77+
async fn run(&self) -> CheckGroupResult {
78+
self.run_all().await
79+
}
80+
81+
fn category(&self) -> CheckGroupCategory {
82+
CheckGroupCategory::Optional("PVH guest support not available on this system".into())
83+
}
84+
}

src/checkers/postinstall/kernel.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use crate::helpers::{
2+
CheckGroup, CheckGroupCategory, CheckGroupResult, CheckResult,
3+
CheckResultValue::{Errored, Failed, Passed},
4+
host_executor::HostNamespaceExecutor,
5+
kernel as khelper,
6+
};
7+
8+
use async_trait::async_trait;
9+
use futures::{FutureExt, future::join_all};
10+
use procfs::sys::kernel;
11+
12+
const GROUP_IDENTIFIER: &str = "kernel";
13+
const NAME: &str = "Postinstall Kernel Checks";
14+
15+
// Stuff we expect to be available under an Edera host kernel,
16+
// or a supported BYO kernel.
17+
const REQUIRED_MODULES: &[&str] = &[
18+
"nf_tables",
19+
"xen_evtchn",
20+
"xen-privcmd",
21+
"xen-netback",
22+
"xen-pciback",
23+
"xen-blkback",
24+
"xen-gntdev",
25+
"xen-gntalloc",
26+
];
27+
28+
const KVER_FLOOR_PATCH: u16 = 0;
29+
const KVER_FLOOR_MINOR: u8 = 15;
30+
const KVER_FLOOR_MAJOR: u8 = 5;
31+
32+
pub struct PostinstallKernelChecks {
33+
host_executor: HostNamespaceExecutor,
34+
}
35+
36+
impl PostinstallKernelChecks {
37+
pub fn new(host_executor: HostNamespaceExecutor) -> Self {
38+
PostinstallKernelChecks { host_executor }
39+
}
40+
41+
/// Run all the checkers asynchronously, then
42+
/// join and collect the results.
43+
pub async fn run_all(&self) -> CheckGroupResult {
44+
let results = join_all([self.has_modules().boxed(), self.version_is_good().boxed()]).await;
45+
46+
let mut group_result = Passed;
47+
for res in results.iter() {
48+
// Set group result to Failed if we failed and aren't already in an Errored state
49+
if !matches!(group_result, Errored(_)) && matches!(res.result, Failed(_)) {
50+
group_result = Failed("".into());
51+
}
52+
53+
if matches!(res.result, Errored(_)) {
54+
group_result = Errored("".into());
55+
}
56+
}
57+
58+
CheckGroupResult {
59+
name: NAME.to_string(),
60+
result: group_result,
61+
results,
62+
}
63+
}
64+
65+
async fn version_is_good(&self) -> CheckResult {
66+
let name = String::from("Host Kernel Version Is Good");
67+
let floor = kernel::Version::new(KVER_FLOOR_MAJOR, KVER_FLOOR_MINOR, KVER_FLOOR_PATCH);
68+
69+
let passed = khelper::host_kver_above_floor(&self.host_executor, floor).await;
70+
71+
match passed {
72+
Err(e) => CheckResult::new(&name, Errored(e.to_string())),
73+
Ok(true) => CheckResult::new(&name, Passed),
74+
Ok(false) => CheckResult::new(
75+
&name,
76+
Failed(String::from("current kernel version is unsupported")),
77+
),
78+
}
79+
}
80+
81+
async fn has_modules(&self) -> CheckResult {
82+
let name = String::from("Host Has Necessary Modules");
83+
84+
let required_modules: Vec<String> =
85+
REQUIRED_MODULES.iter().map(|s| s.to_string()).collect();
86+
87+
// Search builtin modules
88+
let remaining = match khelper::find_builtins(&self.host_executor, &required_modules).await {
89+
Ok(r) => r,
90+
Err(e) => {
91+
return CheckResult::new(&name, Errored(format!("getting kernel builtins {e}")));
92+
}
93+
};
94+
95+
// Search loaded modules
96+
let remaining = match khelper::find_loaded(&self.host_executor, &remaining).await {
97+
Ok(r) => r,
98+
Err(e) => {
99+
return CheckResult::new(&name, Errored(format!("getting kernel modules {e}")));
100+
}
101+
};
102+
103+
// Search loadable modules
104+
let remaining = match khelper::find_loadable(&self.host_executor, &remaining).await {
105+
Ok(r) => r,
106+
Err(e) => {
107+
return CheckResult::new(&name, Errored(format!("getting kernel modules {e}")));
108+
}
109+
};
110+
if !remaining.is_empty() {
111+
return CheckResult::new(&name, Failed(format!("missing {:?}", remaining)));
112+
}
113+
114+
CheckResult::new(&name, Passed)
115+
}
116+
}
117+
118+
#[async_trait]
119+
impl CheckGroup for PostinstallKernelChecks {
120+
fn id(&self) -> &str {
121+
GROUP_IDENTIFIER
122+
}
123+
124+
fn name(&self) -> &str {
125+
NAME
126+
}
127+
128+
fn description(&self) -> &str {
129+
"Postinstall kernel validation checks"
130+
}
131+
132+
async fn run(&self) -> CheckGroupResult {
133+
self.run_all().await
134+
}
135+
136+
fn category(&self) -> CheckGroupCategory {
137+
CheckGroupCategory::Required
138+
}
139+
}

src/checkers/postinstall/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod guest_type;
2+
pub mod kernel;
3+
pub mod services;

0 commit comments

Comments
 (0)