compatibility: keep oldstore for compatibility

Keep old store restore functions for keeping backward compatibility, if
old store files are found from disk, restore them with old store first.

Signed-off-by: Wei Zhang <weizhang555.zw@gmail.com>
This commit is contained in:
Wei Zhang 2020-01-08 22:40:21 +08:00
parent 4a298cb9b7
commit 290339da6b
5 changed files with 177 additions and 25 deletions

View File

@ -29,6 +29,7 @@ import (
"github.com/kata-containers/runtime/pkg/rootless" "github.com/kata-containers/runtime/pkg/rootless"
"github.com/kata-containers/runtime/virtcontainers/device/config" "github.com/kata-containers/runtime/virtcontainers/device/config"
"github.com/kata-containers/runtime/virtcontainers/device/manager" "github.com/kata-containers/runtime/virtcontainers/device/manager"
"github.com/kata-containers/runtime/virtcontainers/store"
) )
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/major.h // https://github.com/torvalds/linux/blob/master/include/uapi/linux/major.h
@ -335,6 +336,8 @@ type Container struct {
systemMountsInfo SystemMountsInfo systemMountsInfo SystemMountsInfo
ctx context.Context ctx context.Context
store *store.VCStore
} }
// ID returns the container identifier string. // ID returns the container identifier string.
@ -426,10 +429,18 @@ func (c *Container) setContainerState(state types.StateString) error {
// update in-memory state // update in-memory state
c.state.State = state c.state.State = state
if useOldStore(c.sandbox.ctx) {
// experimental runtime use "persist.json" which doesn't need "state.json" anymore
// update on-disk state
if err := c.store.Store(store.State, c.state); err != nil {
return err
}
} else {
// flush data to storage // flush data to storage
if err := c.sandbox.Save(); err != nil { if err := c.sandbox.Save(); err != nil {
return err return err
} }
}
return nil return nil
} }
@ -678,6 +689,22 @@ func newContainer(sandbox *Sandbox, contConfig *ContainerConfig) (*Container, er
ctx: sandbox.ctx, ctx: sandbox.ctx,
} }
if useOldStore(sandbox.ctx) {
ctrStore, err := store.NewVCContainerStore(sandbox.ctx, c.sandboxID, c.id)
if err != nil {
return nil, err
}
c.store = ctrStore
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
}
} else {
// experimental runtime use "persist.json" instead of legacy "state.json" as storage // experimental runtime use "persist.json" instead of legacy "state.json" as storage
err := c.Restore() err := c.Restore()
if err == nil { if err == nil {
@ -689,20 +716,49 @@ func newContainer(sandbox *Sandbox, contConfig *ContainerConfig) (*Container, er
if !os.IsNotExist(err) && err != errContainerPersistNotExist { if !os.IsNotExist(err) && err != errContainerPersistNotExist {
return nil, err return nil, err
} }
}
// Go to next step for first created container // Go to next step for first created container
if err = c.createMounts(); err != nil { if err := c.createMounts(); err != nil {
return nil, err return nil, err
} }
if err = c.createDevices(contConfig); err != nil { if err := c.createDevices(contConfig); err != nil {
return nil, err return nil, err
} }
return c, nil return c, nil
} }
func (c *Container) loadMounts() ([]Mount, error) {
var mounts []Mount
if err := c.store.Load(store.Mounts, &mounts); err != nil {
return []Mount{}, err
}
return mounts, nil
}
func (c *Container) loadDevices() ([]ContainerDevice, error) {
var devices []ContainerDevice
if err := c.store.Load(store.DeviceIDs, &devices); err != nil {
return []ContainerDevice{}, err
}
return devices, nil
}
func (c *Container) createMounts() error { func (c *Container) createMounts() error {
if useOldStore(c.sandbox.ctx) {
mounts, err := c.loadMounts()
if err == nil {
// restore mounts from disk
c.mounts = mounts
return nil
}
}
// Create block devices for newly created container // Create block devices for newly created container
if err := c.createBlockDevices(); err != nil { if err := c.createBlockDevices(); err != nil {
return err return err
@ -712,6 +768,18 @@ func (c *Container) createMounts() error {
} }
func (c *Container) createDevices(contConfig *ContainerConfig) error { 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 useOldStore(c.sandbox.ctx) {
// 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
return nil
}
}
// If devices were not found in storage, create Device implementations // If devices were not found in storage, create Device implementations
// from the configuration. This should happen at create. // from the configuration. This should happen at create.
var storedDevices []ContainerDevice var storedDevices []ContainerDevice

View File

@ -31,6 +31,7 @@ import (
ns "github.com/kata-containers/runtime/virtcontainers/pkg/nsenter" ns "github.com/kata-containers/runtime/virtcontainers/pkg/nsenter"
vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types"
"github.com/kata-containers/runtime/virtcontainers/pkg/uuid" "github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
@ -317,6 +318,12 @@ func (k *kataAgent) init(ctx context.Context, sandbox *Sandbox, config interface
k.proxyBuiltIn = isProxyBuiltIn(sandbox.config.ProxyType) k.proxyBuiltIn = isProxyBuiltIn(sandbox.config.ProxyType)
// Fetch agent runtime info.
if useOldStore(sandbox.ctx) {
if err := sandbox.store.Load(store.Agent, &k.state); err != nil {
k.Logger().Debug("Could not retrieve anything from storage")
}
}
return disableVMShutdown, nil return disableVMShutdown, nil
} }

View File

@ -6,12 +6,14 @@
package virtcontainers package virtcontainers
import ( import (
"context"
"errors" "errors"
"github.com/kata-containers/runtime/virtcontainers/device/api" "github.com/kata-containers/runtime/virtcontainers/device/api"
exp "github.com/kata-containers/runtime/virtcontainers/experimental" exp "github.com/kata-containers/runtime/virtcontainers/experimental"
"github.com/kata-containers/runtime/virtcontainers/persist" "github.com/kata-containers/runtime/virtcontainers/persist"
persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api" persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
) )
@ -559,3 +561,25 @@ func loadSandboxConfig(id string) (*SandboxConfig, error) {
} }
return sconfig, nil return sconfig, nil
} }
var oldstoreKey = struct{}{}
func loadSandboxConfigFromOldStore(ctx context.Context, sid string) (*SandboxConfig, context.Context, error) {
var config SandboxConfig
// We're bootstrapping
vcStore, err := store.NewVCSandboxStore(ctx, sid)
if err != nil {
return nil, ctx, err
}
if err := vcStore.Load(store.Configuration, &config); err != nil {
return nil, ctx, err
}
return &config, context.WithValue(ctx, oldstoreKey, true), nil
}
func useOldStore(ctx context.Context) bool {
v := ctx.Value(oldstoreKey)
return v != nil
}

View File

@ -37,6 +37,7 @@ import (
"github.com/kata-containers/runtime/virtcontainers/pkg/annotations" "github.com/kata-containers/runtime/virtcontainers/pkg/annotations"
"github.com/kata-containers/runtime/virtcontainers/pkg/compatoci" "github.com/kata-containers/runtime/virtcontainers/pkg/compatoci"
vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types" vcTypes "github.com/kata-containers/runtime/virtcontainers/pkg/types"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/types" "github.com/kata-containers/runtime/virtcontainers/types"
"github.com/kata-containers/runtime/virtcontainers/utils" "github.com/kata-containers/runtime/virtcontainers/utils"
) )
@ -177,6 +178,8 @@ type Sandbox struct {
factory Factory factory Factory
hypervisor hypervisor hypervisor hypervisor
agent agent agent agent
store *store.VCStore
// store is used to replace VCStore step by step
newStore persistapi.PersistDriver newStore persistapi.PersistDriver
network Network network Network
@ -544,6 +547,36 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor
} }
}() }()
if useOldStore(ctx) {
vcStore, err := store.NewVCSandboxStore(ctx, s.id)
if err != nil {
return nil, err
}
s.store = vcStore
// Fetch sandbox network to be able to access it from the sandbox structure.
var networkNS NetworkNamespace
if err = s.store.Load(store.Network, &networkNS); err == nil {
s.networkNS = networkNS
}
devices, err := s.store.LoadDevices()
if err != nil {
s.Logger().WithError(err).WithField("sandboxid", s.id).Warning("load sandbox devices failed")
}
s.devManager = deviceManager.NewDeviceManager(sandboxConfig.HypervisorConfig.BlockDeviceDriver, devices)
// Load sandbox state. The hypervisor.createSandbox call, may need to access statei.
state, err := s.store.LoadState()
if err == nil {
s.state = state
}
if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.stateful); err != nil {
return nil, err
}
} else {
s.devManager = deviceManager.NewDeviceManager(sandboxConfig.HypervisorConfig.BlockDeviceDriver, nil) s.devManager = deviceManager.NewDeviceManager(sandboxConfig.HypervisorConfig.BlockDeviceDriver, nil)
// Ignore the error. Restore can fail for a new sandbox // Ignore the error. Restore can fail for a new sandbox
@ -555,6 +588,7 @@ func newSandbox(ctx context.Context, sandboxConfig SandboxConfig, factory Factor
if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.stateful); err != nil { if err = s.hypervisor.createSandbox(ctx, s.id, s.networkNS, &sandboxConfig.HypervisorConfig, s.stateful); err != nil {
return nil, err return nil, err
} }
}
agentConfig, err := newAgentConfig(sandboxConfig.AgentType, sandboxConfig.AgentConfig) agentConfig, err := newAgentConfig(sandboxConfig.AgentType, sandboxConfig.AgentConfig)
if err != nil { if err != nil {
@ -612,12 +646,22 @@ func fetchSandbox(ctx context.Context, sandboxID string) (sandbox *Sandbox, err
var config SandboxConfig var config SandboxConfig
c, err := loadSandboxConfig(sandboxID) // Try to load sandbox config from old store at first.
c, ctx, err := loadSandboxConfigFromOldStore(ctx, sandboxID)
if err != nil { if err != nil {
virtLog.Warningf("failed to get sandbox config from old store: %v", err)
// If we failed to load sandbox config from old store, try again with new store.
c, err = loadSandboxConfig(sandboxID)
if err != nil {
virtLog.Warningf("failed to get sandbox config from new store: %v", err)
return nil, err return nil, err
} }
}
config = *c config = *c
if useOldStore(ctx) {
virtLog.Infof("Warning: old store has been deprecated.")
}
// fetchSandbox is not suppose to create new sandbox VM. // fetchSandbox is not suppose to create new sandbox VM.
sandbox, err = createSandbox(ctx, config, nil) sandbox, err = createSandbox(ctx, config, nil)
if err != nil { if err != nil {
@ -1478,6 +1522,10 @@ func (s *Sandbox) setSandboxState(state types.StateString) error {
// update in-memory state // update in-memory state
s.state.State = state s.state.State = state
if useOldStore(s.ctx) {
return s.store.Store(store.State, s.state)
}
return nil return nil
} }

View File

@ -16,6 +16,7 @@ import (
"testing" "testing"
"github.com/kata-containers/runtime/virtcontainers/persist/fs" "github.com/kata-containers/runtime/virtcontainers/persist/fs"
"github.com/kata-containers/runtime/virtcontainers/store"
"github.com/kata-containers/runtime/virtcontainers/utils" "github.com/kata-containers/runtime/virtcontainers/utils"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -60,10 +61,14 @@ func cleanUp() {
os.RemoveAll(testDir) os.RemoveAll(testDir)
os.MkdirAll(testDir, DirMode) os.MkdirAll(testDir, DirMode)
store.DeleteAll()
store.VCStorePrefix = ""
setup() setup()
} }
func setup() { func setup() {
store.VCStorePrefix = testDir
os.Mkdir(filepath.Join(testDir, testBundle), DirMode) os.Mkdir(filepath.Join(testDir, testBundle), DirMode)
for _, filename := range []string{testQemuKernelPath, testQemuInitrdPath, testQemuImagePath, testQemuPath} { for _, filename := range []string{testQemuKernelPath, testQemuInitrdPath, testQemuImagePath, testQemuPath} {