mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-30 09:13:29 +00:00
vc: Revert "vc: change container rootfs to be a mount"
This reverts commit 196661bc0d
.
Reverting because cri-o with devicemapper started
to fail after this commit was merged.
Fixes: #1574.
Signed-off-by: Salvador Fuentes <salvador.fuentes@intel.com>
This commit is contained in:
parent
77309f4982
commit
bc9b9e2af6
@ -128,7 +128,7 @@ func create(ctx context.Context, containerID, bundlePath, console, pidFilePath s
|
|||||||
disableOutput := noNeedForOutput(detach, ociSpec.Process.Terminal)
|
disableOutput := noNeedForOutput(detach, ociSpec.Process.Terminal)
|
||||||
|
|
||||||
//rootfs has been mounted by containerd shim
|
//rootfs has been mounted by containerd shim
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
var process vc.Process
|
var process vc.Process
|
||||||
switch containerType {
|
switch containerType {
|
||||||
|
@ -10,13 +10,12 @@ package containerdshim
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
taskAPI "github.com/containerd/containerd/runtime/v2/task"
|
taskAPI "github.com/containerd/containerd/runtime/v2/task"
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest, netns string) (*container, error) {
|
func create(ctx context.Context, s *service, r *taskAPI.CreateTaskRequest, netns string) (*container, error) {
|
||||||
rootFs := vc.Mount{Mounted: s.mount}
|
rootFs := vc.RootFs{Mounted: s.mount}
|
||||||
if len(r.Rootfs) == 1 {
|
if len(r.Rootfs) == 1 {
|
||||||
m := r.Rootfs[0]
|
m := r.Rootfs[0]
|
||||||
rootFs.Source = m.Source
|
rootFs.Source = m.Source
|
||||||
|
@ -172,7 +172,7 @@ func SetEphemeralStorageType(ociSpec oci.CompatOCISpec) oci.CompatOCISpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateSandbox create a sandbox container
|
// CreateSandbox create a sandbox container
|
||||||
func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec oci.CompatOCISpec, runtimeConfig oci.RuntimeConfig, rootFs vc.Mount,
|
func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec oci.CompatOCISpec, runtimeConfig oci.RuntimeConfig, rootFs vc.RootFs,
|
||||||
containerID, bundlePath, console string, disableOutput, systemdCgroup, builtIn bool) (vc.VCSandbox, vc.Process, error) {
|
containerID, bundlePath, console string, disableOutput, systemdCgroup, builtIn bool) (vc.VCSandbox, vc.Process, error) {
|
||||||
span, ctx := Trace(ctx, "createSandbox")
|
span, ctx := Trace(ctx, "createSandbox")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
@ -237,7 +237,7 @@ func CreateSandbox(ctx context.Context, vci vc.VC, ociSpec oci.CompatOCISpec, ru
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateContainer create a container
|
// CreateContainer create a container
|
||||||
func CreateContainer(ctx context.Context, vci vc.VC, sandbox vc.VCSandbox, ociSpec oci.CompatOCISpec, rootFs vc.Mount, containerID, bundlePath, console string, disableOutput, builtIn bool) (vc.Process, error) {
|
func CreateContainer(ctx context.Context, vci vc.VC, sandbox vc.VCSandbox, ociSpec oci.CompatOCISpec, rootFs vc.RootFs, containerID, bundlePath, console string, disableOutput, builtIn bool) (vc.Process, error) {
|
||||||
var c vc.VCContainer
|
var c vc.VCContainer
|
||||||
|
|
||||||
span, ctx := Trace(ctx, "createContainer")
|
span, ctx := Trace(ctx, "createContainer")
|
||||||
|
@ -306,7 +306,7 @@ func TestCreateSandboxConfigFail(t *testing.T) {
|
|||||||
Quota: "a,
|
Quota: "a,
|
||||||
}
|
}
|
||||||
|
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
_, _, err = CreateSandbox(context.Background(), testingImpl, spec, runtimeConfig, rootFs, testContainerID, bundlePath, testConsole, true, true, false)
|
_, _, err = CreateSandbox(context.Background(), testingImpl, spec, runtimeConfig, rootFs, testContainerID, bundlePath, testConsole, true, true, false)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
@ -342,7 +342,7 @@ func TestCreateSandboxFail(t *testing.T) {
|
|||||||
spec, err := readOCIConfigFile(ociConfigFile)
|
spec, err := readOCIConfigFile(ociConfigFile)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
_, _, err = CreateSandbox(context.Background(), testingImpl, spec, runtimeConfig, rootFs, testContainerID, bundlePath, testConsole, true, true, false)
|
_, _, err = CreateSandbox(context.Background(), testingImpl, spec, runtimeConfig, rootFs, testContainerID, bundlePath, testConsole, true, true, false)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
@ -381,7 +381,7 @@ func TestCreateContainerContainerConfigFail(t *testing.T) {
|
|||||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
for _, disableOutput := range []bool{true, false} {
|
for _, disableOutput := range []bool{true, false} {
|
||||||
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
||||||
@ -424,7 +424,7 @@ func TestCreateContainerFail(t *testing.T) {
|
|||||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
for _, disableOutput := range []bool{true, false} {
|
for _, disableOutput := range []bool{true, false} {
|
||||||
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
||||||
@ -474,7 +474,7 @@ func TestCreateContainer(t *testing.T) {
|
|||||||
err = writeOCIConfigFile(spec, ociConfigFile)
|
err = writeOCIConfigFile(spec, ociConfigFile)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
|
||||||
rootFs := vc.Mount{Mounted: true}
|
rootFs := vc.RootFs{Mounted: true}
|
||||||
|
|
||||||
for _, disableOutput := range []bool{true, false} {
|
for _, disableOutput := range []bool{true, false} {
|
||||||
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
_, err = CreateContainer(context.Background(), testingImpl, nil, spec, rootFs, testContainerID, bundlePath, testConsole, disableOutput, false)
|
||||||
|
@ -601,7 +601,7 @@ func statusContainer(sandbox *Sandbox, containerID string) (ContainerStatus, err
|
|||||||
State: container.state,
|
State: container.state,
|
||||||
PID: container.process.Pid,
|
PID: container.process.Pid,
|
||||||
StartTime: container.process.StartTime,
|
StartTime: container.process.StartTime,
|
||||||
RootFs: container.config.RootFs.Destination,
|
RootFs: container.config.RootFs.Target,
|
||||||
Annotations: container.config.Annotations,
|
Annotations: container.config.Annotations,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func newTestSandboxConfigNoop() SandboxConfig {
|
|||||||
// Define the container command and bundle.
|
// Define the container command and bundle.
|
||||||
container := ContainerConfig{
|
container := ContainerConfig{
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
RootFs: Mount{Destination: filepath.Join(testDir, testBundle), Mounted: true},
|
RootFs: RootFs{Target: filepath.Join(testDir, testBundle), Mounted: true},
|
||||||
Cmd: newBasicTestCmd(),
|
Cmd: newBasicTestCmd(),
|
||||||
Annotations: containerAnnotations,
|
Annotations: containerAnnotations,
|
||||||
}
|
}
|
||||||
@ -751,7 +751,7 @@ func newTestContainerConfigNoop(contID string) ContainerConfig {
|
|||||||
// Define the container command and bundle.
|
// Define the container command and bundle.
|
||||||
container := ContainerConfig{
|
container := ContainerConfig{
|
||||||
ID: contID,
|
ID: contID,
|
||||||
RootFs: Mount{Destination: filepath.Join(testDir, testBundle), Mounted: true},
|
RootFs: RootFs{Target: filepath.Join(testDir, testBundle), Mounted: true},
|
||||||
Cmd: newBasicTestCmd(),
|
Cmd: newBasicTestCmd(),
|
||||||
Annotations: containerAnnotations,
|
Annotations: containerAnnotations,
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ type ContainerConfig struct {
|
|||||||
ID string
|
ID string
|
||||||
|
|
||||||
// RootFs is the container workload image on the host.
|
// RootFs is the container workload image on the host.
|
||||||
RootFs Mount
|
RootFs RootFs
|
||||||
|
|
||||||
// ReadOnlyRootfs indicates if the rootfs should be mounted readonly
|
// ReadOnlyRootfs indicates if the rootfs should be mounted readonly
|
||||||
ReadonlyRootfs bool
|
ReadonlyRootfs bool
|
||||||
@ -272,13 +272,27 @@ type ContainerDevice struct {
|
|||||||
GID uint32
|
GID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootFs describes the container's rootfs.
|
||||||
|
type RootFs struct {
|
||||||
|
// Source specifies the BlockDevice path
|
||||||
|
Source string
|
||||||
|
// Target specify where the rootfs is mounted if it has been mounted
|
||||||
|
Target string
|
||||||
|
// Type specifies the type of filesystem to mount.
|
||||||
|
Type string
|
||||||
|
// Options specifies zero or more fstab style mount options.
|
||||||
|
Options []string
|
||||||
|
// Mounted specifies whether the rootfs has be mounted or not
|
||||||
|
Mounted bool
|
||||||
|
}
|
||||||
|
|
||||||
// Container is composed of a set of containers and a runtime environment.
|
// Container is composed of a set of containers and a runtime environment.
|
||||||
// A Container can be created, deleted, started, stopped, listed, entered, paused and restored.
|
// A Container can be created, deleted, started, stopped, listed, entered, paused and restored.
|
||||||
type Container struct {
|
type Container struct {
|
||||||
id string
|
id string
|
||||||
sandboxID string
|
sandboxID string
|
||||||
|
|
||||||
rootFs Mount
|
rootFs RootFs
|
||||||
|
|
||||||
config *ContainerConfig
|
config *ContainerConfig
|
||||||
|
|
||||||
@ -357,6 +371,19 @@ func (c *Container) SetPid(pid int) error {
|
|||||||
return c.storeProcess()
|
return c.storeProcess()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) setStateFstype(fstype string) error {
|
||||||
|
c.state.Fstype = fstype
|
||||||
|
|
||||||
|
if !c.sandbox.supportNewStore() {
|
||||||
|
// experimental runtime use "persist.json" which doesn't need "state.json" anymore
|
||||||
|
if err := c.storeState(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetAnnotations returns container's annotations
|
// GetAnnotations returns container's annotations
|
||||||
func (c *Container) GetAnnotations() map[string]string {
|
func (c *Container) GetAnnotations() map[string]string {
|
||||||
return c.config.Annotations
|
return c.config.Annotations
|
||||||
@ -384,6 +411,10 @@ func (c *Container) storeDevices() error {
|
|||||||
return c.store.Store(store.DeviceIDs, c.devices)
|
return c.store.Store(store.DeviceIDs, c.devices)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Container) storeState() error {
|
||||||
|
return c.store.Store(store.State, c.state)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Container) loadMounts() ([]Mount, error) {
|
func (c *Container) loadMounts() ([]Mount, error) {
|
||||||
var mounts []Mount
|
var mounts []Mount
|
||||||
if err := c.store.Load(store.Mounts, &mounts); err != nil {
|
if err := c.store.Load(store.Mounts, &mounts); err != nil {
|
||||||
@ -1152,14 +1183,6 @@ func (c *Container) resume() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) hotplugDrive() error {
|
func (c *Container) hotplugDrive() error {
|
||||||
if err := c.hotplugRootfsDrive(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Container) hotplugRootfsDrive() error {
|
|
||||||
var dev device
|
var dev device
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@ -1169,7 +1192,7 @@ func (c *Container) hotplugRootfsDrive() error {
|
|||||||
// there is no "rootfs" dir on block device backed rootfs
|
// there is no "rootfs" dir on block device backed rootfs
|
||||||
c.rootfsSuffix = ""
|
c.rootfsSuffix = ""
|
||||||
} else {
|
} else {
|
||||||
dev, err = getDeviceForPath(c.rootFs.Destination)
|
dev, err = getDeviceForPath(c.rootFs.Target)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == errMountPointNotFound {
|
if err == errMountPointNotFound {
|
||||||
@ -1198,7 +1221,7 @@ func (c *Container) hotplugRootfsDrive() error {
|
|||||||
devicePath := c.rootFs.Source
|
devicePath := c.rootFs.Source
|
||||||
fsType := c.rootFs.Type
|
fsType := c.rootFs.Type
|
||||||
if c.rootFs.Mounted {
|
if c.rootFs.Mounted {
|
||||||
if dev.mountPoint == c.rootFs.Destination {
|
if dev.mountPoint == c.rootFs.Target {
|
||||||
c.rootfsSuffix = ""
|
c.rootfsSuffix = ""
|
||||||
}
|
}
|
||||||
// If device mapper device, then fetch the full path of the device
|
// If device mapper device, then fetch the full path of the device
|
||||||
@ -1206,7 +1229,6 @@ func (c *Container) hotplugRootfsDrive() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.rootFs.Type = fsType
|
|
||||||
}
|
}
|
||||||
|
|
||||||
devicePath, err = filepath.EvalSymlinks(devicePath)
|
devicePath, err = filepath.EvalSymlinks(devicePath)
|
||||||
@ -1219,7 +1241,11 @@ func (c *Container) hotplugRootfsDrive() error {
|
|||||||
"fs-type": fsType,
|
"fs-type": fsType,
|
||||||
}).Info("Block device detected")
|
}).Info("Block device detected")
|
||||||
|
|
||||||
return c.plugDevice(devicePath)
|
if err = c.plugDevice(devicePath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.setStateFstype(fsType)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) plugDevice(devicePath string) error {
|
func (c *Container) plugDevice(devicePath string) error {
|
||||||
@ -1240,7 +1266,7 @@ func (c *Container) plugDevice(devicePath string) error {
|
|||||||
return fmt.Errorf("device manager failed to create rootfs device for %q: %v", devicePath, err)
|
return fmt.Errorf("device manager failed to create rootfs device for %q: %v", devicePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.rootFs.BlockDeviceID = b.DeviceID()
|
c.state.BlockDeviceID = b.DeviceID()
|
||||||
|
|
||||||
// attach rootfs device
|
// attach rootfs device
|
||||||
if err := c.sandbox.devManager.AttachDevice(b.DeviceID(), c.sandbox); err != nil {
|
if err := c.sandbox.devManager.AttachDevice(b.DeviceID(), c.sandbox); err != nil {
|
||||||
@ -1254,11 +1280,16 @@ func (c *Container) plugDevice(devicePath string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isDriveUsed checks if a drive has been used for container rootfs
|
||||||
|
func (c *Container) isDriveUsed() bool {
|
||||||
|
return !(c.state.Fstype == "")
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Container) removeDrive() (err error) {
|
func (c *Container) removeDrive() (err error) {
|
||||||
if c.rootFs.BlockDeviceID != "" {
|
if c.isDriveUsed() {
|
||||||
c.Logger().Info("unplugging block device")
|
c.Logger().Info("unplugging block device")
|
||||||
|
|
||||||
devID := c.rootFs.BlockDeviceID
|
devID := c.state.BlockDeviceID
|
||||||
err := c.sandbox.devManager.DetachDevice(devID, c.sandbox)
|
err := c.sandbox.devManager.DetachDevice(devID, c.sandbox)
|
||||||
if err != nil && err != manager.ErrDeviceNotAttached {
|
if err != nil && err != manager.ErrDeviceNotAttached {
|
||||||
return err
|
return err
|
||||||
|
@ -106,7 +106,7 @@ func TestContainerRemoveDrive(t *testing.T) {
|
|||||||
id: "testContainer",
|
id: "testContainer",
|
||||||
}
|
}
|
||||||
|
|
||||||
container.rootFs.Type = ""
|
container.state.Fstype = ""
|
||||||
err = container.removeDrive()
|
err = container.removeDrive()
|
||||||
|
|
||||||
// hotplugRemoveDevice for hypervisor should not be called.
|
// hotplugRemoveDevice for hypervisor should not be called.
|
||||||
@ -131,8 +131,8 @@ func TestContainerRemoveDrive(t *testing.T) {
|
|||||||
err = sandbox.storeSandboxDevices()
|
err = sandbox.storeSandboxDevices()
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
container.rootFs.Type = "xfs"
|
container.state.Fstype = "xfs"
|
||||||
container.rootFs.BlockDeviceID = device.DeviceID()
|
container.state.BlockDeviceID = device.DeviceID()
|
||||||
err = container.removeDrive()
|
err = container.removeDrive()
|
||||||
assert.Nil(t, err, "remove drive should succeed")
|
assert.Nil(t, err, "remove drive should succeed")
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ func TestContainerAddDriveDir(t *testing.T) {
|
|||||||
container := Container{
|
container := Container{
|
||||||
sandbox: sandbox,
|
sandbox: sandbox,
|
||||||
id: contID,
|
id: contID,
|
||||||
rootFs: Mount{Destination: fakeRootfs, Mounted: true},
|
rootFs: RootFs{Target: fakeRootfs, Mounted: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
containerStore, err := store.NewVCContainerStore(sandbox.ctx, sandbox.id, container.id)
|
containerStore, err := store.NewVCContainerStore(sandbox.ctx, sandbox.id, container.id)
|
||||||
@ -272,14 +272,14 @@ func TestContainerAddDriveDir(t *testing.T) {
|
|||||||
checkStorageDriver = savedFunc
|
checkStorageDriver = savedFunc
|
||||||
}()
|
}()
|
||||||
|
|
||||||
container.rootFs.Type = "xfs"
|
container.state.Fstype = ""
|
||||||
|
|
||||||
err = container.hotplugDrive()
|
err = container.hotplugDrive()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error with hotplugDrive :%v", err)
|
t.Fatalf("Error with hotplugDrive :%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if container.rootFs.Type == "" {
|
if container.state.Fstype == "" {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,7 +315,7 @@ func TestContainerRootfsPath(t *testing.T) {
|
|||||||
container := Container{
|
container := Container{
|
||||||
id: "rootfstestcontainerid",
|
id: "rootfstestcontainerid",
|
||||||
sandbox: sandbox,
|
sandbox: sandbox,
|
||||||
rootFs: Mount{Destination: fakeRootfs, Mounted: true},
|
rootFs: RootFs{Target: fakeRootfs, Mounted: true},
|
||||||
rootfsSuffix: "rootfs",
|
rootfsSuffix: "rootfs",
|
||||||
}
|
}
|
||||||
cvcstore, err := store.NewVCContainerStore(context.Background(),
|
cvcstore, err := store.NewVCContainerStore(context.Background(),
|
||||||
@ -328,7 +328,7 @@ func TestContainerRootfsPath(t *testing.T) {
|
|||||||
assert.Empty(t, container.rootfsSuffix)
|
assert.Empty(t, container.rootfsSuffix)
|
||||||
|
|
||||||
// Reset the value to test the other case
|
// Reset the value to test the other case
|
||||||
container.rootFs = Mount{Destination: fakeRootfs + "/rootfs", Mounted: true}
|
container.rootFs = RootFs{Target: fakeRootfs + "/rootfs", Mounted: true}
|
||||||
container.rootfsSuffix = "rootfs"
|
container.rootfsSuffix = "rootfs"
|
||||||
|
|
||||||
container.hotplugDrive()
|
container.hotplugDrive()
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/kata-containers/runtime/virtcontainers/types"
|
"github.com/kata-containers/runtime/virtcontainers/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
var containerRootfs = vc.Mount{Destination: "/var/lib/container/bundle/", Mounted: true}
|
var containerRootfs = vc.RootFs{Target: "/var/lib/container/bundle/", Mounted: true}
|
||||||
|
|
||||||
// This example creates and starts a single container sandbox,
|
// This example creates and starts a single container sandbox,
|
||||||
// using qemu as the hypervisor and kata as the VM agent.
|
// using qemu as the hypervisor and kata as the VM agent.
|
||||||
|
@ -944,7 +944,7 @@ func (k *kataAgent) rollbackFailingContainerCreation(c *Container) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPathParent string) (*grpc.Storage, error) {
|
func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPathParent string) (*grpc.Storage, error) {
|
||||||
if c.rootFs.BlockDeviceID != "" {
|
if c.state.Fstype != "" && c.state.BlockDeviceID != "" {
|
||||||
// The rootfs storage volume represents the container rootfs
|
// The rootfs storage volume represents the container rootfs
|
||||||
// mount point inside the guest.
|
// mount point inside the guest.
|
||||||
// It can be a block based device (when using block based container
|
// It can be a block based device (when using block based container
|
||||||
@ -953,10 +953,10 @@ func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPat
|
|||||||
rootfs := &grpc.Storage{}
|
rootfs := &grpc.Storage{}
|
||||||
|
|
||||||
// This is a block based device rootfs.
|
// This is a block based device rootfs.
|
||||||
device := sandbox.devManager.GetDeviceByID(c.rootFs.BlockDeviceID)
|
device := sandbox.devManager.GetDeviceByID(c.state.BlockDeviceID)
|
||||||
if device == nil {
|
if device == nil {
|
||||||
k.Logger().WithField("device", c.rootFs.BlockDeviceID).Error("failed to find device by id")
|
k.Logger().WithField("device", c.state.BlockDeviceID).Error("failed to find device by id")
|
||||||
return nil, fmt.Errorf("failed to find device by id %q", c.rootFs.BlockDeviceID)
|
return nil, fmt.Errorf("failed to find device by id %q", c.state.BlockDeviceID)
|
||||||
}
|
}
|
||||||
|
|
||||||
blockDrive, ok := device.GetDeviceInfo().(*config.BlockDrive)
|
blockDrive, ok := device.GetDeviceInfo().(*config.BlockDrive)
|
||||||
@ -976,11 +976,10 @@ func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPat
|
|||||||
rootfs.Source = blockDrive.SCSIAddr
|
rootfs.Source = blockDrive.SCSIAddr
|
||||||
}
|
}
|
||||||
rootfs.MountPoint = rootPathParent
|
rootfs.MountPoint = rootPathParent
|
||||||
rootfs.Fstype = c.rootFs.Type
|
rootfs.Fstype = c.state.Fstype
|
||||||
rootfs.Options = c.rootFs.Options
|
|
||||||
|
|
||||||
if rootfs.Fstype == "xfs" {
|
if c.state.Fstype == "xfs" {
|
||||||
rootfs.Options = append(rootfs.Options, "nouuid")
|
rootfs.Options = []string{"nouuid"}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rootfs, nil
|
return rootfs, nil
|
||||||
@ -994,7 +993,7 @@ func (k *kataAgent) buildContainerRootfs(sandbox *Sandbox, c *Container, rootPat
|
|||||||
// (kataGuestSharedDir) is already mounted in the
|
// (kataGuestSharedDir) is already mounted in the
|
||||||
// guest. We only need to mount the rootfs from
|
// guest. We only need to mount the rootfs from
|
||||||
// the host and it will show up in the guest.
|
// the host and it will show up in the guest.
|
||||||
if err := bindMountContainerRootfs(k.ctx, kataHostSharedDir, sandbox.id, c.id, c.rootFs.Destination, false); err != nil {
|
if err := bindMountContainerRootfs(k.ctx, kataHostSharedDir, sandbox.id, c.id, c.rootFs.Target, false); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +735,9 @@ func TestAgentCreateContainer(t *testing.T) {
|
|||||||
id: "barfoo",
|
id: "barfoo",
|
||||||
sandboxID: "foobar",
|
sandboxID: "foobar",
|
||||||
sandbox: sandbox,
|
sandbox: sandbox,
|
||||||
state: types.ContainerState{},
|
state: types.ContainerState{
|
||||||
|
Fstype: "xfs",
|
||||||
|
},
|
||||||
config: &ContainerConfig{
|
config: &ContainerConfig{
|
||||||
Annotations: map[string]string{},
|
Annotations: map[string]string{},
|
||||||
},
|
},
|
||||||
|
@ -304,10 +304,7 @@ func bindMountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID, cR
|
|||||||
|
|
||||||
// Mount describes a container mount.
|
// Mount describes a container mount.
|
||||||
type Mount struct {
|
type Mount struct {
|
||||||
// Mount source
|
Source string
|
||||||
Source string
|
|
||||||
|
|
||||||
// Mount destination in the guest
|
|
||||||
Destination string
|
Destination string
|
||||||
|
|
||||||
// Type specifies the type of filesystem to mount.
|
// Type specifies the type of filesystem to mount.
|
||||||
@ -319,16 +316,13 @@ type Mount struct {
|
|||||||
// HostPath used to store host side bind mount path
|
// HostPath used to store host side bind mount path
|
||||||
HostPath string
|
HostPath string
|
||||||
|
|
||||||
|
// ReadOnly specifies if the mount should be read only or not
|
||||||
|
ReadOnly bool
|
||||||
|
|
||||||
// BlockDeviceID represents block device that is attached to the
|
// BlockDeviceID represents block device that is attached to the
|
||||||
// VM in case this mount is a block device file or a directory
|
// VM in case this mount is a block device file or a directory
|
||||||
// backed by a block device.
|
// backed by a block device.
|
||||||
BlockDeviceID string
|
BlockDeviceID string
|
||||||
|
|
||||||
// ReadOnly specifies if the mount should be read only or not
|
|
||||||
ReadOnly bool
|
|
||||||
|
|
||||||
// Mounted specifies if the target has been mounted on the host
|
|
||||||
Mounted bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindUnmountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID string) error {
|
func bindUnmountContainerRootfs(ctx context.Context, sharedDir, sandboxID, cID string) error {
|
||||||
@ -347,7 +341,7 @@ func bindUnmountAllRootfs(ctx context.Context, sharedDir string, sandbox *Sandbo
|
|||||||
|
|
||||||
for _, c := range sandbox.containers {
|
for _, c := range sandbox.containers {
|
||||||
c.unmountHostMounts()
|
c.unmountHostMounts()
|
||||||
if c.rootFs.Type == "" {
|
if c.state.Fstype == "" {
|
||||||
// Need to check for error returned by this call.
|
// Need to check for error returned by this call.
|
||||||
// See: https://github.com/containers/virtcontainers/issues/295
|
// See: https://github.com/containers/virtcontainers/issues/295
|
||||||
bindUnmountContainerRootfs(c.ctx, sharedDir, sandbox.id, c.id)
|
bindUnmountContainerRootfs(c.ctx, sharedDir, sandbox.id, c.id)
|
||||||
|
@ -31,9 +31,9 @@ func (s *Sandbox) dumpState(ss *persistapi.SandboxState, cs map[string]persistap
|
|||||||
state = v
|
state = v
|
||||||
}
|
}
|
||||||
state.State = string(cont.state.State)
|
state.State = string(cont.state.State)
|
||||||
state.Rootfs = persistapi.Mount{
|
state.Rootfs = persistapi.RootfsState{
|
||||||
BlockDeviceID: cont.rootFs.BlockDeviceID,
|
BlockDeviceID: cont.state.BlockDeviceID,
|
||||||
Type: cont.rootFs.Type,
|
FsType: cont.state.Fstype,
|
||||||
}
|
}
|
||||||
state.CgroupPath = cont.state.CgroupPath
|
state.CgroupPath = cont.state.CgroupPath
|
||||||
cs[id] = state
|
cs[id] = state
|
||||||
@ -152,8 +152,10 @@ func (c *Container) Restore() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.state = types.ContainerState{
|
c.state = types.ContainerState{
|
||||||
State: types.StateString(cs[c.id].State),
|
State: types.StateString(cs[c.id].State),
|
||||||
CgroupPath: cs[c.id].CgroupPath,
|
BlockDeviceID: cs[c.id].Rootfs.BlockDeviceID,
|
||||||
|
Fstype: cs[c.id].Rootfs.FsType,
|
||||||
|
CgroupPath: cs[c.id].CgroupPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -47,16 +47,23 @@ type Mount struct {
|
|||||||
// HostPath used to store host side bind mount path
|
// HostPath used to store host side bind mount path
|
||||||
HostPath string
|
HostPath string
|
||||||
|
|
||||||
|
// ReadOnly specifies if the mount should be read only or not
|
||||||
|
ReadOnly bool
|
||||||
|
|
||||||
// BlockDeviceID represents block device that is attached to the
|
// BlockDeviceID represents block device that is attached to the
|
||||||
// VM in case this mount is a block device file or a directory
|
// VM in case this mount is a block device file or a directory
|
||||||
// backed by a block device.
|
// backed by a block device.
|
||||||
BlockDeviceID string
|
BlockDeviceID string
|
||||||
|
}
|
||||||
|
|
||||||
// ReadOnly specifies if the mount should be read only or not
|
// RootfsState saves state of container rootfs
|
||||||
ReadOnly bool
|
type RootfsState struct {
|
||||||
|
// BlockDeviceID represents container rootfs block device ID
|
||||||
|
// when backed by devicemapper
|
||||||
|
BlockDeviceID string
|
||||||
|
|
||||||
// Mounted specifies if the target has been mounted on the host
|
// RootFStype is file system of the rootfs incase it is block device
|
||||||
Mounted bool
|
FsType string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process gathers data related to a container process.
|
// Process gathers data related to a container process.
|
||||||
@ -83,7 +90,7 @@ type ContainerState struct {
|
|||||||
State string
|
State string
|
||||||
|
|
||||||
// Rootfs contains information of container rootfs
|
// Rootfs contains information of container rootfs
|
||||||
Rootfs Mount
|
Rootfs RootfsState
|
||||||
|
|
||||||
// CgroupPath is the cgroup hierarchy where sandbox's processes
|
// CgroupPath is the cgroup hierarchy where sandbox's processes
|
||||||
// including the hypervisor are placed.
|
// including the hypervisor are placed.
|
||||||
|
@ -183,7 +183,6 @@ func newMount(m spec.Mount) vc.Mount {
|
|||||||
Destination: m.Destination,
|
Destination: m.Destination,
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
Options: m.Options,
|
Options: m.Options,
|
||||||
Mounted: true, // All OCI volumes are mounted on the host ATM.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,12 +524,12 @@ func ContainerConfig(ocispec CompatOCISpec, bundlePath, cid, console string, det
|
|||||||
return vc.ContainerConfig{}, err
|
return vc.ContainerConfig{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rootfs := vc.Mount{Destination: ocispec.Root.Path, Mounted: true}
|
rootfs := vc.RootFs{Target: ocispec.Root.Path, Mounted: true}
|
||||||
if !filepath.IsAbs(rootfs.Destination) {
|
if !filepath.IsAbs(rootfs.Target) {
|
||||||
rootfs.Destination = filepath.Join(bundlePath, ocispec.Root.Path)
|
rootfs.Target = filepath.Join(bundlePath, ocispec.Root.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
ociLog.Debugf("container rootfs: %s", rootfs.Destination)
|
ociLog.Debugf("container rootfs: %s", rootfs.Target)
|
||||||
|
|
||||||
cmd := types.Cmd{
|
cmd := types.Cmd{
|
||||||
Args: ocispec.Process.Args,
|
Args: ocispec.Process.Args,
|
||||||
|
@ -150,7 +150,6 @@ func TestMinimalSandboxConfig(t *testing.T) {
|
|||||||
Type: "proc",
|
Type: "proc",
|
||||||
Options: nil,
|
Options: nil,
|
||||||
HostPath: "",
|
HostPath: "",
|
||||||
Mounted: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Source: "tmpfs",
|
Source: "tmpfs",
|
||||||
@ -158,7 +157,6 @@ func TestMinimalSandboxConfig(t *testing.T) {
|
|||||||
Type: "tmpfs",
|
Type: "tmpfs",
|
||||||
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
|
||||||
HostPath: "",
|
HostPath: "",
|
||||||
Mounted: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Source: "devpts",
|
Source: "devpts",
|
||||||
@ -166,7 +164,6 @@ func TestMinimalSandboxConfig(t *testing.T) {
|
|||||||
Type: "devpts",
|
Type: "devpts",
|
||||||
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
|
Options: []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
|
||||||
HostPath: "",
|
HostPath: "",
|
||||||
Mounted: true,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +200,7 @@ func TestMinimalSandboxConfig(t *testing.T) {
|
|||||||
|
|
||||||
expectedContainerConfig := vc.ContainerConfig{
|
expectedContainerConfig := vc.ContainerConfig{
|
||||||
ID: containerID,
|
ID: containerID,
|
||||||
RootFs: vc.Mount{Destination: path.Join(tempBundlePath, "rootfs"), Mounted: true},
|
RootFs: vc.RootFs{Target: path.Join(tempBundlePath, "rootfs"), Mounted: true},
|
||||||
ReadonlyRootfs: true,
|
ReadonlyRootfs: true,
|
||||||
Cmd: expectedCmd,
|
Cmd: expectedCmd,
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
|
@ -291,7 +291,7 @@ func (s *Sandbox) Status() SandboxStatus {
|
|||||||
for _, c := range s.containers {
|
for _, c := range s.containers {
|
||||||
rootfs := c.config.RootFs.Source
|
rootfs := c.config.RootFs.Source
|
||||||
if c.config.RootFs.Mounted {
|
if c.config.RootFs.Mounted {
|
||||||
rootfs = c.config.RootFs.Destination
|
rootfs = c.config.RootFs.Target
|
||||||
}
|
}
|
||||||
|
|
||||||
contStatusList = append(contStatusList, ContainerStatus{
|
contStatusList = append(contStatusList, ContainerStatus{
|
||||||
@ -1241,7 +1241,7 @@ func (s *Sandbox) StatusContainer(containerID string) (ContainerStatus, error) {
|
|||||||
for id, c := range s.containers {
|
for id, c := range s.containers {
|
||||||
rootfs := c.config.RootFs.Source
|
rootfs := c.config.RootFs.Source
|
||||||
if c.config.RootFs.Mounted {
|
if c.config.RootFs.Mounted {
|
||||||
rootfs = c.config.RootFs.Destination
|
rootfs = c.config.RootFs.Target
|
||||||
}
|
}
|
||||||
if id == containerID {
|
if id == containerID {
|
||||||
return ContainerStatus{
|
return ContainerStatus{
|
||||||
|
@ -7,6 +7,7 @@ package virtcontainers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -749,6 +750,99 @@ func TestSandboxGetContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestContainerStateSetFstype(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
containers := []ContainerConfig{
|
||||||
|
{
|
||||||
|
ID: "100",
|
||||||
|
Annotations: containerAnnotations,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
hConfig := newHypervisorConfig(nil, nil)
|
||||||
|
sandbox, err := testCreateSandbox(t, testSandboxID, MockHypervisor, hConfig, NoopAgentType, NetworkConfig{}, containers, nil)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer cleanUp()
|
||||||
|
|
||||||
|
vcStore, err := store.NewVCSandboxStore(sandbox.ctx, sandbox.id)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
sandbox.store = vcStore
|
||||||
|
|
||||||
|
c := sandbox.GetContainer("100")
|
||||||
|
if c == nil {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
cImpl, ok := c.(*Container)
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
containerStore, err := store.NewVCContainerStore(sandbox.ctx, sandbox.id, c.ID())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
cImpl.store = containerStore
|
||||||
|
|
||||||
|
path := store.ContainerRuntimeRootPath(testSandboxID, c.ID())
|
||||||
|
stateFilePath := filepath.Join(path, store.StateFile)
|
||||||
|
|
||||||
|
f, err := os.Create(stateFilePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
state := types.ContainerState{
|
||||||
|
State: "ready",
|
||||||
|
Fstype: "vfs",
|
||||||
|
}
|
||||||
|
|
||||||
|
cImpl.state = state
|
||||||
|
|
||||||
|
stateData := `{
|
||||||
|
"state":"ready",
|
||||||
|
"fstype":"vfs",
|
||||||
|
}`
|
||||||
|
|
||||||
|
n, err := f.WriteString(stateData)
|
||||||
|
if err != nil || n != len(stateData) {
|
||||||
|
f.Close()
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
|
newFstype := "ext4"
|
||||||
|
if err := cImpl.setStateFstype(newFstype); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cImpl.state.Fstype != newFstype {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
fileData, err := ioutil.ReadFile(stateFilePath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
// experimental features doesn't write state.json
|
||||||
|
if sandbox.supportNewStore() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var res types.ContainerState
|
||||||
|
err = json.Unmarshal([]byte(string(fileData)), &res)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Fstype != newFstype {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.State != state.State {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const vfioPath = "/dev/vfio/"
|
const vfioPath = "/dev/vfio/"
|
||||||
|
|
||||||
func TestSandboxAttachDevicesVFIO(t *testing.T) {
|
func TestSandboxAttachDevicesVFIO(t *testing.T) {
|
||||||
|
@ -9,6 +9,11 @@ package types
|
|||||||
type ContainerState struct {
|
type ContainerState struct {
|
||||||
State StateString `json:"state"`
|
State StateString `json:"state"`
|
||||||
|
|
||||||
|
BlockDeviceID string
|
||||||
|
|
||||||
|
// File system of the rootfs incase it is block device
|
||||||
|
Fstype string `json:"fstype"`
|
||||||
|
|
||||||
// CgroupPath is the cgroup hierarchy where sandbox's processes
|
// CgroupPath is the cgroup hierarchy where sandbox's processes
|
||||||
// including the hypervisor are placed.
|
// including the hypervisor are placed.
|
||||||
CgroupPath string `json:"cgroupPath,omitempty"`
|
CgroupPath string `json:"cgroupPath,omitempty"`
|
||||||
|
Loading…
Reference in New Issue
Block a user