mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add shared mount hints to VFS2
Container restart test is disabled for VFS2 for now. Updates #1487 PiperOrigin-RevId: 320296401
This commit is contained in:
committed by
gVisor bot
parent
4f7af437e2
commit
c4815af947
@@ -62,6 +62,7 @@ func Boot() (*kernel.Kernel, error) {
|
||||
return nil, fmt.Errorf("creating platform: %v", err)
|
||||
}
|
||||
|
||||
kernel.VFS2Enabled = true
|
||||
k := &kernel.Kernel{
|
||||
Platform: plat,
|
||||
}
|
||||
@@ -103,11 +104,6 @@ func Boot() (*kernel.Kernel, error) {
|
||||
return nil, fmt.Errorf("initializing kernel: %v", err)
|
||||
}
|
||||
|
||||
kernel.VFS2Enabled = true
|
||||
|
||||
if err := k.VFS().Init(); err != nil {
|
||||
return nil, fmt.Errorf("VFS init: %v", err)
|
||||
}
|
||||
k.VFS().MustRegisterFilesystemType(tmpfs.Name, &tmpfs.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
|
||||
AllowUserMount: true,
|
||||
AllowUserList: true,
|
||||
|
||||
@@ -221,14 +221,14 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V
|
||||
// Load the executable itself.
|
||||
loaded, ac, file, newArgv, err := loadExecutable(ctx, args)
|
||||
if err != nil {
|
||||
return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("Failed to load %s: %v", args.Filename, err), syserr.FromError(err).ToLinux())
|
||||
return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("failed to load %s: %v", args.Filename, err), syserr.FromError(err).ToLinux())
|
||||
}
|
||||
defer file.DecRef()
|
||||
|
||||
// Load the VDSO.
|
||||
vdsoAddr, err := loadVDSO(ctx, args.MemoryManager, vdso, loaded)
|
||||
if err != nil {
|
||||
return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("Error loading VDSO: %v", err), syserr.FromError(err).ToLinux())
|
||||
return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("error loading VDSO: %v", err), syserr.FromError(err).ToLinux())
|
||||
}
|
||||
|
||||
// Setup the heap. brk starts at the next page after the end of the
|
||||
|
||||
@@ -123,6 +123,9 @@ type VirtualFilesystem struct {
|
||||
|
||||
// Init initializes a new VirtualFilesystem with no mounts or FilesystemTypes.
|
||||
func (vfs *VirtualFilesystem) Init() error {
|
||||
if vfs.mountpoints != nil {
|
||||
panic("VFS already initialized")
|
||||
}
|
||||
vfs.mountpoints = make(map[*Dentry]map[*Mount]struct{})
|
||||
vfs.devices = make(map[devTuple]*registeredDevice)
|
||||
vfs.anonBlockDevMinorNext = 1
|
||||
|
||||
+7
-2
@@ -29,6 +29,7 @@ import (
|
||||
_ "gvisor.dev/gvisor/pkg/sentry/fs/sys"
|
||||
_ "gvisor.dev/gvisor/pkg/sentry/fs/tmpfs"
|
||||
_ "gvisor.dev/gvisor/pkg/sentry/fs/tty"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
|
||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
@@ -390,6 +391,10 @@ type mountHint struct {
|
||||
// root is the inode where the volume is mounted. For mounts with 'pod' share
|
||||
// the volume is mounted once and then bind mounted inside the containers.
|
||||
root *fs.Inode
|
||||
|
||||
// vfsMount is the master mount for the volume. For mounts with 'pod' share
|
||||
// the master volume is bind mounted inside the containers.
|
||||
vfsMount *vfs.Mount
|
||||
}
|
||||
|
||||
func (m *mountHint) setField(key, val string) error {
|
||||
@@ -571,9 +576,9 @@ func newContainerMounter(spec *specs.Spec, goferFDs []int, k *kernel.Kernel, hin
|
||||
// processHints processes annotations that container hints about how volumes
|
||||
// should be mounted (e.g. a volume shared between containers). It must be
|
||||
// called for the root container only.
|
||||
func (c *containerMounter) processHints(conf *Config) error {
|
||||
func (c *containerMounter) processHints(conf *Config, creds *auth.Credentials) error {
|
||||
if conf.VFS2 {
|
||||
return nil
|
||||
return c.processHintsVFS2(conf, creds)
|
||||
}
|
||||
ctx := c.k.SupervisorContext()
|
||||
for _, hint := range c.hints.mounts {
|
||||
|
||||
@@ -298,6 +298,12 @@ func New(args Args) (*Loader, error) {
|
||||
return nil, fmt.Errorf("initializing kernel: %v", err)
|
||||
}
|
||||
|
||||
if kernel.VFS2Enabled {
|
||||
if err := registerFilesystems(k); err != nil {
|
||||
return nil, fmt.Errorf("registering filesystems: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := adjustDirentCache(k); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -559,7 +565,7 @@ func (l *Loader) run() error {
|
||||
l.startGoferMonitor(l.sandboxID, l.goferFDs)
|
||||
|
||||
mntr := newContainerMounter(l.spec, l.goferFDs, l.k, l.mountHints)
|
||||
if err := mntr.processHints(l.conf); err != nil {
|
||||
if err := mntr.processHints(l.conf, l.rootProcArgs.Credentials); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupContainerFS(ctx, l.conf, mntr, &l.rootProcArgs); err != nil {
|
||||
|
||||
@@ -480,7 +480,7 @@ func TestCreateMountNamespaceVFS2(t *testing.T) {
|
||||
defer loaderCleanup()
|
||||
|
||||
mntr := newContainerMounter(l.spec, l.goferFDs, l.k, l.mountHints)
|
||||
if err := mntr.processHints(l.conf); err != nil {
|
||||
if err := mntr.processHints(l.conf, l.rootProcArgs.Credentials); err != nil {
|
||||
t.Fatalf("failed process hints: %v", err)
|
||||
}
|
||||
|
||||
|
||||
+98
-18
@@ -43,7 +43,11 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/syserror"
|
||||
)
|
||||
|
||||
func registerFilesystems(ctx context.Context, vfsObj *vfs.VirtualFilesystem, creds *auth.Credentials) error {
|
||||
func registerFilesystems(k *kernel.Kernel) error {
|
||||
ctx := k.SupervisorContext()
|
||||
creds := auth.NewRootCredentials(k.RootUserNamespace())
|
||||
vfsObj := k.VFS()
|
||||
|
||||
vfsObj.MustRegisterFilesystemType(devpts.Name, &devpts.FilesystemType{}, &vfs.RegisterFilesystemTypeOptions{
|
||||
AllowUserList: true,
|
||||
// TODO(b/29356795): Users may mount this once the terminals are in a
|
||||
@@ -113,9 +117,6 @@ func registerFilesystems(ctx context.Context, vfsObj *vfs.VirtualFilesystem, cre
|
||||
}
|
||||
|
||||
func setupContainerVFS2(ctx context.Context, conf *Config, mntr *containerMounter, procArgs *kernel.CreateProcessArgs) error {
|
||||
if err := mntr.k.VFS().Init(); err != nil {
|
||||
return fmt.Errorf("failed to initialize VFS: %w", err)
|
||||
}
|
||||
mns, err := mntr.setupVFS2(ctx, conf, procArgs)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to setupFS: %w", err)
|
||||
@@ -144,10 +145,6 @@ func (c *containerMounter) setupVFS2(ctx context.Context, conf *Config, procArgs
|
||||
rootProcArgs.MaxSymlinkTraversals = linux.MaxSymlinkTraversals
|
||||
rootCtx := procArgs.NewContext(c.k)
|
||||
|
||||
if err := registerFilesystems(rootCtx, c.k.VFS(), rootCreds); err != nil {
|
||||
return nil, fmt.Errorf("register filesystems: %w", err)
|
||||
}
|
||||
|
||||
mns, err := c.createMountNamespaceVFS2(rootCtx, conf, rootCreds)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating mount namespace: %w", err)
|
||||
@@ -182,8 +179,14 @@ func (c *containerMounter) mountSubmountsVFS2(ctx context.Context, conf *Config,
|
||||
for i := range mounts {
|
||||
submount := &mounts[i]
|
||||
log.Debugf("Mounting %q to %q, type: %s, options: %s", submount.Source, submount.Destination, submount.Type, submount.Options)
|
||||
if err := c.mountSubmountVFS2(ctx, conf, mns, creds, submount); err != nil {
|
||||
return err
|
||||
if hint := c.hints.findMount(submount.Mount); hint != nil && hint.isSupported() {
|
||||
if err := c.mountSharedSubmountVFS2(ctx, conf, mns, creds, submount.Mount, hint); err != nil {
|
||||
return fmt.Errorf("mount shared mount %q to %q: %v", hint.name, submount.Destination, err)
|
||||
}
|
||||
} else {
|
||||
if err := c.mountSubmountVFS2(ctx, conf, mns, creds, submount); err != nil {
|
||||
return fmt.Errorf("mount submount %q: %w", submount.Destination, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,20 +260,18 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config,
|
||||
// getMountNameAndOptionsVFS2 retrieves the fsName, opts, and useOverlay values
|
||||
// used for mounts.
|
||||
func (c *containerMounter) getMountNameAndOptionsVFS2(conf *Config, m *mountAndFD) (string, *vfs.MountOptions, error) {
|
||||
var (
|
||||
fsName string
|
||||
data []string
|
||||
)
|
||||
fsName := m.Type
|
||||
var data []string
|
||||
|
||||
// Find filesystem name and FS specific data field.
|
||||
switch m.Type {
|
||||
case devpts.Name, devtmpfs.Name, proc.Name, sys.Name:
|
||||
fsName = m.Type
|
||||
// Nothing to do.
|
||||
|
||||
case nonefs:
|
||||
fsName = sys.Name
|
||||
case tmpfs.Name:
|
||||
fsName = m.Type
|
||||
|
||||
case tmpfs.Name:
|
||||
var err error
|
||||
data, err = parseAndFilterOptions(m.Options, tmpfsAllowedData...)
|
||||
if err != nil {
|
||||
@@ -279,10 +280,16 @@ func (c *containerMounter) getMountNameAndOptionsVFS2(conf *Config, m *mountAndF
|
||||
|
||||
case bind:
|
||||
fsName = gofer.Name
|
||||
if m.fd == 0 {
|
||||
// Check that an FD was provided to fails fast. Technically FD=0 is valid,
|
||||
// but unlikely to be correct in this context.
|
||||
return "", nil, fmt.Errorf("9P mount requires a connection FD")
|
||||
}
|
||||
data = p9MountData(m.fd, c.getMountAccessType(m.Mount), true /* vfs2 */)
|
||||
|
||||
default:
|
||||
log.Warningf("ignoring unknown filesystem type %q", m.Type)
|
||||
return "", nil, nil
|
||||
}
|
||||
|
||||
opts := &vfs.MountOptions{
|
||||
@@ -322,7 +329,7 @@ func (c *containerMounter) makeSyntheticMount(ctx context.Context, currentPath s
|
||||
}
|
||||
_, err := c.k.VFS().StatAt(ctx, creds, target, &vfs.StatOptions{})
|
||||
if err == nil {
|
||||
// Mount point exists, nothing else to do.
|
||||
log.Debugf("Mount point %q already exists", currentPath)
|
||||
return nil
|
||||
}
|
||||
if err != syserror.ENOENT {
|
||||
@@ -400,3 +407,76 @@ func (c *containerMounter) mountTmpVFS2(ctx context.Context, conf *Config, creds
|
||||
return fmt.Errorf(`stating "/tmp" inside container: %w`, err)
|
||||
}
|
||||
}
|
||||
|
||||
// processHintsVFS2 processes annotations that container hints about how volumes
|
||||
// should be mounted (e.g. a volume shared between containers). It must be
|
||||
// called for the root container only.
|
||||
func (c *containerMounter) processHintsVFS2(conf *Config, creds *auth.Credentials) error {
|
||||
ctx := c.k.SupervisorContext()
|
||||
for _, hint := range c.hints.mounts {
|
||||
// TODO(b/142076984): Only support tmpfs for now. Bind mounts require a
|
||||
// common gofer to mount all shared volumes.
|
||||
if hint.mount.Type != tmpfs.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Infof("Mounting master of shared mount %q from %q type %q", hint.name, hint.mount.Source, hint.mount.Type)
|
||||
mnt, err := c.mountSharedMasterVFS2(ctx, conf, hint, creds)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mounting shared master %q: %v", hint.name, err)
|
||||
}
|
||||
hint.vfsMount = mnt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// mountSharedMasterVFS2 mounts the master of a volume that is shared among
|
||||
// containers in a pod.
|
||||
func (c *containerMounter) mountSharedMasterVFS2(ctx context.Context, conf *Config, hint *mountHint, creds *auth.Credentials) (*vfs.Mount, error) {
|
||||
// Map mount type to filesystem name, and parse out the options that we are
|
||||
// capable of dealing with.
|
||||
mntFD := &mountAndFD{Mount: hint.mount}
|
||||
fsName, opts, err := c.getMountNameAndOptionsVFS2(conf, mntFD)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(fsName) == 0 {
|
||||
return nil, fmt.Errorf("mount type not supported %q", hint.mount.Type)
|
||||
}
|
||||
return c.k.VFS().MountDisconnected(ctx, creds, "", fsName, opts)
|
||||
}
|
||||
|
||||
// mountSharedSubmount binds mount to a previously mounted volume that is shared
|
||||
// among containers in the same pod.
|
||||
func (c *containerMounter) mountSharedSubmountVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials, mount specs.Mount, source *mountHint) error {
|
||||
if err := source.checkCompatible(mount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, opts, err := c.getMountNameAndOptionsVFS2(conf, &mountAndFD{Mount: mount})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newMnt, err := c.k.VFS().NewDisconnectedMount(source.vfsMount.Filesystem(), source.vfsMount.Root(), opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer newMnt.DecRef()
|
||||
|
||||
root := mns.Root()
|
||||
defer root.DecRef()
|
||||
if err := c.makeSyntheticMount(ctx, mount.Destination, root, creds); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target := &vfs.PathOperation{
|
||||
Root: root,
|
||||
Start: root,
|
||||
Path: fspath.Parse(mount.Destination),
|
||||
}
|
||||
if err := c.k.VFS().ConnectMountAt(ctx, creds, newMnt, target); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("Mounted %q type shared bind to %q", mount.Destination, source.name)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -100,19 +100,20 @@ type execDesc struct {
|
||||
c *Container
|
||||
cmd []string
|
||||
want int
|
||||
desc string
|
||||
name string
|
||||
}
|
||||
|
||||
func execMany(execs []execDesc) error {
|
||||
func execMany(t *testing.T, execs []execDesc) {
|
||||
for _, exec := range execs {
|
||||
args := &control.ExecArgs{Argv: exec.cmd}
|
||||
if ws, err := exec.c.executeSync(args); err != nil {
|
||||
return fmt.Errorf("error executing %+v: %v", args, err)
|
||||
} else if ws.ExitStatus() != exec.want {
|
||||
return fmt.Errorf("%q: exec %q got exit status: %d, want: %d", exec.desc, exec.cmd, ws.ExitStatus(), exec.want)
|
||||
}
|
||||
t.Run(exec.name, func(t *testing.T) {
|
||||
args := &control.ExecArgs{Argv: exec.cmd}
|
||||
if ws, err := exec.c.executeSync(args); err != nil {
|
||||
t.Errorf("error executing %+v: %v", args, err)
|
||||
} else if ws.ExitStatus() != exec.want {
|
||||
t.Errorf("%q: exec %q got exit status: %d, want: %d", exec.name, exec.cmd, ws.ExitStatus(), exec.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func createSharedMount(mount specs.Mount, name string, pod ...*specs.Spec) {
|
||||
@@ -1072,7 +1073,7 @@ func TestMultiContainerContainerDestroyStress(t *testing.T) {
|
||||
// Test that pod shared mounts are properly mounted in 2 containers and that
|
||||
// changes from one container is reflected in the other.
|
||||
func TestMultiContainerSharedMount(t *testing.T) {
|
||||
for name, conf := range configs(t, all...) {
|
||||
for name, conf := range configsWithVFS2(t, all...) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rootDir, cleanup, err := testutil.SetupRootDir()
|
||||
if err != nil {
|
||||
@@ -1110,84 +1111,82 @@ func TestMultiContainerSharedMount(t *testing.T) {
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt0.Destination},
|
||||
desc: "directory is mounted in container0",
|
||||
name: "directory is mounted in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt1.Destination},
|
||||
desc: "directory is mounted in container1",
|
||||
name: "directory is mounted in container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/touch", file0},
|
||||
desc: "create file in container0",
|
||||
cmd: []string{"/bin/touch", file0},
|
||||
name: "create file in container0",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-f", file0},
|
||||
desc: "file appears in container0",
|
||||
name: "file appears in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-f", file1},
|
||||
desc: "file appears in container1",
|
||||
name: "file appears in container1",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/bin/rm", file1},
|
||||
desc: "file removed from container1",
|
||||
name: "remove file from container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "!", "-f", file0},
|
||||
desc: "file removed from container0",
|
||||
name: "file removed from container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "!", "-f", file1},
|
||||
desc: "file removed from container1",
|
||||
name: "file removed from container1",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/bin/mkdir", file1},
|
||||
desc: "create directory in container1",
|
||||
name: "create directory in container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-d", file0},
|
||||
desc: "dir appears in container0",
|
||||
name: "dir appears in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-d", file1},
|
||||
desc: "dir appears in container1",
|
||||
name: "dir appears in container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/bin/rmdir", file0},
|
||||
desc: "create directory in container0",
|
||||
name: "remove directory from container0",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "!", "-d", file0},
|
||||
desc: "dir removed from container0",
|
||||
name: "dir removed from container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "!", "-d", file1},
|
||||
desc: "dir removed from container1",
|
||||
name: "dir removed from container1",
|
||||
},
|
||||
}
|
||||
if err := execMany(execs); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
execMany(t, execs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test that pod mounts are mounted as readonly when requested.
|
||||
func TestMultiContainerSharedMountReadonly(t *testing.T) {
|
||||
for name, conf := range configs(t, all...) {
|
||||
for name, conf := range configsWithVFS2(t, all...) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rootDir, cleanup, err := testutil.SetupRootDir()
|
||||
if err != nil {
|
||||
@@ -1225,35 +1224,34 @@ func TestMultiContainerSharedMountReadonly(t *testing.T) {
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt0.Destination},
|
||||
desc: "directory is mounted in container0",
|
||||
name: "directory is mounted in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt1.Destination},
|
||||
desc: "directory is mounted in container1",
|
||||
name: "directory is mounted in container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/touch", file0},
|
||||
cmd: []string{"/bin/touch", file0},
|
||||
want: 1,
|
||||
desc: "fails to write to container0",
|
||||
name: "fails to write to container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/touch", file1},
|
||||
cmd: []string{"/bin/touch", file1},
|
||||
want: 1,
|
||||
desc: "fails to write to container1",
|
||||
name: "fails to write to container1",
|
||||
},
|
||||
}
|
||||
if err := execMany(execs); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
execMany(t, execs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test that shared pod mounts continue to work after container is restarted.
|
||||
func TestMultiContainerSharedMountRestart(t *testing.T) {
|
||||
//TODO(gvisor.dev/issue/1487): This is failing with VFS2.
|
||||
for name, conf := range configs(t, all...) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rootDir, cleanup, err := testutil.SetupRootDir()
|
||||
@@ -1291,23 +1289,21 @@ func TestMultiContainerSharedMountRestart(t *testing.T) {
|
||||
execs := []execDesc{
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/touch", file0},
|
||||
desc: "create file in container0",
|
||||
cmd: []string{"/bin/touch", file0},
|
||||
name: "create file in container0",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-f", file0},
|
||||
desc: "file appears in container0",
|
||||
name: "file appears in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-f", file1},
|
||||
desc: "file appears in container1",
|
||||
name: "file appears in container1",
|
||||
},
|
||||
}
|
||||
if err := execMany(execs); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
execMany(t, execs)
|
||||
|
||||
containers[1].Destroy()
|
||||
|
||||
@@ -1334,32 +1330,30 @@ func TestMultiContainerSharedMountRestart(t *testing.T) {
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-f", file0},
|
||||
desc: "file is still in container0",
|
||||
name: "file is still in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-f", file1},
|
||||
desc: "file is still in container1",
|
||||
name: "file is still in container1",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/bin/rm", file1},
|
||||
desc: "file removed from container1",
|
||||
name: "file removed from container1",
|
||||
},
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "!", "-f", file0},
|
||||
desc: "file removed from container0",
|
||||
name: "file removed from container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "!", "-f", file1},
|
||||
desc: "file removed from container1",
|
||||
name: "file removed from container1",
|
||||
},
|
||||
}
|
||||
if err := execMany(execs); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
execMany(t, execs)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1367,53 +1361,53 @@ func TestMultiContainerSharedMountRestart(t *testing.T) {
|
||||
// Test that unsupported pod mounts options are ignored when matching master and
|
||||
// slave mounts.
|
||||
func TestMultiContainerSharedMountUnsupportedOptions(t *testing.T) {
|
||||
rootDir, cleanup, err := testutil.SetupRootDir()
|
||||
if err != nil {
|
||||
t.Fatalf("error creating root dir: %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
for name, conf := range configsWithVFS2(t, all...) {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
rootDir, cleanup, err := testutil.SetupRootDir()
|
||||
if err != nil {
|
||||
t.Fatalf("error creating root dir: %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
conf.RootDir = rootDir
|
||||
|
||||
conf := testutil.TestConfig(t)
|
||||
conf.RootDir = rootDir
|
||||
// Setup the containers.
|
||||
sleep := []string{"/bin/sleep", "100"}
|
||||
podSpec, ids := createSpecs(sleep, sleep)
|
||||
mnt0 := specs.Mount{
|
||||
Destination: "/mydir/test",
|
||||
Source: "/some/dir",
|
||||
Type: "tmpfs",
|
||||
Options: []string{"rw", "rbind", "relatime"},
|
||||
}
|
||||
podSpec[0].Mounts = append(podSpec[0].Mounts, mnt0)
|
||||
|
||||
// Setup the containers.
|
||||
sleep := []string{"/bin/sleep", "100"}
|
||||
podSpec, ids := createSpecs(sleep, sleep)
|
||||
mnt0 := specs.Mount{
|
||||
Destination: "/mydir/test",
|
||||
Source: "/some/dir",
|
||||
Type: "tmpfs",
|
||||
Options: []string{"rw", "rbind", "relatime"},
|
||||
}
|
||||
podSpec[0].Mounts = append(podSpec[0].Mounts, mnt0)
|
||||
mnt1 := mnt0
|
||||
mnt1.Destination = "/mydir2/test2"
|
||||
mnt1.Options = []string{"rw", "nosuid"}
|
||||
podSpec[1].Mounts = append(podSpec[1].Mounts, mnt1)
|
||||
|
||||
mnt1 := mnt0
|
||||
mnt1.Destination = "/mydir2/test2"
|
||||
mnt1.Options = []string{"rw", "nosuid"}
|
||||
podSpec[1].Mounts = append(podSpec[1].Mounts, mnt1)
|
||||
createSharedMount(mnt0, "test-mount", podSpec...)
|
||||
|
||||
createSharedMount(mnt0, "test-mount", podSpec...)
|
||||
containers, cleanup, err := startContainers(conf, podSpec, ids)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting containers: %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
containers, cleanup, err := startContainers(conf, podSpec, ids)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting containers: %v", err)
|
||||
}
|
||||
defer cleanup()
|
||||
|
||||
execs := []execDesc{
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt0.Destination},
|
||||
desc: "directory is mounted in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt1.Destination},
|
||||
desc: "directory is mounted in container1",
|
||||
},
|
||||
}
|
||||
if err := execMany(execs); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
execs := []execDesc{
|
||||
{
|
||||
c: containers[0],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt0.Destination},
|
||||
name: "directory is mounted in container0",
|
||||
},
|
||||
{
|
||||
c: containers[1],
|
||||
cmd: []string{"/usr/bin/test", "-d", mnt1.Destination},
|
||||
name: "directory is mounted in container1",
|
||||
},
|
||||
}
|
||||
execMany(t, execs)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user