aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xAPI.md5
-rw-r--r--cmd/podman/commands.go2
-rw-r--r--cmd/podman/container.go2
-rw-r--r--cmd/podman/main_remote.go14
-rw-r--r--cmd/podman/ps.go2
-rw-r--r--cmd/podman/varlink/io.podman.varlink5
-rwxr-xr-xcontrib/cirrus/rootless_test.sh2
-rw-r--r--libpod/container_internal.go2
-rw-r--r--libpod/lock/in_memory_locks.go16
-rw-r--r--libpod/lock/lock.go7
-rw-r--r--libpod/lock/shm/shm_lock.c55
-rw-r--r--libpod/lock/shm/shm_lock.go17
-rw-r--r--libpod/lock/shm/shm_lock.h1
-rw-r--r--libpod/lock/shm_lock_manager_linux.go19
-rw-r--r--libpod/pod_internal.go2
-rw-r--r--libpod/runtime.go2
-rw-r--r--pkg/adapter/containers.go5
-rw-r--r--pkg/adapter/containers_remote.go35
-rw-r--r--pkg/adapter/errors.go31
-rw-r--r--pkg/adapter/info_remote.go7
-rw-r--r--pkg/adapter/pods_remote.go6
-rw-r--r--pkg/varlinkapi/containers.go17
-rw-r--r--pkg/varlinkapi/pods.go6
-rw-r--r--test/e2e/common_test.go7
-rw-r--r--test/e2e/create_test.go2
-rw-r--r--test/e2e/diff_test.go3
-rw-r--r--test/e2e/info_test.go1
-rw-r--r--test/e2e/kill_test.go2
-rw-r--r--test/e2e/libpod_suite_remoteclient_test.go74
-rw-r--r--test/e2e/libpod_suite_test.go3
-rw-r--r--test/e2e/logs_test.go2
-rw-r--r--test/e2e/pod_create_test.go2
-rw-r--r--test/e2e/pod_inspect_test.go2
-rw-r--r--test/e2e/pod_kill_test.go2
-rw-r--r--test/e2e/pod_pause_test.go2
-rw-r--r--test/e2e/pod_prune_test.go2
-rw-r--r--test/e2e/pod_ps_test.go2
-rw-r--r--test/e2e/pod_restart_test.go2
-rw-r--r--test/e2e/pod_rm_test.go2
-rw-r--r--test/e2e/pod_start_test.go2
-rw-r--r--test/e2e/pod_stop_test.go2
-rw-r--r--test/e2e/ps_test.go2
-rw-r--r--test/e2e/refresh_test.go74
-rw-r--r--test/e2e/rm_test.go2
-rw-r--r--test/e2e/run_test.go1
-rw-r--r--test/e2e/save_test.go10
-rw-r--r--test/e2e/stop_test.go2
-rw-r--r--test/e2e/tag_test.go2
-rw-r--r--test/e2e/wait_test.go2
-rw-r--r--test/utils/utils.go6
50 files changed, 307 insertions, 168 deletions
diff --git a/API.md b/API.md
index 11b9a462f..db84f695c 100755
--- a/API.md
+++ b/API.md
@@ -259,6 +259,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in
[error ContainerNotFound](#ContainerNotFound)
+[error ErrCtrStopped](#ErrCtrStopped)
+
[error ErrorOccurred](#ErrorOccurred)
[error ImageNotFound](#ImageNotFound)
@@ -1978,6 +1980,9 @@ force [bool](https://godoc.org/builtin#bool)
### <a name="ContainerNotFound"></a>type ContainerNotFound
ContainerNotFound means the container could not be found by the provided name or ID in local storage.
+### <a name="ErrCtrStopped"></a>type ErrCtrStopped
+
+Container is already stopped
### <a name="ErrorOccurred"></a>type ErrorOccurred
ErrorOccurred is a generic error for an error that occurs during the execution. The actual error message
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 14451d944..3a409f503 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -39,13 +39,11 @@ func getImageSubCommands() []*cobra.Command {
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{
- _checkpointCommand,
_cleanupCommand,
_commitCommand,
_execCommand,
_mountCommand,
_refreshCommand,
- _restoreCommand,
_runlabelCommand,
_statsCommand,
_umountCommand,
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index bbf01d1f8..530175a55 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -51,6 +51,7 @@ var (
// Commands that are universally implemented.
containerCommands = []*cobra.Command{
_attachCommand,
+ _checkpointCommand,
_containerExistsCommand,
_contInspectSubCommand,
_diffCommand,
@@ -64,6 +65,7 @@ var (
_portCommand,
_pruneContainersCommand,
_restartCommand,
+ _restoreCommand,
_runCommand,
_rmCommand,
_startCommand,
diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go
index a3335050a..753730b56 100644
--- a/cmd/podman/main_remote.go
+++ b/cmd/podman/main_remote.go
@@ -3,10 +3,6 @@
package main
import (
- "os"
-
- "github.com/containers/libpod/pkg/rootless"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -29,16 +25,6 @@ func profileOff(cmd *cobra.Command) error {
}
func setupRootless(cmd *cobra.Command, args []string) error {
- if rootless.IsRootless() {
- became, ret, err := rootless.BecomeRootInUserNS()
- if err != nil {
- logrus.Errorf(err.Error())
- os.Exit(1)
- }
- if became {
- os.Exit(ret)
- }
- }
return nil
}
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 623f17050..eb5181126 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -497,7 +497,7 @@ func psDisplay(c *cliconfig.PsValues, runtime *adapter.LocalRuntime) error {
} else {
// Print namespace information
- ns := shared.GetNamespaces(container.Pid)
+ ns := runtime.GetNamespaces(container)
fmt.Fprintf(w, "\n%s\t%s\t%d\t%s\t%s\t%s\t%s\t%s\t%s\t%s", container.ID, container.Names, container.Pid, ns.Cgroup, ns.IPC, ns.MNT, ns.NET, ns.PIDNS, ns.User, ns.UTS)
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index ace81646c..faaecdb6b 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -1254,4 +1254,7 @@ error ErrorOccurred (reason: string)
error RuntimeError (reason: string)
# The Podman endpoint requires that you use a streaming connection.
-error WantsMoreRequired (reason: string) \ No newline at end of file
+error WantsMoreRequired (reason: string)
+
+# Container is already stopped
+error ErrCtrStopped (id: string)
diff --git a/contrib/cirrus/rootless_test.sh b/contrib/cirrus/rootless_test.sh
index 8351214f3..eab06bac0 100755
--- a/contrib/cirrus/rootless_test.sh
+++ b/contrib/cirrus/rootless_test.sh
@@ -14,8 +14,6 @@ then
exit 1
fi
-export PODMAN_VARLINK_ADDRESS=unix:/tmp/podman-$(id -u)
-
echo "."
echo "Hello, my name is $USER and I live in $PWD can I be your friend?"
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 0b4e5763e..e6ffaa6d7 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -516,7 +516,7 @@ func (c *Container) refresh() error {
}
// We need to pick up a new lock
- lock, err := c.runtime.lockManager.RetrieveLock(c.config.LockID)
+ lock, err := c.runtime.lockManager.AllocateAndRetrieveLock(c.config.LockID)
if err != nil {
return errors.Wrapf(err, "error acquiring lock for container %s", c.ID())
}
diff --git a/libpod/lock/in_memory_locks.go b/libpod/lock/in_memory_locks.go
index 7c9605917..f3c842f89 100644
--- a/libpod/lock/in_memory_locks.go
+++ b/libpod/lock/in_memory_locks.go
@@ -90,6 +90,22 @@ func (m *InMemoryManager) RetrieveLock(id uint32) (Locker, error) {
return m.locks[id], nil
}
+// AllocateAndRetrieveLock allocates a lock with the given ID (if not already in
+// use) and returns it.
+func (m *InMemoryManager) AllocateAndRetrieveLock(id uint32) (Locker, error) {
+ if id >= m.numLocks {
+ return nil, errors.Errorf("given lock ID %d is too large - this manager only supports lock indexes up to %d", id, m.numLocks)
+ }
+
+ if m.locks[id].allocated {
+ return nil, errors.Errorf("given lock ID %d is already in use, cannot reallocate", id)
+ }
+
+ m.locks[id].allocated = true
+
+ return m.locks[id], nil
+}
+
// FreeAllLocks frees all locks.
// This function is DANGEROUS. Please read the full comment in locks.go before
// trying to use it.
diff --git a/libpod/lock/lock.go b/libpod/lock/lock.go
index d6841646b..4e1e2e215 100644
--- a/libpod/lock/lock.go
+++ b/libpod/lock/lock.go
@@ -24,6 +24,13 @@ type Manager interface {
// The underlying lock MUST be the same as another other lock with the
// same UUID.
RetrieveLock(id uint32) (Locker, error)
+ // AllocateAndRetrieveLock marks the lock with the given UUID as in use
+ // and retrieves it.
+ // RetrieveAndAllocateLock will error if the lock in question has
+ // already been allocated.
+ // This is mostly used after a system restart to repopulate the list of
+ // locks in use.
+ AllocateAndRetrieveLock(id uint32) (Locker, error)
// PLEASE READ FULL DESCRIPTION BEFORE USING.
// FreeAllLocks frees all allocated locks, in preparation for lock
// reallocation.
diff --git a/libpod/lock/shm/shm_lock.c b/libpod/lock/shm/shm_lock.c
index d11fce71a..047d3c417 100644
--- a/libpod/lock/shm/shm_lock.c
+++ b/libpod/lock/shm/shm_lock.c
@@ -354,6 +354,61 @@ int64_t allocate_semaphore(shm_struct_t *shm) {
return -1 * ENOSPC;
}
+// Allocate the semaphore with the given ID.
+// Returns an error if the semaphore with this ID does not exist, or has already
+// been allocated.
+// Returns 0 on success, or negative errno values on failure.
+int32_t allocate_given_semaphore(shm_struct_t *shm, uint32_t sem_index) {
+ int bitmap_index, index_in_bitmap, ret_code;
+ bitmap_t test_map;
+
+ if (shm == NULL) {
+ return -1 * EINVAL;
+ }
+
+ // Check if the lock index is valid
+ if (sem_index >= shm->num_locks) {
+ return -1 * EINVAL;
+ }
+
+ bitmap_index = sem_index / BITMAP_SIZE;
+ index_in_bitmap = sem_index % BITMAP_SIZE;
+
+ // This should never happen if the sem_index test above succeeded, but better
+ // safe than sorry
+ if (bitmap_index >= shm->num_bitmaps) {
+ return -1 * EFAULT;
+ }
+
+ test_map = 0x1 << index_in_bitmap;
+
+ // Lock the mutex controlling access to our shared memory
+ ret_code = take_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ // Check if the semaphore is allocated
+ if ((test_map & shm->locks[bitmap_index].bitmap) != 0) {
+ ret_code = release_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ return -1 * EEXIST;
+ }
+
+ // The semaphore is not allocated, allocate it
+ shm->locks[bitmap_index].bitmap = shm->locks[bitmap_index].bitmap | test_map;
+
+ ret_code = release_mutex(&(shm->segment_lock));
+ if (ret_code != 0) {
+ return -1 * ret_code;
+ }
+
+ return 0;
+}
+
// Deallocate a given semaphore
// Returns 0 on success, negative ERRNO values on failure
int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index) {
diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go
index e70ea8743..c21e9a221 100644
--- a/libpod/lock/shm/shm_lock.go
+++ b/libpod/lock/shm/shm_lock.go
@@ -134,6 +134,23 @@ func (locks *SHMLocks) AllocateSemaphore() (uint32, error) {
return uint32(retCode), nil
}
+// AllocateGivenSemaphore allocates the given semaphore from the shared-memory
+// segment for use by a container or pod.
+// If the semaphore is already in use or the index is invalid an error will be
+// returned.
+func (locks *SHMLocks) AllocateGivenSemaphore(sem uint32) error {
+ if !locks.valid {
+ return errors.Wrapf(syscall.EINVAL, "locks have already been closed")
+ }
+
+ retCode := C.allocate_given_semaphore(locks.lockStruct, C.uint32_t(sem))
+ if retCode < 0 {
+ return syscall.Errno(-1 * retCode)
+ }
+
+ return nil
+}
+
// DeallocateSemaphore frees a semaphore in a shared-memory segment so it can be
// reallocated to another container or pod.
// The given semaphore must be already allocated, or an error will be returned.
diff --git a/libpod/lock/shm/shm_lock.h b/libpod/lock/shm/shm_lock.h
index 58e4297e2..759f8178a 100644
--- a/libpod/lock/shm/shm_lock.h
+++ b/libpod/lock/shm/shm_lock.h
@@ -39,6 +39,7 @@ shm_struct_t *setup_lock_shm(char *path, uint32_t num_locks, int *error_code);
shm_struct_t *open_lock_shm(char *path, uint32_t num_locks, int *error_code);
int32_t close_lock_shm(shm_struct_t *shm);
int64_t allocate_semaphore(shm_struct_t *shm);
+int32_t allocate_given_semaphore(shm_struct_t *shm, uint32_t sem_index);
int32_t deallocate_semaphore(shm_struct_t *shm, uint32_t sem_index);
int32_t deallocate_all_semaphores(shm_struct_t *shm);
int32_t lock_semaphore(shm_struct_t *shm, uint32_t sem_index);
diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go
index 8678958ee..5f31939f8 100644
--- a/libpod/lock/shm_lock_manager_linux.go
+++ b/libpod/lock/shm_lock_manager_linux.go
@@ -57,6 +57,25 @@ func (m *SHMLockManager) AllocateLock() (Locker, error) {
return lock, nil
}
+// AllocateAndRetrieveLock allocates the lock with the given ID and returns it.
+// If the lock is already allocated, error.
+func (m *SHMLockManager) AllocateAndRetrieveLock(id uint32) (Locker, error) {
+ lock := new(SHMLock)
+ lock.lockID = id
+ lock.manager = m
+
+ if id >= m.locks.GetMaxLocks() {
+ return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d",
+ id, m.locks.GetMaxLocks()-1)
+ }
+
+ if err := m.locks.AllocateGivenSemaphore(id); err != nil {
+ return nil, err
+ }
+
+ return lock, nil
+}
+
// RetrieveLock retrieves a lock from the manager given its ID.
func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) {
lock := new(SHMLock)
diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go
index 25e4e77d7..1fcb5b1a6 100644
--- a/libpod/pod_internal.go
+++ b/libpod/pod_internal.go
@@ -56,7 +56,7 @@ func (p *Pod) refresh() error {
}
// Retrieve the pod's lock
- lock, err := p.runtime.lockManager.RetrieveLock(p.config.LockID)
+ lock, err := p.runtime.lockManager.AllocateAndRetrieveLock(p.config.LockID)
if err != nil {
return errors.Wrapf(err, "error retrieving lock for pod %s", p.ID())
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index 34b6ac74f..e6b84014e 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -922,7 +922,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) {
if os.IsNotExist(errors.Cause(err)) {
manager, err = lock.NewSHMLockManager(lockPath, runtime.config.NumLocks)
if err != nil {
- return err
+ return errors.Wrapf(err, "failed to get new shm lock manager")
}
} else if errors.Cause(err) == syscall.ERANGE && runtime.doRenumber {
logrus.Debugf("Number of locks does not match - removing old locks")
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 0721af773..82d999202 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -1022,3 +1022,8 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
}
return systemdgen.CreateSystemdUnitAsString(name, ctr.ID(), c.RestartPolicy, ctr.Config().StaticDir, timeout)
}
+
+// GetNamespaces returns namespace information about a container for PS
+func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared.Namespace {
+ return shared.GetNamespaces(container.Pid)
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 201249fc3..63b0f9d2f 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -234,15 +234,25 @@ func (r *LocalRuntime) StopContainers(ctx context.Context, cli *cliconfig.StopVa
ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
if err != nil {
- return ok, failures, err
+ return ok, failures, TranslateError(err)
}
for _, id := range ids {
- stopped, err := iopodman.StopContainer().Call(r.Conn, id, int64(cli.Timeout))
- if err != nil {
+ if _, err := iopodman.StopContainer().Call(r.Conn, id, int64(cli.Timeout)); err != nil {
+ transError := TranslateError(err)
+ if errors.Cause(transError) == libpod.ErrCtrStopped {
+ ok = append(ok, id)
+ continue
+ }
+ if errors.Cause(transError) == libpod.ErrCtrStateInvalid && cli.All {
+ ok = append(ok, id)
+ continue
+ }
failures[id] = err
} else {
- ok = append(ok, stopped)
+ // We should be using ID here because in varlink, only successful returns
+ // include the string id
+ ok = append(ok, id)
}
}
return ok, failures, nil
@@ -310,7 +320,7 @@ func (r *LocalRuntime) KillContainers(ctx context.Context, cli *cliconfig.KillVa
func (r *LocalRuntime) RemoveContainers(ctx context.Context, cli *cliconfig.RmValues) ([]string, map[string]error, error) {
ids, err := iopodman.GetContainersByContext().Call(r.Conn, cli.All, cli.Latest, cli.InputArgs)
if err != nil {
- return nil, nil, err
+ return nil, nil, TranslateError(err)
}
var (
@@ -961,3 +971,18 @@ func (r *LocalRuntime) Port(c *cliconfig.PortValues) ([]*Container, error) {
func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (string, error) {
return iopodman.GenerateSystemd().Call(r.Conn, c.InputArgs[0], c.RestartPolicy, int64(c.StopTimeout), c.Name)
}
+
+// GetNamespaces returns namespace information about a container for PS
+func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared.Namespace {
+ ns := shared.Namespace{
+ PID: container.PID,
+ Cgroup: container.Cgroup,
+ IPC: container.IPC,
+ MNT: container.MNT,
+ NET: container.NET,
+ PIDNS: container.PIDNS,
+ User: container.User,
+ UTS: container.UTS,
+ }
+ return &ns
+}
diff --git a/pkg/adapter/errors.go b/pkg/adapter/errors.go
new file mode 100644
index 000000000..7fbbabd93
--- /dev/null
+++ b/pkg/adapter/errors.go
@@ -0,0 +1,31 @@
+// +build remoteclient
+
+package adapter
+
+import (
+ iopodman "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod"
+ "github.com/pkg/errors"
+)
+
+// TranslateMapErrors translates the errors a typical podman output struct
+// from varlink errors to libpod errors
+func TranslateMapErrors(failures map[string]error) map[string]error {
+ for k, v := range failures {
+ failures[k] = TranslateError(v)
+ }
+ return failures
+}
+
+// TranslateError converts a single varlink error to a libpod error
+func TranslateError(err error) error {
+ switch err.(type) {
+ case *iopodman.ContainerNotFound:
+ return errors.Wrap(libpod.ErrNoSuchCtr, err.Error())
+ case *iopodman.ErrCtrStopped:
+ return errors.Wrap(libpod.ErrCtrStopped, err.Error())
+ case *iopodman.InvalidState:
+ return errors.Wrap(libpod.ErrCtrStateInvalid, err.Error())
+ }
+ return err
+}
diff --git a/pkg/adapter/info_remote.go b/pkg/adapter/info_remote.go
index 3b691ed17..3b2d02a5a 100644
--- a/pkg/adapter/info_remote.go
+++ b/pkg/adapter/info_remote.go
@@ -20,12 +20,7 @@ func (r RemoteRuntime) Info() ([]libpod.InfoData, error) {
registries := make(map[string]interface{})
insecureRegistries := make(map[string]interface{})
- conn, err := r.Connect()
- if err != nil {
- return nil, err
- }
- defer conn.Close()
- info, err := iopodman.GetInfo().Call(conn)
+ info, err := iopodman.GetInfo().Call(r.Conn)
if err != nil {
return nil, err
}
diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go
index 7cf38aac0..e2c97c36a 100644
--- a/pkg/adapter/pods_remote.go
+++ b/pkg/adapter/pods_remote.go
@@ -172,11 +172,15 @@ func (r *LocalRuntime) StartPods(ctx context.Context, cli *cliconfig.PodStartVal
// CreatePod creates a pod for the remote client over a varlink connection
func (r *LocalRuntime) CreatePod(ctx context.Context, cli *cliconfig.PodCreateValues, labels map[string]string) (string, error) {
+ var share []string
+ if cli.Share != "" {
+ share = strings.Split(cli.Share, ",")
+ }
pc := iopodman.PodCreate{
Name: cli.Name,
CgroupParent: cli.CgroupParent,
Labels: labels,
- Share: strings.Split(cli.Share, ","),
+ Share: share,
Infra: cli.Infra,
InfraCommand: cli.InfraCommand,
InfraImage: cli.InfraCommand,
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index c8be41636..8611a1a7d 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -119,6 +119,9 @@ func (i *LibpodAPI) GetContainersByContext(call iopodman.VarlinkCall, all, lates
ctrs, err := shortcuts.GetContainersByContext(all, latest, input, i.Runtime)
if err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ return call.ReplyContainerNotFound("", err.Error())
+ }
return call.ReplyErrorOccurred(err.Error())
}
@@ -359,7 +362,11 @@ func (i *LibpodAPI) StartContainer(call iopodman.VarlinkCall, name string) error
if state == libpod.ContainerStateRunning || state == libpod.ContainerStatePaused {
return call.ReplyErrorOccurred("container is already running or paused")
}
- if err := ctr.Start(getContext(), false); err != nil {
+ recursive := false
+ if ctr.PodID() != "" {
+ recursive = true
+ }
+ if err := ctr.Start(getContext(), recursive); err != nil {
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyStartContainer(ctr.ID())
@@ -386,7 +393,13 @@ func (i *LibpodAPI) StopContainer(call iopodman.VarlinkCall, name string, timeou
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
}
- if err := ctr.StopWithTimeout(uint(timeout)); err != nil && err != libpod.ErrCtrStopped {
+ if err := ctr.StopWithTimeout(uint(timeout)); err != nil {
+ if errors.Cause(err) == libpod.ErrCtrStopped {
+ return call.ReplyErrCtrStopped(ctr.ID())
+ }
+ if errors.Cause(err) == libpod.ErrCtrStateInvalid {
+ return call.ReplyInvalidState(ctr.ID(), err.Error())
+ }
return call.ReplyErrorOccurred(err.Error())
}
return call.ReplyStopContainer(ctr.ID())
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index f34375bf5..c0fd8b1f7 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -6,7 +6,6 @@ import (
"encoding/json"
"fmt"
"github.com/containers/libpod/pkg/adapter/shortcuts"
- "github.com/containers/libpod/pkg/rootless"
"syscall"
"github.com/containers/libpod/cmd/podman/shared"
@@ -37,12 +36,9 @@ func (i *LibpodAPI) CreatePod(call iopodman.VarlinkCall, create iopodman.PodCrea
if !create.Infra {
return call.ReplyErrorOccurred("you must have an infra container to publish port bindings to the host")
}
- if rootless.IsRootless() {
- return call.ReplyErrorOccurred("rootless networking does not allow port binding to the host")
- }
portBindings, err := shared.CreatePortBindings(create.Publish)
if err != nil {
- return err
+ return call.ReplyErrorOccurred(err.Error())
}
options = append(options, libpod.WithInfraContainerPorts(portBindings))
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index a6fc211f6..3c7675b35 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -264,9 +264,14 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
}
if remote {
p.PodmanTest.RemotePodmanBinary = podmanRemoteBinary
+ uuid := stringid.GenerateNonCryptoID()
if !rootless.IsRootless() {
- uuid := stringid.GenerateNonCryptoID()
p.VarlinkEndpoint = fmt.Sprintf("unix:/run/podman/io.podman-%s", uuid)
+ } else {
+ runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
+ socket := fmt.Sprintf("io.podman-%s", uuid)
+ fqpath := filepath.Join(runtimeDir, socket)
+ p.VarlinkEndpoint = fmt.Sprintf("unix:%s", fqpath)
}
}
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 105cba37c..f3367337e 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go
index fba65823e..920b920c0 100644
--- a/test/e2e/diff_test.go
+++ b/test/e2e/diff_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
@@ -63,6 +61,7 @@ var _ = Describe("Podman diff", func() {
})
It("podman diff container and committed image", func() {
+ SkipIfRemote()
session := podmanTest.Podman([]string{"run", "--name=diff-test", ALPINE, "touch", "/tmp/diff-test"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go
index c960fb311..ca4012dde 100644
--- a/test/e2e/info_test.go
+++ b/test/e2e/info_test.go
@@ -24,6 +24,7 @@ var _ = Describe("Podman Info", func() {
}
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
+ podmanTest.DelayForVarlink()
})
AfterEach(func() {
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index 618ca5aa0..3286180a4 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go
index 1e477fe2f..05c355711 100644
--- a/test/e2e/libpod_suite_remoteclient_test.go
+++ b/test/e2e/libpod_suite_remoteclient_test.go
@@ -3,13 +3,17 @@
package integration
import (
+ "bytes"
"fmt"
"github.com/containers/libpod/pkg/rootless"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
+ "strconv"
"strings"
+ "syscall"
+ "time"
"github.com/onsi/ginkgo"
)
@@ -50,33 +54,76 @@ func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
return pti
}
+func (p *PodmanTestIntegration) ResetVarlinkAddress() {
+ os.Unsetenv("PODMAN_VARLINK_ADDRESS")
+}
+
+func (p *PodmanTestIntegration) SetVarlinkAddress(addr string) {
+ os.Setenv("PODMAN_VARLINK_ADDRESS", addr)
+}
+
func (p *PodmanTestIntegration) StartVarlink() {
if os.Geteuid() == 0 {
os.MkdirAll("/run/podman", 0755)
}
varlinkEndpoint := p.VarlinkEndpoint
- if addr := os.Getenv("PODMAN_VARLINK_ADDRESS"); addr != "" {
- varlinkEndpoint = addr
- }
+ p.SetVarlinkAddress(p.VarlinkEndpoint)
args := []string{"varlink", "--timeout", "0", varlinkEndpoint}
podmanOptions := getVarlinkOptions(p, args)
command := exec.Command(p.PodmanBinary, podmanOptions...)
fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
command.Start()
+ command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
+ p.VarlinkCommand = command
p.VarlinkSession = command.Process
}
func (p *PodmanTestIntegration) StopVarlink() {
+ var out bytes.Buffer
+ var pids []int
varlinkSession := p.VarlinkSession
- varlinkSession.Kill()
- varlinkSession.Wait()
if !rootless.IsRootless() {
- socket := strings.Split(p.VarlinkEndpoint, ":")[1]
- if err := os.Remove(socket); err != nil {
- fmt.Println(err)
+ if err := varlinkSession.Kill(); err != nil {
+ fmt.Fprintf(os.Stderr, "error on varlink stop-kill %q", err)
}
+ if _, err := varlinkSession.Wait(); err != nil {
+ fmt.Fprintf(os.Stderr, "error on varlink stop-wait %q", err)
+ }
+
+ } else {
+ p.ResetVarlinkAddress()
+ parentPid := fmt.Sprintf("%d", p.VarlinkSession.Pid)
+ pgrep := exec.Command("pgrep", "-P", parentPid)
+ fmt.Printf("running: pgrep %s\n", parentPid)
+ pgrep.Stdout = &out
+ err := pgrep.Run()
+ if err != nil {
+ fmt.Fprint(os.Stderr, "unable to find varlink pid")
+ }
+
+ for _, s := range strings.Split(out.String(), "\n") {
+ if len(s) == 0 {
+ continue
+ }
+ p, err := strconv.Atoi(s)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "unable to convert %s to int", s)
+ }
+ if p != 0 {
+ pids = append(pids, p)
+ }
+ }
+
+ pids = append(pids, p.VarlinkSession.Pid)
+ for _, pid := range pids {
+ syscall.Kill(pid, syscall.SIGKILL)
+ }
+ }
+ socket := strings.Split(p.VarlinkEndpoint, ":")[1]
+ if err := os.Remove(socket); err != nil {
+ fmt.Println(err)
}
}
@@ -110,3 +157,14 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
command.Wait()
return nil
}
+
+func (p *PodmanTestIntegration) DelayForVarlink() {
+ for i := 0; i < 5; i++ {
+ session := p.Podman([]string{"info"})
+ session.WaitWithDefaultTimeout()
+ if session.ExitCode() == 0 || i == 4 {
+ break
+ }
+ time.Sleep(1 * time.Second)
+ }
+}
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index 10ca9ac47..0a85c625d 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -79,4 +79,5 @@ func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
restore.Wait(90)
return nil
}
-func (p *PodmanTestIntegration) StopVarlink() {}
+func (p *PodmanTestIntegration) StopVarlink() {}
+func (p *PodmanTestIntegration) DelayForVarlink() {}
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index d051e3dba..2c82182cf 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index de0734e9f..84966f77b 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 671d203a6..d1a023153 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_kill_test.go b/test/e2e/pod_kill_test.go
index c1f7503e3..23a8ea97e 100644
--- a/test/e2e/pod_kill_test.go
+++ b/test/e2e/pod_kill_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_pause_test.go b/test/e2e/pod_pause_test.go
index 59a4da176..ab828853b 100644
--- a/test/e2e/pod_pause_test.go
+++ b/test/e2e/pod_pause_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_prune_test.go b/test/e2e/pod_prune_test.go
index c20f602ad..8a4ba2399 100644
--- a/test/e2e/pod_prune_test.go
+++ b/test/e2e/pod_prune_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 2fa26d7ad..8513c6c2e 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_restart_test.go b/test/e2e/pod_restart_test.go
index ffb6cb94c..7b19ecc94 100644
--- a/test/e2e/pod_restart_test.go
+++ b/test/e2e/pod_restart_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index 5da3d563b..7417a1298 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_start_test.go b/test/e2e/pod_start_test.go
index de52af2a0..967fbc2da 100644
--- a/test/e2e/pod_start_test.go
+++ b/test/e2e/pod_start_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/pod_stop_test.go b/test/e2e/pod_stop_test.go
index fa285fa80..9fd9e3ef4 100644
--- a/test/e2e/pod_stop_test.go
+++ b/test/e2e/pod_stop_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 957c69aa8..7edb350f3 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/refresh_test.go b/test/e2e/refresh_test.go
deleted file mode 100644
index 56c1d255e..000000000
--- a/test/e2e/refresh_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-// +build !remoteclient
-
-package integration
-
-import (
- "os"
- "time"
-
- . "github.com/containers/libpod/test/utils"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
-)
-
-var _ = Describe("Podman refresh", func() {
- var (
- tmpdir string
- err error
- podmanTest *PodmanTestIntegration
- )
-
- BeforeEach(func() {
- tmpdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
- podmanTest = PodmanTestCreate(tmpdir)
- podmanTest.Setup()
- podmanTest.RestoreAllArtifacts()
- })
-
- AfterEach(func() {
- podmanTest.Cleanup()
- f := CurrentGinkgoTestDescription()
- processTestResult(f)
-
- })
-
- Specify("Refresh with no containers succeeds", func() {
- session := podmanTest.Podman([]string{"container", "refresh"})
- session.WaitWithDefaultTimeout()
- Expect(session.ExitCode()).To(Equal(0))
- })
-
- Specify("Refresh with created container succeeds", func() {
- createSession := podmanTest.Podman([]string{"create", ALPINE, "ls"})
- createSession.WaitWithDefaultTimeout()
- Expect(createSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
-
- refreshSession := podmanTest.Podman([]string{"container", "refresh"})
- refreshSession.WaitWithDefaultTimeout()
- Expect(refreshSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
- })
-
- Specify("Refresh with running container restarts container", func() {
- createSession := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"})
- createSession.WaitWithDefaultTimeout()
- Expect(createSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
-
- // HACK: ensure container starts before we move on
- time.Sleep(1 * time.Second)
-
- refreshSession := podmanTest.Podman([]string{"container", "refresh"})
- refreshSession.WaitWithDefaultTimeout()
- Expect(refreshSession.ExitCode()).To(Equal(0))
- Expect(podmanTest.NumberOfContainers()).To(Equal(1))
- Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
- })
-})
diff --git a/test/e2e/rm_test.go b/test/e2e/rm_test.go
index 9bf742a63..29150d67c 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 030722b47..0e1f0d865 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -273,6 +273,7 @@ var _ = Describe("Podman run", func() {
})
It("podman run notify_socket", func() {
+ SkipIfRemote()
host := GetHostDistributionInfo()
if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" {
Skip("this test requires a working runc")
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index c3edc7c7e..ffb5182d6 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
+ "github.com/containers/libpod/pkg/rootless"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -75,6 +76,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with oci format", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--format", "oci-dir", "-o", outdir, ALPINE})
@@ -83,6 +87,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with v2s2 docker format", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--format", "docker-dir", "-o", outdir, ALPINE})
@@ -91,6 +98,9 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with docker format and compression", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
outdir := filepath.Join(podmanTest.TempDir, "save")
save := podmanTest.Podman([]string{"save", "--compress", "--format", "docker-dir", "-o", outdir, ALPINE})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 717eea441..e201204df 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/tag_test.go b/test/e2e/tag_test.go
index ff0ac31c4..26d6dfa75 100644
--- a/test/e2e/tag_test.go
+++ b/test/e2e/tag_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/e2e/wait_test.go b/test/e2e/wait_test.go
index 5bf0331e5..28a4c1e40 100644
--- a/test/e2e/wait_test.go
+++ b/test/e2e/wait_test.go
@@ -1,5 +1,3 @@
-// +build !remoteclient
-
package integration
import (
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 1e0391d2e..beadab549 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -4,7 +4,6 @@ import (
"bufio"
"encoding/json"
"fmt"
- "github.com/containers/libpod/pkg/rootless"
"io/ioutil"
"os"
"os/exec"
@@ -42,6 +41,7 @@ type PodmanTest struct {
RemotePodmanBinary string
VarlinkSession *os.Process
VarlinkEndpoint string
+ VarlinkCommand *exec.Cmd
}
// PodmanSession wraps the gexec.session so we can extend it
@@ -69,9 +69,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
podmanBinary := p.PodmanBinary
if p.RemoteTest {
podmanBinary = p.RemotePodmanBinary
- if !rootless.IsRootless() {
- env = append(env, fmt.Sprintf("PODMAN_VARLINK_ADDRESS=%s", p.VarlinkEndpoint))
- }
+ env = append(env, fmt.Sprintf("PODMAN_VARLINK_ADDRESS=%s", p.VarlinkEndpoint))
}
if env == nil {