Skip to content
Merged
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
23 changes: 23 additions & 0 deletions protect/control/v1/common.proto
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,28 @@ enum ZoneVirtualizationBackend {
ZONE_VIRTUALIZATION_BACKEND_KVM = 4;
}

// Hypervisor family a zone snapshot was exported from. A snapshot may only be
// imported on a host running the same backend: the guest-state records inside
// it are backend-private, so a Xen stream carries nothing a KVM host can act
// on, and vice versa. The tag is checked before any of that state is
// interpreted, which is what lets a second backend be added later without
// either being able to consume the other's stream.
enum ZoneSnapshotBackend {
ZONE_SNAPSHOT_BACKEND_UNKNOWN = 0;
ZONE_SNAPSHOT_BACKEND_XEN_PV = 1;
ZONE_SNAPSHOT_BACKEND_XEN_PVH = 2;
ZONE_SNAPSHOT_BACKEND_KVM = 3;
}

// Guest instruction set a zone snapshot was exported for. Held separately from
// the backend: one backend spans architectures whose guest state has nothing in
// common.
enum ZoneSnapshotArch {
ZONE_SNAPSHOT_ARCH_UNKNOWN = 0;
ZONE_SNAPSHOT_ARCH_X86_64 = 1;
ZONE_SNAPSHOT_ARCH_AARCH64 = 2;
}

// Strategy used when expanding the selected node set beyond the seed node.
// - UNSPECIFIED is treated as COMPACT.
// - COMPACT: Expand to the nearest unselected NUMA node by SLIT distance from the already-selected set, tie-breaking by most free memory.
Expand Down Expand Up @@ -261,6 +283,7 @@ enum ZoneState {
ZONE_STATE_SUSPENDED = 9;
ZONE_STATE_RESUMING = 10;
ZONE_STATE_FORKING = 11;
ZONE_STATE_IMPORTING = 12;
}

enum ZoneNetworkIpVersion {
Expand Down
79 changes: 79 additions & 0 deletions protect/control/v1/control.proto
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ service ControlService {
rpc SuspendZone(SuspendZoneRequest) returns (SuspendZoneReply);
rpc ResumeZone(ResumeZoneRequest) returns (ResumeZoneReply);
rpc ForkZone(ForkZoneRequest) returns (ForkZoneReply);
rpc ExportZone(ExportZoneRequest) returns (stream ExportZoneReply);
rpc ImportZone(stream ImportZoneRequest) returns (ImportZoneReply);

rpc ResolveZoneId(ResolveZoneIdRequest) returns (ResolveZoneIdReply);
rpc ResolveZoneIds(ResolveZoneIdsRequest) returns (ResolveZoneIdsReply);
Expand Down Expand Up @@ -145,6 +147,83 @@ message ForkZoneReply {
string zone_id = 1;
}

// Exports a zone's complete state -- vcpus, guest memory, hypervisor
// configuration, device topology, the contents of its writable disks, and the
// zone's own control-plane record and workloads -- as a snapshot: a stream of
// opaque bytes the caller stores and later hands back to `ImportZone`.
//
// The zone is cooperatively suspended for the export and resumed afterwards
// unless `leave_suspended` is set, so a snapshot is a consistent point rather
// than a smear of a running guest.
message ExportZoneRequest {
reserved 4;
reserved "include_disk_contents";

string zone_id = 1;
// Leave the zone suspended once the export completes instead of resuming it.
// Use this when the snapshot is about to become the live copy elsewhere.
bool leave_suspended = 2;
// Compress record payloads. Guest memory compresses well; the cost is host
// CPU during the export.
bool compress = 3;
}

// Streamed reply for `ExportZone`. The first message carries `start`,
// describing the snapshot about to be streamed; then `chunk`s carrying its
// bytes in order; then a final `complete`. The concatenation of every `chunk`
// is the snapshot, and nothing else in the stream belongs in the stored bytes.
message ExportZoneReply {
oneof reply {
ExportZoneStart start = 1;
bytes chunk = 2;
ExportZoneComplete complete = 3;
}
}

message ExportZoneStart {
string zone_id = 1;
ZoneSnapshotBackend backend = 2;
ZoneSnapshotArch arch = 3;
uint32 format_version = 4;
}

// Closes the reply stream once the export is complete, so a caller can check
// that the snapshot it wrote is as long as what the daemon sent.
message ExportZoneComplete {
uint64 total_bytes = 1;
}

// Recreates a zone from a snapshot produced by `ExportZone`. The first message
// must carry `start`; every message after it carries a `chunk` of the
// snapshot, in the order it was received.
//
// The daemon checks the snapshot against this host before acting on any of the
// guest state it carries: the backend and architecture must match, and the
// guest's CPU, clock, zone agent and hypervisor state must be ones this host
// can continue. Read-only images the snapshot references by path must exist
// here unchanged in size. A refusal names every incompatibility found.
message ImportZoneRequest {
oneof request {
ImportZoneStart start = 1;
bytes chunk = 2;
}
}

message ImportZoneStart {
reserved 3;
reserved "allow_foreign_host";

// Overrides the zone name recorded in the snapshot. Empty keeps it.
string name = 1;
// Import under this zone id instead of a freshly allocated one. Empty
// allocates a new id, which is what lets one snapshot seed many zones.
string zone_id = 2;
}

message ImportZoneReply {
string zone_id = 1;
}

// Resolves zone "friendly name" to a singular zone UUID, if possible. Matching is exact.
// See also `ResolveZoneIdsRequest` (plural).
message ResolveZoneIdRequest {
Expand Down
Loading