Implement full snapshot lifecycle: pause (snapshot + free resources), resume (UFFD-based lazy restore), and named snapshot templates that can spawn new sandboxes from frozen VM state. Key changes: - Snapshot header system with generational diff mapping (inspired by e2b) - UFFD server for lazy page fault handling during snapshot restore - Stable rootfs symlink path (/tmp/fc-vm/) for snapshot compatibility - Templates DB table and CRUD API endpoints (POST/GET/DELETE /v1/snapshots) - CreateSnapshot/DeleteSnapshot RPCs in hostagent proto - Reconciler excludes paused sandboxes (expected absent from host agent) - Snapshot templates lock vcpus/memory to baked-in values - Proper cleanup of uffd sockets and pause snapshot files on destroy
136 lines
2.9 KiB
Go
136 lines
2.9 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: templates.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const deleteTemplate = `-- name: DeleteTemplate :exec
|
|
DELETE FROM templates WHERE name = $1
|
|
`
|
|
|
|
func (q *Queries) DeleteTemplate(ctx context.Context, name string) error {
|
|
_, err := q.db.Exec(ctx, deleteTemplate, name)
|
|
return err
|
|
}
|
|
|
|
const getTemplate = `-- name: GetTemplate :one
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at FROM templates WHERE name = $1
|
|
`
|
|
|
|
func (q *Queries) GetTemplate(ctx context.Context, name string) (Template, error) {
|
|
row := q.db.QueryRow(ctx, getTemplate, name)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const insertTemplate = `-- name: InsertTemplate :one
|
|
INSERT INTO templates (name, type, vcpus, memory_mb, size_bytes)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING name, type, vcpus, memory_mb, size_bytes, created_at
|
|
`
|
|
|
|
type InsertTemplateParams struct {
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Vcpus pgtype.Int4 `json:"vcpus"`
|
|
MemoryMb pgtype.Int4 `json:"memory_mb"`
|
|
SizeBytes int64 `json:"size_bytes"`
|
|
}
|
|
|
|
func (q *Queries) InsertTemplate(ctx context.Context, arg InsertTemplateParams) (Template, error) {
|
|
row := q.db.QueryRow(ctx, insertTemplate,
|
|
arg.Name,
|
|
arg.Type,
|
|
arg.Vcpus,
|
|
arg.MemoryMb,
|
|
arg.SizeBytes,
|
|
)
|
|
var i Template
|
|
err := row.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const listTemplates = `-- name: ListTemplates :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at FROM templates ORDER BY created_at DESC
|
|
`
|
|
|
|
func (q *Queries) ListTemplates(ctx context.Context) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplates)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const listTemplatesByType = `-- name: ListTemplatesByType :many
|
|
SELECT name, type, vcpus, memory_mb, size_bytes, created_at FROM templates WHERE type = $1 ORDER BY created_at DESC
|
|
`
|
|
|
|
func (q *Queries) ListTemplatesByType(ctx context.Context, type_ string) ([]Template, error) {
|
|
rows, err := q.db.Query(ctx, listTemplatesByType, type_)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Template
|
|
for rows.Next() {
|
|
var i Template
|
|
if err := rows.Scan(
|
|
&i.Name,
|
|
&i.Type,
|
|
&i.Vcpus,
|
|
&i.MemoryMb,
|
|
&i.SizeBytes,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|