Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patch(main): Live Migration Support #11

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions .github/workflows/hydrun.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: hydrun CI

on:
push:
pull_request:
schedule:
- cron: "0 0 * * 0"

jobs:
build-linux:
runs-on: ${{ matrix.target.runner }}
permissions:
contents: read
strategy:
matrix:
target:
# Binaries
- id: rust.x86_64
src: .
os: public.ecr.aws/firecracker/fcuvm:v75
flags: ""
cmd: ./Hydrunfile rust x86_64
dst: out/*
runner: depot-ubuntu-22.04-32
- id: rust.aarch64
src: .
os: public.ecr.aws/firecracker/fcuvm:v75
flags: ""
cmd: ./Hydrunfile rust aarch64
dst: out/*
runner: depot-ubuntu-22.04-arm-32

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Restore ccache
uses: actions/cache/restore@v4
with:
path: |
/tmp/ccache
key: cache-ccache-${{ matrix.target.id }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up hydrun
run: |
curl -L -o /tmp/hydrun "https://github.com/pojntfx/hydrun/releases/latest/download/hydrun.linux-$(uname -m)"
sudo install /tmp/hydrun /usr/local/bin
- name: Build with hydrun
working-directory: ${{ matrix.target.src }}
run: hydrun -o ${{ matrix.target.os }} ${{ matrix.target.flags }} "${{ matrix.target.cmd }}"
- name: Fix permissions for output
run: sudo chown -R $USER .
- name: Save ccache
uses: actions/cache/save@v4
with:
path: |
/tmp/ccache
key: cache-ccache-${{ matrix.target.id }}
- name: Upload output
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target.id }}
path: ${{ matrix.target.dst }}

publish-linux:
runs-on: ubuntu-latest
permissions:
contents: write
needs: build-linux

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download output
uses: actions/download-artifact@v4
with:
path: /tmp/out
- name: Extract branch name
id: extract_branch
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
- name: Publish pre-release to GitHub releases
if: ${{ github.ref == 'refs/heads/main-live-migration-pvm' || github.ref == 'refs/heads/main-live-migration' || github.ref == 'refs/heads/firecracker-v1.8-live-migration-pvm' || github.ref == 'refs/heads/firecracker-v1.8-live-migration' }}
uses: softprops/action-gh-release@v2
with:
tag_name: release-${{ steps.extract_branch.outputs.branch }}
prerelease: true
files: |
/tmp/out/*/*
- name: Publish release to GitHub releases
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
prerelease: false
files: |
/tmp/out/*/*
25 changes: 25 additions & 0 deletions Hydrunfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/bash

set -e

# Rust
if [ "$1" = "rust" ]; then
# Configure Git
git config --global --add safe.directory '*'

# Build
export RUSTFLAGS='-C target-feature=+crt-static'
cargo build --package firecracker --package jailer --package seccompiler --package rebase-snap --package cpu-template-helper --target "$2-unknown-linux-musl" --all-features --release

# Stage binaries
mkdir -p out

dir="./build/cargo_target/$2-unknown-linux-musl/release"
for file in $(ls "$dir"); do
if [[ -x "$dir/$file" && ! -d "$dir/$file" ]]; then
cp "$dir/$file" "./out/${file}.linux-$2"
fi
done

exit 0
fi
1 change: 1 addition & 0 deletions docs/cpu_templates/cpu-template-helper.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ CPU features to a heterogeneous fleet consisting of multiple CPU models.
| HV_X64_MSR_SYNDBG_PENDING_BUFFER | 0x400000f5 |
| HV_X64_MSR_SYNDBG_OPTIONS | 0x400000ff |
| HV_X64_MSR_TSC_INVARIANT_CONTROL | 0x40000118 |
| HV_X64_MSR_TSC_INVARIANT_CONTROL | 0x40000118 |

### ARM registers excluded from guest CPU configuration dump

Expand Down
4 changes: 4 additions & 0 deletions resources/seccomp/aarch64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
{
"syscall": "fsync"
},
{
"syscall": "msync",
"comment": "Used for live migration to sync dirty pages"
},
{
"syscall": "close"
},
Expand Down
4 changes: 4 additions & 0 deletions resources/seccomp/x86_64-unknown-linux-musl.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
{
"syscall": "fsync"
},
{
"syscall": "msync",
"comment": "Used for live migration to sync dirty pages"
},
{
"syscall": "close"
},
Expand Down
8 changes: 8 additions & 0 deletions src/firecracker/src/api_server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,14 @@ impl ApiServer {
&METRICS.latencies_us.diff_create_snapshot,
"create diff snapshot",
)),
SnapshotType::Msync => Some((
&METRICS.latencies_us.diff_create_snapshot,
"memory synchronization snapshot",
)),
SnapshotType::MsyncAndState => Some((
&METRICS.latencies_us.diff_create_snapshot,
"memory synchronization and state snapshot",
)),
},
VmmAction::LoadSnapshot(_) => {
Some((&METRICS.latencies_us.load_snapshot, "load snapshot"))
Expand Down
5 changes: 5 additions & 0 deletions src/firecracker/src/api_server/request/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ fn parse_put_snapshot_load(body: &Body) -> Result<ParsedRequest, RequestError> {
mem_backend,
enable_diff_snapshots: snapshot_config.enable_diff_snapshots,
resume_vm: snapshot_config.resume_vm,
shared: snapshot_config.shared,
};

// Construct the `ParsedRequest` object.
Expand Down Expand Up @@ -181,6 +182,7 @@ mod tests {
},
enable_diff_snapshots: false,
resume_vm: false,
shared: false,
};
let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap();
assert!(parsed_request
Expand Down Expand Up @@ -208,6 +210,7 @@ mod tests {
},
enable_diff_snapshots: true,
resume_vm: false,
shared: false,
};
let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap();
assert!(parsed_request
Expand Down Expand Up @@ -235,6 +238,7 @@ mod tests {
},
enable_diff_snapshots: false,
resume_vm: true,
shared: false,
};
let mut parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap();
assert!(parsed_request
Expand All @@ -259,6 +263,7 @@ mod tests {
},
enable_diff_snapshots: false,
resume_vm: true,
shared: false,
};
let parsed_request = parse_put_snapshot(&Body::new(body), Some("load")).unwrap();
assert_eq!(
Expand Down
7 changes: 7 additions & 0 deletions src/firecracker/swagger/firecracker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1212,6 +1212,8 @@ definitions:
enum:
- Full
- Diff
- Msync
- MsyncAndState
description:
Type of snapshot to create. It is optional and by default, a full
snapshot is created.
Expand Down Expand Up @@ -1247,6 +1249,11 @@ definitions:
type: boolean
description:
When set to true, the vm is also resumed if the snapshot load is successful.
shared:
type: boolean
description: When set to true and the guest memory backend is a file,
changes to the memory are asynchronously written back to the
backend as the VM is running.

TokenBucket:
type: object
Expand Down
6 changes: 6 additions & 0 deletions src/vmm/src/logger/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,10 @@ pub struct PerformanceMetrics {
pub full_create_snapshot: SharedStoreMetric,
/// Measures the snapshot diff create time, at the API (user) level, in microseconds.
pub diff_create_snapshot: SharedStoreMetric,
/// Measures the snapshot memory synchronization time, at the VMM level, in microseconds.
pub msync_create_snapshot: SharedStoreMetric,
/// Measures the snapshot memory synchronization and state time, at the VMM level, in microseconds.
pub msync_and_state_create_snapshot: SharedStoreMetric,
/// Measures the snapshot load time, at the API (user) level, in microseconds.
pub load_snapshot: SharedStoreMetric,
/// Measures the microVM pausing duration, at the API (user) level, in microseconds.
Expand All @@ -627,6 +631,8 @@ impl PerformanceMetrics {
Self {
full_create_snapshot: SharedStoreMetric::new(),
diff_create_snapshot: SharedStoreMetric::new(),
msync_create_snapshot: SharedStoreMetric::new(),
msync_and_state_create_snapshot: SharedStoreMetric::new(),
load_snapshot: SharedStoreMetric::new(),
pause_vm: SharedStoreMetric::new(),
resume_vm: SharedStoreMetric::new(),
Expand Down
Loading
Loading