summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/markdown/podman-unshare.1.md5
-rw-r--r--libpod/networking_linux.go26
-rw-r--r--pkg/domain/infra/abi/system.go7
-rw-r--r--test/e2e/common_test.go61
-rw-r--r--test/e2e/libpod_suite_remote_test.go21
-rw-r--r--test/e2e/libpod_suite_test.go12
-rw-r--r--test/utils/utils.go1
7 files changed, 70 insertions, 63 deletions
diff --git a/docs/source/markdown/podman-unshare.1.md b/docs/source/markdown/podman-unshare.1.md
index 5676b1be7..01393a862 100644
--- a/docs/source/markdown/podman-unshare.1.md
+++ b/docs/source/markdown/podman-unshare.1.md
@@ -35,7 +35,6 @@ Print usage statement
Join the rootless network namespace used for CNI and netavark networking. It can be used to
connect to a rootless container via IP address (bridge networking). This is otherwise
not possible from the host network namespace.
-_Note: Using this option with more than one unshare session can have unexpected results._
## Exit Codes
@@ -57,13 +56,13 @@ the exit codes follow the `chroot` standard, see below:
**127** Executing a _contained command_ and the _command_ cannot be found
- $ podman run busybox foo; echo $?
+ $ podman unshare foo; echo $?
Error: fork/exec /usr/bin/bogus: no such file or directory
127
**Exit code** _contained command_ exit code
- $ podman run busybox /bin/sh -c 'exit 3'; echo $?
+ $ podman unshare /bin/sh -c 'exit 3'; echo $?
3
## EXAMPLE
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 7d1214183..b734b9c95 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -322,17 +322,14 @@ func (r *RootlessNetNS) Do(toRun func() error) error {
// Cleanup the rootless network namespace if needed.
// It checks if we have running containers with the bridge network mode.
-// Cleanup() will try to lock RootlessNetNS, therefore you have to call
-// it with an unlocked lock.
+// Cleanup() expects that r.Lock is locked
func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
_, err := os.Stat(r.dir)
if os.IsNotExist(err) {
// the directory does not exists no need for cleanup
return nil
}
- r.Lock.Lock()
- defer r.Lock.Unlock()
- running := func(c *Container) bool {
+ activeNetns := func(c *Container) bool {
// no bridge => no need to check
if !c.config.NetMode.IsBridge() {
return false
@@ -352,15 +349,18 @@ func (r *RootlessNetNS) Cleanup(runtime *Runtime) error {
return false
}
- state := c.state.State
- return state == define.ContainerStateRunning
+ // only check for an active netns, we cannot use the container state
+ // because not running does not mean that the netns does not need cleanup
+ // only if the netns is empty we know that we do not need cleanup
+ return c.state.NetNS != nil
}
- ctrs, err := runtime.GetContainersWithoutLock(running)
+ ctrs, err := runtime.GetContainersWithoutLock(activeNetns)
if err != nil {
return err
}
- // no cleanup if we found containers
- if len(ctrs) > 0 {
+ // no cleanup if we found no other containers with a netns
+ // we will always find one container (the container cleanup that is currently calling us)
+ if len(ctrs) > 1 {
return nil
}
logrus.Debug("Cleaning up rootless network namespace")
@@ -809,10 +809,10 @@ func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error {
if rootlessNetNS != nil {
// execute the cni setup in the rootless net ns
err = rootlessNetNS.Do(tearDownPod)
- rootlessNetNS.Lock.Unlock()
- if err == nil {
- err = rootlessNetNS.Cleanup(r)
+ if cerr := rootlessNetNS.Cleanup(r); cerr != nil {
+ logrus.WithError(err).Error("failed to cleanup rootless netns")
}
+ rootlessNetNS.Lock.Unlock()
} else {
err = tearDownPod()
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 7da7754f2..e6c9d850b 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -365,9 +365,12 @@ func (ic *ContainerEngine) Unshare(ctx context.Context, args []string, options e
if err != nil {
return err
}
- // make sure to unlock, unshare can run for a long time
+ // Make sure to unlock, unshare can run for a long time.
rootlessNetNS.Lock.Unlock()
- defer rootlessNetNS.Cleanup(ic.Libpod)
+ // We do not want to cleanup the netns after unshare.
+ // The problem is that we cannot know if we need to cleanup and
+ // secondly unshare should allow user to setup the namespace with
+ // special things, e.g. potentially macvlan or something like that.
return rootlessNetNS.Do(unshare)
}
return unshare()
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 63cb4f091..a411a860b 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -36,7 +36,6 @@ var (
PODMAN_BINARY string //nolint:golint,stylecheck
INTEGRATION_ROOT string //nolint:golint,stylecheck
CGROUP_MANAGER = "systemd" //nolint:golint,stylecheck
- ARTIFACT_DIR = "/tmp/.artifacts" //nolint:golint,stylecheck
RESTORE_IMAGES = []string{ALPINE, BB, nginx} //nolint:golint,stylecheck
defaultWaitTimeout = 90
CGROUPSV2, _ = cgroups.IsCgroup2UnifiedMode() //nolint:golint,stylecheck
@@ -46,7 +45,7 @@ var (
type PodmanTestIntegration struct {
PodmanTest
ConmonBinary string
- CrioRoot string
+ Root string
CNIConfigDir string
OCIRuntime string
RunRoot string
@@ -111,13 +110,6 @@ var _ = SynchronizedBeforeSuite(func() []byte {
cwd, _ := os.Getwd()
INTEGRATION_ROOT = filepath.Join(cwd, "../../")
podman := PodmanTestSetup("/tmp")
- podman.ArtifactPath = ARTIFACT_DIR
- if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) {
- if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil {
- fmt.Printf("%q\n", err)
- os.Exit(1)
- }
- }
// Pull cirros but don't put it into the cache
pullImages := []string{cirros, fedoraToolbox, volumeTest}
@@ -130,7 +122,7 @@ var _ = SynchronizedBeforeSuite(func() []byte {
fmt.Printf("%q\n", err)
os.Exit(1)
}
- podman.CrioRoot = ImageCacheDir
+ podman.Root = ImageCacheDir
// If running localized tests, the cache dir is created and populated. if the
// tests are remote, this is a no-op
populateCache(podman)
@@ -170,7 +162,6 @@ var _ = SynchronizedBeforeSuite(func() []byte {
func (p *PodmanTestIntegration) Setup() {
cwd, _ := os.Getwd()
INTEGRATION_ROOT = filepath.Join(cwd, "../../")
- p.ArtifactPath = ARTIFACT_DIR
}
var _ = SynchronizedAfterSuite(func() {},
@@ -181,14 +172,14 @@ var _ = SynchronizedAfterSuite(func() {},
fmt.Printf("%s\t\t%f\n", result.name, result.length)
}
- // previous crio-run
+ // previous runroot
tempdir, err := CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest := PodmanTestCreate(tempdir)
- if err := os.RemoveAll(podmanTest.CrioRoot); err != nil {
+ if err := os.RemoveAll(podmanTest.Root); err != nil {
fmt.Printf("%q\n", err)
}
@@ -265,18 +256,17 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
PodmanTest: PodmanTest{
PodmanBinary: podmanBinary,
RemotePodmanBinary: podmanRemoteBinary,
- ArtifactPath: ARTIFACT_DIR,
TempDir: tempDir,
RemoteTest: remote,
ImageCacheFS: storageFs,
ImageCacheDir: ImageCacheDir,
},
ConmonBinary: conmonBinary,
- CrioRoot: filepath.Join(tempDir, "crio"),
+ Root: filepath.Join(tempDir, "root"),
TmpDir: tempDir,
CNIConfigDir: CNIConfigDir,
OCIRuntime: ociRuntime,
- RunRoot: filepath.Join(tempDir, "crio-run"),
+ RunRoot: filepath.Join(tempDir, "runroot"),
StorageOptions: storageOptions,
SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"),
CgroupManager: cgroupManager,
@@ -308,15 +298,29 @@ func (p PodmanTestIntegration) AddImageToRWStore(image string) {
}
}
-// createArtifact creates a cached image in the artifact dir
+func imageTarPath(image string) string {
+ cacheDir := os.Getenv("PODMAN_TEST_IMAGE_CACHE_DIR")
+ if cacheDir == "" {
+ cacheDir = os.Getenv("TMPDIR")
+ if cacheDir == "" {
+ cacheDir = "/tmp"
+ }
+ }
+
+ // e.g., registry.com/fubar:latest -> registry.com-fubar-latest.tar
+ imageCacheName := strings.Replace(strings.Replace(image, ":", "-", -1), "/", "-", -1) + ".tar"
+
+ return filepath.Join(cacheDir, imageCacheName)
+}
+
+// createArtifact creates a cached image tarball in a local directory
func (p *PodmanTestIntegration) createArtifact(image string) {
if os.Getenv("NO_TEST_CACHE") != "" {
return
}
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- fmt.Printf("Caching %s at %s...\n", image, destName)
+ destName := imageTarPath(image)
if _, err := os.Stat(destName); os.IsNotExist(err) {
+ fmt.Printf("Caching %s at %s...\n", image, destName)
pull := p.PodmanNoCache([]string{"pull", image})
pull.Wait(440)
Expect(pull).Should(Exit(0))
@@ -326,7 +330,7 @@ func (p *PodmanTestIntegration) createArtifact(image string) {
Expect(save).Should(Exit(0))
fmt.Printf("\n")
} else {
- fmt.Printf(" already exists.\n")
+ fmt.Printf("[image already cached: %s]\n", destName)
}
}
@@ -738,12 +742,13 @@ func (p *PodmanTestIntegration) RestartRemoteService() {
// RestoreArtifactToCache populates the imagecache from tarballs that were cached earlier
func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- p.CrioRoot = p.ImageCacheDir
- restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName})
- restore.WaitWithDefaultTimeout()
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ p.Root = p.ImageCacheDir
+ restore := p.PodmanNoEvents([]string{"load", "-q", "-i", tarball})
+ restore.WaitWithDefaultTimeout()
+ }
return nil
}
@@ -795,7 +800,7 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
}
podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s",
- debug, p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
+ debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go
index 2ecbd0eab..d60383029 100644
--- a/test/e2e/libpod_suite_remote_test.go
+++ b/test/e2e/libpod_suite_remote_test.go
@@ -148,7 +148,7 @@ func (p *PodmanTestIntegration) StopRemoteService() {
//MakeOptions assembles all the podman main options
func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s",
- p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
+ p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
@@ -164,15 +164,16 @@ func (p *PodmanTestIntegration) SeedImages() error {
// RestoreArtifact puts the cached image into our test store
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- args := []string{"load", "-q", "-i", destName}
- podmanOptions := getRemoteOptions(p, args)
- command := exec.Command(p.PodmanBinary, podmanOptions...)
- fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
- command.Start()
- command.Wait()
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ args := []string{"load", "-q", "-i", tarball}
+ podmanOptions := getRemoteOptions(p, args)
+ command := exec.Command(p.PodmanBinary, podmanOptions...)
+ fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
+ command.Start()
+ command.Wait()
+ }
return nil
}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 001a869b1..4147ba2c3 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -7,7 +7,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
- "strings"
"github.com/containers/podman/v3/pkg/rootless"
)
@@ -59,11 +58,12 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
// RestoreArtifact puts the cached image into our test store
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
- fmt.Printf("Restoring %s...\n", image)
- dest := strings.Split(image, "/")
- destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1))
- restore := p.PodmanNoEvents([]string{"load", "-q", "-i", destName})
- restore.Wait(90)
+ tarball := imageTarPath(image)
+ if _, err := os.Stat(tarball); err == nil {
+ fmt.Printf("Restoring %s...\n", image)
+ restore := p.PodmanNoEvents([]string{"load", "-q", "-i", tarball})
+ restore.Wait(90)
+ }
return nil
}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 944c1ac3c..f41024072 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -36,7 +36,6 @@ type PodmanTestCommon interface {
type PodmanTest struct {
PodmanMakeOptions func(args []string, noEvents, noCache bool) []string
PodmanBinary string
- ArtifactPath string
TempDir string
RemoteTest bool
RemotePodmanBinary string