mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-09-12 12:29:11 +00:00
Merge pull request #1668 from WeiZhang555/use-newstore
persist: merge more files with `persist.json`
This commit is contained in:
@@ -372,8 +372,11 @@ func (c *Container) GetPid() int {
|
||||
func (c *Container) SetPid(pid int) error {
|
||||
c.process.Pid = pid
|
||||
|
||||
if !c.sandbox.supportNewStore() {
|
||||
return c.storeProcess()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Container) setStateFstype(fstype string) error {
|
||||
c.state.Fstype = fstype
|
||||
@@ -592,9 +595,11 @@ func (c *Container) mountSharedDirMounts(hostSharedDir, guestSharedDir string) (
|
||||
sharedDirMounts = append(sharedDirMounts, sharedDirMount)
|
||||
}
|
||||
|
||||
if !c.sandbox.supportNewStore() {
|
||||
if err := c.storeMounts(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return sharedDirMounts, ignoredMounts, nil
|
||||
}
|
||||
@@ -716,21 +721,28 @@ func newContainer(sandbox *Sandbox, contConfig ContainerConfig) (*Container, err
|
||||
|
||||
// experimental runtime use "persist.json" instead of legacy "state.json" as storage
|
||||
if c.sandbox.supportNewStore() {
|
||||
if err := c.Restore(); err != nil &&
|
||||
!os.IsNotExist(err) && err != errContainerPersistNotExist {
|
||||
err := c.Restore()
|
||||
if err == nil {
|
||||
//container restored
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// Unexpected error
|
||||
if !os.IsNotExist(err) && err != errContainerPersistNotExist {
|
||||
return nil, err
|
||||
}
|
||||
// Go to next step for first created container
|
||||
} else {
|
||||
state, err := c.store.LoadContainerState()
|
||||
if err == nil {
|
||||
c.state = state
|
||||
}
|
||||
}
|
||||
|
||||
var process Process
|
||||
if err := c.store.Load(store.Process, &process); err == nil {
|
||||
c.process = process
|
||||
}
|
||||
}
|
||||
|
||||
if err = c.createMounts(); err != nil {
|
||||
return nil, err
|
||||
@@ -744,29 +756,41 @@ func newContainer(sandbox *Sandbox, contConfig ContainerConfig) (*Container, err
|
||||
}
|
||||
|
||||
func (c *Container) createMounts() error {
|
||||
// If sandbox supports "newstore", only newly created container can reach this function,
|
||||
// so we don't call restore when `supportNewStore` is true
|
||||
if !c.sandbox.supportNewStore() {
|
||||
mounts, err := c.loadMounts()
|
||||
if err == nil {
|
||||
// restore mounts from disk
|
||||
c.mounts = mounts
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Create block devices for newly created container
|
||||
if err := c.createBlockDevices(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Container) createDevices(contConfig ContainerConfig) error {
|
||||
// If sandbox supports "newstore", only newly created container can reach this function,
|
||||
// so we don't call restore when `supportNewStore` is true
|
||||
if !c.sandbox.supportNewStore() {
|
||||
// Devices will be found in storage after create stage has completed.
|
||||
// We load devices from storage at all other stages.
|
||||
storedDevices, err := c.loadDevices()
|
||||
if err == nil {
|
||||
c.devices = storedDevices
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// If devices were not found in storage, create Device implementations
|
||||
// from the configuration. This should happen at create.
|
||||
var storedDevices []ContainerDevice
|
||||
for _, info := range contConfig.DeviceInfos {
|
||||
dev, err := c.sandbox.devManager.NewDevice(info)
|
||||
if err != nil {
|
||||
@@ -782,7 +806,6 @@ func (c *Container) createDevices(contConfig ContainerConfig) error {
|
||||
})
|
||||
}
|
||||
c.devices = filterDevices(c, storedDevices)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -838,9 +861,11 @@ func (c *Container) create() (err error) {
|
||||
// inside the VM
|
||||
c.getSystemMountInfo()
|
||||
|
||||
if !c.sandbox.supportNewStore() {
|
||||
if err = c.storeDevices(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
process, err := c.sandbox.agent.createContainer(c.sandbox, c)
|
||||
if err != nil {
|
||||
@@ -852,10 +877,12 @@ func (c *Container) create() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if !c.sandbox.supportNewStore() {
|
||||
// Store the container process returned by the agent.
|
||||
if err = c.storeProcess(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = c.setContainerState(types.StateReady); err != nil {
|
||||
return
|
||||
|
@@ -1311,10 +1311,13 @@ func (k *kataAgent) handleBlockVolumes(c *Container) []*grpc.Storage {
|
||||
// Add the block device to the list of container devices, to make sure the
|
||||
// device is detached with detachDevices() for a container.
|
||||
c.devices = append(c.devices, ContainerDevice{ID: id, ContainerPath: m.Destination})
|
||||
|
||||
if !c.sandbox.supportNewStore() {
|
||||
if err := c.storeDevices(); err != nil {
|
||||
k.Logger().WithField("device", id).WithError(err).Error("store device failed")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
vol := &grpc.Storage{}
|
||||
|
||||
|
@@ -99,6 +99,59 @@ func (s *Sandbox) dumpDevices(ss *persistapi.SandboxState, cs map[string]persist
|
||||
}
|
||||
}
|
||||
|
||||
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) Save() error {
|
||||
var (
|
||||
ss = persistapi.SandboxState{}
|
||||
@@ -109,6 +162,8 @@ func (s *Sandbox) Save() error {
|
||||
s.dumpState(&ss, cs)
|
||||
s.dumpHypervisor(&ss, cs)
|
||||
s.dumpDevices(&ss, cs)
|
||||
s.dumpProcess(cs)
|
||||
s.dumpMounts(cs)
|
||||
|
||||
if err := s.newStore.ToDisk(ss, cs); err != nil {
|
||||
return err
|
||||
@@ -126,10 +181,54 @@ func (s *Sandbox) loadState(ss persistapi.SandboxState) {
|
||||
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) loadDevices(devStates []persistapi.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,
|
||||
}
|
||||
}
|
||||
|
||||
// Restore will restore sandbox data from persist file on disk
|
||||
func (s *Sandbox) Restore() error {
|
||||
ss, _, err := s.newStore.FromDisk(s.id)
|
||||
@@ -144,22 +243,20 @@ func (s *Sandbox) Restore() error {
|
||||
|
||||
// Restore will restore container data from persist file on disk
|
||||
func (c *Container) Restore() error {
|
||||
_, cs, err := c.sandbox.newStore.FromDisk(c.sandbox.id)
|
||||
_, css, err := c.sandbox.newStore.FromDisk(c.sandbox.id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ok := cs[c.id]; !ok {
|
||||
cs, ok := css[c.id]
|
||||
if !ok {
|
||||
return errContainerPersistNotExist
|
||||
}
|
||||
|
||||
c.state = types.ContainerState{
|
||||
State: types.StateString(cs[c.id].State),
|
||||
BlockDeviceID: cs[c.id].Rootfs.BlockDeviceID,
|
||||
Fstype: cs[c.id].Rootfs.FsType,
|
||||
CgroupPath: cs[c.id].CgroupPath,
|
||||
}
|
||||
|
||||
c.loadContState(cs)
|
||||
c.loadContDevices(cs)
|
||||
c.loadContProcess(cs)
|
||||
c.loadContMounts(cs)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -103,8 +103,7 @@ type ContainerState struct {
|
||||
Mounts []Mount
|
||||
|
||||
// Process on host representing container process
|
||||
// FIXME: []Process or Process ?
|
||||
Process []Process
|
||||
Process Process
|
||||
|
||||
// BundlePath saves container OCI config.json, which can be unmarshaled
|
||||
// and translated to "CompatOCISpec"
|
||||
|
@@ -14,7 +14,7 @@ type SetFunc (func(*SandboxState, map[string]ContainerState) error)
|
||||
|
||||
// Bridge is a bridge where devices can be hot plugged
|
||||
type Bridge struct {
|
||||
// Address contains information about devices plugged and its address in the bridge
|
||||
// DeviceAddr contains information about devices plugged and its address in the bridge
|
||||
DeviceAddr map[uint32]string
|
||||
|
||||
// Type is the type of the bridge (pci, pcie, etc)
|
||||
|
Reference in New Issue
Block a user