firecracker
179 строк · 5.3 Кб
1# Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2# SPDX-License-Identifier: Apache-2.0
3"""Functionality for a shared binary build and release path for all tests."""
4
5import os
6import platform
7from pathlib import Path
8
9from framework import defs, utils
10from framework.defs import FC_WORKSPACE_DIR
11from framework.with_filelock import with_filelock
12
13CARGO_BUILD_REL_PATH = "firecracker_binaries"
14"""Keep a single build path across all build tests."""
15
16CARGO_RELEASE_REL_PATH = os.path.join(CARGO_BUILD_REL_PATH, "release")
17"""Keep a single Firecracker release binary path across all test types."""
18
19
20DEFAULT_BUILD_TARGET = "{}-unknown-linux-musl".format(platform.machine())
21RELEASE_BINARIES_REL_PATH = "{}/release/".format(DEFAULT_BUILD_TARGET)
22
23CARGO_UNITTEST_REL_PATH = os.path.join(CARGO_BUILD_REL_PATH, "test")
24
25
26def cargo(
27subcommand,
28cargo_args: str = "",
29subcommand_args: str = "",
30*,
31env: dict = None,
32cwd: str = None,
33):
34"""Executes the specified cargo subcommand"""
35env = env or {}
36
37env_string = " ".join(f'{key}="{str(value)}"' for key, value in env.items())
38
39cmd = f"{env_string} cargo {subcommand} {cargo_args} -- {subcommand_args}"
40
41return utils.run_cmd(cmd, cwd=cwd)
42
43
44def get_rustflags():
45"""Get the relevant rustflags for building/unit testing."""
46if platform.machine() == "aarch64":
47return "-C link-arg=-lgcc -C link-arg=-lfdt "
48return ""
49
50
51@with_filelock
52def cargo_build(path, extra_args="", src_dir=None):
53"""Trigger build depending on flags provided."""
54cargo("build", extra_args, env={"CARGO_TARGET_DIR": path}, cwd=src_dir)
55
56
57def cargo_test(path, extra_args=""):
58"""Trigger unit tests depending on flags provided."""
59env = {
60"CARGO_TARGET_DIR": os.path.join(path, CARGO_UNITTEST_REL_PATH),
61"RUST_TEST_THREADS": 1,
62"RUST_BACKTRACE": 1,
63"RUSTFLAGS": get_rustflags(),
64}
65cargo("test", extra_args + " --all --no-fail-fast", env=env)
66
67
68@with_filelock
69def get_binary(name, *, workspace_dir=FC_WORKSPACE_DIR, example=None):
70"""Build a binary"""
71target = DEFAULT_BUILD_TARGET
72target_dir = workspace_dir / "build" / "cargo_target"
73bin_path = target_dir / target / "release" / name
74cmd = f"-p {name}"
75if example:
76bin_path = target_dir / target / "release" / "examples" / example
77cmd += f" --example {example}"
78if not bin_path.exists():
79env = {"RUSTFLAGS": get_rustflags()}
80cargo(
81"build",
82f"--release --target {target} {cmd}",
83env=env,
84cwd=workspace_dir,
85)
86utils.run_cmd(f"strip --strip-debug {bin_path}")
87return bin_path
88
89
90@with_filelock
91def get_firecracker_binaries(*, workspace_dir=FC_WORKSPACE_DIR):
92"""Build the Firecracker and Jailer binaries if they don't exist.
93
94Returns the location of the firecracker related binaries eventually after
95building them in case they do not exist at the specified root_path.
96"""
97return get_binary("firecracker", workspace_dir=workspace_dir), get_binary(
98"jailer", workspace_dir=workspace_dir
99)
100
101
102def get_example(name, *args, package="firecracker", **kwargs):
103"""Build an example binary"""
104return get_binary(package, *args, **kwargs, example=name)
105
106
107@with_filelock
108def run_seccompiler_bin(bpf_path, json_path=defs.SECCOMP_JSON_DIR, basic=False):
109"""
110Run seccompiler-bin.
111
112:param bpf_path: path to the output file
113:param json_path: optional path to json file
114"""
115cargo_target = "{}-unknown-linux-musl".format(platform.machine())
116
117# If no custom json filter, use the default one for the current target.
118if json_path == defs.SECCOMP_JSON_DIR:
119json_path = json_path / "{}.json".format(cargo_target)
120
121seccompiler_args = f"--input-file {json_path} --target-arch {platform.machine()} --output-file {bpf_path}"
122
123if basic:
124seccompiler_args += " --basic"
125
126rc, _, _ = cargo(
127"run",
128f"-p seccompiler --target-dir {defs.SECCOMPILER_TARGET_DIR} --target {cargo_target}",
129seccompiler_args,
130)
131
132assert rc == 0
133
134
135@with_filelock
136def run_snap_editor_rebase(base_snap, diff_snap):
137"""
138Run apply_diff_snap.
139
140:param base_snap: path to the base snapshot mem file
141:param diff_snap: path to diff snapshot mem file
142"""
143cargo_target = "{}-unknown-linux-musl".format(platform.machine())
144
145rc, _, _ = cargo(
146"run",
147f"-p snapshot-editor --target {cargo_target}",
148f"edit-memory rebase --memory-path {base_snap} --diff-path {diff_snap}",
149)
150
151assert rc == 0
152
153
154@with_filelock
155def run_rebase_snap_bin(base_snap, diff_snap):
156"""
157Run apply_diff_snap.
158
159:param base_snap: path to the base snapshot mem file
160:param diff_snap: path to diff snapshot mem file
161"""
162cargo_target = "{}-unknown-linux-musl".format(platform.machine())
163
164rc, _, _ = cargo(
165"run",
166f"-p rebase-snap --target {cargo_target}",
167f"--base-file {base_snap} --diff-file {diff_snap}",
168)
169
170assert rc == 0
171
172
173@with_filelock
174def gcc_compile(src_file, output_file, extra_flags="-static -O3"):
175"""Build a source file with gcc."""
176output_file = Path(output_file)
177if not output_file.exists():
178compile_cmd = f"gcc {src_file} -o {output_file} {extra_flags}"
179utils.run_cmd(compile_cmd)
180