Skip to content

Commit 6817994

Browse files
committed
fix: use stateless structs for public VMM code
resolve TODO: use VmmActions with (entrypoint, args) tuples and rename structs and varaibles to with `spec` suffix Signed-off-by: Aaron Ang <aaron.angyd@gmail.com>
1 parent 4993d4d commit 6817994

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1204
-1162
lines changed

src/cpu-template-helper/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ fn run(cli: Cli) -> Result<(), HelperError> {
161161
let (vmm, vm_resources) = utils::build_microvm_from_config(config, template)?;
162162

163163
let cpu_template = vm_resources
164-
.machine_config
164+
.machine_spec
165165
.cpu_template
166166
.get_cpu_template()?
167167
.into_owned();

src/cpu-template-helper/src/utils/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn add_suffix(path: &Path, suffix: &str) -> PathBuf {
165165
pub mod tests {
166166
use std::fmt::Display;
167167

168-
use vmm::resources::VmmConfig;
168+
use vmm::resources::VmmSpec;
169169

170170
use super::*;
171171

@@ -217,8 +217,8 @@ pub mod tests {
217217
assert!(kernel.as_file().metadata().unwrap().len() > 0);
218218
// Ensure the rootfs exists and it is empty.
219219
assert_eq!(rootfs.as_file().metadata().unwrap().len(), 0);
220-
// Ensure the generated config is valid as `VmmConfig`.
221-
serde_json::from_str::<VmmConfig>(&config).unwrap();
220+
// Ensure the generated config is valid as `VmmSpec`.
221+
serde_json::from_str::<VmmSpec>(&config).unwrap();
222222
}
223223
// Ensure the temporary mock resources are deleted.
224224
assert!(!kernel_path.exists());

src/firecracker/src/api_server/parsed_request.rs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl TryFrom<&Request> for ParsedRequest {
8484
(Method::Get, "balloon", None) => parse_get_balloon(path_tokens),
8585
(Method::Get, "version", None) => parse_get_version(),
8686
(Method::Get, "vm", None) if path_tokens.next() == Some("config") => {
87-
Ok(ParsedRequest::new_sync(VmmAction::GetFullVmConfig))
87+
Ok(ParsedRequest::new_sync(VmmAction::GetFullVmSpec))
8888
}
8989
(Method::Get, "machine-config", None) => parse_get_machine_config(),
9090
(Method::Get, "mmds", None) => parse_get_mmds(),
@@ -179,12 +179,12 @@ impl ParsedRequest {
179179
info!("The request was executed successfully. Status code: 204 No Content.");
180180
Response::new(Version::Http11, StatusCode::NoContent)
181181
}
182-
VmmData::MachineConfiguration(machine_config) => {
183-
Self::success_response_with_data(machine_config)
182+
VmmData::MachineSpec(machine_spec) => {
183+
Self::success_response_with_data(machine_spec)
184184
}
185185
VmmData::MmdsValue(value) => Self::success_response_with_mmds_value(value),
186-
VmmData::BalloonConfig(balloon_config) => {
187-
Self::success_response_with_data(balloon_config)
186+
VmmData::BalloonSpec(balloon_spec) => {
187+
Self::success_response_with_data(balloon_spec)
188188
}
189189
VmmData::BalloonStats(stats) => Self::success_response_with_data(stats),
190190
VmmData::VirtioMemStatus(data) => Self::success_response_with_data(data),
@@ -195,7 +195,7 @@ impl ParsedRequest {
195195
VmmData::VmmVersion(version) => Self::success_response_with_data(
196196
&serde_json::json!({ "firecracker_version": version.as_str() }),
197197
),
198-
VmmData::FullVmConfig(config) => Self::success_response_with_data(config),
198+
VmmData::FullVmSpec(vmm_spec) => Self::success_response_with_data(vmm_spec),
199199
},
200200
Err(vmm_action_error) => {
201201
let mut response = match vmm_action_error {
@@ -223,8 +223,19 @@ impl ParsedRequest {
223223
}
224224

225225
/// Helper function to avoid boiler-plate code.
226-
pub(crate) fn new_sync(vmm_action: VmmAction) -> ParsedRequest {
227-
ParsedRequest::new(RequestAction::Sync(Box::new(vmm_action)))
226+
pub(crate) fn new_sync<T>(vmm_action: T) -> ParsedRequest
227+
where
228+
T: Into<VmmAction>,
229+
{
230+
ParsedRequest::new(RequestAction::Sync(Box::new(vmm_action.into())))
231+
}
232+
233+
pub(crate) fn new_stateless<F, A>(entrypoint: F, args: A) -> ParsedRequest
234+
where
235+
F: FnOnce(A) -> VmmAction,
236+
A: vmm::vmm_config::StatelessArgs,
237+
{
238+
ParsedRequest::new_sync(vmm::vmm_config::VmmActionPayload::new(entrypoint, args))
228239
}
229240
}
230241

@@ -342,11 +353,11 @@ pub mod tests {
342353
use vmm::builder::StartMicrovmError;
343354
use vmm::cpu_config::templates::test_utils::build_test_template;
344355
use vmm::devices::virtio::balloon::device::HintingStatus;
345-
use vmm::resources::VmmConfig;
356+
use vmm::resources::VmmSpec;
346357
use vmm::rpc_interface::VmmActionError;
347-
use vmm::vmm_config::balloon::{BalloonDeviceConfig, BalloonStats};
358+
use vmm::vmm_config::balloon::{BalloonDeviceSpec, BalloonStats};
348359
use vmm::vmm_config::instance_info::InstanceInfo;
349-
use vmm::vmm_config::machine_config::MachineConfig;
360+
use vmm::vmm_config::machine_config::MachineSpec;
350361

351362
use super::*;
352363

@@ -581,8 +592,8 @@ pub mod tests {
581592
let data = Ok(vmm_data);
582593
let mut buf = Cursor::new(vec![0]);
583594
let expected_response = match data.as_ref().unwrap() {
584-
VmmData::BalloonConfig(cfg) => {
585-
http_response(&serde_json::to_string(cfg).unwrap(), 200)
595+
VmmData::BalloonSpec(spec) => {
596+
http_response(&serde_json::to_string(spec).unwrap(), 200)
586597
}
587598
VmmData::BalloonStats(stats) => {
588599
http_response(&serde_json::to_string(stats).unwrap(), 200)
@@ -594,11 +605,11 @@ pub mod tests {
594605
http_response(&serde_json::to_string(status).unwrap(), 200)
595606
}
596607
VmmData::Empty => http_response("", 204),
597-
VmmData::FullVmConfig(cfg) => {
598-
http_response(&serde_json::to_string(cfg).unwrap(), 200)
608+
VmmData::FullVmSpec(spec) => {
609+
http_response(&serde_json::to_string(spec).unwrap(), 200)
599610
}
600-
VmmData::MachineConfiguration(cfg) => {
601-
http_response(&serde_json::to_string(cfg).unwrap(), 200)
611+
VmmData::MachineSpec(spec) => {
612+
http_response(&serde_json::to_string(spec).unwrap(), 200)
602613
}
603614
VmmData::MmdsValue(value) => {
604615
http_response(&serde_json::to_string(value).unwrap(), 200)
@@ -616,7 +627,7 @@ pub mod tests {
616627
assert_eq!(buf.into_inner(), expected_response.as_bytes());
617628
};
618629

619-
verify_ok_response_with(VmmData::BalloonConfig(BalloonDeviceConfig::default()));
630+
verify_ok_response_with(VmmData::BalloonSpec(BalloonDeviceSpec::default()));
620631
verify_ok_response_with(VmmData::BalloonStats(BalloonStats {
621632
swap_in: Some(1),
622633
swap_out: Some(1),
@@ -626,8 +637,8 @@ pub mod tests {
626637
..Default::default()
627638
}));
628639
verify_ok_response_with(VmmData::Empty);
629-
verify_ok_response_with(VmmData::FullVmConfig(VmmConfig::default()));
630-
verify_ok_response_with(VmmData::MachineConfiguration(MachineConfig::default()));
640+
verify_ok_response_with(VmmData::FullVmSpec(VmmSpec::default()));
641+
verify_ok_response_with(VmmData::MachineSpec(MachineSpec::default()));
631642
verify_ok_response_with(VmmData::MmdsValue(serde_json::from_str("{}").unwrap()));
632643
verify_ok_response_with(VmmData::InstanceInformation(InstanceInfo::default()));
633644
verify_ok_response_with(VmmData::VmmVersion(String::default()));

src/firecracker/src/api_server/request/balloon.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
use micro_http::{Method, StatusCode};
55
use vmm::rpc_interface::VmmAction;
6-
use vmm::vmm_config::balloon::{
7-
BalloonDeviceConfig, BalloonUpdateConfig, BalloonUpdateStatsConfig,
8-
};
6+
use vmm::vmm_config::balloon::{BalloonDeviceSpec, BalloonUpdateSpec, BalloonUpdateStatsSpec};
97

108
use super::super::parsed_request::{ParsedRequest, RequestError};
119
use super::Body;
@@ -39,14 +37,15 @@ where
3937
StatusCode::BadRequest,
4038
format!("Unrecognized GET request path `{}`.", stats_path),
4139
)),
42-
None => Ok(ParsedRequest::new_sync(VmmAction::GetBalloonConfig)),
40+
None => Ok(ParsedRequest::new_sync(VmmAction::GetBalloonSpec)),
4341
}
4442
}
4543

4644
pub(crate) fn parse_put_balloon(body: &Body) -> Result<ParsedRequest, RequestError> {
47-
Ok(ParsedRequest::new_sync(VmmAction::SetBalloonDevice(
48-
serde_json::from_slice::<BalloonDeviceConfig>(body.raw())?,
49-
)))
45+
Ok(ParsedRequest::new_stateless(
46+
VmmAction::SetBalloonDevice,
47+
serde_json::from_slice::<BalloonDeviceSpec>(body.raw())?,
48+
))
5049
}
5150

5251
fn parse_patch_hinting<'a, T>(
@@ -64,9 +63,10 @@ where
6463
Some(b) => serde_json::from_slice(b.raw())?,
6564
};
6665

67-
Ok(ParsedRequest::new_sync(VmmAction::StartFreePageHinting(
66+
Ok(ParsedRequest::new_stateless(
67+
VmmAction::StartFreePageHinting,
6868
cmd,
69-
)))
69+
))
7070
}
7171
Some("stop") => Ok(ParsedRequest::new_sync(VmmAction::StopFreePageHinting)),
7272
Some(stats_path) => Err(RequestError::Generic(
@@ -88,15 +88,15 @@ where
8888
T: Iterator<Item = &'a str>,
8989
{
9090
match (path_tokens.next(), body) {
91-
(Some("statistics"), Some(body)) => {
92-
Ok(ParsedRequest::new_sync(VmmAction::UpdateBalloonStatistics(
93-
serde_json::from_slice::<BalloonUpdateStatsConfig>(body.raw())?,
94-
)))
95-
}
91+
(Some("statistics"), Some(body)) => Ok(ParsedRequest::new_stateless(
92+
VmmAction::UpdateBalloonStatistics,
93+
serde_json::from_slice::<BalloonUpdateStatsSpec>(body.raw())?,
94+
)),
9695
(Some("hinting"), body) => parse_patch_hinting(body, path_tokens),
97-
(_, Some(body)) => Ok(ParsedRequest::new_sync(VmmAction::UpdateBalloon(
98-
serde_json::from_slice::<BalloonUpdateConfig>(body.raw())?,
99-
))),
96+
(_, Some(body)) => Ok(ParsedRequest::new_stateless(
97+
VmmAction::UpdateBalloon,
98+
serde_json::from_slice::<BalloonUpdateSpec>(body.raw())?,
99+
)),
100100
(_, None) => method_to_error(Method::Patch),
101101
}
102102
}
@@ -183,25 +183,25 @@ mod tests {
183183
let body = r#"{
184184
"amount_mib": 1
185185
}"#;
186-
let expected_config = BalloonUpdateConfig { amount_mib: 1 };
186+
let expected_spec = BalloonUpdateSpec { amount_mib: 1 };
187187
assert_eq!(
188188
vmm_action_from_request(
189189
parse_patch_balloon(Some(&Body::new(body)), [].into_iter()).unwrap()
190190
),
191-
VmmAction::UpdateBalloon(expected_config)
191+
VmmAction::UpdateBalloon(expected_spec)
192192
);
193193

194194
let body = r#"{
195195
"stats_polling_interval_s": 1
196196
}"#;
197-
let expected_config = BalloonUpdateStatsConfig {
197+
let expected_spec = BalloonUpdateStatsSpec {
198198
stats_polling_interval_s: 1,
199199
};
200200
assert_eq!(
201201
vmm_action_from_request(
202202
parse_patch_balloon(Some(&Body::new(body)), ["statistics"].into_iter()).unwrap()
203203
),
204-
VmmAction::UpdateBalloonStatistics(expected_config)
204+
VmmAction::UpdateBalloonStatistics(expected_spec)
205205
);
206206

207207
// PATCH start hinting run valid data

src/firecracker/src/api_server/request/boot_source.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33

44
use vmm::logger::{IncMetric, METRICS};
55
use vmm::rpc_interface::VmmAction;
6-
use vmm::vmm_config::boot_source::BootSourceConfig;
6+
use vmm::vmm_config::boot_source::BootSourceSpec;
77

88
use super::super::parsed_request::{ParsedRequest, RequestError};
99
use super::Body;
1010

1111
pub(crate) fn parse_put_boot_source(body: &Body) -> Result<ParsedRequest, RequestError> {
1212
METRICS.put_api_requests.boot_source_count.inc();
13-
Ok(ParsedRequest::new_sync(VmmAction::ConfigureBootSource(
14-
serde_json::from_slice::<BootSourceConfig>(body.raw()).inspect_err(|_| {
13+
Ok(ParsedRequest::new_stateless(
14+
VmmAction::ConfigureBootSource,
15+
serde_json::from_slice::<BootSourceSpec>(body.raw()).inspect_err(|_| {
1516
METRICS.put_api_requests.boot_source_fails.inc();
1617
})?,
17-
)))
18+
))
1819
}
1920

2021
#[cfg(test)]
@@ -30,7 +31,7 @@ mod tests {
3031
"initrd_path": "/bar/foo",
3132
"boot_args": "foobar"
3233
}"#;
33-
let same_body = BootSourceConfig {
34+
let same_body = BootSourceSpec {
3435
kernel_image_path: String::from("/foo/bar"),
3536
initrd_path: Some(String::from("/bar/foo")),
3637
boot_args: Some(String::from("foobar")),

src/firecracker/src/api_server/request/cpu_configuration.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ pub(crate) fn parse_put_cpu_config(body: &Body) -> Result<ParsedRequest, Request
1212
METRICS.put_api_requests.cpu_cfg_count.inc();
1313

1414
// Convert the API request into a a deserialized/binary format
15-
Ok(ParsedRequest::new_sync(VmmAction::PutCpuConfiguration(
15+
Ok(ParsedRequest::new_stateless(
16+
VmmAction::PutCpuConfiguration,
1617
CustomCpuTemplate::try_from(body.raw()).map_err(|err| {
1718
METRICS.put_api_requests.cpu_cfg_fails.inc();
1819
RequestError::SerdeJson(err)
1920
})?,
20-
)))
21+
))
2122
}
2223

2324
#[cfg(test)]

src/firecracker/src/api_server/request/drive.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use vmm::logger::{IncMetric, METRICS};
55
use vmm::rpc_interface::VmmAction;
6-
use vmm::vmm_config::drive::{BlockDeviceConfig, BlockDeviceUpdateConfig};
6+
use vmm::vmm_config::drive::{BlockDeviceSpec, BlockDeviceUpdateSpec};
77

88
use super::super::parsed_request::{ParsedRequest, RequestError, checked_id};
99
use super::{Body, StatusCode};
@@ -20,20 +20,21 @@ pub(crate) fn parse_put_drive(
2020
return Err(RequestError::EmptyID);
2121
};
2222

23-
let device_cfg = serde_json::from_slice::<BlockDeviceConfig>(body.raw()).inspect_err(|_| {
23+
let device_spec = serde_json::from_slice::<BlockDeviceSpec>(body.raw()).inspect_err(|_| {
2424
METRICS.put_api_requests.drive_fails.inc();
2525
})?;
2626

27-
if id != device_cfg.drive_id {
27+
if id != device_spec.drive_id {
2828
METRICS.put_api_requests.drive_fails.inc();
2929
Err(RequestError::Generic(
3030
StatusCode::BadRequest,
3131
"The id from the path does not match the id from the body!".to_string(),
3232
))
3333
} else {
34-
Ok(ParsedRequest::new_sync(VmmAction::InsertBlockDevice(
35-
device_cfg,
36-
)))
34+
Ok(ParsedRequest::new_stateless(
35+
VmmAction::InsertBlockDevice,
36+
device_spec,
37+
))
3738
}
3839
}
3940

@@ -49,22 +50,23 @@ pub(crate) fn parse_patch_drive(
4950
return Err(RequestError::EmptyID);
5051
};
5152

52-
let block_device_update_cfg: BlockDeviceUpdateConfig =
53-
serde_json::from_slice::<BlockDeviceUpdateConfig>(body.raw()).inspect_err(|_| {
53+
let block_device_update_spec: BlockDeviceUpdateSpec =
54+
serde_json::from_slice::<BlockDeviceUpdateSpec>(body.raw()).inspect_err(|_| {
5455
METRICS.patch_api_requests.drive_fails.inc();
5556
})?;
5657

57-
if id != block_device_update_cfg.drive_id {
58+
if id != block_device_update_spec.drive_id {
5859
METRICS.patch_api_requests.drive_fails.inc();
5960
return Err(RequestError::Generic(
6061
StatusCode::BadRequest,
6162
String::from("The id from the path does not match the id from the body!"),
6263
));
6364
}
6465

65-
Ok(ParsedRequest::new_sync(VmmAction::UpdateBlockDevice(
66-
block_device_update_cfg,
67-
)))
66+
Ok(ParsedRequest::new_stateless(
67+
VmmAction::UpdateBlockDevice,
68+
block_device_update_spec,
69+
))
6870
}
6971

7072
#[cfg(test)]
@@ -133,14 +135,14 @@ mod tests {
133135
"drive_id": "foo",
134136
"path_on_host": "dummy"
135137
}"#;
136-
let expected_config = BlockDeviceUpdateConfig {
138+
let expected_spec = BlockDeviceUpdateSpec {
137139
drive_id: "foo".to_string(),
138140
path_on_host: Some("dummy".to_string()),
139141
rate_limiter: None,
140142
};
141143
assert_eq!(
142144
vmm_action_from_request(parse_patch_drive(&Body::new(body), Some("foo")).unwrap()),
143-
VmmAction::UpdateBlockDevice(expected_config)
145+
VmmAction::UpdateBlockDevice(expected_spec)
144146
);
145147

146148
let body = r#"{

src/firecracker/src/api_server/request/entropy.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use vmm::rpc_interface::VmmAction;
5-
use vmm::vmm_config::entropy::EntropyDeviceConfig;
5+
use vmm::vmm_config::entropy::EntropyDeviceSpec;
66

77
use super::super::parsed_request::{ParsedRequest, RequestError};
88
use super::Body;
99

1010
pub(crate) fn parse_put_entropy(body: &Body) -> Result<ParsedRequest, RequestError> {
11-
let cfg = serde_json::from_slice::<EntropyDeviceConfig>(body.raw())?;
12-
Ok(ParsedRequest::new_sync(VmmAction::SetEntropyDevice(cfg)))
11+
let spec = serde_json::from_slice::<EntropyDeviceSpec>(body.raw())?;
12+
Ok(ParsedRequest::new_stateless(
13+
VmmAction::SetEntropyDevice,
14+
spec,
15+
))
1316
}
1417

1518
#[cfg(test)]

0 commit comments

Comments
 (0)