Skip to content

Commit 7c40c00

Browse files
authored
Merge branch 'main' into skip-redundant-check
2 parents 63e5adb + be2f41a commit 7c40c00

File tree

11 files changed

+62
-121
lines changed

11 files changed

+62
-121
lines changed

Cargo.lock

Lines changed: 13 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/getting-started.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ HOST_IFACE="eth0"
182182
sudo iptables -t nat -D POSTROUTING -o "$HOST_IFACE" -j MASQUERADE || true
183183
sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT \
184184
|| true
185-
sudo iptables -D FORWARD -i tap0 -o "$HOST_IFACE" -j ACCEPT || true
185+
sudo iptables -D FORWARD -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT || true
186186
sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE
187187
sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
188-
sudo iptables -I FORWARD 1 -i tap0 -o "$HOST_IFACE" -j ACCEPT
188+
sudo iptables -I FORWARD 1 -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT
189189

190190
API_SOCKET="/tmp/firecracker.socket"
191191
LOGFILE="./firecracker.log"
@@ -203,7 +203,7 @@ sudo curl -X PUT --unix-socket "${API_SOCKET}" \
203203
}" \
204204
"http://localhost/logger"
205205

206-
KERNEL="./vmlinux-5.10.210"
206+
KERNEL="./$(ls vmlinux* | tail -1)"
207207
KERNEL_BOOT_ARGS="console=ttyS0 reboot=k panic=1 pci=off"
208208

209209
ARCH=$(uname -m)

src/firecracker/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ vmm = { path = "../vmm" }
3434
[dev-dependencies]
3535
cargo_toml = "0.20.4"
3636
libc = "0.2.155"
37-
regex = { version = "1.10.5", default-features = false, features = ["std", "unicode-perl"] }
37+
regex = { version = "1.10.6", default-features = false, features = ["std", "unicode-perl"] }
3838

3939
# Dev-Dependencies for uffd examples
4040
serde = { version = "1.0.204", features = ["derive"] }

src/jailer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ bench = false
1515
libc = "0.2.155"
1616
log-instrument = { path = "../log-instrument", optional = true }
1717
nix = { version = "0.29.0", default-features = false, features = ["dir"] }
18-
regex = { version = "1.10.5", default-features = false, features = ["std"] }
18+
regex = { version = "1.10.6", default-features = false, features = ["std"] }
1919
thiserror = "1.0.63"
2020

2121
utils = { path = "../utils" }

tests/framework/microvm.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from framework.microvm_helpers import MicrovmHelpers
4040
from framework.properties import global_props
4141
from framework.utils_drive import VhostUserBlkBackend, VhostUserBlkBackendType
42+
from host_tools.fcmetrics import FCMetricsMonitor
4243
from host_tools.memory import MemoryMonitor
4344

4445
LOG = logging.getLogger("microvm")
@@ -558,6 +559,7 @@ def spawn(
558559
log_show_level=False,
559560
log_show_origin=False,
560561
metrics_path="fc.ndjson",
562+
emit_metrics: bool = False,
561563
):
562564
"""Start a microVM as a daemon or in a screen session."""
563565
# pylint: disable=subprocess-run-check
@@ -583,6 +585,8 @@ def spawn(
583585
self.metrics_file.touch()
584586
self.create_jailed_resource(self.metrics_file)
585587
self.jailer.extra_args.update({"metrics-path": self.metrics_file.name})
588+
else:
589+
assert not emit_metrics
586590

587591
if self.metadata_file:
588592
if os.path.exists(self.metadata_file):
@@ -619,6 +623,9 @@ def spawn(
619623

620624
self._spawned = True
621625

626+
if emit_metrics:
627+
self.monitors.append(FCMetricsMonitor(self))
628+
622629
# Wait for the jailer to create resources needed, and Firecracker to
623630
# create its API socket.
624631
# We expect the jailer to start within 80 ms. However, we wait for

tests/host_tools/fcmetrics.py

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -437,53 +437,39 @@ def get_emf_unit_for_fc_metrics(full_key):
437437

438438
def flush_fc_metrics_to_cw(fc_metrics, metrics):
439439
"""
440-
Flush Firecracker metrics to CloudWatch
441-
Use an existing metrics logger with existing dimensions so
442-
that its easier to corelate the metrics with the test calling it.
443-
Add a prefix "fc_metrics." to differentiate these metrics, this
444-
also helps to avoid using this metrics in AB tests.
440+
Flush Firecracker metrics to CloudWatch. Use an existing metrics logger with existing dimensions so that it is
441+
easier to correlate the metrics with the test calling it. Add a prefix "fc_metrics." to differentiate these metrics,
442+
this also helps to avoid using this metrics in A/B tests.
445443
NOTE:
446-
There are metrics with keywords "fail", "err",
447-
"num_faults", "panic" in their name and represent
448-
some kind of failure in Firecracker.
449-
This function `does not` assert on these failure metrics
450-
since some tests might not want to assert on them while
451-
some tests might want to assert on some but not others.
444+
There are metrics with keywords "fail", "err", "num_faults", "panic" in their name and represent some kind of
445+
failure in Firecracker. We assert that all these are zero, to catch potentially silent failure modes. This
446+
means the FcMonitor cannot be used in negative tests that might cause such metrics to be emitted.
452447
"""
453448

454-
def walk_key(full_key, keys):
455-
for key, value in keys.items():
456-
final_full_key = full_key + "." + key
457-
if isinstance(value, dict):
458-
walk_key(final_full_key, value)
459-
else:
460-
# values are 0 when:
461-
# - there is no update
462-
# - device is not used
463-
# - SharedIncMetric reset to 0 on flush so if
464-
# there is no change metric the values remain 0.
465-
# We can save the amount of bytes we export to
466-
# CloudWatch in these cases.
467-
# however it is difficult to differentiate if a 0
468-
# should be skipped or upload because it could be
469-
# an expected value in some cases so we upload
470-
# all the metrics even if data is 0.
471-
unit = get_emf_unit_for_fc_metrics(final_full_key)
472-
metrics.put_metric(f"fc_metrics.{final_full_key}", value, unit=unit)
473-
474-
# List of SharedStoreMetric that once updated have the same value thoughout the life of vm
475-
metrics_to_export_once = {
476-
"api_server",
477-
"latencies_us",
478-
}
479-
skip = set()
480-
for group, keys in fc_metrics.items():
481-
if group == "utc_timestamp_ms":
449+
# Pre-order tree traversal to convert a tree into its list of paths with dot separate segments
450+
def flatten_dict(node, prefix: str):
451+
if not isinstance(node, dict):
452+
return {prefix: node}
453+
454+
result = {}
455+
for child_metric_name, child_metrics in node.items():
456+
result.update(flatten_dict(child_metrics, f"{prefix}.{child_metric_name}"))
457+
return result
458+
459+
flattened_metrics = flatten_dict(fc_metrics, "fc_metrics")
460+
461+
for key, value in flattened_metrics.items():
462+
if ".utc_timestamp_ms." in key:
482463
continue
483-
if group not in skip:
484-
walk_key(group, keys)
485-
if group in metrics_to_export_once:
486-
skip.add(group)
464+
metrics.put_metric(key, value, get_emf_unit_for_fc_metrics(key))
465+
466+
assert not {
467+
key: value
468+
for key, value in flattened_metrics.items()
469+
if "err" in key or "fail" in key or "panic" in key or "num_faults" in key
470+
if value
471+
}
472+
487473
metrics.flush()
488474

489475

@@ -514,6 +500,7 @@ def __init__(self, vm, timer=60):
514500
"guest_kernel": vm.kernel_file.stem[2:],
515501
}
516502
)
503+
self.start()
517504

518505
def _flush_metrics(self):
519506
"""

tests/integration_tests/performance/test_block_ab.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
import host_tools.drive as drive_tools
1313
from framework.utils import CmdBuilder, check_output, track_cpu_utilization
14-
from host_tools.fcmetrics import FCMetricsMonitor
1514

1615
# size of the block device used in the test, in MB
1716
BLOCK_DEVICE_SIZE_MB = 2048
@@ -155,7 +154,7 @@ def test_block_performance(
155154
Execute block device emulation benchmarking scenarios.
156155
"""
157156
vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
158-
vm.spawn(log_level="Info")
157+
vm.spawn(log_level="Info", emit_metrics=True)
159158
vm.basic_config(vcpu_count=vcpus, mem_size_mib=GUEST_MEM_MIB)
160159
vm.add_net_iface()
161160
# Add a secondary block device for benchmark tests.
@@ -174,8 +173,6 @@ def test_block_performance(
174173
**vm.dimensions,
175174
}
176175
)
177-
fcmetrics = FCMetricsMonitor(vm)
178-
fcmetrics.start()
179176

180177
vm.pin_threads(0)
181178

@@ -187,8 +184,6 @@ def test_block_performance(
187184
for value in values:
188185
metrics.put_metric(f"cpu_utilization_{thread_name}", value, "Percent")
189186

190-
fcmetrics.stop()
191-
192187

193188
@pytest.mark.nonci
194189
@pytest.mark.parametrize("vcpus", [1, 2], ids=["1vcpu", "2vcpu"])
@@ -208,7 +203,7 @@ def test_block_vhost_user_performance(
208203
"""
209204

210205
vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
211-
vm.spawn(log_level="Info")
206+
vm.spawn(log_level="Info", emit_metrics=True)
212207
vm.basic_config(vcpu_count=vcpus, mem_size_mib=GUEST_MEM_MIB)
213208
vm.add_net_iface()
214209

@@ -226,8 +221,6 @@ def test_block_vhost_user_performance(
226221
**vm.dimensions,
227222
}
228223
)
229-
fcmetrics = FCMetricsMonitor(vm)
230-
fcmetrics.start()
231224

232225
next_cpu = vm.pin_threads(0)
233226
vm.disks_vhost_user["scratch"].pin(next_cpu)
@@ -239,5 +232,3 @@ def test_block_vhost_user_performance(
239232
for thread_name, values in cpu_util.items():
240233
for value in values:
241234
metrics.put_metric(f"cpu_utilization_{thread_name}", value, "Percent")
242-
243-
fcmetrics.stop()

tests/integration_tests/performance/test_memory_overhead.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import psutil
2121
import pytest
2222

23-
from host_tools.fcmetrics import FCMetricsMonitor
24-
2523
# If guest memory is >3328MB, it is split in a 2nd region
2624
X86_MEMORY_GAP_START = 3328 * 2**20
2725

@@ -40,15 +38,13 @@ def test_memory_overhead(
4038

4139
for _ in range(5):
4240
microvm = microvm_factory.build(guest_kernel, rootfs)
43-
microvm.spawn()
41+
microvm.spawn(emit_metrics=True)
4442
microvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib)
4543
microvm.add_net_iface()
4644
microvm.start()
4745
metrics.set_dimensions(
4846
{"performance_test": "test_memory_overhead", **microvm.dimensions}
4947
)
50-
fcmetrics = FCMetricsMonitor(microvm)
51-
fcmetrics.start()
5248
microvm.wait_for_up()
5349

5450
guest_mem_bytes = mem_size_mib * 2**20
@@ -84,4 +80,3 @@ def test_memory_overhead(
8480
for metric in ["uss", "text"]:
8581
val = getattr(mem_info, metric)
8682
metrics.put_metric(metric, val, unit="Bytes")
87-
fcmetrics.stop()

0 commit comments

Comments
 (0)