Merge pull request #1668 from WeiZhang555/use-newstore

persist: merge more files with `persist.json`
This commit is contained in:
Peng Tao
2019-05-16 17:38:30 +08:00
committed by GitHub
5 changed files with 185 additions and 59 deletions

View File

@@ -372,7 +372,10 @@ 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 {
@@ -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

View File

@@ -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{}

View File

@@ -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
}

View File

@@ -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"

View File

@@ -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)