Initial push
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
package spec
|
||||
|
||||
import "time"
|
||||
|
||||
// ImageMode decides how the container image reaches the target host.
|
||||
type ImageMode string
|
||||
|
||||
const (
|
||||
// ImageAuto pulls from a registry when the reference looks pullable and
|
||||
// falls back to streaming the image layers otherwise.
|
||||
ImageAuto ImageMode = "auto"
|
||||
// ImagePull always runs `docker pull` on the target.
|
||||
ImagePull ImageMode = "pull"
|
||||
// ImageStream always transfers `docker save` output.
|
||||
ImageStream ImageMode = "stream"
|
||||
// ImageSkip assumes the image is already present on the target.
|
||||
ImageSkip ImageMode = "skip"
|
||||
)
|
||||
|
||||
// ConflictPolicy decides what to do when the target already has a container,
|
||||
// volume or network with the same name.
|
||||
type ConflictPolicy string
|
||||
|
||||
const (
|
||||
ConflictFail ConflictPolicy = "fail" // abort the item
|
||||
ConflictSkip ConflictPolicy = "skip" // leave the target object untouched
|
||||
ConflictReplace ConflictPolicy = "replace" // remove the target object first
|
||||
ConflictRename ConflictPolicy = "rename" // create alongside with a suffix
|
||||
)
|
||||
|
||||
// ItemSelection is the per-container answer to "what do you want to migrate?".
|
||||
// Every data location is opted in or out individually.
|
||||
type ItemSelection struct {
|
||||
ContainerID string `json:"containerId"`
|
||||
|
||||
// Include is the master switch for this container.
|
||||
Include bool `json:"include"`
|
||||
|
||||
// NameOverride renames the container on the target.
|
||||
NameOverride string `json:"nameOverride,omitempty"`
|
||||
|
||||
// MigrateImage brings the image across; when false the container is
|
||||
// created assuming the image already exists on the target.
|
||||
MigrateImage bool `json:"migrateImage"`
|
||||
ImageMode ImageMode `json:"imageMode"`
|
||||
|
||||
// MigrateNetworks recreates user-defined networks and reattaches them.
|
||||
MigrateNetworks bool `json:"migrateNetworks"`
|
||||
KeepStaticIPs bool `json:"keepStaticIps"`
|
||||
MigratePorts bool `json:"migratePorts"`
|
||||
|
||||
// Mounts maps a container-side destination path to how it is handled.
|
||||
Mounts map[string]MountSelection `json:"mounts"`
|
||||
|
||||
// StartAfter starts the container on the target once restored.
|
||||
StartAfter bool `json:"startAfter"`
|
||||
// StopSourceDuringCopy stops the source container for the duration of the
|
||||
// data copy so the files are consistent, then restores its former state.
|
||||
StopSourceDuringCopy bool `json:"stopSourceDuringCopy"`
|
||||
// StopSourceAfter leaves the source container stopped once the migration
|
||||
// succeeded, so the two hosts do not both serve the same workload.
|
||||
StopSourceAfter bool `json:"stopSourceAfter"`
|
||||
}
|
||||
|
||||
// MountAction is what to do with one data location.
|
||||
type MountAction string
|
||||
|
||||
const (
|
||||
// MountActionCopy recreates the mount and copies its contents.
|
||||
MountActionCopy MountAction = "copy"
|
||||
// MountActionStructure recreates the mount (volume or host directory) but
|
||||
// leaves it empty.
|
||||
MountActionStructure MountAction = "structure"
|
||||
// MountActionSkip drops the mount from the target container entirely.
|
||||
MountActionSkip MountAction = "skip"
|
||||
)
|
||||
|
||||
// MountSelection is the per-mount answer, including an optional relocation of
|
||||
// a bind mount to a different path on the target host.
|
||||
type MountSelection struct {
|
||||
Action MountAction `json:"action"`
|
||||
// TargetSource relocates a bind mount on the target host. Empty keeps the
|
||||
// source path. Ignored for volumes.
|
||||
TargetSource string `json:"targetSource,omitempty"`
|
||||
// TargetName renames a named volume on the target. Empty keeps the name.
|
||||
TargetName string `json:"targetName,omitempty"`
|
||||
}
|
||||
|
||||
// Options are the settings shared by every item in one migration run.
|
||||
type Options struct {
|
||||
Conflict ConflictPolicy `json:"conflict"`
|
||||
RenameSuffix string `json:"renameSuffix,omitempty"` // used by ConflictRename, default "-migrated"
|
||||
|
||||
// Compress gzips data and image streams. Requires gzip on the target for
|
||||
// SSH mode; always safe for package mode.
|
||||
Compress bool `json:"compress"`
|
||||
// CompressLevel is 1..9, defaulting to 1 (fast) because these transfers
|
||||
// are usually bound by disk and network, not CPU.
|
||||
CompressLevel int `json:"compressLevel"`
|
||||
|
||||
// DryRun performs every check and prints every command without changing
|
||||
// anything on the target.
|
||||
DryRun bool `json:"dryRun"`
|
||||
|
||||
// Parallelism is how many containers migrate at once.
|
||||
Parallelism int `json:"parallelism"`
|
||||
|
||||
// VerifyAfter re-inspects each container on the target and compares the
|
||||
// resulting spec against the source.
|
||||
VerifyAfter bool `json:"verifyAfter"`
|
||||
}
|
||||
|
||||
// DefaultOptions returns the options used when the UI has not overridden them.
|
||||
func DefaultOptions() Options {
|
||||
return Options{
|
||||
Conflict: ConflictFail,
|
||||
RenameSuffix: "-migrated",
|
||||
Compress: true,
|
||||
CompressLevel: 1,
|
||||
Parallelism: 1,
|
||||
VerifyAfter: true,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultSelection builds the "migrate everything" answer for a container,
|
||||
// which is what the UI presents before the user changes anything.
|
||||
func DefaultSelection(c *Container) ItemSelection {
|
||||
sel := ItemSelection{
|
||||
ContainerID: c.ID,
|
||||
Include: false,
|
||||
MigrateImage: true,
|
||||
ImageMode: ImageAuto,
|
||||
MigrateNetworks: true,
|
||||
KeepStaticIPs: false,
|
||||
MigratePorts: true,
|
||||
Mounts: map[string]MountSelection{},
|
||||
StartAfter: c.State == "running",
|
||||
StopSourceDuringCopy: true,
|
||||
StopSourceAfter: true,
|
||||
}
|
||||
for _, m := range c.Mounts {
|
||||
action := MountActionCopy
|
||||
if m.Kind == MountTmpfs {
|
||||
action = MountActionStructure
|
||||
}
|
||||
sel.Mounts[m.Destination] = MountSelection{Action: action}
|
||||
}
|
||||
return sel
|
||||
}
|
||||
|
||||
// Plan is a complete migration request: what to move, where, and how.
|
||||
type Plan struct {
|
||||
Items []ItemSelection `json:"items"`
|
||||
Options Options `json:"options"`
|
||||
// Target is the SSH connection id for host-to-host mode. Empty means the
|
||||
// plan produces an offline package instead.
|
||||
Target string `json:"target,omitempty"`
|
||||
// PackageName is the base name of the produced package (package mode).
|
||||
PackageName string `json:"packageName,omitempty"`
|
||||
}
|
||||
|
||||
// Manifest is written into an offline migration package. It is descriptive:
|
||||
// the generated install.sh is self-contained and does not parse it.
|
||||
type Manifest struct {
|
||||
FormatVersion int `json:"formatVersion"`
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
CreatedBy string `json:"createdBy"`
|
||||
SourceHost string `json:"sourceHost"`
|
||||
DockerVersion string `json:"dockerVersion"`
|
||||
|
||||
Containers []Container `json:"containers"`
|
||||
Volumes []Volume `json:"volumes"`
|
||||
Networks []Network `json:"networks"`
|
||||
Items []ItemSelection `json:"items"`
|
||||
Options Options `json:"options"`
|
||||
|
||||
// Payloads lists every data file in the package with its checksum, so the
|
||||
// installer can verify the archive survived the trip.
|
||||
Payloads []Payload `json:"payloads"`
|
||||
}
|
||||
|
||||
// Payload is one file inside a migration package.
|
||||
type Payload struct {
|
||||
Path string `json:"path"` // relative to the package root
|
||||
Kind string `json:"kind"` // "image" | "mount"
|
||||
Container string `json:"container,omitempty"`
|
||||
Destination string `json:"destination,omitempty"` // mount destination it restores
|
||||
Image string `json:"image,omitempty"`
|
||||
Bytes int64 `json:"bytes"`
|
||||
SHA256 string `json:"sha256"`
|
||||
Compressed bool `json:"compressed"`
|
||||
}
|
||||
Reference in New Issue
Block a user