diff --git a/.buildkite/common.py b/.buildkite/common.py
index 196435bb2e0..a8913d5d6ef 100644
--- a/.buildkite/common.py
+++ b/.buildkite/common.py
@@ -13,14 +13,14 @@
import subprocess
from pathlib import Path
-DEFAULT_INSTANCES = {
- "c5n.metal": "x86_64", # Intel Skylake
- "m5n.metal": "x86_64", # Intel Cascade Lake
- "m6i.metal": "x86_64", # Intel Icelake
- "m6a.metal": "x86_64", # AMD Milan
- "m6g.metal": "aarch64", # Graviton2
- "m7g.metal": "aarch64", # Graviton3
-}
+DEFAULT_INSTANCES = [
+ "c5n.metal", # Intel Skylake
+ "m5n.metal", # Intel Cascade Lake
+ "m6i.metal", # Intel Icelake
+ "m6a.metal", # AMD Milan
+ "m6g.metal", # Graviton2
+ "m7g.metal", # Graviton3
+]
DEFAULT_PLATFORMS = [
("al2", "linux_5.10"),
@@ -28,6 +28,11 @@
]
+def get_arch_for_instance(instance):
+ """Return instance architecture"""
+ return "x86_64" if instance[2] != "g" else "aarch64"
+
+
def overlay_dict(base: dict, update: dict):
"""Overlay a dict over a base one"""
base = base.copy()
@@ -145,7 +150,7 @@ def __call__(self, parser, namespace, value, option_string=None):
"--instances",
required=False,
nargs="+",
- default=DEFAULT_INSTANCES.keys(),
+ default=DEFAULT_INSTANCES,
)
COMMON_PARSER.add_argument(
"--platforms",
@@ -288,7 +293,7 @@ def _adapt_group(self, group):
step["command"] = prepend + step["command"]
if self.shared_build is not None:
step["depends_on"] = self.build_key(
- DEFAULT_INSTANCES[step["agents"]["instance"]]
+ get_arch_for_instance(step["agents"]["instance"])
)
return group
@@ -323,7 +328,7 @@ def build_group_per_arch(self, label, *args, **kwargs):
if set_key:
for step in grp["steps"]:
step["key"] = self.build_key(
- DEFAULT_INSTANCES[step["agents"]["instance"]]
+ get_arch_for_instance(step["agents"]["instance"])
)
return self.add_step(grp, depends_on_build=depends_on_build)
diff --git a/.buildkite/pipeline_cpu_template.py b/.buildkite/pipeline_cpu_template.py
index 72a67ea5e7d..c8c5f75fa09 100755
--- a/.buildkite/pipeline_cpu_template.py
+++ b/.buildkite/pipeline_cpu_template.py
@@ -34,7 +34,7 @@ class BkStep(str, Enum):
"tools/devtool -y test --no-build -- -m no_block_pr integration_tests/functional/test_cpu_template_helper.py -k test_guest_cpu_config_change",
],
BkStep.LABEL: "🖐️ fingerprint",
- "instances": DEFAULT_INSTANCES.keys(),
+ "instances": DEFAULT_INSTANCES,
"platforms": DEFAULT_PLATFORMS,
},
"cpuid_wrmsr": {
diff --git a/.buildkite/pipeline_perf.py b/.buildkite/pipeline_perf.py
index e8169bfb2cd..2a26f4277cc 100755
--- a/.buildkite/pipeline_perf.py
+++ b/.buildkite/pipeline_perf.py
@@ -124,6 +124,8 @@
pins = {
# TODO: Unpin when performance instability on m6i/5.10 has gone.
"linux_5.10-pinned": {"instance": "m6i.metal", "kv": "linux_5.10"},
+ # TODO: Unpin when performance instability on m6i/6.1 has gone.
+ "linux_6.1-pinned": {"instance": "m6i.metal", "kv": "linux_6.1"},
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7da89123eab..6e7be8f518f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,9 @@ and this project adheres to
### Fixed
+- [#4921](https://github.com/firecracker-microvm/firecracker/pull/4921): Fixed
+ swagger `CpuConfig` definition to include missing aarch64-specific fields.
+
## \[1.10.1\]
### Changed
diff --git a/Cargo.lock b/Cargo.lock
index fe779e26d13..521552d3f87 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -9,7 +9,7 @@ dependencies = [
"displaydoc",
"thiserror 2.0.3",
"vm-memory",
- "zerocopy 0.8.9",
+ "zerocopy 0.8.11",
]
[[package]]
@@ -125,11 +125,11 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "aws-lc-fips-sys"
-version = "0.12.13"
+version = "0.12.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf12b67bc9c5168f68655aadb2a12081689a58f1d9b1484705e4d1810ed6e4ac"
+checksum = "df1e8a8e212a7851ef3d4c28cdfc017072bc684f0e0f57c7943ab60f695c3bfb"
dependencies = [
- "bindgen 0.69.4",
+ "bindgen 0.69.5",
"cc",
"cmake",
"dunce",
@@ -140,13 +140,12 @@ dependencies = [
[[package]]
name = "aws-lc-rs"
-version = "1.10.0"
+version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdd82dba44d209fddb11c190e0a94b78651f95299598e472215667417a03ff1d"
+checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3"
dependencies = [
"aws-lc-fips-sys",
"aws-lc-sys",
- "mirai-annotations",
"paste",
"untrusted",
"zeroize",
@@ -154,11 +153,11 @@ dependencies = [
[[package]]
name = "aws-lc-sys"
-version = "0.22.0"
+version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df7a4168111d7eb622a31b214057b8509c0a7e1794f44c546d742330dc793972"
+checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7"
dependencies = [
- "bindgen 0.69.4",
+ "bindgen 0.69.5",
"cc",
"cmake",
"dunce",
@@ -204,9 +203,9 @@ dependencies = [
[[package]]
name = "bindgen"
-version = "0.69.4"
+version = "0.69.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
+checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
dependencies = [
"bitflags 2.6.0",
"cexpr",
@@ -261,9 +260,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
-version = "1.1.37"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf"
+checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc"
dependencies = [
"jobserver",
"libc",
@@ -341,9 +340,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.20"
+version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
+checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
dependencies = [
"clap_builder",
"clap_derive",
@@ -360,9 +359,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.20"
+version = "4.5.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
+checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
dependencies = [
"anstream",
"anstyle",
@@ -384,9 +383,9 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.2"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7"
[[package]]
name = "clippy-tracing"
@@ -403,9 +402,9 @@ dependencies = [
[[package]]
name = "cmake"
-version = "0.1.51"
+version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a"
+checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e"
dependencies = [
"cc",
]
@@ -433,9 +432,9 @@ dependencies = [
[[package]]
name = "cpufeatures"
-version = "0.2.14"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0"
+checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
dependencies = [
"libc",
]
@@ -586,12 +585,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
-version = "0.3.9"
+version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -707,9 +706,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.15.1"
+version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
[[package]]
name = "heck"
@@ -740,9 +739,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "indexmap"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
+checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [
"equivalent",
"hashbrown",
@@ -794,9 +793,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.11"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jailer"
@@ -857,15 +856,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.162"
+version = "0.2.167"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398"
+checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc"
[[package]]
name = "libloading"
-version = "0.8.5"
+version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
+checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets",
@@ -955,12 +954,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-[[package]]
-name = "mirai-annotations"
-version = "1.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1"
-
[[package]]
name = "nix"
version = "0.27.1"
@@ -1067,9 +1060,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.89"
+version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
@@ -1187,9 +1180,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustix"
-version = "0.38.40"
+version = "0.38.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
+checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
dependencies = [
"bitflags 2.6.0",
"errno",
@@ -1239,18 +1232,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.214"
+version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
+checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.214"
+version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
+checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
@@ -1259,9 +1252,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.132"
+version = "1.0.133"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
+checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
dependencies = [
"itoa",
"memchr",
@@ -1323,9 +1316,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
-version = "2.0.87"
+version = "2.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
+checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
dependencies = [
"proc-macro2",
"quote",
@@ -1630,7 +1623,7 @@ dependencies = [
"vm-memory",
"vm-superio",
"vmm-sys-util",
- "zerocopy 0.8.9",
+ "zerocopy 0.8.11",
]
[[package]]
@@ -1807,11 +1800,11 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.9"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f49e690f8f352f4a9ee8679a8c5921f42ffd0d6d6413a0a66b8e81cf524e109c"
+checksum = "cce3b5629d87654b53a49002acc2ce64aa5aa7255f5c718374a37ac7fd98c218"
dependencies = [
- "zerocopy-derive 0.8.9",
+ "zerocopy-derive 0.8.11",
]
[[package]]
@@ -1827,9 +1820,9 @@ dependencies = [
[[package]]
name = "zerocopy-derive"
-version = "0.8.9"
+version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa732fcc881df7a6fbe8e3ed17baadece53b379ad58fe2633396b1a2b108a7b1"
+checksum = "74a82c26c3986af2623ec9eb890ff4aa19c006e30a1133dc9bd1830ec1612e20"
dependencies = [
"proc-macro2",
"quote",
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 644d31e78a8..02a2077207b 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -100,21 +100,23 @@ kernel image with a Ubuntu 24.04 rootfs from our CI:
```bash
ARCH="$(uname -m)"
-latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.10/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.10/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)")
+latest=$(wget "http://spec.ccfc.min.s3.amazonaws.com/?prefix=firecracker-ci/v1.11/$ARCH/vmlinux-5.10&list-type=2" -O - 2>/dev/null | grep -oP "(?<=)(firecracker-ci/v1.11/$ARCH/vmlinux-5\.10\.[0-9]{1,3})(?=)")
# Download a linux kernel binary
wget "https://s3.amazonaws.com/spec.ccfc.min/${latest}"
# Download a rootfs
-wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.10/${ARCH}/ubuntu-24.04.squashfs"
+wget -O ubuntu-24.04.squashfs.upstream "https://s3.amazonaws.com/spec.ccfc.min/firecracker-ci/v1.11/${ARCH}/ubuntu-24.04.squashfs"
# Create an ssh key for the rootfs
unsquashfs ubuntu-24.04.squashfs.upstream
ssh-keygen -f id_rsa -N ""
cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys
mv -v id_rsa ./ubuntu-24.04.id_rsa
-# re-squash
-mksquashfs squashfs-root ubuntu-24.04.squashfs -all-root -noappend -comp zstd
+# create ext4 filesystem image
+sudo chown -R root:root squashfs-root
+truncate -s 400M ubuntu-24.04.ext4
+sudo mkfs.ext4 -d squashfs-root -F ubuntu-24.04.ext4
```
### Getting a Firecracker Binary
@@ -195,17 +197,16 @@ sudo ip link set dev "$TAP_DEV" up
# Enable ip forwarding
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
+sudo iptables -P FORWARD ACCEPT
-HOST_IFACE="eth0"
+# This tries to determine the name of the host network interface to forward
+# VM's outbound network traffic through. If outbound traffic doesn't work,
+# double check this returns the correct interface!
+HOST_IFACE=$(ip -j route list default |jq -r '.[0].dev')
# Set up microVM internet access
sudo iptables -t nat -D POSTROUTING -o "$HOST_IFACE" -j MASQUERADE || true
-sudo iptables -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT \
- || true
-sudo iptables -D FORWARD -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT || true
sudo iptables -t nat -A POSTROUTING -o "$HOST_IFACE" -j MASQUERADE
-sudo iptables -I FORWARD 1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo iptables -I FORWARD 1 -i "$TAP_DEV" -o "$HOST_IFACE" -j ACCEPT
API_SOCKET="/tmp/firecracker.socket"
LOGFILE="./firecracker.log"
diff --git a/docs/network-setup.md b/docs/network-setup.md
index ad77bd3e7e9..fb2c1ca0977 100644
--- a/docs/network-setup.md
+++ b/docs/network-setup.md
@@ -1,49 +1,108 @@
# Getting Started Firecracker Network Setup
-This is a very simple quick-start guide to getting a Firecracker guest connected
-to the network. If you're using Firecracker in production, or even want to run
-multiple guests, you'll need to adapt this setup.
+This is a simple quick-start guide to getting one or more Firecracker microVMs
+connected to the Internet via the host. If you run a production setup, you
+should consider modifying this setup to accommodate your specific needs.
-**Note** Currently firecracker supports only TUN/TAP network backend with no
+**Note:** Currently, Firecracker supports only a TUN/TAP network backend with no
multi queue support.
-The simple steps in this guide assume that your internet-facing interface is
-`eth0`, you have nothing else using `tap0` and no other `iptables` rules. Check
-out the *Advanced:* sections if that doesn't work for you.
+The steps in this guide assume `eth0` to be your Internet-facing network
+interface on the host. If `eth0` isn't your main network interface, you should
+change the value to the correct one in the commands below. IPv4 is also assumed
+to be used, so you will need to adapt the instructions accordingly to support
+IPv6.
+
+Each microVM requires a host network interface (like `eth0`) and a Linux `tap`
+device (like `tap0`) used by Firecracker, but the differences in configuration
+stem from routing: how packets from the `tap` get to the network interface
+(egress) and vice-versa (ingress). There are three main approaches of how to
+configure routing for a microVM.
+
+1. **NAT-based**, which is presented in the main part of this guide. It is
+ simple but doesn't expose your microVM to the local network (LAN).
+1. **Bridge-based**, which exposes your microVM to the local network. Learn more
+ about in the _Advanced: Bridge-based routing_ section of this guide.
+1. **Namespaced NAT**, which sacrifices performance in comparison to the other
+ approaches but is desired in the scenario when two clones of the same microVM
+ are running at the same time. To learn more about it, check out the
+ [Network Connectivity for Clones](./snapshotting/network-for-clones.md)
+ guide.
+
+To run multiple microVMs while using NAT-based routing, check out the _Advanced:
+Multiple guests_ section. The same principles can be applied to other routing
+methods with a bit more effort.
+
+For the choice of firewall, `nft` is recommended for use on production Linux
+systems, but, for the sake of compatibility, this guide provides a choice
+between either `nft` or the `iptables-nft` translation layer. The latter is
+[no longer recommended](https://access.redhat.com/solutions/6739041) but may be
+more familiar to readers.
+
+## On the Host
+
+The first step on the host for any microVM is to create a Linux `tap` device,
+which Firecracker will use for networking.
+
+For this setup, only two IP addresses will be necessary - one for the `tap`
+device and one for the guest itself, through which you will, for example, `ssh`
+into the guest. So, we'll choose the smallest IPv4 subnet needed for 2
+addresses: `/30`. For this VM, let's use the `172.16.0.1` `tap` IP and the
+`172.16.0.2` guest IP.
-## On The Host
+```bash
+# Create the tap device.
+sudo ip tuntap add tap0 mode tap
+# Assign it the tap IP and start up the device.
+sudo ip addr add 172.16.0.1/30 dev tap0
+sudo ip link set tap0 up
+```
-The first step on the host is to create a `tap` device:
+**Note:** The IP of the TAP device should be chosen such that it's not in the
+same subnet as the IP address of the host.
+
+We'll need to enable IPv4 forwarding on the system.
```bash
-sudo ip tuntap add tap0 mode tap
+echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
```
-Then you have a few options for routing traffic out of the tap device, through
-your host's network interface. One option is NAT, set up like this:
+### Configuration via `nft`
+
+We'll need an nftables table for our routing needs, and 2 chains inside that
+table: one for NAT on `postrouting` stage, and another one for filtering on
+`forward` stage:
```bash
-sudo ip addr add 172.16.0.1/24 dev tap0
-sudo ip link set tap0 up
-sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
-sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
-sudo iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-sudo iptables -A FORWARD -i tap0 -o eth0 -j ACCEPT
+sudo nft add table firecracker
+sudo nft 'add chain firecracker postrouting { type nat hook postrouting priority srcnat; policy accept; }'
+sudo nft 'add chain firecracker filter { type filter hook forward priority filter; policy accept; }'
```
-*Note:* The IP of the TAP device should be chosen such that it's not in the same
-subnet as the IP address of the host.
+The first rule we'll need will masquerade packets from the guest IP as if they
+came from the host's IP, by changing the source IP address of these packets:
-*Advanced:* If you are running multiple Firecracker MicroVMs in parallel, or
-have something else on your system using `tap0` then you need to create a `tap`
-for each one, with a unique name.
+```bash
+sudo nft add rule firecracker postrouting ip saddr 172.16.0.2 oifname eth0 counter masquerade
+```
-*Advanced:* You also need to do the `iptables` set up for each new `tap`. If you
-have `iptables` rules you care about on your host, you may want to save those
-rules before starting.
+The second rule we'll need will accept packets from the tap IP (the guest will
+use the tap IP as its gateway and will therefore route its own packets through
+the tap IP) and direct them to the host network interface:
```bash
-sudo iptables-save > iptables.rules.old
+sudo nft add rule firecracker filter iifname tap0 oifname eth0 accept
+```
+
+### Configuration via `iptables-nft`
+
+Tables and chains are managed by `iptables-nft` automatically, but we'll need
+three rules to perform the NAT steps:
+
+```bash
+sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE
+sudo iptables-nft -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+sudo iptables-nft -A FORWARD -i tap0 -o eth0 -j ACCEPT
```
## Setting Up Firecracker
@@ -85,14 +144,20 @@ configuration file like this:
```
Alternatively, if you are using firectl, add
---tap-device=tap0/06:00:AC:10:00:02\` to your command line.
+`--tap-device=tap0/06:00:AC:10:00:02\` to your command line.
## In The Guest
-Once you have booted the guest, bring up networking within the guest:
+Once you have booted the guest, it will have its networking interface with the
+name specified by `iface_id` in the Firecracker configuration.
+
+You'll now need to assign the guest its IP, activate the guest's networking
+interface and set up the `tap` IP as the guest's gateway address, so that
+packets are routed through the `tap` device, where they are then picked up by
+the setup on the host prepared before:
```bash
-ip addr add 172.16.0.2/24 dev eth0
+ip addr add 172.16.0.2/30 dev eth0
ip link set eth0 up
ip route add default via 172.16.0.1 dev eth0
```
@@ -107,23 +172,183 @@ your environment. For testing, you can add a public DNS server to
nameserver 8.8.8.8
```
-## \[Advanced\] Setting Up a Bridge Interface
+**Note:** Sometimes, it's undesirable to have `iproute2` (providing the `ip`
+command) installed on your guest OS, or you simply want to have these steps be
+performed automatically. To do this, check out the _Advanced: Guest network
+configuration using kernel command line_ section.
+
+## Cleaning up
+
+The first step to cleaning up is to delete the tap device on the host:
+
+```bash
+sudo ip link del tap0
+```
+
+### Cleanup using `nft`
+
+You'll want to delete the two nftables rules for NAT routing from the
+`postrouting` and `filter` chains. To do this with nftables, you'll need to look
+up the _handles_ (identifiers) of these rules by running:
+
+```bash
+sudo nft -a list ruleset
+```
+
+Now, find the `# handle` comments relating to the two rules and delete them. For
+example, if the handle to the masquerade rule is 1 and the one to the forwarding
+rule is 2:
+
+```bash
+sudo nft delete rule firecracker postrouting handle 1
+sudo nft delete rule firecracker filter handle 2
+```
+
+Run the following steps only **if you have no more guests** running on the host:
+
+Set IPv4 forwarding back to disabled:
+
+```bash
+echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward
+```
+
+If you're using `nft`, delete the `firecracker` table to revert your nftables
+configuration fully back to its initial state:
+
+```bash
+sudo nft delete table firecracker
+```
+
+### Cleanup using `iptables-nft`
+
+Of the configured `iptables-nft` rules, two should be deleted if you have guests
+remaining in your configuration:
+
+```bash
+sudo iptables-nft -t nat -D POSTROUTING -o eth0 -s 172.16.0.2 -j MASQUERADE
+sudo iptables-nft -D FORWARD -i tap0 -o eth0 -j ACCEPT
+```
+
+**If you have no more guests** running on the host, then similarly set IPv4
+forwarding back to disabled:
+
+```bash
+echo 0 | sudo tee /proc/sys/net/ipv4/ip_forward
+```
+
+And delete the remaining `conntrack` rule that applies to all guests:
+
+```bash
+sudo iptables-nft -D FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
+```
+
+If nothing else is using `iptables-nft` on the system, you may even want to
+delete the entire system ruleset like so:
+
+```bash
+sudo iptables-nft -F
+sudo iptables-nft -t nat -F
+```
+
+## Advanced: Multiple guests
+
+To configure multiple guests, we will only need to repeat some of the steps in
+this setup for each of the microVMs:
+
+1. Each microVM has its own subnet and the two IP addresses inside of it: the
+ `tap` IP and the guest IP.
+1. Each microVM has its own two nftables rules for masquerading and forwarding,
+ while the same table and two chains can be shared between the microVMs.
+1. Each microVM has its own routing configuration inside the guest itself
+ (achieved through `iproute2` or the method described in the _Advanced: Guest
+ network configuration at kernel level_ section).
+
+To give a more concrete example, **let's add a second microVM** to the one
+you've already configured:
+
+Let's assume we allocate /30 subnets in the 172.16.0.0/16 range sequentially to
+give out as few addresses as needed.
+
+The next /30 subnet in the 172.16.0.0/16 range will give us these two IPs:
+172.16.0.5 as the `tap` IP and 172.16.0.6 as the guest IP.
+
+Our new `tap` device will, sequentially, have the name `tap1`:
+
+```bash
+sudo ip tuntap add tap1 mode tap
+sudo ip addr add 172.16.0.5/30 dev tap1
+sudo ip link set tap1 up
+```
+
+Now, let's add the new two `nft` rules, also with the new values:
+
+```bash
+sudo nft add rule firecracker postrouting ip saddr 172.16.0.6 oifname eth0 counter masquerade
+sudo nft add rule firecracker filter iifname tap1 oifname eth0 accept
+```
+
+If using `iptables-nft`, add the rules like so:
+
+```bash
+sudo iptables-nft -t nat -A POSTROUTING -o eth0 -s 172.16.0.6 -j MASQUERADE
+sudo iptables-nft -A FORWARD -i tap1 -o eth0 -j ACCEPT
+```
+
+Modify your Firecracker configuration with the `host_dev_name` now being `tap1`
+instead of `tap0`, boot up the guest and perform the routing inside of it like
+so, changing the guest IP and `tap` IP:
+
+```bash
+ip addr add 172.16.0.6/30 dev eth0
+ip link set eth0 up
+ip route add default via 172.16.0.5 dev eth0
+```
+
+Or, you can use the setup from _Advanced: Guest network configuration at kernel
+level_ by simply changing the G and T variables, i.e. the guest IP and `tap` IP.
+
+**Note:** if you'd like to calculate the guest and `tap` IPs using the
+sequential subnet allocation method that has been used here, you can use the
+following formulas specific to IPv4 addresses:
+
+`tap` IP = `172.16.[(A*O+1)/256].[(A*O+1)%256]`.
+
+Guest IP = `172.16.[(A*O+2)/256].[(A*O+2)%256]`.
+
+Round down the division and replace `A` with the amount of IP addresses inside
+your subnet (for a /30 subnet, that will be 4 addresses, for example) and
+replace `O` with the sequential number of your microVM, starting at 0. You can
+replace `172.16` with any other values that fit between between 1 and 255 as
+usual with an IPv4 address.
+
+For example, let's calculate the addresses of the 1000-th microVM with a /30
+subnet in the `172.16.0.0/16` range:
+
+`tap` IP = `172.16.[(4*999+1)/256].[(4*999+1)%256]` = `172.16.15.157`.
+
+Guest IP = `172.16.[(4*999+2)/256].[(4*999+2)%256]` = `172.16.15.158`.
+
+This allocation setup has been used successfully in the `firecracker-demo`
+project for launching several thousand microVMs on the same host:
+[relevant lines](https://github.com/firecracker-microvm/firecracker-demo/blob/63717c6e7fbd277bdec8e26a5533d53544a760bb/start-firecracker.sh#L45).
+
+## Advanced: Bridge-based routing
### On The Host
-1. Create a bridge interface
+1. Create a bridge interface:
```bash
sudo ip link add name br0 type bridge
```
-1. Add tap interface [created above](#on-the-host) to the bridge
+1. Add the `tap` device [created above](#on-the-host) to the bridge:
```bash
sudo ip link set dev tap0 master br0
```
-1. Define an IP address in your network for the bridge.
+1. Define an IP address in your network for the bridge:
For example, if your gateway were on `192.168.1.1` and you wanted to use this
for getting dynamic IPs, you would want to give the bridge an unused IP
@@ -133,24 +358,30 @@ nameserver 8.8.8.8
sudo ip address add 192.168.1.7/24 dev br0
```
-1. Add firewall rules to allow traffic to be routed to the guest
+1. Add a firewall rule to allow traffic to be routed to the guest:
```bash
sudo iptables -t nat -A POSTROUTING -o br0 -j MASQUERADE
```
+1. Once you're cleaning up the configuration, make sure to delete the bridge:
+
+ ```bash
+ sudo ip link del br0
+ ```
+
### On The Guest
1. Define an unused IP address in the bridge's subnet e.g., `192.168.1.169/24`.
- _Note: Alternatively, you could rely on DHCP for getting a dynamic IP address
- from your gateway._
+ **Note**: Alternatively, you could rely on DHCP for getting a dynamic IP
+ address from your gateway.
```bash
ip addr add 192.168.1.169/24 dev eth0
```
-1. Set the interface up.
+1. Enable the network interface:
```bash
ip link set eth0 up
@@ -177,43 +408,38 @@ nameserver 8.8.8.8
192.168.1.1 via 192.168.1.7 dev eth0
```
-1. Add your nameserver to `resolve.conf`
+1. Add your nameserver to `/etc/resolve.conf`
```bash
# cat /etc/resolv.conf
nameserver 192.168.1.1
```
-## Cleaning up
+## Advanced: Guest network configuration using kernel command line
-The first step to cleaning up is deleting the tap device:
+The Linux kernel supports an `ip` CLI arguments that can be passed to it when
+booting. Boot arguments in Firecracker are configured in the `boot_args`
+property of the boot source (`boot-source` object in the JSON configuration or
+the equivalent endpoint in the API server).
-```bash
-sudo ip link del tap0
-```
+The value of the `ip` CLI argument for our setup will be the of this format:
+`G::T:GM::GI:off`. G is the guest IP (without the subnet), T is the `tap` IP
+(without the subnet), GM is the "long" mask IP of the guest CIDR and GI is the
+name of the guest network interface.
-If you don't have anything else using `iptables` on your machine, clean up those
-rules:
-
-```bash
-sudo iptables -F
-sudo sh -c "echo 0 > /proc/sys/net/ipv4/ip_forward" # usually the default
-```
+Substituting our values, we get:
+`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off`. Insert this at the end of
+your boot arguments for your microVM, and the guest Linux kernel will
+automatically perform the routing configuration done in the _In the Guest_
+section without needing `iproute2` installed in the guest.
-If you have an existing iptables setup, you'll want to be more careful about
-cleaning up.
+As soon as you boot the guest, it will already be connected to the network
+(assuming you correctly performing the other steps).
-*Advanced:* If you saved your iptables rules in the first step, then you can
-restore them like this:
+**Note**: you can also use the `ip` argument to configure a primary DNS server
+and, optionally, a second DNS server without needing to touch
+`/etc/resolv.conf`. As an example:
-```bash
-if [ -f iptables.rules.old ]; then
- sudo iptables-restore < iptables.rules.old
-fi
-```
-
-*Advanced:* If you created a bridge interface, delete it using the following:
-
-```bash
-sudo ip link del br0
-```
+`ip=172.16.0.2::172.16.0.1:255.255.255.252::eth0:off:8.8.8.8:1.1.1.1` configures
+`8.8.8.8` as the primary DNS server and `1.1.1.1` as the secondary DNS server,
+as well as the rest of the guest-side routing.
diff --git a/src/acpi-tables/Cargo.toml b/src/acpi-tables/Cargo.toml
index 5932faa732b..39b8f1574c9 100644
--- a/src/acpi-tables/Cargo.toml
+++ b/src/acpi-tables/Cargo.toml
@@ -10,7 +10,7 @@ license = "Apache-2.0"
displaydoc = "0.2.5"
thiserror = "2.0.3"
vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
-zerocopy = { version = "0.8.9", features = ["derive"] }
+zerocopy = { version = "0.8.11", features = ["derive"] }
[lib]
bench = false
diff --git a/src/clippy-tracing/Cargo.toml b/src/clippy-tracing/Cargo.toml
index 4dcd08e42eb..e22cd6a1eae 100644
--- a/src/clippy-tracing/Cargo.toml
+++ b/src/clippy-tracing/Cargo.toml
@@ -10,11 +10,11 @@ name = "clippy-tracing"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive"] }
+clap = { version = "4.5.21", features = ["derive"] }
itertools = "0.13.0"
-proc-macro2 = { version = "1.0.89", features = ["span-locations"] }
+proc-macro2 = { version = "1.0.92", features = ["span-locations"] }
quote = "1.0.37"
-syn = { version = "2.0.85", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] }
+syn = { version = "2.0.90", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] }
walkdir = "2.5.0"
[dev-dependencies]
diff --git a/src/cpu-template-helper/Cargo.toml b/src/cpu-template-helper/Cargo.toml
index 365945b6198..eb7c16472e0 100644
--- a/src/cpu-template-helper/Cargo.toml
+++ b/src/cpu-template-helper/Cargo.toml
@@ -10,12 +10,12 @@ name = "cpu-template-helper"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive", "string"] }
+clap = { version = "4.5.21", features = ["derive", "string"] }
displaydoc = "0.2.5"
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.214", features = ["derive"] }
-serde_json = "1.0.132"
+serde = { version = "1.0.215", features = ["derive"] }
+serde_json = "1.0.133"
thiserror = "2.0.3"
vmm = { path = "../vmm" }
diff --git a/src/firecracker/Cargo.toml b/src/firecracker/Cargo.toml
index 39153386379..6cd237aaabe 100644
--- a/src/firecracker/Cargo.toml
+++ b/src/firecracker/Cargo.toml
@@ -18,14 +18,14 @@ bench = false
[dependencies]
displaydoc = "0.2.5"
event-manager = "0.4.0"
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http" }
seccompiler = { path = "../seccompiler" }
-serde = { version = "1.0.214", features = ["derive"] }
+serde = { version = "1.0.215", features = ["derive"] }
serde_derive = "1.0.136"
-serde_json = "1.0.132"
+serde_json = "1.0.133"
thiserror = "2.0.3"
timerfd = "1.6.0"
utils = { path = "../utils" }
@@ -34,18 +34,18 @@ vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
[dev-dependencies]
cargo_toml = "0.20.5"
-libc = "0.2.162"
+libc = "0.2.167"
regex = { version = "1.11.1", default-features = false, features = ["std", "unicode-perl"] }
# Dev-Dependencies for uffd examples
-serde = { version = "1.0.214", features = ["derive"] }
+serde = { version = "1.0.215", features = ["derive"] }
userfaultfd = "0.8.1"
[build-dependencies]
bincode = "1.2.1"
seccompiler = { path = "../seccompiler" }
-serde = { version = "1.0.214" }
-serde_json = "1.0.132"
+serde = { version = "1.0.215" }
+serde_json = "1.0.133"
[features]
tracing = ["log-instrument", "seccompiler/tracing", "utils/tracing", "vmm/tracing"]
diff --git a/src/firecracker/swagger/firecracker.yaml b/src/firecracker/swagger/firecracker.yaml
index 06f449db431..20bad48bf64 100644
--- a/src/firecracker/swagger/firecracker.yaml
+++ b/src/firecracker/swagger/firecracker.yaml
@@ -840,7 +840,7 @@ definitions:
default: "None"
CpuConfig:
- type: string
+ type: object
description:
The CPU configuration template defines a set of bit maps as modifiers of flags accessed by register
to be disabled/enabled for the microvm.
@@ -854,6 +854,12 @@ definitions:
reg_modifiers:
type: object
description: A collection of registers to be modified. (aarch64)
+ vcpu_features:
+ type: object
+ description: A collection of vcpu features to be modified. (aarch64)
+ kvm_capabilities:
+ type: object
+ description: A collection of kvm capabilities to be modified. (aarch64)
Drive:
type: object
diff --git a/src/jailer/Cargo.toml b/src/jailer/Cargo.toml
index 95dc953ae77..ef9162027be 100644
--- a/src/jailer/Cargo.toml
+++ b/src/jailer/Cargo.toml
@@ -12,7 +12,7 @@ name = "jailer"
bench = false
[dependencies]
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
nix = { version = "0.29.0", default-features = false, features = ["dir"] }
regex = { version = "1.11.1", default-features = false, features = ["std"] }
diff --git a/src/log-instrument-macros/Cargo.toml b/src/log-instrument-macros/Cargo.toml
index fd25f4ffe08..2129df061f2 100644
--- a/src/log-instrument-macros/Cargo.toml
+++ b/src/log-instrument-macros/Cargo.toml
@@ -11,9 +11,9 @@ proc-macro = true
bench = false
[dependencies]
-proc-macro2 = "1.0.89"
+proc-macro2 = "1.0.92"
quote = "1.0.37"
-syn = { version = "2.0.85", features = ["full", "extra-traits"] }
+syn = { version = "2.0.90", features = ["full", "extra-traits"] }
[lints]
workspace = true
diff --git a/src/rebase-snap/Cargo.toml b/src/rebase-snap/Cargo.toml
index 1a0dab4c2a8..1615260b03b 100644
--- a/src/rebase-snap/Cargo.toml
+++ b/src/rebase-snap/Cargo.toml
@@ -11,7 +11,7 @@ bench = false
[dependencies]
displaydoc = "0.2.5"
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
thiserror = "2.0.3"
vmm-sys-util = "0.12.1"
diff --git a/src/seccompiler/Cargo.toml b/src/seccompiler/Cargo.toml
index 91a556d8996..90477e3e025 100644
--- a/src/seccompiler/Cargo.toml
+++ b/src/seccompiler/Cargo.toml
@@ -18,10 +18,10 @@ bench = false
[dependencies]
bincode = "1.2.1"
displaydoc = "0.2.5"
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.214", features = ["derive"] }
-serde_json = "1.0.132"
+serde = { version = "1.0.215", features = ["derive"] }
+serde_json = "1.0.133"
thiserror = "2.0.3"
utils = { path = "../utils" }
diff --git a/src/snapshot-editor/Cargo.toml b/src/snapshot-editor/Cargo.toml
index af59a6c5e03..91bbebf7f27 100644
--- a/src/snapshot-editor/Cargo.toml
+++ b/src/snapshot-editor/Cargo.toml
@@ -10,11 +10,11 @@ name = "snapshot-editor"
bench = false
[dependencies]
-clap = { version = "4.5.20", features = ["derive", "string"] }
+clap = { version = "4.5.21", features = ["derive", "string"] }
displaydoc = "0.2.5"
fc_utils = { package = "utils", path = "../utils" }
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
semver = "1.0.23"
thiserror = "2.0.3"
diff --git a/src/utils/Cargo.toml b/src/utils/Cargo.toml
index bc792ac5801..7f57e5081a0 100644
--- a/src/utils/Cargo.toml
+++ b/src/utils/Cargo.toml
@@ -11,15 +11,15 @@ bench = false
[dependencies]
derive_more = { version = "1.0.0", default-features = false, features = ["from"] }
displaydoc = "0.2.5"
-libc = "0.2.162"
+libc = "0.2.167"
log-instrument = { path = "../log-instrument", optional = true }
-serde = { version = "1.0.214", features = ["derive"] }
+serde = { version = "1.0.215", features = ["derive"] }
thiserror = "2.0.3"
vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
vmm-sys-util = "0.12.1"
[dev-dependencies]
-serde_json = "1.0.132"
+serde_json = "1.0.133"
[features]
tracing = ["log-instrument"]
diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml
index 2115b0e7253..283a47a5982 100644
--- a/src/vmm/Cargo.toml
+++ b/src/vmm/Cargo.toml
@@ -12,7 +12,7 @@ bench = false
acpi_tables = { path = "../acpi-tables" }
aes-gcm = { version = "0.10.1", default-features = false, features = ["aes"] }
arrayvec = { version = "0.7.6", optional = true }
-aws-lc-rs = { version = "1.10.0", features = ["bindgen"] }
+aws-lc-rs = { version = "1.11.1", features = ["bindgen"] }
base64 = "0.22.1"
bincode = "1.2.1"
bitflags = "2.6.0"
@@ -25,7 +25,7 @@ gdbstub_arch = { version = "0.3.1", optional = true }
kvm-bindings = { version = "0.10.0", features = ["fam-wrappers", "serde"] }
kvm-ioctls = "0.19.0"
lazy_static = "1.5.0"
-libc = "0.2.162"
+libc = "0.2.167"
linux-loader = "0.13.0"
log = { version = "0.4.22", features = ["std", "serde"] }
log-instrument = { path = "../log-instrument", optional = true }
@@ -34,8 +34,8 @@ micro_http = { git = "https://github.com/firecracker-microvm/micro-http" }
seccompiler = { path = "../seccompiler" }
semver = { version = "1.0.23", features = ["serde"] }
-serde = { version = "1.0.214", features = ["derive", "rc"] }
-serde_json = "1.0.132"
+serde = { version = "1.0.215", features = ["derive", "rc"] }
+serde_json = "1.0.133"
slab = "0.4.7"
thiserror = "2.0.3"
timerfd = "1.5.0"
@@ -46,7 +46,7 @@ vm-allocator = "0.1.0"
vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] }
vm-superio = "0.8.0"
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
-zerocopy = { version = "0.8.9" }
+zerocopy = { version = "0.8.11" }
[target.'cfg(target_arch = "aarch64")'.dependencies]
vm-fdt = "0.3.0"
diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs
index 1f52fdad063..3355633e3c8 100644
--- a/src/vmm/src/builder.rs
+++ b/src/vmm/src/builder.rs
@@ -259,7 +259,9 @@ pub fn build_microvm_for_boot(
let request_ts = TimestampUs::default();
let boot_config = vm_resources
- .boot_source_builder()
+ .boot_source
+ .builder
+ .as_ref()
.ok_or(MissingKernelConfig)?;
let guest_memory = vm_resources
@@ -508,7 +510,7 @@ pub fn build_microvm_from_snapshot(
vmm.vm.restore_state(µvm_state.vm_state)?;
// Restore the boot source config paths.
- vm_resources.set_boot_source_config(microvm_state.vm_info.boot_source);
+ vm_resources.boot_source.config = microvm_state.vm_info.boot_source;
// Restore devices states.
let mmio_ctor_args = MMIODevManagerConstructorArgs {
diff --git a/src/vmm/src/devices/virtio/device.rs b/src/vmm/src/devices/virtio/device.rs
index b5af6862af9..5adf4873dc6 100644
--- a/src/vmm/src/devices/virtio/device.rs
+++ b/src/vmm/src/devices/virtio/device.rs
@@ -156,7 +156,7 @@ pub trait VirtioDevice: AsAny + Send {
let avail_features = self.avail_features();
let unrequested_features = v & !avail_features;
if unrequested_features != 0 {
- warn!("Received acknowledge request for unknown feature: {:x}", v);
+ warn!("Received acknowledge request for unknown feature: {:#x}", v);
// Don't count these features as acked.
v &= !unrequested_features;
}
diff --git a/src/vmm/src/devices/virtio/mmio.rs b/src/vmm/src/devices/virtio/mmio.rs
index 463d11ca2e2..f734058c5b1 100644
--- a/src/vmm/src/devices/virtio/mmio.rs
+++ b/src/vmm/src/devices/virtio/mmio.rs
@@ -138,7 +138,7 @@ impl MmioTransport {
self.with_queue_mut(f);
} else {
warn!(
- "update virtio queue in invalid state 0x{:x}",
+ "update virtio queue in invalid state {:#x}",
self.device_status
);
}
@@ -227,7 +227,7 @@ impl MmioTransport {
}
_ => {
warn!(
- "invalid virtio driver status transition: 0x{:x} -> 0x{:x}",
+ "invalid virtio driver status transition: {:#x} -> {:#x}",
self.device_status, status
);
}
@@ -282,7 +282,7 @@ impl MmioTransport {
0x70 => self.device_status,
0xfc => self.config_generation,
_ => {
- warn!("unknown virtio mmio register read: 0x{:x}", offset);
+ warn!("unknown virtio mmio register read: {:#x}", offset);
return;
}
};
@@ -290,11 +290,7 @@ impl MmioTransport {
}
0x100..=0xfff => self.locked_device().read_config(offset - 0x100, data),
_ => {
- warn!(
- "invalid virtio mmio read: 0x{:x}:0x{:x}",
- offset,
- data.len()
- );
+ warn!("invalid virtio mmio read: {:#x}:{:#x}", offset, data.len());
}
};
}
@@ -324,7 +320,7 @@ impl MmioTransport {
.ack_features_by_page(self.acked_features_select, v);
} else {
warn!(
- "ack virtio features in invalid state 0x{:x}",
+ "ack virtio features in invalid state {:#x}",
self.device_status
);
}
@@ -346,7 +342,7 @@ impl MmioTransport {
0xa0 => self.update_queue_field(|q| lo(&mut q.used_ring_address, v)),
0xa4 => self.update_queue_field(|q| hi(&mut q.used_ring_address, v)),
_ => {
- warn!("unknown virtio mmio register write: 0x{:x}", offset);
+ warn!("unknown virtio mmio register write: {:#x}", offset);
}
}
}
@@ -361,11 +357,7 @@ impl MmioTransport {
}
}
_ => {
- warn!(
- "invalid virtio mmio write: 0x{:x}:0x{:x}",
- offset,
- data.len()
- );
+ warn!("invalid virtio mmio write: {:#x}:{:#x}", offset, data.len());
}
}
}
diff --git a/src/vmm/src/devices/virtio/vsock/device.rs b/src/vmm/src/devices/virtio/vsock/device.rs
index bf438aca99f..eb7c144c4be 100644
--- a/src/vmm/src/devices/virtio/vsock/device.rs
+++ b/src/vmm/src/devices/virtio/vsock/device.rs
@@ -322,7 +322,7 @@ where
fn write_config(&mut self, offset: u64, data: &[u8]) {
METRICS.cfg_fails.inc();
warn!(
- "vsock: guest driver attempted to write device config (offset={:x}, len={:x})",
+ "vsock: guest driver attempted to write device config (offset={:#x}, len={:#x})",
offset,
data.len()
);
diff --git a/src/vmm/src/gdb/target.rs b/src/vmm/src/gdb/target.rs
index fc2da289e8a..b8230342b27 100644
--- a/src/vmm/src/gdb/target.rs
+++ b/src/vmm/src/gdb/target.rs
@@ -390,7 +390,7 @@ impl MultiThreadBase for FirecrackerTarget {
while !data.is_empty() {
let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| {
- error!("Error {e:?} translating gva on read address: {gva:X}");
+ error!("Error {e:?} translating gva on read address: {gva:#X}");
})?;
// Compute the amount space left in the page after the gpa
@@ -424,7 +424,7 @@ impl MultiThreadBase for FirecrackerTarget {
while !data.is_empty() {
let gpa = arch::translate_gva(&vcpu_state.vcpu_fd, gva, &vmm).map_err(|e| {
- error!("Error {e:?} translating gva on read address: {gva:X}");
+ error!("Error {e:?} translating gva on read address: {gva:#X}");
})?;
// Compute the amount space left in the page after the gpa
@@ -436,7 +436,7 @@ impl MultiThreadBase for FirecrackerTarget {
vmm.guest_memory()
.write(&data[..write_len], GuestAddress(gpa))
.map_err(|e| {
- error!("Error {e:?} writing memory at {gpa:X}");
+ error!("Error {e:?} writing memory at {gpa:#X}");
})?;
data = &data[write_len..];
diff --git a/src/vmm/src/persist.rs b/src/vmm/src/persist.rs
index 5b01ed49c75..3479e0b6309 100644
--- a/src/vmm/src/persist.rs
+++ b/src/vmm/src/persist.rs
@@ -64,7 +64,7 @@ impl From<&VmResources> for VmInfo {
mem_size_mib: value.vm_config.mem_size_mib as u64,
smt: value.vm_config.smt,
cpu_template: StaticCpuTemplate::from(&value.vm_config.cpu_template),
- boot_source: value.boot_source_config().clone(),
+ boot_source: value.boot_source.config.clone(),
huge_pages: value.vm_config.huge_pages,
}
}
diff --git a/src/vmm/src/resources.rs b/src/vmm/src/resources.rs
index a4d15641975..0ad4df8aa19 100644
--- a/src/vmm/src/resources.rs
+++ b/src/vmm/src/resources.rs
@@ -315,16 +315,6 @@ impl VmResources {
mmds_config
}
- /// Gets a reference to the boot source configuration.
- pub fn boot_source_config(&self) -> &BootSourceConfig {
- &self.boot_source.config
- }
-
- /// Gets a reference to the boot source builder.
- pub fn boot_source_builder(&self) -> Option<&BootConfig> {
- self.boot_source.builder.as_ref()
- }
-
/// Sets a balloon device to be attached when the VM starts.
pub fn set_balloon_device(
&mut self,
@@ -354,14 +344,12 @@ impl VmResources {
return Err(BootSourceConfigError::HugePagesAndInitRd);
}
- self.set_boot_source_config(boot_source_cfg);
- self.boot_source.builder = Some(BootConfig::new(self.boot_source_config())?);
- Ok(())
- }
+ self.boot_source = BootSource {
+ builder: Some(BootConfig::new(&boot_source_cfg)?),
+ config: boot_source_cfg,
+ };
- /// Set the boot source configuration (contains raw kernel config details).
- pub fn set_boot_source_config(&mut self, boot_source_cfg: BootSourceConfig) {
- self.boot_source.config = boot_source_cfg;
+ Ok(())
}
/// Inserts a block to be attached when the VM starts.
@@ -512,7 +500,7 @@ impl From<&VmResources> for VmmConfig {
VmmConfig {
balloon_device: resources.balloon.get_config().ok(),
block_devices: resources.block.configs(),
- boot_source: resources.boot_source_config().clone(),
+ boot_source: resources.boot_source.config.clone(),
cpu_config: None,
logger: None,
machine_config: Some(MachineConfig::from(&resources.vm_config)),
@@ -1521,15 +1509,6 @@ mod tests {
assert_eq!(actual_entropy_cfg, entropy_device_cfg);
}
- #[test]
- fn test_boot_config() {
- let vm_resources = default_vm_resources();
- let expected_boot_cfg = vm_resources.boot_source.builder.as_ref().unwrap();
- let actual_boot_cfg = vm_resources.boot_source_builder().unwrap();
-
- assert!(actual_boot_cfg == expected_boot_cfg);
- }
-
#[test]
fn test_set_boot_source() {
let tmp_file = TempFile::new().unwrap();
@@ -1541,7 +1520,7 @@ mod tests {
};
let mut vm_resources = default_vm_resources();
- let boot_builder = vm_resources.boot_source_builder().unwrap();
+ let boot_builder = vm_resources.boot_source.builder.as_ref().unwrap();
let tmp_ino = tmp_file.as_file().metadata().unwrap().st_ino();
assert_ne!(
@@ -1568,7 +1547,7 @@ mod tests {
);
vm_resources.build_boot_source(expected_boot_cfg).unwrap();
- let boot_source_builder = vm_resources.boot_source_builder().unwrap();
+ let boot_source_builder = vm_resources.boot_source.builder.unwrap();
assert_eq!(
boot_source_builder
.cmdline
diff --git a/src/vmm/src/vstate/vcpu/x86_64.rs b/src/vmm/src/vstate/vcpu/x86_64.rs
index 6fee3933435..a1bb22d1bb7 100644
--- a/src/vmm/src/vstate/vcpu/x86_64.rs
+++ b/src/vmm/src/vstate/vcpu/x86_64.rs
@@ -61,7 +61,7 @@ pub enum KvmVcpuError {
VcpuGetLapic(kvm_ioctls::Error),
/// Failed to get KVM vcpu mp state: {0}
VcpuGetMpState(kvm_ioctls::Error),
- /// Failed to get KVM vcpu msr: 0x{0:x}
+ /// Failed to get KVM vcpu msr: {0:#x}
VcpuGetMsr(u32),
/// Failed to get KVM vcpu msrs: {0}
VcpuGetMsrs(kvm_ioctls::Error),
@@ -321,7 +321,7 @@ impl KvmVcpu {
.filter(|msr| msr.index == MSR_IA32_TSC_DEADLINE && msr.data == 0)
.for_each(|msr| {
warn!(
- "MSR_IA32_TSC_DEADLINE is 0, replacing with {:x}.",
+ "MSR_IA32_TSC_DEADLINE is 0, replacing with {:#x}.",
tsc_value
);
msr.data = tsc_value;
diff --git a/src/vmm/src/vstate/vm.rs b/src/vmm/src/vstate/vm.rs
index 0f72abcf68f..3d24dc6f9ac 100644
--- a/src/vmm/src/vstate/vm.rs
+++ b/src/vmm/src/vstate/vm.rs
@@ -34,7 +34,7 @@ use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestMemoryRe
pub enum VmError {
/// The host kernel reports an invalid KVM API version: {0}
ApiVersion(i32),
- /// Missing KVM capabilities: {0:x?}
+ /// Missing KVM capabilities: {0:#x?}
Capabilities(u32),
/** Error creating KVM object: {0} Make sure the user launching the firecracker process is \
configured on the /dev/kvm file's ACL. */
diff --git a/tests/README.md b/tests/README.md
index ea46ff56786..bf7aba9a547 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -306,10 +306,14 @@ that are pre-initialized with specific guest kernels and rootfs:
24.04 squashfs as rootfs,
- `uvm_plain` yields a Firecracker process pre-initialized with a 5.10 kernel
and the same Ubuntu 24.04 squashfs.
-
-Generally, tests should use the former if you are testing some interaction
-between the guest and Firecracker, while the latter should be used if
-Firecracker functionality unrelated to the guest is being tested.
+- `uvm_any` yields started microvms, parametrized by all supported kernels, all
+ CPU templates (static, custom and none), and either booted or restored from a
+ snapshot.
+- `uvm_any_booted` works the same as `uvm_any`, but only for booted VMs.
+
+Generally, tests should use `uvm_plain_any` if you are testing some interaction
+between the guest and Firecracker, and `uvm_plain` should be used if Firecracker
+functionality unrelated to the guest is being tested.
### Markers
diff --git a/tests/conftest.py b/tests/conftest.py
index 8f4c2e51ff5..ac73b4bd8ab 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -35,7 +35,7 @@
import host_tools.cargo_build as build_tools
from framework import defs, utils
-from framework.artifacts import kernel_params, rootfs_params
+from framework.artifacts import disks, kernel_params
from framework.microvm import MicroVMFactory
from framework.properties import global_props
from framework.utils_cpu_templates import (
@@ -292,13 +292,6 @@ def microvm_factory(request, record_property, results_dir):
uvm_factory.kill()
-@pytest.fixture(params=static_cpu_templates_params())
-def cpu_template(request, record_property):
- """Return all static CPU templates supported by the vendor."""
- record_property("static_cpu_template", request.param)
- return request.param
-
-
@pytest.fixture(params=custom_cpu_templates_params())
def custom_cpu_template(request, record_property):
"""Return all dummy custom CPU templates supported by the vendor."""
@@ -361,13 +354,6 @@ def guest_kernel_fxt(request, record_property):
return kernel
-def rootfs_fxt(request, record_property):
- """Return all supported rootfs."""
- fs = request.param
- record_property("rootfs", fs.name)
- return fs
-
-
# Fixtures for all guest kernels, and specific versions
guest_kernel = pytest.fixture(guest_kernel_fxt, params=kernel_params("vmlinux-*"))
guest_kernel_acpi = pytest.fixture(
@@ -387,9 +373,17 @@ def rootfs_fxt(request, record_property):
params=kernel_params("vmlinux-6.1*"),
)
-# Fixtures for all Ubuntu rootfs, and specific versions
-rootfs = pytest.fixture(rootfs_fxt, params=rootfs_params("ubuntu-24*.squashfs"))
-rootfs_rw = pytest.fixture(rootfs_fxt, params=rootfs_params("*.ext4"))
+
+@pytest.fixture
+def rootfs():
+ """Return an Ubuntu 24.04 read-only rootfs"""
+ return disks("ubuntu-24.04.squashfs")[0]
+
+
+@pytest.fixture
+def rootfs_rw():
+ """Return an Ubuntu 24.04 ext4 rootfs"""
+ return disks("ubuntu-24.04.ext4")[0]
@pytest.fixture
@@ -459,3 +453,80 @@ def uvm_with_initrd(
uvm = microvm_factory.build(guest_kernel_linux_5_10)
uvm.initrd_file = fs
yield uvm
+
+
+@pytest.fixture
+def vcpu_count():
+ """Return default vcpu_count. Use indirect parametrization to override."""
+ return 2
+
+
+@pytest.fixture
+def mem_size_mib():
+ """Return memory size. Use indirect parametrization to override."""
+ return 256
+
+
+def uvm_booted(
+ microvm_factory, guest_kernel, rootfs, cpu_template, vcpu_count=2, mem_size_mib=256
+):
+ """Return a booted uvm"""
+ uvm = microvm_factory.build(guest_kernel, rootfs)
+ uvm.spawn()
+ uvm.basic_config(vcpu_count=vcpu_count, mem_size_mib=mem_size_mib)
+ uvm.set_cpu_template(cpu_template)
+ uvm.add_net_iface()
+ uvm.start()
+ return uvm
+
+
+def uvm_restored(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs):
+ """Return a restored uvm"""
+ uvm = uvm_booted(microvm_factory, guest_kernel, rootfs, cpu_template, **kwargs)
+ snapshot = uvm.snapshot_full()
+ uvm.kill()
+ uvm2 = microvm_factory.build_from_snapshot(snapshot)
+ uvm2.cpu_template_name = uvm.cpu_template_name
+ return uvm2
+
+
+@pytest.fixture(params=[uvm_booted, uvm_restored])
+def uvm_ctor(request):
+ """Fixture to return uvms with different constructors"""
+ return request.param
+
+
+@pytest.fixture
+def uvm_any(
+ microvm_factory,
+ uvm_ctor,
+ guest_kernel,
+ rootfs,
+ cpu_template_any,
+ vcpu_count,
+ mem_size_mib,
+):
+ """Return booted and restored uvms"""
+ return uvm_ctor(
+ microvm_factory,
+ guest_kernel,
+ rootfs,
+ cpu_template_any,
+ vcpu_count=vcpu_count,
+ mem_size_mib=mem_size_mib,
+ )
+
+
+@pytest.fixture
+def uvm_any_booted(
+ microvm_factory, guest_kernel, rootfs, cpu_template_any, vcpu_count, mem_size_mib
+):
+ """Return booted uvms"""
+ return uvm_booted(
+ microvm_factory,
+ guest_kernel,
+ rootfs,
+ cpu_template_any,
+ vcpu_count=vcpu_count,
+ mem_size_mib=mem_size_mib,
+ )
diff --git a/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json b/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json
index b155d81dc34..29e47be4a92 100644
--- a/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json
+++ b/tests/data/static_cpu_templates/aarch64_with_sve_and_pac.json
@@ -1,4 +1,4 @@
{
"kvm_capabilities": ["170", "171", "172"],
- "vcpu_features": [{ "index": 0, "bitmap": "0b1110000" }]
+ "vcpu_features": [{ "index": 0, "bitmap": "0b111xxxx" }]
}
diff --git a/tests/framework/ab_test.py b/tests/framework/ab_test.py
index cf909d44fa6..2ef3e2350a7 100644
--- a/tests/framework/ab_test.py
+++ b/tests/framework/ab_test.py
@@ -21,7 +21,6 @@
of both invocations is the same, the test passes (with us being alerted to this situtation via a special pipeline that
does not block PRs). If not, it fails, preventing PRs from introducing new vulnerable dependencies.
"""
-import os
import statistics
from pathlib import Path
from tempfile import TemporaryDirectory
@@ -31,14 +30,14 @@
from framework import utils
from framework.defs import FC_WORKSPACE_DIR
-from framework.microvm import Microvm
+from framework.properties import global_props
from framework.utils import CommandReturn
from framework.with_filelock import with_filelock
-from host_tools.cargo_build import DEFAULT_TARGET_DIR, get_firecracker_binaries
+from host_tools.cargo_build import DEFAULT_TARGET_DIR
# Locally, this will always compare against main, even if we try to merge into, say, a feature branch.
# We might want to do a more sophisticated way to determine a "parent" branch here.
-DEFAULT_A_REVISION = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH") or "main"
+DEFAULT_A_REVISION = global_props.buildkite_revision_a or "main"
T = TypeVar("T")
@@ -120,11 +119,6 @@ def binary_ab_test(
return result_a, result_b, comparator(result_a, result_b)
-def is_pr() -> bool:
- """Returns `True` iff we are executing in the context of a build kite run on a pull request"""
- return os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false"
-
-
def git_ab_test_host_command_if_pr(
command: str,
*,
@@ -134,7 +128,7 @@ def git_ab_test_host_command_if_pr(
"""Runs the given bash command as an A/B-Test if we're in a pull request context (asserting that its stdout and
stderr did not change across the PR). Otherwise runs the command, asserting it returns a zero exit code
"""
- if is_pr():
+ if global_props.buildkite_pr:
git_ab_test_host_command(command, comparator=comparator)
return None
@@ -176,56 +170,6 @@ def set_did_not_grow_comparator(
)
-def precompiled_ab_test_guest_command(
- microvm_factory: Callable[[Path, Path], Microvm],
- command: str,
- *,
- comparator: Callable[[CommandReturn, CommandReturn], bool] = default_comparator,
- a_revision: str = DEFAULT_A_REVISION,
- b_revision: Optional[str] = None,
-):
- """The same as git_ab_test_command, but via SSH. The closure argument should setup a microvm using the passed
- paths to firecracker and jailer binaries."""
- b_directory = (
- DEFAULT_B_DIRECTORY
- if b_revision is None
- else FC_WORKSPACE_DIR / "build" / b_revision
- )
-
- def test_runner(bin_dir, _is_a: bool):
- microvm = microvm_factory(bin_dir / "firecracker", bin_dir / "jailer")
- return microvm.ssh.run(command)
-
- (_, old_out, old_err), (_, new_out, new_err), the_same = binary_ab_test(
- test_runner,
- comparator,
- a_directory=FC_WORKSPACE_DIR / "build" / a_revision,
- b_directory=b_directory,
- )
-
- assert (
- the_same
- ), f"The output of running command `{command}` changed:\nOld:\nstdout:\n{old_out}\nstderr\n{old_err}\n\nNew:\nstdout:\n{new_out}\nstderr:\n{new_err}"
-
-
-def precompiled_ab_test_guest_command_if_pr(
- microvm_factory: Callable[[Path, Path], Microvm],
- command: str,
- *,
- comparator=default_comparator,
- check_in_nonpr=True,
-):
- """The same as git_ab_test_command_if_pr, but via SSH"""
- if is_pr():
- precompiled_ab_test_guest_command(
- microvm_factory, command, comparator=comparator
- )
- return None
-
- microvm = microvm_factory(*get_firecracker_binaries())
- return microvm.ssh.run(command, check=check_in_nonpr)
-
-
def check_regression(
a_samples: List[float], b_samples: List[float], *, n_resamples: int = 9999
):
diff --git a/tests/framework/artifacts.py b/tests/framework/artifacts.py
index 77584f02129..0ed27c16b61 100644
--- a/tests/framework/artifacts.py
+++ b/tests/framework/artifacts.py
@@ -44,9 +44,9 @@ def kernels(glob, artifact_dir: Path = ARTIFACT_DIR) -> Iterator:
break
-def disks(glob) -> Iterator:
+def disks(glob) -> list:
"""Return supported rootfs"""
- yield from sorted(ARTIFACT_DIR.glob(glob))
+ return sorted(ARTIFACT_DIR.glob(glob))
def kernel_params(
@@ -57,12 +57,6 @@ def kernel_params(
yield pytest.param(kernel, id=kernel.name)
-def rootfs_params(glob="ubuntu-*.squashfs") -> Iterator:
- """Return supported rootfs as pytest parameters"""
- for rootfs in disks(glob=glob):
- yield pytest.param(rootfs, id=rootfs.name)
-
-
@dataclass(frozen=True, repr=True)
class FirecrackerArtifact:
"""Utility class for Firecracker binary artifacts."""
diff --git a/tests/framework/microvm.py b/tests/framework/microvm.py
index ed02488bc7b..572437c758b 100644
--- a/tests/framework/microvm.py
+++ b/tests/framework/microvm.py
@@ -75,6 +75,7 @@ class Snapshot:
disks: dict
ssh_key: Path
snapshot_type: SnapshotType
+ meta: dict
@property
def is_diff(self) -> bool:
@@ -110,6 +111,7 @@ def copy_to_chroot(self, chroot) -> "Snapshot":
disks=self.disks,
ssh_key=self.ssh_key,
snapshot_type=self.snapshot_type,
+ meta=self.meta,
)
@classmethod
@@ -125,6 +127,7 @@ def load_from(cls, src: Path) -> "Snapshot":
disks={dsk: src / p for dsk, p in obj["disks"].items()},
ssh_key=src / obj["ssh_key"],
snapshot_type=SnapshotType(obj["snapshot_type"]),
+ meta=obj["meta"],
)
def save_to(self, dst: Path):
@@ -241,6 +244,7 @@ def __init__(
self.disks_vhost_user = {}
self.vcpus_count = None
self.mem_size_bytes = None
+ self.cpu_template_name = None
self._pre_cmd = []
if numa_node:
@@ -732,12 +736,14 @@ def basic_config(
smt=smt,
mem_size_mib=mem_size_mib,
track_dirty_pages=track_dirty_pages,
- cpu_template=cpu_template,
huge_pages=huge_pages,
)
self.vcpus_count = vcpu_count
self.mem_size_bytes = mem_size_mib * 2**20
+ if cpu_template is not None:
+ self.set_cpu_template(cpu_template)
+
if self.memory_monitor:
self.memory_monitor.start()
@@ -770,6 +776,19 @@ def basic_config(
if enable_entropy_device:
self.enable_entropy_device()
+ def set_cpu_template(self, cpu_template):
+ """Set guest CPU template."""
+ if cpu_template is None:
+ return
+ # static CPU template
+ if isinstance(cpu_template, str):
+ self.api.machine_config.patch(cpu_template=cpu_template)
+ self.cpu_template_name = cpu_template.lower()
+ # custom CPU template
+ elif isinstance(cpu_template, dict):
+ self.api.cpu_config.put(**cpu_template["template"])
+ self.cpu_template_name = cpu_template["name"].lower()
+
def add_drive(
self,
drive_id,
@@ -917,6 +936,9 @@ def make_snapshot(
net_ifaces=[x["iface"] for ifname, x in self.iface.items()],
ssh_key=self.ssh_key,
snapshot_type=snapshot_type,
+ meta={
+ "kernel_file": self.kernel_file,
+ },
)
def snapshot_diff(self, *, mem_path: str = "mem", vmstate_path="vmstate"):
@@ -954,6 +976,9 @@ def restore_from_snapshot(
if uffd_path is not None:
mem_backend = {"backend_type": "Uffd", "backend_path": str(uffd_path)}
+ for key, value in snapshot.meta.items():
+ setattr(self, key, value)
+
self.api.snapshot_load.put(
mem_backend=mem_backend,
snapshot_path=str(jailed_vmstate),
@@ -1059,6 +1084,13 @@ def build(self, kernel=None, rootfs=None, **kwargs):
vm.ssh_key = ssh_key
return vm
+ def build_from_snapshot(self, snapshot: Snapshot):
+ """Build a microvm from a snapshot"""
+ vm = self.build()
+ vm.spawn()
+ vm.restore_from_snapshot(snapshot, resume=True)
+ return vm
+
def kill(self):
"""Clean up all built VMs"""
for vm in self.vms:
diff --git a/tests/framework/properties.py b/tests/framework/properties.py
index 92ded595299..7072a2ff3ca 100644
--- a/tests/framework/properties.py
+++ b/tests/framework/properties.py
@@ -71,11 +71,14 @@ def __init__(self):
# major.minor.patch
self.host_linux_patch = get_kernel_version(2)
self.os = get_os_version()
- self.host_os = get_host_os()
+ self.host_os = get_host_os() or "NA"
self.libc_ver = "-".join(platform.libc_ver())
self.rust_version = run_cmd("rustc --version |awk '{print $2}'")
+ # Buildkite/PR information
self.buildkite_pipeline_slug = os.environ.get("BUILDKITE_PIPELINE_SLUG")
self.buildkite_build_number = os.environ.get("BUILDKITE_BUILD_NUMBER")
+ self.buildkite_pr = os.environ.get("BUILDKITE_PULL_REQUEST", "false") != "false"
+ self.buildkite_revision_a = os.environ.get("BUILDKITE_PULL_REQUEST_BASE_BRANCH")
if self._in_git_repo():
self.git_commit_id = run_cmd("git rev-parse HEAD")
diff --git a/tests/framework/utils_cpu_templates.py b/tests/framework/utils_cpu_templates.py
index 96bf197efda..56021a21aaa 100644
--- a/tests/framework/utils_cpu_templates.py
+++ b/tests/framework/utils_cpu_templates.py
@@ -3,6 +3,8 @@
"""Utilities for CPU template related functionality."""
+# pylint:disable=too-many-return-statements
+
import json
from pathlib import Path
@@ -20,16 +22,12 @@
def get_supported_cpu_templates():
- """
- Return the list of CPU templates supported by the platform.
- """
- # pylint:disable=too-many-return-statements
+ """Return the list of static CPU templates supported by the platform."""
host_linux = global_props.host_linux_version_tpl
-
match get_cpu_vendor(), global_props.cpu_codename:
# T2CL template is only supported on Cascade Lake and newer CPUs.
case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE:
- return sorted(set(INTEL_TEMPLATES) - set(["T2CL"]))
+ return sorted(set(INTEL_TEMPLATES) - {"T2CL"})
case CpuVendor.INTEL, _:
return INTEL_TEMPLATES
case CpuVendor.AMD, _:
@@ -44,12 +42,8 @@ def get_supported_cpu_templates():
def get_supported_custom_cpu_templates():
- """
- Return the list of custom CPU templates supported by the platform.
- """
- # pylint:disable=too-many-return-statements
+ """Return the list of custom CPU templates supported by the platform."""
host_linux = global_props.host_linux_version_tpl
-
match get_cpu_vendor(), global_props.cpu_codename:
# T2CL template is only supported on Cascade Lake and newer CPUs.
case CpuVendor.INTEL, CpuModel.INTEL_SKYLAKE:
diff --git a/tests/framework/utils_cpuid.py b/tests/framework/utils_cpuid.py
index 4303e3ba967..dabfb220240 100644
--- a/tests/framework/utils_cpuid.py
+++ b/tests/framework/utils_cpuid.py
@@ -25,6 +25,7 @@ class CpuModel(str, Enum):
"""CPU models"""
AMD_MILAN = "AMD_MILAN"
+ AMD_GENOA = "AMD_GENOA"
ARM_NEOVERSE_N1 = "ARM_NEOVERSE_N1"
ARM_NEOVERSE_V1 = "ARM_NEOVERSE_V1"
INTEL_SKYLAKE = "INTEL_SKYLAKE"
@@ -39,9 +40,7 @@ class CpuModel(str, Enum):
"Intel(R) Xeon(R) Platinum 8259CL CPU": "INTEL_CASCADELAKE",
"Intel(R) Xeon(R) Platinum 8375C CPU": "INTEL_ICELAKE",
},
- CpuVendor.AMD: {
- "AMD EPYC 7R13": "AMD_MILAN",
- },
+ CpuVendor.AMD: {"AMD EPYC 7R13": "AMD_MILAN", "AMD EPYC 9R14": "AMD_GENOA"},
CpuVendor.ARM: {"0xd0c": "ARM_NEOVERSE_N1", "0xd40": "ARM_NEOVERSE_V1"},
}
diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py
index 27366529c39..1e54c7b4fb1 100644
--- a/tests/integration_tests/functional/test_api.py
+++ b/tests/integration_tests/functional/test_api.py
@@ -1166,10 +1166,7 @@ def test_get_full_config_after_restoring_snapshot(microvm_factory, uvm_nano):
]
snapshot = uvm_nano.snapshot_full()
- uvm2 = microvm_factory.build()
- uvm2.spawn()
- uvm2.restore_from_snapshot(snapshot, resume=True)
-
+ uvm2 = microvm_factory.build_from_snapshot(snapshot)
expected_cfg = setup_cfg.copy()
# We expect boot-source to be set with the following values
diff --git a/tests/integration_tests/functional/test_balloon.py b/tests/integration_tests/functional/test_balloon.py
index ee750dcac7d..2c59fd2e814 100644
--- a/tests/integration_tests/functional/test_balloon.py
+++ b/tests/integration_tests/functional/test_balloon.py
@@ -484,9 +484,7 @@ def test_balloon_snapshot(microvm_factory, guest_kernel, rootfs):
assert first_reading > second_reading
snapshot = vm.snapshot_full()
- microvm = microvm_factory.build()
- microvm.spawn()
- microvm.restore_from_snapshot(snapshot, resume=True)
+ microvm = microvm_factory.build_from_snapshot(snapshot)
# Get the firecracker from snapshot pid, and open an ssh connection.
firecracker_pid = microvm.firecracker_pid
diff --git a/tests/integration_tests/functional/test_cmd_line_parameters.py b/tests/integration_tests/functional/test_cmd_line_parameters.py
index 25e47a50e17..79af938b1f7 100644
--- a/tests/integration_tests/functional/test_cmd_line_parameters.py
+++ b/tests/integration_tests/functional/test_cmd_line_parameters.py
@@ -96,9 +96,7 @@ def test_cli_metrics_if_resume_no_metrics(uvm_plain, microvm_factory):
snapshot = uvm1.snapshot_full()
# When: restoring from the snapshot
- uvm2 = microvm_factory.build()
- uvm2.spawn()
- uvm2.restore_from_snapshot(snapshot)
+ uvm2 = microvm_factory.build_from_snapshot(snapshot)
# Then: the old metrics configuration does not exist
metrics2 = Path(uvm2.jailer.chroot_path()) / metrics_path.name
diff --git a/tests/integration_tests/functional/test_cpu_features_aarch64.py b/tests/integration_tests/functional/test_cpu_features_aarch64.py
index 8357f54b568..2068194a894 100644
--- a/tests/integration_tests/functional/test_cpu_features_aarch64.py
+++ b/tests/integration_tests/functional/test_cpu_features_aarch64.py
@@ -2,218 +2,47 @@
# SPDX-License-Identifier: Apache-2.0
"""Tests for the CPU features for aarch64."""
-import os
-import platform
-import re
-
import pytest
-import framework.utils_cpuid as cpuid_utils
-from framework import utils
from framework.properties import global_props
from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel
-PLATFORM = platform.machine()
+pytestmark = pytest.mark.skipif(
+ global_props.cpu_architecture != "aarch64", reason="Only run in aarch64"
+)
-DEFAULT_G2_FEATURES = set(
+G2_FEATS = set(
(
"fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp "
"asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs"
- ).split(" ")
+ ).split()
)
-DEFAULT_G3_FEATURES_5_10 = DEFAULT_G2_FEATURES | set(
- "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split(
- " "
- )
+G3_FEATS = G2_FEATS | set(
+ "sha512 asimdfhm dit uscat ilrcpc flagm jscvt fcma sha3 sm3 sm4 rng dcpodp i8mm bf16 dgh".split()
)
-DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10 = DEFAULT_G3_FEATURES_5_10 | set(
- "paca pacg sve svebf16 svei8mm".split(" ")
-)
+G3_SVE_AND_PAC = set("paca pacg sve svebf16 svei8mm".split())
-DEFAULT_G3_FEATURES_V1N1 = DEFAULT_G2_FEATURES
+def test_guest_cpu_features(uvm_any):
+ """Check the CPU features for a microvm with different CPU templates"""
-def _check_cpu_features_arm(test_microvm, guest_kv, template_name=None):
- expected_cpu_features = {"Flags": []}
- match cpuid_utils.get_cpu_model_name(), guest_kv, template_name:
- case CpuModel.ARM_NEOVERSE_N1, _, "v1n1":
- expected_cpu_features = DEFAULT_G2_FEATURES
- case CpuModel.ARM_NEOVERSE_N1, _, None:
- expected_cpu_features = DEFAULT_G2_FEATURES
+ vm = uvm_any
+ expected_cpu_features = set()
+ match global_props.cpu_model, vm.cpu_template_name:
+ case CpuModel.ARM_NEOVERSE_N1, "v1n1":
+ expected_cpu_features = G2_FEATS
+ case CpuModel.ARM_NEOVERSE_N1, None:
+ expected_cpu_features = G2_FEATS
# [cm]7g with guest kernel 5.10 and later
- case CpuModel.ARM_NEOVERSE_V1, _, "v1n1":
- expected_cpu_features = DEFAULT_G3_FEATURES_V1N1
- case CpuModel.ARM_NEOVERSE_V1, _, "aarch64_with_sve_and_pac":
- expected_cpu_features = DEFAULT_G3_FEATURES_WITH_SVE_AND_PAC_5_10
- case CpuModel.ARM_NEOVERSE_V1, _, None:
- expected_cpu_features = DEFAULT_G3_FEATURES_5_10
-
- _, stdout, _ = test_microvm.ssh.check_output(CPU_FEATURES_CMD)
- flags = set(stdout.strip().split(" "))
- assert flags == expected_cpu_features
-
-
-def get_cpu_template_dir(cpu_template):
- """
- Utility function to return a valid string which will be used as
- name of the directory where snapshot artifacts are stored during
- snapshot test and loaded from during restore test.
-
- """
- return cpu_template if cpu_template else "none"
-
-
-@pytest.mark.skipif(
- PLATFORM != "aarch64",
- reason="This is aarch64 specific test.",
-)
-def test_host_vs_guest_cpu_features_aarch64(uvm_nano):
- """Check CPU features host vs guest"""
-
- vm = uvm_nano
- vm.add_net_iface()
- vm.start()
- host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
- guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
-
- cpu_model = cpuid_utils.get_cpu_model_name()
- match cpu_model:
- case CpuModel.ARM_NEOVERSE_N1:
- expected_guest_minus_host = set()
- expected_host_minus_guest = set()
-
- # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
- # they have an errata whereby an MSR to the SSBS special-purpose register does not
- # affect subsequent speculative instructions, permitting speculative store bypassing for
- # a window of time.
- # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
- #
- # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
- # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
- host_has_ssbs = global_props.host_os not in {
- "amzn2",
- "amzn2023",
- } and global_props.host_linux_version_tpl < (6, 11)
- guest_has_ssbs = vm.guest_kernel_version < (6, 11)
-
- if host_has_ssbs and not guest_has_ssbs:
- expected_host_minus_guest |= {"ssbs"}
- if not host_has_ssbs and guest_has_ssbs:
- expected_guest_minus_host |= {"ssbs"}
-
- assert host_feats - guest_feats == expected_host_minus_guest
- assert guest_feats - host_feats == expected_guest_minus_host
- case CpuModel.ARM_NEOVERSE_V1:
- expected_guest_minus_host = set()
- # KVM does not enable PAC or SVE features by default
- # and Firecracker does not enable them either.
- expected_host_minus_guest = {
- "paca",
- "pacg",
- "sve",
- "svebf16",
- "svei8mm",
- }
-
- # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
- # they have an errata whereby an MSR to the SSBS special-purpose register does not
- # affect subsequent speculative instructions, permitting speculative store bypassing for
- # a window of time.
- # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
- #
- # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
- # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
- host_has_ssbs = global_props.host_os not in {
- "amzn2",
- "amzn2023",
- } and global_props.host_linux_version_tpl < (6, 11)
- guest_has_ssbs = vm.guest_kernel_version < (6, 11)
-
- if host_has_ssbs and not guest_has_ssbs:
- expected_host_minus_guest |= {"ssbs"}
- if not host_has_ssbs and guest_has_ssbs:
- expected_guest_minus_host |= {"ssbs"}
-
- assert host_feats - guest_feats == expected_host_minus_guest
- assert guest_feats - host_feats == expected_guest_minus_host
- case _:
- if os.environ.get("BUILDKITE") is not None:
- assert False, f"Cpu model {cpu_model} is not supported"
-
-
-@pytest.mark.skipif(
- PLATFORM != "aarch64",
- reason="This is aarch64 specific test.",
-)
-def test_default_cpu_features(microvm_factory, guest_kernel, rootfs):
- """
- Check the CPU features for a microvm with the specified config.
- """
-
- vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
- vm.spawn()
- vm.basic_config()
- vm.add_net_iface()
- vm.start()
- guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1)
- _check_cpu_features_arm(vm, guest_kv)
-
-
-@pytest.mark.skipif(
- PLATFORM != "aarch64",
- reason="This is aarch64 specific test.",
-)
-def test_cpu_features_with_static_template(
- microvm_factory, guest_kernel, rootfs, cpu_template
-):
- """
- Check the CPU features for a microvm with the specified config.
- """
-
- vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
- vm.spawn()
- vm.basic_config(cpu_template=cpu_template)
- vm.add_net_iface()
- vm.start()
- guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1)
- _check_cpu_features_arm(vm, guest_kv, "v1n1")
-
- # Check that cpu features are still correct
- # after snap/restore cycle.
- snapshot = vm.snapshot_full()
- restored_vm = microvm_factory.build()
- restored_vm.spawn()
- restored_vm.restore_from_snapshot(snapshot, resume=True)
- _check_cpu_features_arm(restored_vm, guest_kv, "v1n1")
-
-
-@pytest.mark.skipif(
- PLATFORM != "aarch64",
- reason="This is aarch64 specific test.",
-)
-def test_cpu_features_with_custom_template(
- microvm_factory, guest_kernel, rootfs, custom_cpu_template
-):
- """
- Check the CPU features for a microvm with the specified config.
- """
-
- vm = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
- vm.spawn()
- vm.basic_config()
- vm.api.cpu_config.put(**custom_cpu_template["template"])
- vm.add_net_iface()
- vm.start()
- guest_kv = re.search(r"vmlinux-(\d+\.\d+)", guest_kernel.name).group(1)
- _check_cpu_features_arm(vm, guest_kv, custom_cpu_template["name"])
-
- # Check that cpu features are still correct
- # after snap/restore cycle.
- snapshot = vm.snapshot_full()
- restored_vm = microvm_factory.build()
- restored_vm.spawn()
- restored_vm.restore_from_snapshot(snapshot, resume=True)
- _check_cpu_features_arm(restored_vm, guest_kv, custom_cpu_template["name"])
+ case CpuModel.ARM_NEOVERSE_V1, "v1n1":
+ expected_cpu_features = G2_FEATS
+ case CpuModel.ARM_NEOVERSE_V1, "aarch64_with_sve_and_pac":
+ expected_cpu_features = G3_FEATS | G3_SVE_AND_PAC
+ case CpuModel.ARM_NEOVERSE_V1, None:
+ expected_cpu_features = G3_FEATS
+
+ guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split())
+ assert guest_feats == expected_cpu_features
diff --git a/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py
new file mode 100644
index 00000000000..bbf4ed57d21
--- /dev/null
+++ b/tests/integration_tests/functional/test_cpu_features_host_vs_guest.py
@@ -0,0 +1,272 @@
+# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+# pylint: disable=too-many-statements
+
+"""
+Check CPU features in the host vs the guest.
+
+This test can highlight differences between the host and what the guest sees.
+
+No CPU templates as we are interested only on what is passed through to the guest by default.
+For that, check test_feat_parity.py
+"""
+
+import os
+
+from framework import utils
+from framework.properties import global_props
+from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel
+
+CPU_MODEL = global_props.cpu_codename
+
+INTEL_HOST_ONLY_FEATS = {
+ "acpi",
+ "aperfmperf",
+ "arch_perfmon",
+ "art",
+ "bts",
+ "cat_l3",
+ "cdp_l3",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "dca",
+ "ds_cpl",
+ "dtes64",
+ "dtherm",
+ "dts",
+ "epb",
+ "ept",
+ "ept_ad",
+ "est",
+ "flexpriority",
+ "flush_l1d",
+ "hwp",
+ "hwp_act_window",
+ "hwp_epp",
+ "hwp_pkg_req",
+ "ida",
+ "intel_ppin",
+ "intel_pt",
+ "mba",
+ "monitor",
+ "pbe",
+ "pdcm",
+ "pebs",
+ "pln",
+ "pts",
+ "rdt_a",
+ "sdbg",
+ "smx",
+ "tm",
+ "tm2",
+ "tpr_shadow",
+ "vmx",
+ "vnmi",
+ "vpid",
+ "xtpr",
+}
+
+
+def test_host_vs_guest_cpu_features(uvm_nano):
+ """Check CPU features host vs guest"""
+
+ vm = uvm_nano
+ vm.add_net_iface()
+ vm.start()
+ host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.split())
+ guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.split())
+
+ match CPU_MODEL:
+ case CpuModel.AMD_MILAN:
+ host_guest_diff_5_10 = {
+ "amd_ppin",
+ "aperfmperf",
+ "bpext",
+ "cat_l3",
+ "cdp_l3",
+ "cpb",
+ "cqm",
+ "cqm_llc",
+ "cqm_mbm_local",
+ "cqm_mbm_total",
+ "cqm_occup_llc",
+ "decodeassists",
+ "extapic",
+ "extd_apicid",
+ "flushbyasid",
+ "hw_pstate",
+ "ibs",
+ "irperf",
+ "lbrv",
+ "mba",
+ "monitor",
+ "mwaitx",
+ "overflow_recov",
+ "pausefilter",
+ "perfctr_llc",
+ "perfctr_nb",
+ "pfthreshold",
+ "rdpru",
+ "rdt_a",
+ "sev",
+ "sev_es",
+ "skinit",
+ "smca",
+ "sme",
+ "succor",
+ "svm_lock",
+ "tce",
+ "tsc_scale",
+ "v_vmsave_vmload",
+ "vgif",
+ "vmcb_clean",
+ "wdt",
+ }
+
+ host_guest_diff_6_1 = host_guest_diff_5_10 - {
+ "lbrv",
+ "pausefilter",
+ "pfthreshold",
+ "sme",
+ "tsc_scale",
+ "v_vmsave_vmload",
+ "vgif",
+ "vmcb_clean",
+ } | {"brs", "rapl", "v_spec_ctrl"}
+
+ if global_props.host_linux_version_tpl < (6, 1):
+ assert host_feats - guest_feats == host_guest_diff_5_10
+ else:
+ assert host_feats - guest_feats == host_guest_diff_6_1
+
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_adjust",
+ "tsc_deadline_timer",
+ "tsc_known_freq",
+ }
+
+ case CpuModel.INTEL_SKYLAKE:
+ assert host_feats - guest_feats == INTEL_HOST_ONLY_FEATS
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_known_freq",
+ "umip",
+ }
+
+ case CpuModel.INTEL_CASCADELAKE:
+ expected_host_minus_guest = INTEL_HOST_ONLY_FEATS
+ expected_guest_minus_host = {
+ "hypervisor",
+ "tsc_known_freq",
+ "umip",
+ }
+
+ # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests.
+ # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e
+ #
+ # Our test ubuntu host kernel is v6.8 and has the commit.
+ if global_props.host_linux_version_tpl >= (6, 4):
+ expected_host_minus_guest -= {"flush_l1d"}
+
+ # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit.
+ # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d
+ #
+ # Our test ubuntu host kernel is v6.8 and has the commit.
+ host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6)
+ guest_has_invpcid_single = vm.guest_kernel_version < (6, 6)
+ if host_has_invpcid_single and not guest_has_invpcid_single:
+ expected_host_minus_guest |= {"invpcid_single"}
+ if not host_has_invpcid_single and guest_has_invpcid_single:
+ expected_guest_minus_host |= {"invpcid_single"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+
+ case CpuModel.INTEL_ICELAKE:
+ host_guest_diff_5_10 = INTEL_HOST_ONLY_FEATS - {"cdp_l3"} | {
+ "pconfig",
+ "tme",
+ "split_lock_detect",
+ }
+ host_guest_diff_6_1 = host_guest_diff_5_10 - {
+ "bts",
+ "dtes64",
+ "dts",
+ "pebs",
+ }
+
+ if global_props.host_linux_version_tpl < (6, 1):
+ assert host_feats - guest_feats == host_guest_diff_5_10
+ else:
+ assert host_feats - guest_feats == host_guest_diff_6_1
+
+ assert guest_feats - host_feats == {
+ "hypervisor",
+ "tsc_known_freq",
+ }
+
+ case CpuModel.ARM_NEOVERSE_N1:
+ expected_guest_minus_host = set()
+ expected_host_minus_guest = set()
+
+ # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
+ # they have an errata whereby an MSR to the SSBS special-purpose register does not
+ # affect subsequent speculative instructions, permitting speculative store bypassing for
+ # a window of time.
+ # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
+ #
+ # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
+ # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
+ host_has_ssbs = global_props.host_os not in {
+ "amzn2",
+ "amzn2023",
+ } and global_props.host_linux_version_tpl < (6, 11)
+ guest_has_ssbs = vm.guest_kernel_version < (6, 11)
+
+ if host_has_ssbs and not guest_has_ssbs:
+ expected_host_minus_guest |= {"ssbs"}
+ if not host_has_ssbs and guest_has_ssbs:
+ expected_guest_minus_host |= {"ssbs"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+
+ case CpuModel.ARM_NEOVERSE_V1:
+ expected_guest_minus_host = set()
+ # KVM does not enable PAC or SVE features by default
+ # and Firecracker does not enable them either.
+ expected_host_minus_guest = {"paca", "pacg", "sve", "svebf16", "svei8mm"}
+
+ # Upstream kernel v6.11+ hides "ssbs" from "lscpu" on Neoverse-N1 and Neoverse-V1 since
+ # they have an errata whereby an MSR to the SSBS special-purpose register does not
+ # affect subsequent speculative instructions, permitting speculative store bypassing for
+ # a window of time.
+ # https://github.com/torvalds/linux/commit/adeec61a4723fd3e39da68db4cc4d924e6d7f641
+ #
+ # While Amazon Linux kernels (v5.10 and v6.1) backported the above commit, our test
+ # ubuntu kernel (v6.8) and our guest kernels (v5.10 and v6.1) don't pick it.
+ host_has_ssbs = global_props.host_os not in {
+ "amzn2",
+ "amzn2023",
+ } and global_props.host_linux_version_tpl < (6, 11)
+ guest_has_ssbs = vm.guest_kernel_version < (6, 11)
+
+ if host_has_ssbs and not guest_has_ssbs:
+ expected_host_minus_guest |= {"ssbs"}
+ if not host_has_ssbs and guest_has_ssbs:
+ expected_guest_minus_host |= {"ssbs"}
+
+ assert host_feats - guest_feats == expected_host_minus_guest
+ assert guest_feats - host_feats == expected_guest_minus_host
+
+ case _:
+ # only fail if running in CI
+ if os.environ.get("BUILDKITE") is not None:
+ assert (
+ guest_feats == host_feats
+ ), f"Cpu model {CPU_MODEL} is not supported"
diff --git a/tests/integration_tests/functional/test_cpu_features_x86_64.py b/tests/integration_tests/functional/test_cpu_features_x86_64.py
index 23818ddc6b1..1af6a39f83a 100644
--- a/tests/integration_tests/functional/test_cpu_features_x86_64.py
+++ b/tests/integration_tests/functional/test_cpu_features_x86_64.py
@@ -22,7 +22,6 @@
from framework.defs import SUPPORTED_HOST_KERNELS
from framework.properties import global_props
from framework.utils_cpu_templates import SUPPORTED_CPU_TEMPLATES
-from framework.utils_cpuid import CPU_FEATURES_CMD, CpuModel
PLATFORM = platform.machine()
UNSUPPORTED_HOST_KERNEL = (
@@ -30,6 +29,10 @@
)
DATA_FILES = Path("./data/msr")
+pytestmark = pytest.mark.skipif(
+ global_props.cpu_architecture != "x86_64", reason="Only run in x86_64"
+)
+
def read_msr_csv(fd):
"""Read a CSV of MSRs"""
@@ -105,7 +108,6 @@ def skip_test_based_on_artifacts(snapshot_artifacts_dir):
pytest.skip(re.sub(" +", " ", reason))
-@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.")
@pytest.mark.parametrize(
"num_vcpus",
[1, 2, 16],
@@ -126,7 +128,6 @@ def test_cpuid(uvm_plain_any, num_vcpus, htt):
_check_cpuid_x86(vm, num_vcpus, "true" if num_vcpus > 1 else "false")
-@pytest.mark.skipif(PLATFORM != "x86_64", reason="CPUID is only supported on x86_64.")
@pytest.mark.skipif(
cpuid_utils.get_cpu_vendor() != cpuid_utils.CpuVendor.AMD,
reason="L3 cache info is only present in 0x80000006 for AMD",
@@ -143,9 +144,6 @@ def test_extended_cache_features(uvm_plain_any):
_check_extended_cache_features(vm)
-@pytest.mark.skipif(
- PLATFORM != "x86_64", reason="The CPU brand string is masked only on x86_64."
-)
def test_brand_string(uvm_plain_any):
"""
Ensure good formatting for the guest brand string.
@@ -204,293 +202,6 @@ def test_brand_string(uvm_plain_any):
assert False
-@pytest.mark.skipif(
- PLATFORM != "x86_64",
- reason="This is x86_64 specific test.",
-)
-def test_host_vs_guest_cpu_features_x86_64(uvm_nano):
- """Check CPU features host vs guest"""
-
- vm = uvm_nano
- vm.add_net_iface()
- vm.start()
- host_feats = set(utils.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
- guest_feats = set(vm.ssh.check_output(CPU_FEATURES_CMD).stdout.strip().split(" "))
-
- cpu_model = cpuid_utils.get_cpu_codename()
- match cpu_model:
- case CpuModel.AMD_MILAN:
- host_guest_diff_5_10 = {
- "amd_ppin",
- "aperfmperf",
- "bpext",
- "cat_l3",
- "cdp_l3",
- "cpb",
- "cqm",
- "cqm_llc",
- "cqm_mbm_local",
- "cqm_mbm_total",
- "cqm_occup_llc",
- "decodeassists",
- "extapic",
- "extd_apicid",
- "flushbyasid",
- "hw_pstate",
- "ibs",
- "irperf",
- "lbrv",
- "mba",
- "monitor",
- "mwaitx",
- "overflow_recov",
- "pausefilter",
- "perfctr_llc",
- "perfctr_nb",
- "pfthreshold",
- "rdpru",
- "rdt_a",
- "sev",
- "sev_es",
- "skinit",
- "smca",
- "sme",
- "succor",
- "svm_lock",
- "tce",
- "tsc_scale",
- "v_vmsave_vmload",
- "vgif",
- "vmcb_clean",
- "wdt",
- }
-
- host_guest_diff_6_1 = host_guest_diff_5_10 - {
- "lbrv",
- "pausefilter",
- "pfthreshold",
- "sme",
- "tsc_scale",
- "v_vmsave_vmload",
- "vgif",
- "vmcb_clean",
- } | {"brs", "rapl", "v_spec_ctrl"}
-
- if global_props.host_linux_version_tpl < (6, 1):
- assert host_feats - guest_feats == host_guest_diff_5_10
- else:
- assert host_feats - guest_feats == host_guest_diff_6_1
-
- assert guest_feats - host_feats == {
- "hypervisor",
- "tsc_adjust",
- "tsc_deadline_timer",
- "tsc_known_freq",
- }
- case CpuModel.INTEL_SKYLAKE:
- assert host_feats - guest_feats == {
- "acpi",
- "aperfmperf",
- "arch_perfmon",
- "art",
- "bts",
- "cat_l3",
- "cdp_l3",
- "cqm",
- "cqm_llc",
- "cqm_mbm_local",
- "cqm_mbm_total",
- "cqm_occup_llc",
- "dca",
- "ds_cpl",
- "dtes64",
- "dtherm",
- "dts",
- "epb",
- "ept",
- "ept_ad",
- "est",
- "flexpriority",
- "flush_l1d",
- "hwp",
- "hwp_act_window",
- "hwp_epp",
- "hwp_pkg_req",
- "ida",
- "intel_ppin",
- "intel_pt",
- "mba",
- "monitor",
- "pbe",
- "pdcm",
- "pebs",
- "pln",
- "pts",
- "rdt_a",
- "sdbg",
- "smx",
- "tm",
- "tm2",
- "tpr_shadow",
- "vmx",
- "vnmi",
- "vpid",
- "xtpr",
- }
- assert guest_feats - host_feats == {
- "hypervisor",
- "tsc_known_freq",
- "umip",
- }
- case CpuModel.INTEL_CASCADELAKE:
- expected_host_minus_guest = {
- "acpi",
- "aperfmperf",
- "arch_perfmon",
- "art",
- "bts",
- "cat_l3",
- "cdp_l3",
- "cqm",
- "cqm_llc",
- "cqm_mbm_local",
- "cqm_mbm_total",
- "cqm_occup_llc",
- "dca",
- "ds_cpl",
- "dtes64",
- "dtherm",
- "dts",
- "epb",
- "ept",
- "ept_ad",
- "est",
- "flexpriority",
- "flush_l1d",
- "hwp",
- "hwp_act_window",
- "hwp_epp",
- "hwp_pkg_req",
- "ida",
- "intel_ppin",
- "intel_pt",
- "mba",
- "monitor",
- "pbe",
- "pdcm",
- "pebs",
- "pln",
- "pts",
- "rdt_a",
- "sdbg",
- "smx",
- "tm",
- "tm2",
- "tpr_shadow",
- "vmx",
- "vnmi",
- "vpid",
- "xtpr",
- }
- expected_guest_minus_host = {
- "hypervisor",
- "tsc_known_freq",
- "umip",
- }
-
- # Linux kernel v6.4+ passes through the CPUID bit for "flush_l1d" to guests.
- # https://github.com/torvalds/linux/commit/45cf86f26148e549c5ba4a8ab32a390e4bde216e
- #
- # Our test ubuntu host kernel is v6.8 and has the commit.
- if global_props.host_linux_version_tpl >= (6, 4):
- expected_host_minus_guest -= {"flush_l1d"}
-
- # Linux kernel v6.6+ drops the "invpcid_single" synthetic feature bit.
- # https://github.com/torvalds/linux/commit/54e3d9434ef61b97fd3263c141b928dc5635e50d
- #
- # Our test ubuntu host kernel is v6.8 and has the commit.
- host_has_invpcid_single = global_props.host_linux_version_tpl < (6, 6)
- guest_has_invpcid_single = vm.guest_kernel_version < (6, 6)
- if host_has_invpcid_single and not guest_has_invpcid_single:
- expected_host_minus_guest |= {"invpcid_single"}
- if not host_has_invpcid_single and guest_has_invpcid_single:
- expected_guest_minus_host |= {"invpcid_single"}
-
- assert host_feats - guest_feats == expected_host_minus_guest
- assert guest_feats - host_feats == expected_guest_minus_host
- case CpuModel.INTEL_ICELAKE:
- host_guest_diff_5_10 = {
- "dtes64",
- "hwp_act_window",
- "pdcm",
- "acpi",
- "aperfmperf",
- "arch_perfmon",
- "art",
- "bts",
- "cat_l3",
- "cqm",
- "cqm_llc",
- "cqm_mbm_local",
- "cqm_mbm_total",
- "cqm_occup_llc",
- "dca",
- "ds_cpl",
- "dtherm",
- "dts",
- "epb",
- "ept",
- "ept_ad",
- "est",
- "flexpriority",
- "flush_l1d",
- "hwp",
- "hwp_epp",
- "hwp_pkg_req",
- "ida",
- "intel_ppin",
- "intel_pt",
- "mba",
- "monitor",
- "pbe",
- "pconfig",
- "pebs",
- "pln",
- "pts",
- "rdt_a",
- "sdbg",
- "smx",
- "split_lock_detect",
- "tm",
- "tm2",
- "tme",
- "tpr_shadow",
- "vmx",
- "vnmi",
- "vpid",
- "xtpr",
- }
- host_guest_diff_6_1 = host_guest_diff_5_10 - {
- "bts",
- "dtes64",
- "dts",
- "pebs",
- }
-
- if global_props.host_linux_version_tpl < (6, 1):
- assert host_feats - guest_feats == host_guest_diff_5_10
- else:
- assert host_feats - guest_feats == host_guest_diff_6_1
-
- assert guest_feats - host_feats == {
- "hypervisor",
- "tsc_known_freq",
- }
- case _:
- if os.environ.get("BUILDKITE") is not None:
- assert False, f"Cpu model {cpu_model} is not supported"
-
-
# From the `Intel® 64 Architecture x2APIC Specification`
# (https://courses.cs.washington.edu/courses/cse451/24wi/documentation/x2apic.pdf):
# > The X2APIC MSRs cannot to be loaded and stored on VMX transitions. A VMX transition fails
@@ -924,9 +635,6 @@ def test_cpu_cpuid_restore(microvm_factory, guest_kernel, msr_cpu_template):
)
-@pytest.mark.skipif(
- PLATFORM != "x86_64", reason="CPU features are masked only on x86_64."
-)
@pytest.mark.parametrize("cpu_template", ["T2", "T2S", "C3"])
def test_cpu_template(uvm_plain_any, cpu_template, microvm_factory):
"""
@@ -1244,19 +952,16 @@ def check_enabled_features(test_microvm, cpu_template):
)
-@pytest.mark.skipif(PLATFORM != "x86_64", reason="This test is specific to x86_64.")
-def test_c3_on_skylake_show_warning(uvm_plain, cpu_template):
+def test_c3_on_skylake_show_warning(uvm_plain, cpu_template_any):
"""
This test verifies that the warning message about MMIO stale data mitigation
- is displayed only on Intel Skylake with C3 template.
+ is displayed only on Intel Skylake with static C3 template.
"""
uvm = uvm_plain
uvm.spawn()
- uvm.basic_config(
- vcpu_count=2,
- mem_size_mib=256,
- cpu_template=cpu_template,
- )
+ uvm.basic_config(vcpu_count=2, mem_size_mib=256)
+ uvm.add_net_iface()
+ uvm.set_cpu_template(cpu_template_any)
uvm.start()
message = (
@@ -1265,7 +970,8 @@ def test_c3_on_skylake_show_warning(uvm_plain, cpu_template):
"does not apply the mitigation against MMIO stale data "
"vulnerability."
)
- if cpu_template == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE":
+
+ if cpu_template_any == "C3" and global_props.cpu_codename == "INTEL_SKYLAKE":
assert message in uvm.log_data
else:
assert message not in uvm.log_data
diff --git a/tests/integration_tests/functional/test_net.py b/tests/integration_tests/functional/test_net.py
index a804b8f90a8..2072d015ca2 100644
--- a/tests/integration_tests/functional/test_net.py
+++ b/tests/integration_tests/functional/test_net.py
@@ -84,14 +84,23 @@ def test_multi_queue_unsupported(uvm_plain):
)
-def run_udp_offload_test(vm):
+@pytest.fixture
+def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs):
+ """Return booted and restored uvm with no CPU templates"""
+ return uvm_ctor(microvm_factory, guest_kernel, rootfs, None)
+
+
+def test_tap_offload(uvm_any):
"""
+ Verify that tap offload features are configured for a booted/restored VM.
+
- Start a socat UDP server in the guest.
- Try to send a UDP message with UDP offload enabled.
If tap offload features are not configured, an attempt to send a message will fail with EIO "Input/output error".
More info (search for "TUN_F_CSUM is a must"): https://blog.cloudflare.com/fr-fr/virtual-networking-101-understanding-tap/
"""
+ vm = uvm_any
port = "81"
out_filename = "/tmp/out.txt"
message = "x"
@@ -112,35 +121,3 @@ def run_udp_offload_test(vm):
# Check that the server received the message
ret = vm.ssh.run(f"cat {out_filename}")
assert ret.stdout == message, f"{ret.stdout=} {ret.stderr=}"
-
-
-def test_tap_offload_booted(uvm_plain_any):
- """
- Verify that tap offload features are configured for a booted VM.
- """
- vm = uvm_plain_any
- vm.spawn()
- vm.basic_config()
- vm.add_net_iface()
- vm.start()
-
- run_udp_offload_test(vm)
-
-
-def test_tap_offload_restored(microvm_factory, guest_kernel, rootfs):
- """
- Verify that tap offload features are configured for a restored VM.
- """
- src = microvm_factory.build(guest_kernel, rootfs, monitor_memory=False)
- src.spawn()
- src.basic_config()
- src.add_net_iface()
- src.start()
- snapshot = src.snapshot_full()
- src.kill()
-
- dst = microvm_factory.build()
- dst.spawn()
- dst.restore_from_snapshot(snapshot, resume=True)
-
- run_udp_offload_test(dst)
diff --git a/tests/integration_tests/functional/test_rng.py b/tests/integration_tests/functional/test_rng.py
index b40aa66033d..1893230c51a 100644
--- a/tests/integration_tests/functional/test_rng.py
+++ b/tests/integration_tests/functional/test_rng.py
@@ -8,11 +8,9 @@
from host_tools.network import SSHConnection
-@pytest.fixture(params=[None])
-def uvm_with_rng(uvm_plain, request):
- """Fixture of a microvm with virtio-rng configured"""
- rate_limiter = request.param
- uvm = uvm_plain
+def uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter):
+ """Return a booted microvm with virtio-rng configured"""
+ uvm = microvm_factory.build(guest_kernel, rootfs)
uvm.spawn(log_level="INFO")
uvm.basic_config(vcpu_count=2, mem_size_mib=256)
uvm.add_net_iface()
@@ -23,6 +21,34 @@ def uvm_with_rng(uvm_plain, request):
return uvm
+def uvm_with_rng_restored(microvm_factory, guest_kernel, rootfs, rate_limiter):
+ """Return a restored uvm with virtio-rng configured"""
+ uvm = uvm_with_rng_booted(microvm_factory, guest_kernel, rootfs, rate_limiter)
+ snapshot = uvm.snapshot_full()
+ uvm.kill()
+ uvm2 = microvm_factory.build_from_snapshot(snapshot)
+ uvm2.rng_rate_limiter = uvm.rng_rate_limiter
+ return uvm2
+
+
+@pytest.fixture(params=[uvm_with_rng_booted, uvm_with_rng_restored])
+def uvm_ctor(request):
+ """Fixture to return uvms with different constructors"""
+ return request.param
+
+
+@pytest.fixture(params=[None])
+def rate_limiter(request):
+ """Fixture to return different rate limiters"""
+ return request.param
+
+
+@pytest.fixture
+def uvm_any(microvm_factory, uvm_ctor, guest_kernel, rootfs, rate_limiter):
+ """Return booted and restored uvms"""
+ return uvm_ctor(microvm_factory, guest_kernel, rootfs, rate_limiter)
+
+
def list_rng_available(ssh_connection: SSHConnection) -> list[str]:
"""Returns a list of rng devices available in the VM"""
return (
@@ -62,35 +88,17 @@ def test_rng_not_present(uvm_nano):
), "virtio_rng device should not be available in the uvm"
-def test_rng_present(uvm_with_rng):
+def test_rng_present(uvm_any):
"""
Test a guest microVM with an entropy defined configured and ensure
that we can access `/dev/hwrng`
"""
- vm = uvm_with_rng
+ vm = uvm_any
assert_virtio_rng_is_current_hwrng_device(vm.ssh)
check_entropy(vm.ssh)
-def test_rng_snapshot(uvm_with_rng, microvm_factory):
- """
- Test that a virtio-rng device is functional after resuming from
- a snapshot
- """
-
- vm = uvm_with_rng
- assert_virtio_rng_is_current_hwrng_device(vm.ssh)
- check_entropy(vm.ssh)
- snapshot = vm.snapshot_full()
-
- new_vm = microvm_factory.build()
- new_vm.spawn()
- new_vm.restore_from_snapshot(snapshot, resume=True)
- assert_virtio_rng_is_current_hwrng_device(new_vm.ssh)
- check_entropy(new_vm.ssh)
-
-
def _get_percentage_difference(measured, base):
"""Return the percentage delta between the arguments."""
if measured == base:
@@ -199,7 +207,7 @@ def _rate_limiter_id(rate_limiter):
# parametrize the RNG rate limiter
@pytest.mark.parametrize(
- "uvm_with_rng",
+ "rate_limiter",
[
{"bandwidth": {"size": 1000, "refill_time": 100}},
{"bandwidth": {"size": 10000, "refill_time": 100}},
@@ -208,16 +216,14 @@ def _rate_limiter_id(rate_limiter):
indirect=True,
ids=_rate_limiter_id,
)
-def test_rng_bw_rate_limiter(uvm_with_rng):
+@pytest.mark.parametrize("uvm_ctor", [uvm_with_rng_booted], indirect=True)
+def test_rng_bw_rate_limiter(uvm_any):
"""
Test that rate limiter without initial burst budget works
"""
- vm = uvm_with_rng
- # _start_vm_with_rng(vm, rate_limiter)
-
+ vm = uvm_any
size = vm.rng_rate_limiter["bandwidth"]["size"]
refill_time = vm.rng_rate_limiter["bandwidth"]["refill_time"]
-
expected_kbps = size / refill_time
assert_virtio_rng_is_current_hwrng_device(vm.ssh)
diff --git a/tests/integration_tests/functional/test_snapshot_basic.py b/tests/integration_tests/functional/test_snapshot_basic.py
index ac596440f67..4030bb4e981 100644
--- a/tests/integration_tests/functional/test_snapshot_basic.py
+++ b/tests/integration_tests/functional/test_snapshot_basic.py
@@ -50,39 +50,25 @@ def _get_guest_drive_size(ssh_connection, guest_dev_name="/dev/vdb"):
return lines[1].strip()
-def test_resume_after_restoration(uvm_nano, microvm_factory):
- """Tests snapshot is resumable after restoration.
+@pytest.mark.parametrize("resume_at_restore", [True, False])
+def test_resume(uvm_nano, microvm_factory, resume_at_restore):
+ """Tests snapshot is resumable at or after restoration.
- Check that a restored microVM is resumable by calling PATCH /vm with Resumed
- after PUT /snapshot/load with `resume_vm=False`.
+ Check that a restored microVM is resumable by either
+ a. PUT /snapshot/load with `resume_vm=False`, then calling PATCH /vm resume=True
+ b. PUT /snapshot/load with `resume_vm=True`
"""
vm = uvm_nano
vm.add_net_iface()
vm.start()
-
- snapshot = vm.snapshot_full()
-
- restored_vm = microvm_factory.build()
- restored_vm.spawn()
- restored_vm.restore_from_snapshot(snapshot)
- restored_vm.resume()
-
-
-def test_resume_at_restoration(uvm_nano, microvm_factory):
- """Tests snapshot is resumable at restoration.
-
- Check that a restored microVM is resumable by calling PUT /snapshot/load
- with `resume_vm=True`.
- """
- vm = uvm_nano
- vm.add_net_iface()
- vm.start()
-
snapshot = vm.snapshot_full()
-
restored_vm = microvm_factory.build()
restored_vm.spawn()
- restored_vm.restore_from_snapshot(snapshot, resume=True)
+ restored_vm.restore_from_snapshot(snapshot, resume=resume_at_restore)
+ if not resume_at_restore:
+ assert restored_vm.state == "Paused"
+ restored_vm.resume()
+ assert restored_vm.state == "Running"
def test_snapshot_current_version(uvm_nano):
@@ -228,9 +214,7 @@ def test_patch_drive_snapshot(uvm_nano, microvm_factory):
# Load snapshot in a new Firecracker microVM.
logger.info("Load snapshot, mem %s", snapshot.mem)
- vm = microvm_factory.build()
- vm.spawn()
- vm.restore_from_snapshot(snapshot, resume=True)
+ vm = microvm_factory.build_from_snapshot(snapshot)
# Attempt to connect to resumed microvm and verify the new microVM has the
# right scratch drive.
@@ -319,9 +303,7 @@ def test_negative_postload_api(uvm_plain, microvm_factory):
basevm.kill()
# Do not resume, just load, so we can still call APIs that work.
- microvm = microvm_factory.build()
- microvm.spawn()
- microvm.restore_from_snapshot(snapshot, resume=True)
+ microvm = microvm_factory.build_from_snapshot(snapshot)
fail_msg = "The requested operation is not supported after starting the microVM"
with pytest.raises(RuntimeError, match=fail_msg):
@@ -486,9 +468,7 @@ def test_diff_snapshot_overlay(guest_kernel, rootfs, microvm_factory):
assert not filecmp.cmp(merged_snapshot.mem, first_snapshot_backup, shallow=False)
- new_vm = microvm_factory.build()
- new_vm.spawn()
- new_vm.restore_from_snapshot(merged_snapshot, resume=True)
+ _ = microvm_factory.build_from_snapshot(merged_snapshot)
# Check that the restored VM works
@@ -510,9 +490,7 @@ def test_snapshot_overwrite_self(guest_kernel, rootfs, microvm_factory):
snapshot = base_vm.snapshot_full()
base_vm.kill()
- vm = microvm_factory.build()
- vm.spawn()
- vm.restore_from_snapshot(snapshot, resume=True)
+ vm = microvm_factory.build_from_snapshot(snapshot)
# When restoring a snapshot, vm.restore_from_snapshot first copies
# the memory file (inside of the jailer) to /mem.src
diff --git a/tests/integration_tests/functional/test_snapshot_editor.py b/tests/integration_tests/functional/test_snapshot_editor.py
index 4d466a441ce..9323695628c 100644
--- a/tests/integration_tests/functional/test_snapshot_editor.py
+++ b/tests/integration_tests/functional/test_snapshot_editor.py
@@ -68,6 +68,4 @@ def test_remove_regs(uvm_nano, microvm_factory):
assert MIDR_EL1 not in stdout
# test that we can restore from a snapshot
- new_vm = microvm_factory.build()
- new_vm.spawn()
- new_vm.restore_from_snapshot(snapshot, resume=True)
+ _ = microvm_factory.build_from_snapshot(snapshot)
diff --git a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
index 5584cfceac8..79366f13f0b 100644
--- a/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
+++ b/tests/integration_tests/functional/test_snapshot_not_losing_dirty_pages.py
@@ -63,9 +63,6 @@ def test_diff_snapshot_works_after_error(
# Now there is enough space for it to work
snap2 = uvm.snapshot_diff()
-
- vm2 = microvm_factory.build()
- vm2.spawn()
- vm2.restore_from_snapshot(snap2, resume=True)
-
uvm.kill()
+
+ _vm2 = microvm_factory.build_from_snapshot(snap2)
diff --git a/tests/integration_tests/functional/test_vsock.py b/tests/integration_tests/functional/test_vsock.py
index 2d540b8f934..dfa02510b37 100644
--- a/tests/integration_tests/functional/test_vsock.py
+++ b/tests/integration_tests/functional/test_vsock.py
@@ -199,10 +199,7 @@ def test_vsock_transport_reset_h2g(
test_vm.kill()
# Load snapshot.
-
- vm2 = microvm_factory.build()
- vm2.spawn()
- vm2.restore_from_snapshot(snapshot, resume=True)
+ vm2 = microvm_factory.build_from_snapshot(snapshot)
# Check that vsock device still works.
# Test guest-initiated connections.
@@ -231,9 +228,7 @@ def test_vsock_transport_reset_g2h(uvm_nano, microvm_factory):
for _ in range(5):
# Load snapshot.
- new_vm = microvm_factory.build()
- new_vm.spawn()
- new_vm.restore_from_snapshot(snapshot, resume=True)
+ new_vm = microvm_factory.build_from_snapshot(snapshot)
# After snap restore all vsock connections should be
# dropped. This means guest socat should exit same way
diff --git a/tests/integration_tests/security/test_nv.py b/tests/integration_tests/security/test_nv.py
index 5dd5acb2308..73f042d5ae3 100644
--- a/tests/integration_tests/security/test_nv.py
+++ b/tests/integration_tests/security/test_nv.py
@@ -16,31 +16,7 @@
start providing the feature by mistake.
"""
-import pytest
-
-@pytest.fixture
-def uvm_with_cpu_template(microvm_factory, guest_kernel, rootfs, cpu_template_any):
- """A microvm fixture parametrized with all possible templates"""
- vm = microvm_factory.build(guest_kernel, rootfs)
- vm.spawn()
- cpu_template = None
- if isinstance(cpu_template_any, str):
- cpu_template = cpu_template_any
- vm.basic_config(cpu_template=cpu_template)
- if isinstance(cpu_template_any, dict):
- vm.api.cpu_config.put(**cpu_template_any["template"])
- vm.add_net_iface()
- vm.start()
- yield vm
-
-
-def test_no_nv_when_using_cpu_templates(uvm_with_cpu_template):
- """
- Double-check that guests using CPU templates don't have Nested Virtualization
- enabled.
- """
-
- vm = uvm_with_cpu_template
- rc, _, _ = vm.ssh.run("[ ! -e /dev/kvm ]")
- assert rc == 0, "/dev/kvm exists"
+def test_no_nested_virtualization(uvm_any_booted):
+ """Validate that guests don't have Nested Virtualization enabled."""
+ uvm_any_booted.ssh.check_output("[ ! -e /dev/kvm ]")
diff --git a/tests/integration_tests/security/test_vulnerabilities.py b/tests/integration_tests/security/test_vulnerabilities.py
index fed9dbc96d7..a4461aded78 100644
--- a/tests/integration_tests/security/test_vulnerabilities.py
+++ b/tests/integration_tests/security/test_vulnerabilities.py
@@ -5,21 +5,17 @@
# script from the third party "Spectre & Meltdown Checker" project. This script is under the
# GPL-3.0-only license.
"""Tests vulnerabilities mitigations."""
+
import json
-import os
+from pathlib import Path
import pytest
import requests
from framework import utils
-from framework.ab_test import (
- is_pr,
- precompiled_ab_test_guest_command,
- precompiled_ab_test_guest_command_if_pr,
- set_did_not_grow_comparator,
-)
+from framework.ab_test import git_clone
+from framework.microvm import MicroVMFactory
from framework.properties import global_props
-from framework.utils import CommandReturn
CHECKER_URL = "https://meltdown.ovh"
CHECKER_FILENAME = "spectre-meltdown-checker.sh"
@@ -29,119 +25,71 @@
VULN_DIR = "/sys/devices/system/cpu/vulnerabilities"
-def configure_microvm(
- factory,
- kernel,
- rootfs,
- *,
- firecracker=None,
- jailer=None,
- cpu_template=None,
- custom_cpu_template=None,
-):
- """Build a microvm for vulnerability tests"""
- assert not (cpu_template and custom_cpu_template)
- # Either both or neither are specified
- assert firecracker and jailer or not firecracker and not jailer
-
- if firecracker:
- microvm = factory.build(
- kernel, rootfs, fc_binary_path=firecracker, jailer_binary_path=jailer
- )
- else:
- microvm = factory.build(kernel, rootfs)
-
- microvm.spawn()
- microvm.basic_config(vcpu_count=2, mem_size_mib=256, cpu_template=cpu_template)
- if custom_cpu_template:
- microvm.api.cpu_config.put(**custom_cpu_template["template"])
- microvm.cpu_template = cpu_template
- if cpu_template is None and custom_cpu_template is not None:
- microvm.cpu_template = custom_cpu_template["name"]
- microvm.add_net_iface()
- microvm.start()
- return microvm
+class SpectreMeltdownChecker:
+ """Helper class to use Spectre & Meltdown Checker"""
+ def __init__(self, path):
+ self.path = path
-@pytest.fixture
-def build_microvm(
- microvm_factory,
- guest_kernel_linux_5_10,
- rootfs,
-):
- """Fixture returning a factory function for a normal microvm"""
- return lambda firecracker=None, jailer=None: configure_microvm(
- microvm_factory,
- guest_kernel_linux_5_10,
- rootfs,
- firecracker=firecracker,
- jailer=jailer,
- )
-
-
-@pytest.fixture
-def build_microvm_with_template(
- microvm_factory, guest_kernel_linux_5_10, rootfs, cpu_template
-):
- """Fixture returning a factory function for microvms with our built-in template"""
- return lambda firecracker=None, jailer=None: configure_microvm(
- microvm_factory,
- guest_kernel_linux_5_10,
- rootfs,
- firecracker=firecracker,
- jailer=jailer,
- cpu_template=cpu_template,
- )
-
-
-@pytest.fixture
-def build_microvm_with_custom_template(
- microvm_factory, guest_kernel_linux_5_10, rootfs, custom_cpu_template
-):
- """Fixture returning a factory function for microvms with custom cpu templates"""
- return lambda firecracker=None, jailer=None: configure_microvm(
- microvm_factory,
- guest_kernel_linux_5_10,
- rootfs,
- firecracker=firecracker,
- jailer=jailer,
- custom_cpu_template=custom_cpu_template,
- )
-
-
-def with_restore(factory, microvm_factory):
- """Turns the given microvm factory into one that makes the microvm go through a snapshot-restore cycle"""
-
- def restore(firecracker=None, jailer=None):
- microvm = factory(firecracker, jailer)
-
- snapshot = microvm.snapshot_full()
-
- if firecracker:
- dst_vm = microvm_factory.build(
- fc_binary_path=firecracker, jailer_binary_path=jailer
- )
- else:
- dst_vm = microvm_factory.build()
- dst_vm.spawn()
- # Restore the destination VM from the snapshot
- dst_vm.restore_from_snapshot(snapshot, resume=True)
- dst_vm.cpu_template = microvm.cpu_template
-
- return dst_vm
-
- return restore
-
-
-def with_checker(factory, spectre_meltdown_checker):
- """Turns the given microvm factory function into one that also contains the spectre-meltdown checker script"""
+ def _parse_output(self, output):
+ return {
+ json.dumps(entry) # dict is unhashable
+ for entry in json.loads(output)
+ if entry["VULNERABLE"]
+ }
- def download_checker(firecracker, jailer):
- microvm = factory(firecracker, jailer)
- microvm.ssh.scp_put(spectre_meltdown_checker, REMOTE_CHECKER_PATH)
- return microvm
+ def get_report_for_guest(self, vm) -> set:
+ """Parses the output of `spectre-meltdown-checker.sh --batch json`
+ and returns the set of issues for which it reported 'Vulnerable'.
- return download_checker
+ Sample stdout:
+ ```
+ [
+ {
+ "NAME": "SPECTRE VARIANT 1",
+ "CVE": "CVE-2017-5753",
+ "VULNERABLE": false,
+ "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization"
+ },
+ { ... }
+ ]
+ ```
+ """
+ vm.ssh.scp_put(self.path, REMOTE_CHECKER_PATH)
+ res = vm.ssh.run(REMOTE_CHECKER_COMMAND)
+ return self._parse_output(res.stdout)
+
+ def get_report_for_host(self) -> set:
+ """Runs `spectre-meltdown-checker.sh` in the host and returns the set of
+ issues for which it reported 'Vulnerable'.
+ """
+
+ res = utils.check_output(f"sh {self.path} --batch json")
+ return self._parse_output(res.stdout)
+
+ def expected_vulnerabilities(self, cpu_template_name):
+ """
+ There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh
+ script is run inside the guest from below the tests:
+ test_spectre_meltdown_checker_on_guest and
+ test_spectre_meltdown_checker_on_restored_guest
+ The same script when run on host doesn't report the
+ exception which means the instances are actually not vulnerable to REPTAR.
+ The only reason why the script cannot determine if the guest
+ is vulnerable or not because Firecracker does not expose the microcode
+ version to the guest.
+
+ The check in spectre_meltdown_checker is here:
+ https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637
+
+ Since we have a test on host and the exception in guest is not valid,
+ we add a check to ignore this exception.
+ """
+ if global_props.cpu_codename == "INTEL_ICELAKE" and cpu_template_name is None:
+ return {
+ '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}'
+ }
+ return set()
@pytest.fixture(scope="session", name="spectre_meltdown_checker")
@@ -149,189 +97,32 @@ def download_spectre_meltdown_checker(tmp_path_factory):
"""Download spectre / meltdown checker script."""
resp = requests.get(CHECKER_URL, timeout=5)
resp.raise_for_status()
-
path = tmp_path_factory.mktemp("tmp", True) / CHECKER_FILENAME
path.write_bytes(resp.content)
-
- return path
-
-
-def spectre_meltdown_reported_vulnerablities(
- spectre_meltdown_checker_output: CommandReturn,
-) -> set:
- """
- Parses the output of `spectre-meltdown-checker.sh --batch json` and returns the set of issues
- for which it reported 'Vulnerable'.
-
- Sample stdout:
- ```
- [
- {
- "NAME": "SPECTRE VARIANT 1",
- "CVE": "CVE-2017-5753",
- "VULNERABLE": false,
- "INFOS": "Mitigation: usercopy/swapgs barriers and __user pointer sanitization"
- },
- {
- ...
- }
- ]
- ```
- """
- return {
- json.dumps(entry) # dict is unhashable
- for entry in json.loads(spectre_meltdown_checker_output.stdout)
- if entry["VULNERABLE"]
- }
-
-
-def check_vulnerabilities_on_guest(status):
- """
- There is a REPTAR exception reported on INTEL_ICELAKE when spectre-meltdown-checker.sh
- script is run inside the guest from below the tests:
- test_spectre_meltdown_checker_on_guest and
- test_spectre_meltdown_checker_on_restored_guest
- The same script when run on host doesn't report the
- exception which means the instances are actually not vulnerable to REPTAR.
- The only reason why the script cannot determine if the guest
- is vulnerable or not because Firecracker does not expose the microcode
- version to the guest.
-
- The check in spectre_meltdown_checker is here:
- https://github.com/speed47/spectre-meltdown-checker/blob/0f2edb1a71733c1074550166c5e53abcfaa4d6ca/spectre-meltdown-checker.sh#L6635-L6637
-
- Since we have a test on host and the exception in guest is not valid,
- we add a check to ignore this exception.
- """
- report_guest_vulnerabilities = spectre_meltdown_reported_vulnerablities(status)
- known_guest_vulnerabilities = set()
- if global_props.cpu_codename == "INTEL_ICELAKE":
- known_guest_vulnerabilities = {
- '{"NAME": "REPTAR", "CVE": "CVE-2023-23583", "VULNERABLE": true, "INFOS": "Your microcode is too old to mitigate the vulnerability"}'
- }
- assert report_guest_vulnerabilities == known_guest_vulnerabilities
+ return SpectreMeltdownChecker(path)
# Nothing can be sensibly tested in a PR context here
@pytest.mark.skipif(
- is_pr(), reason="Test depends solely on factors external to GitHub repository"
+ global_props.buildkite_pr,
+ reason="Test depends solely on factors external to GitHub repository",
)
def test_spectre_meltdown_checker_on_host(spectre_meltdown_checker):
- """
- Test with the spectre / meltdown checker on host.
- """
- rc, output, _ = utils.run_cmd(f"sh {spectre_meltdown_checker} --batch json")
-
- if output and rc != 0:
- report = spectre_meltdown_reported_vulnerablities(output)
- expected = {}
- assert report == expected, f"Unexpected vulnerabilities: {report} vs {expected}"
-
-
-def test_spectre_meltdown_checker_on_guest(spectre_meltdown_checker, build_microvm):
- """
- Test with the spectre / meltdown checker on guest.
- """
-
- status = precompiled_ab_test_guest_command_if_pr(
- with_checker(build_microvm, spectre_meltdown_checker),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- check_in_nonpr=False,
- )
- if status and status.returncode != 0:
- check_vulnerabilities_on_guest(status)
-
-
-def test_spectre_meltdown_checker_on_restored_guest(
- spectre_meltdown_checker, build_microvm, microvm_factory
-):
- """
- Test with the spectre / meltdown checker on a restored guest.
- """
- status = precompiled_ab_test_guest_command_if_pr(
- with_checker(
- with_restore(build_microvm, microvm_factory), spectre_meltdown_checker
- ),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- check_in_nonpr=False,
- )
- if status and status.returncode != 0:
- check_vulnerabilities_on_guest(status)
-
-
-def test_spectre_meltdown_checker_on_guest_with_template(
- spectre_meltdown_checker, build_microvm_with_template
-):
- """
- Test with the spectre / meltdown checker on guest with CPU template.
- """
+ """Test with the spectre / meltdown checker on host."""
+ report = spectre_meltdown_checker.get_report_for_host()
+ assert report == set(), f"Unexpected vulnerabilities: {report}"
- precompiled_ab_test_guest_command_if_pr(
- with_checker(build_microvm_with_template, spectre_meltdown_checker),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- )
-
-def test_spectre_meltdown_checker_on_guest_with_custom_template(
- spectre_meltdown_checker, build_microvm_with_custom_template
-):
- """
- Test with the spectre / meltdown checker on guest with a custom CPU template.
- """
- precompiled_ab_test_guest_command_if_pr(
- with_checker(build_microvm_with_custom_template, spectre_meltdown_checker),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- )
-
-
-def test_spectre_meltdown_checker_on_restored_guest_with_template(
- spectre_meltdown_checker, build_microvm_with_template, microvm_factory
-):
- """
- Test with the spectre / meltdown checker on a restored guest with a CPU template.
- """
- precompiled_ab_test_guest_command_if_pr(
- with_checker(
- with_restore(build_microvm_with_template, microvm_factory),
- spectre_meltdown_checker,
- ),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- )
-
-
-def test_spectre_meltdown_checker_on_restored_guest_with_custom_template(
- spectre_meltdown_checker,
- build_microvm_with_custom_template,
- microvm_factory,
-):
- """
- Test with the spectre / meltdown checker on a restored guest with a custom CPU template.
- """
- precompiled_ab_test_guest_command_if_pr(
- with_checker(
- with_restore(build_microvm_with_custom_template, microvm_factory),
- spectre_meltdown_checker,
- ),
- REMOTE_CHECKER_COMMAND,
- comparator=set_did_not_grow_comparator(
- spectre_meltdown_reported_vulnerablities
- ),
- )
+# Nothing can be sensibly tested here in a PR context
+@pytest.mark.skipif(
+ global_props.buildkite_pr,
+ reason="Test depends solely on factors external to GitHub repository",
+)
+def test_vulnerabilities_on_host():
+ """Test vulnerability files on host."""
+ res = utils.run_cmd(f"grep -r Vulnerable {VULN_DIR}")
+ # if grep finds no matching lines, it exits with status 1
+ assert res.returncode == 1, res.stdout
def get_vuln_files_exception_dict(template):
@@ -372,25 +163,14 @@ def get_vuln_files_exception_dict(template):
# Since those bits are not set on Intel Skylake and C3 template makes guests pretend to be AWS
# C3 instance (quite old processor now) by overwriting CPUID.1H:EAX, it is impossible to avoid
# this "Unknown" state.
- if global_props.cpu_codename == "INTEL_SKYLAKE" and template == "C3":
+ if global_props.cpu_codename == "INTEL_SKYLAKE" and template == "c3":
exception_dict["mmio_stale_data"] = "Unknown: No mitigations"
- elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "T2S":
+ elif global_props.cpu_codename == "INTEL_SKYLAKE" or template == "t2s":
exception_dict["mmio_stale_data"] = "Clear CPU buffers"
return exception_dict
-# Nothing can be sensibly tested here in a PR context
-@pytest.mark.skipif(
- is_pr(), reason="Test depends solely on factors external to GitHub repository"
-)
-def test_vulnerabilities_on_host():
- """
- Test vulnerabilities files on host.
- """
- utils.check_output(f"! grep -r Vulnerable {VULN_DIR}")
-
-
def check_vulnerabilities_files_on_guest(microvm):
"""
Check that the guest's vulnerabilities files do not contain `Vulnerable`.
@@ -400,88 +180,75 @@ def check_vulnerabilities_files_on_guest(microvm):
# Retrieve a list of vulnerabilities files available inside guests.
vuln_dir = "/sys/devices/system/cpu/vulnerabilities"
_, stdout, _ = microvm.ssh.check_output(f"find -D all {vuln_dir} -type f")
- vuln_files = stdout.split("\n")
+ vuln_files = stdout.splitlines()
# Fixtures in this file (test_vulnerabilities.py) add this special field.
- template = microvm.cpu_template
+ template = microvm.cpu_template_name
# Check that vulnerabilities files in the exception dictionary have the expected values and
# the others do not contain "Vulnerable".
exceptions = get_vuln_files_exception_dict(template)
+ results = []
for vuln_file in vuln_files:
- filename = os.path.basename(vuln_file)
+ filename = Path(vuln_file).name
if filename in exceptions:
- _, stdout, _ = microvm.ssh.run(f"cat {vuln_file}")
+ _, stdout, _ = microvm.ssh.check_output(f"cat {vuln_file}")
assert exceptions[filename] in stdout
else:
cmd = f"grep Vulnerable {vuln_file}"
- ecode, stdout, stderr = microvm.ssh.run(cmd)
- assert ecode == 1, f"{vuln_file}: stdout:\n{stdout}\nstderr:\n{stderr}\n"
-
-
-def check_vulnerabilities_files_ab(builder):
- """Does an A/B test on the contents of the /sys/devices/system/cpu/vulnerabilities files in the guest if
- running in a PR pipeline, and otherwise calls `check_vulnerabilities_files_on_guest`
- """
- if is_pr():
- precompiled_ab_test_guest_command(
- builder,
- f"! grep -r Vulnerable {VULN_DIR}",
- comparator=set_did_not_grow_comparator(
- lambda output: set(output.stdout.splitlines())
- ),
- )
- else:
- check_vulnerabilities_files_on_guest(builder())
+ _ecode, stdout, _stderr = microvm.ssh.run(cmd)
+ results.append({"file": vuln_file, "stdout": stdout})
+ return results
-def test_vulnerabilities_files_on_guest(build_microvm):
- """
- Test vulnerabilities files on guest.
- """
- check_vulnerabilities_files_ab(build_microvm)
-
-
-def test_vulnerabilities_files_on_restored_guest(build_microvm, microvm_factory):
- """
- Test vulnerabilities files on a restored guest.
- """
- check_vulnerabilities_files_ab(with_restore(build_microvm, microvm_factory))
+@pytest.fixture
+def microvm_factory_a(record_property):
+ """MicroVMFactory using revision A binaries"""
+ revision_a = global_props.buildkite_revision_a
+ bin_dir = git_clone(Path("../build") / revision_a, revision_a).resolve()
+ fc_bin = bin_dir / "firecracker"
+ jailer_bin = bin_dir / "jailer"
+ record_property("firecracker_bin", str(fc_bin))
+ uvm_factory = MicroVMFactory(fc_bin, jailer_bin)
+ yield uvm_factory
+ uvm_factory.kill()
-def test_vulnerabilities_files_on_guest_with_template(build_microvm_with_template):
- """
- Test vulnerabilities files on guest with CPU template.
- """
- check_vulnerabilities_files_ab(build_microvm_with_template)
-
+@pytest.fixture
+def uvm_any_a(microvm_factory_a, uvm_ctor, guest_kernel, rootfs, cpu_template_any):
+ """Return uvm with revision A firecracker
-def test_vulnerabilities_files_on_guest_with_custom_template(
- build_microvm_with_custom_template,
-):
+ Since pytest caches fixtures, this guarantees uvm_any_a will match a vm from uvm_any.
+ See https://docs.pytest.org/en/stable/how-to/fixtures.html#fixtures-can-be-requested-more-than-once-per-test-return-values-are-cached
"""
- Test vulnerabilities files on guest with a custom CPU template.
- """
- check_vulnerabilities_files_ab(build_microvm_with_custom_template)
+ return uvm_ctor(microvm_factory_a, guest_kernel, rootfs, cpu_template_any)
-def test_vulnerabilities_files_on_restored_guest_with_template(
- build_microvm_with_template, microvm_factory
-):
- """
- Test vulnerabilities files on a restored guest with a CPU template.
- """
- check_vulnerabilities_files_ab(
- with_restore(build_microvm_with_template, microvm_factory)
- )
+def test_check_vulnerability_files_ab(request, uvm_any):
+ """Test vulnerability files on guests"""
+ res_b = check_vulnerabilities_files_on_guest(uvm_any)
+ if global_props.buildkite_pr:
+ # we only get the uvm_any_a fixtures if we need it
+ uvm_a = request.getfixturevalue("uvm_any_a")
+ res_a = check_vulnerabilities_files_on_guest(uvm_a)
+ assert res_b <= res_a
+ else:
+ assert not [x for x in res_b if "Vulnerable" in x["stdout"]]
-def test_vulnerabilities_files_on_restored_guest_with_custom_template(
- build_microvm_with_custom_template, microvm_factory
+def test_spectre_meltdown_checker_on_guest(
+ request,
+ uvm_any,
+ spectre_meltdown_checker,
):
- """
- Test vulnerabilities files on a restored guest with a custom CPU template.
- """
- check_vulnerabilities_files_ab(
- with_restore(build_microvm_with_custom_template, microvm_factory)
- )
+ """Test with the spectre / meltdown checker on any supported guest."""
+ res_b = spectre_meltdown_checker.get_report_for_guest(uvm_any)
+ if global_props.buildkite_pr:
+ # we only get the uvm_any_a fixtures if we need it
+ uvm_a = request.getfixturevalue("uvm_any_a")
+ res_a = spectre_meltdown_checker.get_report_for_guest(uvm_a)
+ assert res_b <= res_a
+ else:
+ assert res_b == spectre_meltdown_checker.expected_vulnerabilities(
+ uvm_any.cpu_template_name
+ )
diff --git a/tools/devctr/poetry.lock b/tools/devctr/poetry.lock
index fef3e284ade..96f1d0c990a 100644
--- a/tools/devctr/poetry.lock
+++ b/tools/devctr/poetry.lock
@@ -13,112 +13,112 @@ files = [
[[package]]
name = "aiohttp"
-version = "3.10.5"
+version = "3.10.11"
description = "Async http client/server framework (asyncio)"
optional = false
python-versions = ">=3.8"
files = [
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"},
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"},
- {file = "aiohttp-3.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb"},
- {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3"},
- {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683"},
- {file = "aiohttp-3.10.5-cp310-cp310-win32.whl", hash = "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef"},
- {file = "aiohttp-3.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf"},
- {file = "aiohttp-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7"},
- {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277"},
- {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058"},
- {file = "aiohttp-3.10.5-cp311-cp311-win32.whl", hash = "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072"},
- {file = "aiohttp-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a"},
- {file = "aiohttp-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f"},
- {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91"},
- {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6"},
- {file = "aiohttp-3.10.5-cp312-cp312-win32.whl", hash = "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12"},
- {file = "aiohttp-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77"},
- {file = "aiohttp-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa"},
- {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5"},
- {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987"},
- {file = "aiohttp-3.10.5-cp313-cp313-win32.whl", hash = "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04"},
- {file = "aiohttp-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a"},
- {file = "aiohttp-3.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5"},
- {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f"},
- {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511"},
- {file = "aiohttp-3.10.5-cp38-cp38-win32.whl", hash = "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a"},
- {file = "aiohttp-3.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172"},
- {file = "aiohttp-3.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f"},
- {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857"},
- {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11"},
- {file = "aiohttp-3.10.5-cp39-cp39-win32.whl", hash = "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1"},
- {file = "aiohttp-3.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862"},
- {file = "aiohttp-3.10.5.tar.gz", hash = "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"},
+ {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"},
+ {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"},
+ {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"},
+ {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"},
+ {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"},
+ {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"},
+ {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"},
+ {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"},
+ {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"},
+ {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"},
+ {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"},
+ {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"},
+ {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"},
+ {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"},
+ {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"},
+ {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"},
+ {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"},
+ {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"},
+ {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"},
+ {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"},
+ {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"},
+ {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"},
+ {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"},
+ {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"},
+ {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"},
+ {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"},
+ {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"},
+ {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"},
+ {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"},
+ {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"},
+ {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"},
]
[package.dependencies]
aiohappyeyeballs = ">=2.3.0"
aiosignal = ">=1.1.2"
-async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""}
+async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""}
attrs = ">=17.3.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
-yarl = ">=1.0,<2.0"
+yarl = ">=1.12.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"]
@@ -1317,6 +1317,113 @@ files = [
[package.dependencies]
wcwidth = "*"
+[[package]]
+name = "propcache"
+version = "0.2.0"
+description = "Accelerated property cache"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"},
+ {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"},
+ {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"},
+ {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"},
+ {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"},
+ {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"},
+ {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"},
+ {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"},
+ {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"},
+ {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"},
+ {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"},
+ {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"},
+ {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"},
+ {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"},
+ {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"},
+ {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"},
+ {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"},
+ {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"},
+ {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"},
+ {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"},
+ {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"},
+ {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"},
+ {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"},
+ {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"},
+ {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"},
+ {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"},
+ {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"},
+ {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"},
+ {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"},
+ {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"},
+ {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"},
+ {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"},
+ {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"},
+]
+
[[package]]
name = "psutil"
version = "6.0.0"
@@ -2155,108 +2262,99 @@ files = [
[[package]]
name = "yarl"
-version = "1.11.1"
+version = "1.17.2"
description = "Yet another URL library"
optional = false
-python-versions = ">=3.8"
-files = [
- {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:400cd42185f92de559d29eeb529e71d80dfbd2f45c36844914a4a34297ca6f00"},
- {file = "yarl-1.11.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8258c86f47e080a258993eed877d579c71da7bda26af86ce6c2d2d072c11320d"},
- {file = "yarl-1.11.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2164cd9725092761fed26f299e3f276bb4b537ca58e6ff6b252eae9631b5c96e"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08ea567c16f140af8ddc7cb58e27e9138a1386e3e6e53982abaa6f2377b38cc"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:768ecc550096b028754ea28bf90fde071c379c62c43afa574edc6f33ee5daaec"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2909fa3a7d249ef64eeb2faa04b7957e34fefb6ec9966506312349ed8a7e77bf"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01a8697ec24f17c349c4f655763c4db70eebc56a5f82995e5e26e837c6eb0e49"},
- {file = "yarl-1.11.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e286580b6511aac7c3268a78cdb861ec739d3e5a2a53b4809faef6b49778eaff"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4179522dc0305c3fc9782549175c8e8849252fefeb077c92a73889ccbcd508ad"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:27fcb271a41b746bd0e2a92182df507e1c204759f460ff784ca614e12dd85145"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f61db3b7e870914dbd9434b560075e0366771eecbe6d2b5561f5bc7485f39efd"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c92261eb2ad367629dc437536463dc934030c9e7caca861cc51990fe6c565f26"},
- {file = "yarl-1.11.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d95b52fbef190ca87d8c42f49e314eace4fc52070f3dfa5f87a6594b0c1c6e46"},
- {file = "yarl-1.11.1-cp310-cp310-win32.whl", hash = "sha256:489fa8bde4f1244ad6c5f6d11bb33e09cf0d1d0367edb197619c3e3fc06f3d91"},
- {file = "yarl-1.11.1-cp310-cp310-win_amd64.whl", hash = "sha256:476e20c433b356e16e9a141449f25161e6b69984fb4cdbd7cd4bd54c17844998"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:946eedc12895873891aaceb39bceb484b4977f70373e0122da483f6c38faaa68"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:21a7c12321436b066c11ec19c7e3cb9aec18884fe0d5b25d03d756a9e654edfe"},
- {file = "yarl-1.11.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c35f493b867912f6fda721a59cc7c4766d382040bdf1ddaeeaa7fa4d072f4675"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25861303e0be76b60fddc1250ec5986c42f0a5c0c50ff57cc30b1be199c00e63"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4b53f73077e839b3f89c992223f15b1d2ab314bdbdf502afdc7bb18e95eae27"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:327c724b01b8641a1bf1ab3b232fb638706e50f76c0b5bf16051ab65c868fac5"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4307d9a3417eea87715c9736d050c83e8c1904e9b7aada6ce61b46361b733d92"},
- {file = "yarl-1.11.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48a28bed68ab8fb7e380775f0029a079f08a17799cb3387a65d14ace16c12e2b"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:067b961853c8e62725ff2893226fef3d0da060656a9827f3f520fb1d19b2b68a"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8215f6f21394d1f46e222abeb06316e77ef328d628f593502d8fc2a9117bde83"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:498442e3af2a860a663baa14fbf23fb04b0dd758039c0e7c8f91cb9279799bff"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:69721b8effdb588cb055cc22f7c5105ca6fdaa5aeb3ea09021d517882c4a904c"},
- {file = "yarl-1.11.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e969fa4c1e0b1a391f3fcbcb9ec31e84440253325b534519be0d28f4b6b533e"},
- {file = "yarl-1.11.1-cp311-cp311-win32.whl", hash = "sha256:7d51324a04fc4b0e097ff8a153e9276c2593106a811704025bbc1d6916f45ca6"},
- {file = "yarl-1.11.1-cp311-cp311-win_amd64.whl", hash = "sha256:15061ce6584ece023457fb8b7a7a69ec40bf7114d781a8c4f5dcd68e28b5c53b"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a4264515f9117be204935cd230fb2a052dd3792789cc94c101c535d349b3dab0"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f41fa79114a1d2eddb5eea7b912d6160508f57440bd302ce96eaa384914cd265"},
- {file = "yarl-1.11.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:02da8759b47d964f9173c8675710720b468aa1c1693be0c9c64abb9d8d9a4867"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9361628f28f48dcf8b2f528420d4d68102f593f9c2e592bfc842f5fb337e44fd"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b91044952da03b6f95fdba398d7993dd983b64d3c31c358a4c89e3c19b6f7aef"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:74db2ef03b442276d25951749a803ddb6e270d02dda1d1c556f6ae595a0d76a8"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e975a2211952a8a083d1b9d9ba26472981ae338e720b419eb50535de3c02870"},
- {file = "yarl-1.11.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8aef97ba1dd2138112890ef848e17d8526fe80b21f743b4ee65947ea184f07a2"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a7915ea49b0c113641dc4d9338efa9bd66b6a9a485ffe75b9907e8573ca94b84"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:504cf0d4c5e4579a51261d6091267f9fd997ef58558c4ffa7a3e1460bd2336fa"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:3de5292f9f0ee285e6bd168b2a77b2a00d74cbcfa420ed078456d3023d2f6dff"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a34e1e30f1774fa35d37202bbeae62423e9a79d78d0874e5556a593479fdf239"},
- {file = "yarl-1.11.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66b63c504d2ca43bf7221a1f72fbe981ff56ecb39004c70a94485d13e37ebf45"},
- {file = "yarl-1.11.1-cp312-cp312-win32.whl", hash = "sha256:a28b70c9e2213de425d9cba5ab2e7f7a1c8ca23a99c4b5159bf77b9c31251447"},
- {file = "yarl-1.11.1-cp312-cp312-win_amd64.whl", hash = "sha256:17b5a386d0d36fb828e2fb3ef08c8829c1ebf977eef88e5367d1c8c94b454639"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:1fa2e7a406fbd45b61b4433e3aa254a2c3e14c4b3186f6e952d08a730807fa0c"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:750f656832d7d3cb0c76be137ee79405cc17e792f31e0a01eee390e383b2936e"},
- {file = "yarl-1.11.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0b8486f322d8f6a38539136a22c55f94d269addb24db5cb6f61adc61eabc9d93"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fce4da3703ee6048ad4138fe74619c50874afe98b1ad87b2698ef95bf92c96d"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ed653638ef669e0efc6fe2acb792275cb419bf9cb5c5049399f3556995f23c7"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18ac56c9dd70941ecad42b5a906820824ca72ff84ad6fa18db33c2537ae2e089"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:688654f8507464745ab563b041d1fb7dab5d9912ca6b06e61d1c4708366832f5"},
- {file = "yarl-1.11.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4973eac1e2ff63cf187073cd4e1f1148dcd119314ab79b88e1b3fad74a18c9d5"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:964a428132227edff96d6f3cf261573cb0f1a60c9a764ce28cda9525f18f7786"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6d23754b9939cbab02c63434776df1170e43b09c6a517585c7ce2b3d449b7318"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c2dc4250fe94d8cd864d66018f8344d4af50e3758e9d725e94fecfa27588ff82"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09696438cb43ea6f9492ef237761b043f9179f455f405279e609f2bc9100212a"},
- {file = "yarl-1.11.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:999bfee0a5b7385a0af5ffb606393509cfde70ecca4f01c36985be6d33e336da"},
- {file = "yarl-1.11.1-cp313-cp313-win32.whl", hash = "sha256:ce928c9c6409c79e10f39604a7e214b3cb69552952fbda8d836c052832e6a979"},
- {file = "yarl-1.11.1-cp313-cp313-win_amd64.whl", hash = "sha256:501c503eed2bb306638ccb60c174f856cc3246c861829ff40eaa80e2f0330367"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dae7bd0daeb33aa3e79e72877d3d51052e8b19c9025ecf0374f542ea8ec120e4"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3ff6b1617aa39279fe18a76c8d165469c48b159931d9b48239065767ee455b2b"},
- {file = "yarl-1.11.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3257978c870728a52dcce8c2902bf01f6c53b65094b457bf87b2644ee6238ddc"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f351fa31234699d6084ff98283cb1e852270fe9e250a3b3bf7804eb493bd937"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8aef1b64da41d18026632d99a06b3fefe1d08e85dd81d849fa7c96301ed22f1b"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7175a87ab8f7fbde37160a15e58e138ba3b2b0e05492d7351314a250d61b1591"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba444bdd4caa2a94456ef67a2f383710928820dd0117aae6650a4d17029fa25e"},
- {file = "yarl-1.11.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ea9682124fc062e3d931c6911934a678cb28453f957ddccf51f568c2f2b5e05"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8418c053aeb236b20b0ab8fa6bacfc2feaaf7d4683dd96528610989c99723d5f"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:61a5f2c14d0a1adfdd82258f756b23a550c13ba4c86c84106be4c111a3a4e413"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f3a6d90cab0bdf07df8f176eae3a07127daafcf7457b997b2bf46776da2c7eb7"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:077da604852be488c9a05a524068cdae1e972b7dc02438161c32420fb4ec5e14"},
- {file = "yarl-1.11.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:15439f3c5c72686b6c3ff235279630d08936ace67d0fe5c8d5bbc3ef06f5a420"},
- {file = "yarl-1.11.1-cp38-cp38-win32.whl", hash = "sha256:238a21849dd7554cb4d25a14ffbfa0ef380bb7ba201f45b144a14454a72ffa5a"},
- {file = "yarl-1.11.1-cp38-cp38-win_amd64.whl", hash = "sha256:67459cf8cf31da0e2cbdb4b040507e535d25cfbb1604ca76396a3a66b8ba37a6"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:884eab2ce97cbaf89f264372eae58388862c33c4f551c15680dd80f53c89a269"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a336eaa7ee7e87cdece3cedb395c9657d227bfceb6781295cf56abcd3386a26"},
- {file = "yarl-1.11.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87f020d010ba80a247c4abc335fc13421037800ca20b42af5ae40e5fd75e7909"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:637c7ddb585a62d4469f843dac221f23eec3cbad31693b23abbc2c366ad41ff4"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:48dfd117ab93f0129084577a07287376cc69c08138694396f305636e229caa1a"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e0ae31fb5ccab6eda09ba1494e87eb226dcbd2372dae96b87800e1dcc98804"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f46f81501160c28d0c0b7333b4f7be8983dbbc161983b6fb814024d1b4952f79"},
- {file = "yarl-1.11.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04293941646647b3bfb1719d1d11ff1028e9c30199509a844da3c0f5919dc520"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:250e888fa62d73e721f3041e3a9abf427788a1934b426b45e1b92f62c1f68366"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e8f63904df26d1a66aabc141bfd258bf738b9bc7bc6bdef22713b4f5ef789a4c"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:aac44097d838dda26526cffb63bdd8737a2dbdf5f2c68efb72ad83aec6673c7e"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:267b24f891e74eccbdff42241c5fb4f974de2d6271dcc7d7e0c9ae1079a560d9"},
- {file = "yarl-1.11.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6907daa4b9d7a688063ed098c472f96e8181733c525e03e866fb5db480a424df"},
- {file = "yarl-1.11.1-cp39-cp39-win32.whl", hash = "sha256:14438dfc5015661f75f85bc5adad0743678eefee266ff0c9a8e32969d5d69f74"},
- {file = "yarl-1.11.1-cp39-cp39-win_amd64.whl", hash = "sha256:94d0caaa912bfcdc702a4204cd5e2bb01eb917fc4f5ea2315aa23962549561b0"},
- {file = "yarl-1.11.1-py3-none-any.whl", hash = "sha256:72bf26f66456baa0584eff63e44545c9f0eaed9b73cb6601b647c91f14c11f38"},
- {file = "yarl-1.11.1.tar.gz", hash = "sha256:1bb2d9e212fb7449b8fb73bc461b51eaa17cc8430b4a87d87be7b25052d92f53"},
+python-versions = ">=3.9"
+files = [
+ {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"},
+ {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"},
+ {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"},
+ {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"},
+ {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"},
+ {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"},
+ {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"},
+ {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"},
+ {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"},
+ {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"},
+ {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"},
+ {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"},
+ {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"},
+ {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"},
+ {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"},
+ {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"},
+ {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"},
+ {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"},
+ {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"},
+ {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"},
+ {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"},
+ {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"},
+ {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"},
+ {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"},
+ {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"},
+ {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"},
+ {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"},
+ {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"},
+ {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"},
]
[package.dependencies]
idna = ">=2.0"
multidict = ">=4.0"
+propcache = ">=0.2.0"
[metadata]
lock-version = "2.0"
diff --git a/tools/devtool b/tools/devtool
index 00e453486e3..36406c61bda 100755
--- a/tools/devtool
+++ b/tools/devtool
@@ -127,10 +127,6 @@ PRIV_KEY_PATH=/root/.ssh/id_rsa
# Path to the linux kernel directory, as bind-mounted in the container.
CTR_KERNEL_DIR="${CTR_FC_ROOT_DIR}/.kernel"
-# Global options received by $0
-# These options are not command-specific, so we store them as global vars
-OPT_UNATTENDED=false
-
# Get the target prefix to avoid repeated calls to uname -m
TARGET_PREFIX="$(uname -m)-unknown-linux-"
@@ -195,7 +191,6 @@ ensure_devctr() {
# download it, if we don't.
[[ $(docker images -q "$DEVCTR_IMAGE" | wc -l) -gt 0 ]] || {
say "About to pull docker image $DEVCTR_IMAGE"
- get_user_confirmation || die "Aborted."
# Run docker pull 5 times in case it fails - sleep 3 seconds
# between attempts
@@ -418,6 +413,10 @@ cmd_help() {
echo " Builds the rootfs and guest kernel artifacts we use for our CI."
echo " Run './tools/devtool build_ci_artifacts help' for more details about the available commands."
echo ""
+ echo " download_ci_artifacts [--force]"
+ echo " Downloads the CI artifacts used for testing from our S3 bucket. If --force is passed, purges any existing"
+ echo " artifacts first. Useful for refreshing local artifacts after an update, or if something got messed up."
+ echo ""
cat <]]
@@ -555,6 +554,14 @@ cmd_distclean() {
fi
}
+cmd_download_ci_artifacts() {
+ if [ "$1" = "--force" ]; then
+ rm -rf $FC_BUILD_DIR/img
+ fi
+
+ ensure_ci_artifacts
+}
+
ensure_ci_artifacts() {
if ! command -v aws >/dev/null; then
die "AWS CLI not installed, which is required for downloading artifacts for integration tests."
@@ -562,7 +569,8 @@ ensure_ci_artifacts() {
# Fetch all the artifacts so they are local
say "Fetching CI artifacts from S3"
- S3_URL=s3://spec.ccfc.min/firecracker-ci/v1.11/$(uname -m)
+ FC_VERSION=$(cmd_sh "cd src/firecracker/src; cargo pkgid | cut -d# -f2 | cut -d. -f1-2")
+ S3_URL=s3://spec.ccfc.min/firecracker-ci/v$FC_VERSION/$(uname -m)
ARTIFACTS=$MICROVM_IMAGES_DIR/$(uname -m)
if [ ! -d "$ARTIFACTS" ]; then
mkdir -pv $ARTIFACTS
@@ -878,7 +886,6 @@ cmd_shell() {
cmd_sh() {
ensure_build_dir
- ensure_ci_artifacts
run_devctr \
--privileged \
--ulimit nofile=4096:4096 \
@@ -890,6 +897,7 @@ cmd_sh() {
cmd_sandbox() {
cmd_build --release
+ ensure_ci_artifacts
cmd_sh "tmux new env PYTEST_ADDOPTS=--pdbcls=IPython.terminal.debugger:TerminalPdb PYTHONPATH=tests IPYTHONDIR=\$PWD/.ipython ipython -i ./tools/sandbox.py $@"
}
@@ -915,6 +923,7 @@ cmd_sandbox_native() {
}
cmd_test_debug() {
+ ensure_ci_artifacts
cmd_sh "tmux new ./tools/test.sh --pdb $@"
}
@@ -1191,7 +1200,7 @@ cmd_install() {
# Install the binaries
for binary in "${binaries[@]}"; do
say "Installing $binary in $install_path"
- install -m 755 "$( build_bin_path "$target" "$profile" "$binary" )" "$install_path"
+ install -m 755 -D -t "$install_path" "$( build_bin_path "$target" "$profile" "$binary" )"
done
}
@@ -1221,7 +1230,8 @@ main() {
while [ $# -gt 0 ]; do
case "$1" in
-h|--help) { cmd_help; exit 1; } ;;
- -y|--unattended) { OPT_UNATTENDED=true; } ;;
+ -y|--unattended) # purposefully ignored
+ ;;
-*)
die "Unknown arg: $1. Please use \`$0 help\` for help."
;;
diff --git a/tools/functions b/tools/functions
index 429a082d7a9..90e75c251bd 100644
--- a/tools/functions
+++ b/tools/functions
@@ -71,12 +71,7 @@ function SGR {
# exit code 0 for successful confirmation
# exit code != 0 if the user declined
#
-OPT_UNATTENDED=false
get_user_confirmation() {
-
- # Pass if running unattended
- [[ "$OPT_UNATTENDED" = true ]] && return 0
-
# Fail if STDIN is not a terminal (there's no user to confirm anything)
[[ -t 0 ]] || return 1