-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathlibvirt_ignition.rs
More file actions
172 lines (139 loc) · 5.23 KB
/
libvirt_ignition.rs
File metadata and controls
172 lines (139 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//! Integration tests for Ignition config injection in libvirt VMs
use integration_tests::integration_test;
use itest::TestResult;
use scopeguard::defer;
use tempfile::TempDir;
use xshell::cmd;
use std::fs;
use camino::Utf8Path;
use crate::{get_bck_command, shell, LIBVIRT_INTEGRATION_TEST_LABEL};
/// Generate a random alphanumeric suffix for VM names to avoid collisions
fn random_suffix() -> String {
use rand::{distr::Alphanumeric, Rng};
rand::rng()
.sample_iter(&Alphanumeric)
.take(8)
.map(char::from)
.collect()
}
/// Fedora CoreOS image that supports Ignition
const FCOS_IMAGE: &str = "quay.io/fedora/fedora-coreos:stable";
/// Test that Ignition config injection mechanism works for libvirt
///
/// This test verifies that the Ignition config injection mechanism is working
/// by checking that the VM can be created with --ignition flag and that the
/// config file is properly stored.
fn test_libvirt_ignition_works() -> TestResult {
let sh = shell()?;
let bck = get_bck_command()?;
let label = LIBVIRT_INTEGRATION_TEST_LABEL;
// Pull FCOS image first
cmd!(sh, "podman pull -q {FCOS_IMAGE}").run()?;
// Create a temporary Ignition config
let temp_dir = TempDir::new()?;
let config_path = Utf8Path::from_path(temp_dir.path())
.expect("temp dir is not utf8")
.join("config.ign");
// Minimal valid Ignition config (v3.3.0 for FCOS)
let ignition_config = r#"{"ignition": {"version": "3.3.0"}}"#;
fs::write(&config_path, ignition_config)?;
// Generate a unique VM name to avoid conflicts
let vm_name = format!("test-ignition-{}", random_suffix());
// Create VM with Ignition config
// We use --ssh-wait to wait for the VM to boot and verify SSH connectivity
// FCOS requires --filesystem to be specified
let output = cmd!(
sh,
"{bck} libvirt run --name {vm_name} --label {label} --ignition {config_path} --filesystem xfs --ssh-wait --memory 2G --cpus 2 {FCOS_IMAGE}"
)
.ignore_status()
.output()?;
// Cleanup: remove the VM
defer! {
let _ = cmd!(sh, "{bck} libvirt rm {vm_name} --force").run();
}
// Check that the command succeeded
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
panic!(
"Failed to create VM with Ignition config.\nStdout: {}\nStderr: {}",
stdout, stderr
);
}
// Verify the VM was created
let vm_list = cmd!(sh, "{bck} libvirt list").read()?;
assert!(
vm_list.contains(&vm_name),
"VM should be listed after creation"
);
println!("Ignition config injection test passed");
Ok(())
}
integration_test!(test_libvirt_ignition_works);
/// Test that Ignition config validation rejects nonexistent files
fn test_libvirt_ignition_invalid_path() -> TestResult {
let sh = shell()?;
let bck = get_bck_command()?;
let label = LIBVIRT_INTEGRATION_TEST_LABEL;
// Pull FCOS image first
cmd!(sh, "podman pull -q {FCOS_IMAGE}").run()?;
let temp = TempDir::new()?;
let nonexistent_path = Utf8Path::from_path(temp.path())
.expect("temp dir is not utf8")
.join("nonexistent-config.ign");
let vm_name = format!("test-ignition-invalid-{}", random_suffix());
let output = cmd!(
sh,
"{bck} libvirt run --name {vm_name} --label {label} --ignition {nonexistent_path} {FCOS_IMAGE}"
)
.ignore_status()
.output()?;
assert!(
!output.status.success(),
"Should fail with nonexistent Ignition config file"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("not found"),
"Error should mention missing file: {}",
stderr
);
println!("Ignition invalid path test passed");
Ok(())
}
integration_test!(test_libvirt_ignition_invalid_path);
/// Test that Ignition is rejected for images that don't support it
fn test_libvirt_ignition_unsupported_image() -> TestResult {
let sh = shell()?;
let bck = get_bck_command()?;
let label = LIBVIRT_INTEGRATION_TEST_LABEL;
// Use standard bootc image that doesn't have Ignition support
let image = "quay.io/centos-bootc/centos-bootc:stream10";
let temp_dir = TempDir::new()?;
let config_path = Utf8Path::from_path(temp_dir.path())
.expect("temp dir is not utf8")
.join("config.ign");
let ignition_config = r#"{"ignition": {"version": "3.3.0"}}"#;
fs::write(&config_path, ignition_config)?;
let vm_name = format!("test-ignition-unsupported-{}", random_suffix());
let output = cmd!(
sh,
"{bck} libvirt run --name {vm_name} --label {label} --ignition {config_path} {image}"
)
.ignore_status()
.output()?;
assert!(
!output.status.success(),
"Should fail when using --ignition with non-Ignition image"
);
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
stderr.contains("does not support Ignition"),
"Error should mention missing Ignition support: {}",
stderr
);
println!("Ignition unsupported image test passed");
Ok(())
}
integration_test!(test_libvirt_ignition_unsupported_image);