Skip to content

Commit f70cc8e

Browse files
zulinx86kalyazin
authored andcommitted
feat(tool): Add fingerprint subcommand
Add an additional nested structure to accomodate two different types of operations (template-related and fingerprint-related operations). This leads to a double-nested structure, but instead gives clarity about how to use the tool preventing users from misuse. Signed-off-by: Takahiro Itazuri <[email protected]>
1 parent 194e22c commit f70cc8e

File tree

2 files changed

+73
-54
lines changed

2 files changed

+73
-54
lines changed

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

Lines changed: 62 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ const EXIT_CODE_ERROR: i32 = 1;
1818
enum Error {
1919
#[error("Failed to operate file: {0}")]
2020
FileIo(#[from] std::io::Error),
21-
#[error("{0}")]
22-
DumpCpuConfig(#[from] dump::Error),
2321
#[error("CPU template is not specified: {0}")]
2422
NoCpuTemplate(#[from] GetCpuTemplateError),
2523
#[error("Failed to serialize/deserialize JSON file: {0}")]
2624
Serde(#[from] serde_json::Error),
2725
#[error("{0}")]
2826
Utils(#[from] utils::Error),
2927
#[error("{0}")]
30-
VerifyCpuTemplate(#[from] verify::Error),
28+
TemplateDump(#[from] dump::Error),
29+
#[error("{0}")]
30+
TemplateVerify(#[from] verify::Error),
3131
}
3232

3333
type Result<T> = std::result::Result<T, Error>;
@@ -41,7 +41,17 @@ struct Cli {
4141

4242
#[derive(Subcommand)]
4343
enum Command {
44-
/// Dump CPU configuration in custom CPU template format.
44+
/// Template-related operations
45+
#[command(subcommand)]
46+
Template(TemplateOperation),
47+
/// Fingerprint-related operations
48+
#[command(subcommand)]
49+
Fingerprint(FingerprintOperation),
50+
}
51+
52+
#[derive(Subcommand)]
53+
enum TemplateOperation {
54+
/// Dump guest CPU configuration in the custom CPU template format.
4555
Dump {
4656
/// Path of firecracker config file.
4757
#[arg(short, long, value_name = "PATH")]
@@ -50,7 +60,7 @@ enum Command {
5060
#[arg(short, long, value_name = "PATH", default_value = "cpu_config.json")]
5161
output: PathBuf,
5262
},
53-
/// Strip items shared between multiple CPU configurations.
63+
/// Strip entries shared between multiple CPU template files.
5464
Strip {
5565
/// List of paths of input CPU configuration files.
5666
#[arg(short, long, num_args = 2..)]
@@ -59,55 +69,61 @@ enum Command {
5969
#[arg(short, long, default_value = "_stripped")]
6070
suffix: String,
6171
},
62-
/// Verify that the given CPU template is applied as intended.
72+
/// Verify that the given CPU template file is applied as intended.
6373
Verify {
64-
/// Path of firecracker config file specifying CPU template.
74+
/// Path of firecracker config file specifying the target CPU template.
6575
#[arg(short, long, value_name = "PATH")]
6676
config: PathBuf,
6777
},
6878
}
6979

80+
#[derive(Subcommand)]
81+
enum FingerprintOperation {}
82+
7083
fn run(cli: Cli) -> Result<()> {
7184
match cli.command {
72-
Command::Dump { config, output } => {
73-
let config = read_to_string(config)?;
74-
let (vmm, _) = utils::build_microvm_from_config(&config)?;
75-
76-
let cpu_config = dump::dump(vmm)?;
77-
78-
let cpu_config_json = serde_json::to_string_pretty(&cpu_config)?;
79-
write(output, cpu_config_json)?;
80-
}
81-
Command::Strip { paths, suffix } => {
82-
let mut templates = Vec::with_capacity(paths.len());
83-
for path in &paths {
84-
let template_json = read_to_string(path)?;
85-
let template: CustomCpuTemplate = serde_json::from_str(&template_json)?;
86-
templates.push(template);
87-
}
85+
Command::Template(op) => match op {
86+
TemplateOperation::Dump { config, output } => {
87+
let config = read_to_string(config)?;
88+
let (vmm, _) = utils::build_microvm_from_config(&config)?;
8889

89-
let stripped_templates = strip::strip(templates);
90+
let cpu_config = dump::dump(vmm)?;
9091

91-
for (path, template) in paths.into_iter().zip(stripped_templates.into_iter()) {
92-
let path = utils::add_suffix(&path, &suffix);
93-
let template_json = serde_json::to_string_pretty(&template)?;
94-
write(path, template_json)?;
92+
let cpu_config_json = serde_json::to_string_pretty(&cpu_config)?;
93+
write(output, cpu_config_json)?;
9594
}
96-
}
97-
Command::Verify { config } => {
98-
let config = read_to_string(config)?;
99-
let (vmm, vm_resources) = utils::build_microvm_from_config(&config)?;
100-
101-
let cpu_template = vm_resources
102-
.vm_config
103-
.cpu_template
104-
.get_cpu_template()?
105-
.into_owned();
106-
let cpu_config = dump::dump(vmm)?;
107-
108-
verify::verify(cpu_template, cpu_config)?;
109-
}
110-
};
95+
TemplateOperation::Strip { paths, suffix } => {
96+
let mut templates = Vec::with_capacity(paths.len());
97+
for path in &paths {
98+
let template_json = read_to_string(path)?;
99+
let template: CustomCpuTemplate = serde_json::from_str(&template_json)?;
100+
templates.push(template);
101+
}
102+
103+
let stripped_templates = strip::strip(templates);
104+
105+
for (path, template) in paths.into_iter().zip(stripped_templates.into_iter()) {
106+
let path = utils::add_suffix(&path, &suffix);
107+
let template_json = serde_json::to_string_pretty(&template)?;
108+
write(path, template_json)?;
109+
}
110+
}
111+
TemplateOperation::Verify { config } => {
112+
let config = read_to_string(config)?;
113+
let (vmm, vm_resources) = utils::build_microvm_from_config(&config)?;
114+
115+
let cpu_template = vm_resources
116+
.vm_config
117+
.cpu_template
118+
.get_cpu_template()?
119+
.into_owned();
120+
let cpu_config = dump::dump(vmm)?;
121+
122+
verify::verify(cpu_template, cpu_config)?;
123+
}
124+
},
125+
Command::Fingerprint(_) => {}
126+
}
111127

112128
Ok(())
113129
}
@@ -263,6 +279,7 @@ mod tests {
263279

264280
let args = vec![
265281
"cpu-template-helper",
282+
"template",
266283
"dump",
267284
"--config",
268285
config_file.as_path().to_str().unwrap(),
@@ -278,7 +295,7 @@ mod tests {
278295
fn test_strip_command() {
279296
let files = vec![generate_sample_modifiers(), generate_sample_modifiers()];
280297

281-
let mut args = vec!["cpu-template-helper", "strip", "-p"];
298+
let mut args = vec!["cpu-template-helper", "template", "strip", "-p"];
282299
let paths = files
283300
.iter()
284301
.map(|file| file.as_path().to_str().unwrap())
@@ -302,6 +319,7 @@ mod tests {
302319

303320
let args = vec![
304321
"cpu-template-helper",
322+
"template",
305323
"verify",
306324
"--config",
307325
config_file.as_path().to_str().unwrap(),

tests/integration_tests/functional/test_cpu_template_helper.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,17 @@ def __init__(self):
4646
cwd=defs.FC_WORKSPACE_DIR,
4747
)
4848

49-
def dump(self, vm_config_path, output_path):
50-
"""Dump CPU config in JSON format by calling dump subcommand"""
49+
def template_dump(self, vm_config_path, output_path):
50+
"""Dump guest CPU config in the JSON custom CPU template format"""
5151
cmd = (
52-
f"{self.BINARY_PATH} dump --config {vm_config_path} --output {output_path}"
52+
f"{self.BINARY_PATH} template dump"
53+
f" --config {vm_config_path} --output {output_path}"
5354
)
5455
utils.run_cmd(cmd)
5556

56-
def verify(self, vm_config_path):
57-
"""Verify the specified CPU template by calling verify subcommand"""
58-
cmd = f"{self.BINARY_PATH} verify --config {vm_config_path}"
57+
def template_verify(self, vm_config_path):
58+
"""Verify the specified CPU template"""
59+
cmd = f"{self.BINARY_PATH} template verify --config {vm_config_path}"
5960
utils.run_cmd(cmd)
6061

6162

@@ -240,7 +241,7 @@ def test_cpu_config_dump_vs_actual(
240241

241242
# Dump CPU config with the helper tool.
242243
cpu_config_path = tmp_path / "cpu_config.json"
243-
cpu_template_helper.dump(vm_config_path, cpu_config_path)
244+
cpu_template_helper.template_dump(vm_config_path, cpu_config_path)
244245
dump_cpu_config = build_cpu_config_dict(cpu_config_path)
245246

246247
# Retrieve actual CPU config from guest
@@ -304,12 +305,12 @@ def test_cpu_config_change(test_microvm_with_api, cpu_template_helper, tmp_path)
304305

305306
# Dump CPU config with the generated VM config.
306307
cpu_config_path = tmp_path / "cpu_config.json"
307-
cpu_template_helper.dump(vm_config_path, cpu_config_path)
308+
cpu_template_helper.template_dump(vm_config_path, cpu_config_path)
308309

309310
# Baseline CPU config.
310311
baseline_path = f"{TEST_RESOURCES_DIR}/cpu_config_{global_props.cpu_codename}_{global_props.host_linux_version}host.json"
311312
# Use this code to generate baseline CPU config.
312-
# cpu_template_helper.dump(vm_config_path, baseline_path)
313+
# cpu_template_helper.template_dump(vm_config_path, baseline_path)
313314

314315
# Compare with baseline
315316
utils.run_cmd(f"diff {cpu_config_path} {baseline_path} -C 10")
@@ -328,4 +329,4 @@ def test_json_static_templates(
328329
vm_config_path = save_vm_config(microvm, tmp_path, custom_cpu_template["template"])
329330

330331
# Verify the JSON static CPU template.
331-
cpu_template_helper.verify(vm_config_path)
332+
cpu_template_helper.template_verify(vm_config_path)

0 commit comments

Comments
 (0)