diff --git a/CHANGELOG.md b/CHANGELOG.md index 61f0c26a66b4..b1a0773c52eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ - Changed the dump feature of `cpu-template-helper` tool not to enumerate program counter (PC) on ARM because it is determined by the given kernel image and it is useless in the custom CPU template context. +- The ability to create snapshots for an older version of Firecracker is now + deprecated. As a result, the `version` body field in `PUT` on + `/snapshot/create` request in deprecated. ### Fixed diff --git a/docs/snapshotting/snapshot-support.md b/docs/snapshotting/snapshot-support.md index 2d16bdd64611..3590f496bd05 100644 --- a/docs/snapshotting/snapshot-support.md +++ b/docs/snapshotting/snapshot-support.md @@ -176,6 +176,11 @@ The Firecracker snapshotting implementation offers support for snapshot versioni - Saving snapshots at older versions + **DEPRECATED**: This feature is deprecated starting with version 1.5.0. It + will be removed in a subsequent release. After dropping support, Firecracker + will be able to create snapshots only for the version supported by the + Firecracker binary that launched the microVM and not for older versions. + This refers to being able to create a snapshot with any version in the `[N, N + o]` interval, while running Firecracker version `N+o`. diff --git a/src/api_server/src/request/snapshot.rs b/src/api_server/src/request/snapshot.rs index 3563c85f9b9d..3d5e47c38def 100644 --- a/src/api_server/src/request/snapshot.rs +++ b/src/api_server/src/request/snapshot.rs @@ -14,6 +14,9 @@ use crate::request::{Body, Method, StatusCode}; /// Deprecation message for the `mem_file_path` field. const LOAD_DEPRECATION_MESSAGE: &str = "PUT /snapshot/load: mem_file_path field is deprecated."; +/// Deprecation message for the `version` field. +const CREATE_WITH_VERSION_DEPRECATION_MESSAGE: &str = + "PUT /snapshot/create: 'version' field is deprecated."; /// None of the `mem_backend` or `mem_file_path` fields has been specified. pub const MISSING_FIELD: &str = "missing field: either `mem_backend` or `mem_file_path` is required"; @@ -28,9 +31,7 @@ pub(crate) fn parse_put_snapshot( ) -> Result { match request_type_from_path { Some(request_type) => match request_type { - "create" => Ok(ParsedRequest::new_sync(VmmAction::CreateSnapshot( - serde_json::from_slice::(body.raw())?, - ))), + "create" => parse_put_snapshot_create(body), "load" => parse_put_snapshot_load(body), _ => Err(Error::InvalidPathMethod( format!("/snapshot/{}", request_type), @@ -53,6 +54,23 @@ pub(crate) fn parse_patch_vm_state(body: &Body) -> Result } } +fn parse_put_snapshot_create(body: &Body) -> Result { + let snapshot_config = serde_json::from_slice::(body.raw())?; + let uses_deprecated_version_field = snapshot_config.version.is_some(); + + let mut parsed_req = ParsedRequest::new_sync(VmmAction::CreateSnapshot(snapshot_config)); + // `version` field is deprecated as a parameter for `CreateSnapshotParams`. + // Add a deprecation message if the request includes the parameter. + if uses_deprecated_version_field { + METRICS.deprecated_api.deprecated_http_api_calls.inc(); + parsed_req + .parsing_info() + .append_deprecation_message(CREATE_WITH_VERSION_DEPRECATION_MESSAGE); + } + + Ok(parsed_req) +} + fn parse_put_snapshot_load(body: &Body) -> Result { let snapshot_config = serde_json::from_slice::(body.raw())?; @@ -134,8 +152,11 @@ mod tests { version: Some(Version::new(0, 23, 0)), }; - match vmm_action_from_request(parse_put_snapshot(&Body::new(body), Some("create")).unwrap()) - { + let parsed_request = parse_put_snapshot(&Body::new(body), Some("create")).unwrap(); + match depr_action_from_req( + parsed_request, + Some(CREATE_WITH_VERSION_DEPRECATION_MESSAGE.to_string()), + ) { VmmAction::CreateSnapshot(cfg) => assert_eq!(cfg, expected_cfg), _ => panic!("Test failed."), } diff --git a/src/api_server/swagger/firecracker.yaml b/src/api_server/swagger/firecracker.yaml index 4cfb61265619..e2290b53b23c 100644 --- a/src/api_server/swagger/firecracker.yaml +++ b/src/api_server/swagger/firecracker.yaml @@ -1179,7 +1179,8 @@ definitions: type: string description: The microVM version for which we want to create the snapshot. - It is optional and it defaults to the current version. + It is optional and it defaults to the current version. This parameter + has been deprecated and it will be removed in future Firecracker release. SnapshotLoadParams: type: object diff --git a/tests/integration_tests/functional/test_api.py b/tests/integration_tests/functional/test_api.py index 55df8d887337..110980adab89 100644 --- a/tests/integration_tests/functional/test_api.py +++ b/tests/integration_tests/functional/test_api.py @@ -1261,6 +1261,28 @@ def test_map_private_seccomp_regression(test_microvm_with_api): test_microvm.api.mmds.put(**data_store) +def test_negative_snapshot_create_api(microvm_factory, guest_kernel, rootfs): + """ + Test snapshot create API. + """ + + vm = microvm_factory.build(guest_kernel, rootfs) + vm.spawn() + vm.basic_config() + vm.start() + + # Specifying `version` in the create API is deprecated + vm.pause() + response = vm.api.snapshot_create.put( + mem_file_path="mem", + snapshot_path="vmstate", + snapshot_type="Full", + version="1.4.0", + ) + assert response.headers["deprecation"] + assert "PUT /snapshot/create: \'version\' field is deprecated." in vm.log_data + + # pylint: disable=protected-access def test_negative_snapshot_load_api(microvm_factory): """