kata-containers/src/runtime/virtcontainers/persist.go
Fabiano Fidêncio fefcf7cfa4 acrn: Drop support
As we don't have any CI, nor maintainer to keep ACRN code around, we
better have it removed than give users the expectation that it should or
would work at some point.

Signed-off-by: Fabiano Fidêncio <fabiano@fidencio.org>
2024-09-19 16:05:43 +02:00

517 lines
17 KiB
Go

// Copyright (c) 2019 Huawei Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"errors"
"github.com/kata-containers/kata-containers/src/runtime/pkg/device/api"
devconfig "github.com/kata-containers/kata-containers/src/runtime/pkg/device/config"
hv "github.com/kata-containers/kata-containers/src/runtime/pkg/hypervisors"
exp "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/experimental"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist"
persistapi "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/persist/api"
"github.com/kata-containers/kata-containers/src/runtime/virtcontainers/types"
)
var (
errContainerPersistNotExist = errors.New("container doesn't exist in persist data")
)
func (s *Sandbox) dumpVersion(ss *persistapi.SandboxState) {
// New created sandbox has a uninitialized `PersistVersion` which should be set to current version when do the first saving;
// Old restored sandbox should keep its original version and shouldn't be modified any more after it's initialized.
ss.PersistVersion = s.state.PersistVersion
if ss.PersistVersion == 0 {
ss.PersistVersion = persistapi.CurPersistVersion
}
}
func (s *Sandbox) dumpState(ss *persistapi.SandboxState, cs map[string]persistapi.ContainerState) {
ss.SandboxContainer = s.id
ss.GuestMemoryBlockSizeMB = s.state.GuestMemoryBlockSizeMB
ss.GuestMemoryHotplugProbe = s.state.GuestMemoryHotplugProbe
ss.State = string(s.state.State)
ss.SandboxCgroupPath = s.state.SandboxCgroupPath
ss.OverheadCgroupPath = s.state.OverheadCgroupPath
for id, cont := range s.containers {
state := persistapi.ContainerState{}
if v, ok := cs[id]; ok {
state = v
}
state.State = string(cont.state.State)
state.Rootfs = persistapi.RootfsState{
BlockDeviceID: cont.state.BlockDeviceID,
FsType: cont.state.Fstype,
}
state.CgroupPath = cont.state.CgroupPath
cs[id] = state
}
// delete removed containers
for id := range cs {
if _, ok := s.containers[id]; !ok {
delete(cs, id)
}
}
}
func (s *Sandbox) dumpHypervisor(ss *persistapi.SandboxState) {
ss.HypervisorState = s.hypervisor.Save()
// BlockIndexMap will be moved from sandbox state to hypervisor state later
ss.HypervisorState.BlockIndexMap = s.state.BlockIndexMap
}
func deviceToDeviceState(devices []api.Device) (dss []devconfig.DeviceState) {
for _, dev := range devices {
dss = append(dss, dev.Save())
}
return
}
func (s *Sandbox) dumpDevices(ss *persistapi.SandboxState, cs map[string]persistapi.ContainerState) {
ss.Devices = deviceToDeviceState(s.devManager.GetAllDevices())
for id, cont := range s.containers {
state := persistapi.ContainerState{}
if v, ok := cs[id]; ok {
state = v
}
state.DeviceMaps = nil
for _, dev := range cont.devices {
state.DeviceMaps = append(state.DeviceMaps, persistapi.DeviceMap{
ID: dev.ID,
ContainerPath: dev.ContainerPath,
FileMode: dev.FileMode,
UID: dev.UID,
GID: dev.GID,
})
}
cs[id] = state
}
// delete removed containers
for id := range cs {
if _, ok := s.containers[id]; !ok {
delete(cs, id)
}
}
}
func (s *Sandbox) dumpProcess(cs map[string]persistapi.ContainerState) {
for id, cont := range s.containers {
state := persistapi.ContainerState{}
if v, ok := cs[id]; ok {
state = v
}
state.Process = persistapi.Process{
Token: cont.process.Token,
Pid: cont.process.Pid,
StartTime: cont.process.StartTime,
}
cs[id] = state
}
// delete removed containers
for id := range cs {
if _, ok := s.containers[id]; !ok {
delete(cs, id)
}
}
}
func (s *Sandbox) dumpMounts(cs map[string]persistapi.ContainerState) {
for id, cont := range s.containers {
state := persistapi.ContainerState{}
if v, ok := cs[id]; ok {
state = v
}
for _, m := range cont.mounts {
state.Mounts = append(state.Mounts, persistapi.Mount{
Source: m.Source,
Destination: m.Destination,
Options: m.Options,
HostPath: m.HostPath,
ReadOnly: m.ReadOnly,
BlockDeviceID: m.BlockDeviceID,
})
}
cs[id] = state
}
// delete removed containers
for id := range cs {
if _, ok := s.containers[id]; !ok {
delete(cs, id)
}
}
}
func (s *Sandbox) dumpAgent(ss *persistapi.SandboxState) {
if s.agent != nil {
ss.AgentState = s.agent.save()
}
}
func (s *Sandbox) dumpNetwork(ss *persistapi.SandboxState) {
ss.Network = persistapi.NetworkInfo{
NetworkID: s.network.NetworkID(),
NetworkCreated: s.network.NetworkCreated(),
}
for _, e := range s.network.Endpoints() {
ss.Network.Endpoints = append(ss.Network.Endpoints, e.save())
}
}
func (s *Sandbox) dumpConfig(ss *persistapi.SandboxState) {
sconfig := s.config
ss.Config = persistapi.SandboxConfig{
HypervisorType: string(sconfig.HypervisorType),
NetworkConfig: persistapi.NetworkConfig{
NetworkID: sconfig.NetworkConfig.NetworkID,
NetworkCreated: sconfig.NetworkConfig.NetworkCreated,
DisableNewNetwork: sconfig.NetworkConfig.DisableNewNetwork,
InterworkingModel: int(sconfig.NetworkConfig.InterworkingModel),
},
ShmSize: sconfig.ShmSize,
SharePidNs: sconfig.SharePidNs,
SystemdCgroup: sconfig.SystemdCgroup,
SandboxCgroupOnly: sconfig.SandboxCgroupOnly,
DisableGuestSeccomp: sconfig.DisableGuestSeccomp,
EnableVCPUsPinning: sconfig.EnableVCPUsPinning,
GuestSeLinuxLabel: sconfig.GuestSeLinuxLabel,
}
ss.Config.SandboxBindMounts = append(ss.Config.SandboxBindMounts, sconfig.SandboxBindMounts...)
for _, e := range sconfig.Experimental {
ss.Config.Experimental = append(ss.Config.Experimental, e.Name)
}
ss.Config.HypervisorConfig = persistapi.HypervisorConfig{
NumVCPUsF: sconfig.HypervisorConfig.NumVCPUsF,
DefaultMaxVCPUs: sconfig.HypervisorConfig.DefaultMaxVCPUs,
MemorySize: sconfig.HypervisorConfig.MemorySize,
DefaultBridges: sconfig.HypervisorConfig.DefaultBridges,
Msize9p: sconfig.HypervisorConfig.Msize9p,
MemSlots: sconfig.HypervisorConfig.MemSlots,
MemOffset: sconfig.HypervisorConfig.MemOffset,
VirtioMem: sconfig.HypervisorConfig.VirtioMem,
VirtioFSCacheSize: sconfig.HypervisorConfig.VirtioFSCacheSize,
KernelPath: sconfig.HypervisorConfig.KernelPath,
ImagePath: sconfig.HypervisorConfig.ImagePath,
InitrdPath: sconfig.HypervisorConfig.InitrdPath,
FirmwarePath: sconfig.HypervisorConfig.FirmwarePath,
MachineAccelerators: sconfig.HypervisorConfig.MachineAccelerators,
CPUFeatures: sconfig.HypervisorConfig.CPUFeatures,
HypervisorPath: sconfig.HypervisorConfig.HypervisorPath,
HypervisorPathList: sconfig.HypervisorConfig.HypervisorPathList,
JailerPath: sconfig.HypervisorConfig.JailerPath,
JailerPathList: sconfig.HypervisorConfig.JailerPathList,
BlockDeviceDriver: sconfig.HypervisorConfig.BlockDeviceDriver,
HypervisorMachineType: sconfig.HypervisorConfig.HypervisorMachineType,
MemoryPath: sconfig.HypervisorConfig.MemoryPath,
DevicesStatePath: sconfig.HypervisorConfig.DevicesStatePath,
EntropySource: sconfig.HypervisorConfig.EntropySource,
EntropySourceList: sconfig.HypervisorConfig.EntropySourceList,
SharedFS: sconfig.HypervisorConfig.SharedFS,
VirtioFSDaemon: sconfig.HypervisorConfig.VirtioFSDaemon,
VirtioFSDaemonList: sconfig.HypervisorConfig.VirtioFSDaemonList,
VirtioFSCache: sconfig.HypervisorConfig.VirtioFSCache,
VirtioFSExtraArgs: sconfig.HypervisorConfig.VirtioFSExtraArgs[:],
BlockDeviceCacheSet: sconfig.HypervisorConfig.BlockDeviceCacheSet,
BlockDeviceCacheDirect: sconfig.HypervisorConfig.BlockDeviceCacheDirect,
BlockDeviceCacheNoflush: sconfig.HypervisorConfig.BlockDeviceCacheNoflush,
DisableBlockDeviceUse: sconfig.HypervisorConfig.DisableBlockDeviceUse,
EnableIOThreads: sconfig.HypervisorConfig.EnableIOThreads,
Debug: sconfig.HypervisorConfig.Debug,
MemPrealloc: sconfig.HypervisorConfig.MemPrealloc,
HugePages: sconfig.HypervisorConfig.HugePages,
FileBackedMemRootDir: sconfig.HypervisorConfig.FileBackedMemRootDir,
FileBackedMemRootList: sconfig.HypervisorConfig.FileBackedMemRootList,
DisableNestingChecks: sconfig.HypervisorConfig.DisableNestingChecks,
DisableImageNvdimm: sconfig.HypervisorConfig.DisableImageNvdimm,
BootToBeTemplate: sconfig.HypervisorConfig.BootToBeTemplate,
BootFromTemplate: sconfig.HypervisorConfig.BootFromTemplate,
DisableVhostNet: sconfig.HypervisorConfig.DisableVhostNet,
EnableVhostUserStore: sconfig.HypervisorConfig.EnableVhostUserStore,
SeccompSandbox: sconfig.HypervisorConfig.SeccompSandbox,
VhostUserStorePath: sconfig.HypervisorConfig.VhostUserStorePath,
VhostUserStorePathList: sconfig.HypervisorConfig.VhostUserStorePathList,
GuestHookPath: sconfig.HypervisorConfig.GuestHookPath,
VMid: sconfig.HypervisorConfig.VMid,
RxRateLimiterMaxRate: sconfig.HypervisorConfig.RxRateLimiterMaxRate,
TxRateLimiterMaxRate: sconfig.HypervisorConfig.TxRateLimiterMaxRate,
SGXEPCSize: sconfig.HypervisorConfig.SGXEPCSize,
EnableAnnotations: sconfig.HypervisorConfig.EnableAnnotations,
}
ss.Config.KataAgentConfig = &persistapi.KataAgentConfig{
LongLiveConn: sconfig.AgentConfig.LongLiveConn,
}
for _, contConf := range sconfig.Containers {
ss.Config.ContainerConfigs = append(ss.Config.ContainerConfigs, persistapi.ContainerConfig{
ID: contConf.ID,
Annotations: contConf.Annotations,
RootFs: contConf.RootFs.Target,
Resources: contConf.Resources,
})
}
}
func (s *Sandbox) Save() error {
var (
ss = persistapi.SandboxState{}
cs = make(map[string]persistapi.ContainerState)
)
s.dumpVersion(&ss)
s.dumpState(&ss, cs)
s.dumpHypervisor(&ss)
s.dumpDevices(&ss, cs)
s.dumpProcess(cs)
s.dumpMounts(cs)
s.dumpAgent(&ss)
s.dumpNetwork(&ss)
s.dumpConfig(&ss)
if err := s.store.ToDisk(ss, cs); err != nil {
return err
}
return nil
}
func (s *Sandbox) loadState(ss persistapi.SandboxState) {
s.state.PersistVersion = ss.PersistVersion
s.state.GuestMemoryBlockSizeMB = ss.GuestMemoryBlockSizeMB
s.state.BlockIndexMap = ss.HypervisorState.BlockIndexMap
s.state.State = types.StateString(ss.State)
s.state.SandboxCgroupPath = ss.SandboxCgroupPath
s.state.OverheadCgroupPath = ss.OverheadCgroupPath
s.state.GuestMemoryHotplugProbe = ss.GuestMemoryHotplugProbe
}
func (c *Container) loadContState(cs persistapi.ContainerState) {
c.state = types.ContainerState{
State: types.StateString(cs.State),
BlockDeviceID: cs.Rootfs.BlockDeviceID,
Fstype: cs.Rootfs.FsType,
CgroupPath: cs.CgroupPath,
}
}
func (s *Sandbox) loadHypervisor(hs hv.HypervisorState) {
s.hypervisor.Load(hs)
}
func (s *Sandbox) loadAgent(as persistapi.AgentState) {
if s.agent != nil {
s.agent.load(as)
}
}
func (s *Sandbox) loadDevices(devStates []devconfig.DeviceState) {
s.devManager.LoadDevices(devStates)
}
func (c *Container) loadContDevices(cs persistapi.ContainerState) {
c.devices = nil
for _, dev := range cs.DeviceMaps {
c.devices = append(c.devices, ContainerDevice{
ID: dev.ID,
ContainerPath: dev.ContainerPath,
FileMode: dev.FileMode,
UID: dev.UID,
GID: dev.GID,
})
}
}
func (c *Container) loadContMounts(cs persistapi.ContainerState) {
c.mounts = nil
for _, m := range cs.Mounts {
c.mounts = append(c.mounts, Mount{
Source: m.Source,
Destination: m.Destination,
Options: m.Options,
HostPath: m.HostPath,
ReadOnly: m.ReadOnly,
BlockDeviceID: m.BlockDeviceID,
})
}
}
func (c *Container) loadContProcess(cs persistapi.ContainerState) {
c.process = Process{
Token: cs.Process.Token,
Pid: cs.Process.Pid,
StartTime: cs.Process.StartTime,
}
}
func (s *Sandbox) loadNetwork(netInfo persistapi.NetworkInfo) {
s.network = LoadNetwork(netInfo)
}
// Restore will restore sandbox data from persist file on disk
func (s *Sandbox) Restore() error {
ss, _, err := s.store.FromDisk(s.id)
if err != nil {
return err
}
s.loadState(ss)
s.loadHypervisor(ss.HypervisorState)
s.loadDevices(ss.Devices)
s.loadAgent(ss.AgentState)
s.loadNetwork(ss.Network)
return nil
}
// Restore will restore container data from persist file on disk
func (c *Container) Restore() error {
_, css, err := c.sandbox.store.FromDisk(c.sandbox.id)
if err != nil {
return err
}
cs, ok := css[c.id]
if !ok {
return errContainerPersistNotExist
}
c.loadContState(cs)
c.loadContDevices(cs)
c.loadContProcess(cs)
c.loadContMounts(cs)
return nil
}
func loadSandboxConfig(id string) (*SandboxConfig, error) {
store, err := persist.GetDriver()
if err != nil || store == nil {
return nil, errors.New("failed to get fs persist driver")
}
ss, _, err := store.FromDisk(id)
if err != nil {
return nil, err
}
savedConf := ss.Config
sconfig := &SandboxConfig{
ID: id,
HypervisorType: HypervisorType(savedConf.HypervisorType),
NetworkConfig: NetworkConfig{
NetworkID: savedConf.NetworkConfig.NetworkID,
NetworkCreated: savedConf.NetworkConfig.NetworkCreated,
DisableNewNetwork: savedConf.NetworkConfig.DisableNewNetwork,
InterworkingModel: NetInterworkingModel(savedConf.NetworkConfig.InterworkingModel),
},
ShmSize: savedConf.ShmSize,
SharePidNs: savedConf.SharePidNs,
SystemdCgroup: savedConf.SystemdCgroup,
SandboxCgroupOnly: savedConf.SandboxCgroupOnly,
DisableGuestSeccomp: savedConf.DisableGuestSeccomp,
EnableVCPUsPinning: savedConf.EnableVCPUsPinning,
GuestSeLinuxLabel: savedConf.GuestSeLinuxLabel,
}
sconfig.SandboxBindMounts = append(sconfig.SandboxBindMounts, savedConf.SandboxBindMounts...)
for _, name := range savedConf.Experimental {
sconfig.Experimental = append(sconfig.Experimental, *exp.Get(name))
}
hconf := savedConf.HypervisorConfig
sconfig.HypervisorConfig = HypervisorConfig{
NumVCPUsF: hconf.NumVCPUsF,
DefaultMaxVCPUs: hconf.DefaultMaxVCPUs,
MemorySize: hconf.MemorySize,
DefaultBridges: hconf.DefaultBridges,
Msize9p: hconf.Msize9p,
MemSlots: hconf.MemSlots,
MemOffset: hconf.MemOffset,
VirtioMem: hconf.VirtioMem,
VirtioFSCacheSize: hconf.VirtioFSCacheSize,
KernelPath: hconf.KernelPath,
ImagePath: hconf.ImagePath,
InitrdPath: hconf.InitrdPath,
FirmwarePath: hconf.FirmwarePath,
MachineAccelerators: hconf.MachineAccelerators,
CPUFeatures: hconf.CPUFeatures,
HypervisorPath: hconf.HypervisorPath,
HypervisorPathList: hconf.HypervisorPathList,
JailerPath: hconf.JailerPath,
JailerPathList: hconf.JailerPathList,
BlockDeviceDriver: hconf.BlockDeviceDriver,
HypervisorMachineType: hconf.HypervisorMachineType,
MemoryPath: hconf.MemoryPath,
DevicesStatePath: hconf.DevicesStatePath,
EntropySource: hconf.EntropySource,
EntropySourceList: hconf.EntropySourceList,
SharedFS: hconf.SharedFS,
VirtioFSDaemon: hconf.VirtioFSDaemon,
VirtioFSDaemonList: hconf.VirtioFSDaemonList,
VirtioFSCache: hconf.VirtioFSCache,
VirtioFSExtraArgs: hconf.VirtioFSExtraArgs[:],
BlockDeviceCacheSet: hconf.BlockDeviceCacheSet,
BlockDeviceCacheDirect: hconf.BlockDeviceCacheDirect,
BlockDeviceCacheNoflush: hconf.BlockDeviceCacheNoflush,
DisableBlockDeviceUse: hconf.DisableBlockDeviceUse,
EnableIOThreads: hconf.EnableIOThreads,
Debug: hconf.Debug,
MemPrealloc: hconf.MemPrealloc,
HugePages: hconf.HugePages,
FileBackedMemRootDir: hconf.FileBackedMemRootDir,
FileBackedMemRootList: hconf.FileBackedMemRootList,
DisableNestingChecks: hconf.DisableNestingChecks,
DisableImageNvdimm: hconf.DisableImageNvdimm,
HotPlugVFIO: hconf.HotPlugVFIO,
ColdPlugVFIO: hconf.ColdPlugVFIO,
PCIeRootPort: hconf.PCIeRootPort,
PCIeSwitchPort: hconf.PCIeSwitchPort,
BootToBeTemplate: hconf.BootToBeTemplate,
BootFromTemplate: hconf.BootFromTemplate,
DisableVhostNet: hconf.DisableVhostNet,
EnableVhostUserStore: hconf.EnableVhostUserStore,
VhostUserStorePath: hconf.VhostUserStorePath,
VhostUserStorePathList: hconf.VhostUserStorePathList,
GuestHookPath: hconf.GuestHookPath,
VMid: hconf.VMid,
RxRateLimiterMaxRate: hconf.RxRateLimiterMaxRate,
TxRateLimiterMaxRate: hconf.TxRateLimiterMaxRate,
SGXEPCSize: hconf.SGXEPCSize,
EnableAnnotations: hconf.EnableAnnotations,
}
sconfig.AgentConfig = KataAgentConfig{
LongLiveConn: savedConf.KataAgentConfig.LongLiveConn,
}
for _, contConf := range savedConf.ContainerConfigs {
sconfig.Containers = append(sconfig.Containers, ContainerConfig{
ID: contConf.ID,
Annotations: contConf.Annotations,
Resources: contConf.Resources,
RootFs: RootFs{
Target: contConf.RootFs,
},
})
}
return sconfig, nil
}