summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go69
-rw-r--r--pkg/adapter/containers_remote.go72
-rw-r--r--pkg/adapter/runtime.go29
-rw-r--r--pkg/adapter/runtime_remote.go19
-rw-r--r--pkg/rootless/rootless_linux.c7
-rw-r--r--pkg/rootless/rootless_linux.go14
-rw-r--r--pkg/varlinkapi/generate.go30
7 files changed, 214 insertions, 26 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index d4e8e30d9..931c55a57 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -257,7 +257,10 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
results := shared.NewIntermediateLayer(&c.PodmanCommand, false)
ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime)
- return ctr.ID(), err
+ if err != nil {
+ return "", err
+ }
+ return ctr.ID(), nil
}
// Run a libpod container
@@ -443,3 +446,67 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
}
return nil
}
+
+// Checkpoint one or more containers
+func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
+ var (
+ containers []*libpod.Container
+ err, lastError error
+ )
+
+ if c.All {
+ containers, err = r.Runtime.GetRunningContainers()
+ } else {
+ containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ }
+ if err != nil {
+ return err
+ }
+
+ for _, ctr := range containers {
+ if err = ctr.Checkpoint(context.TODO(), options); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to checkpoint container %v", ctr.ID())
+ } else {
+ fmt.Println(ctr.ID())
+ }
+ }
+ return lastError
+}
+
+// Restore one or more containers
+func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
+ var (
+ containers []*libpod.Container
+ err, lastError error
+ filterFuncs []libpod.ContainerFilter
+ )
+
+ filterFuncs = append(filterFuncs, func(c *libpod.Container) bool {
+ state, _ := c.State()
+ return state == libpod.ContainerStateExited
+ })
+
+ if c.All {
+ containers, err = r.GetContainers(filterFuncs...)
+ } else {
+ containers, err = shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime)
+ }
+ if err != nil {
+ return err
+ }
+
+ for _, ctr := range containers {
+ if err = ctr.Restore(context.TODO(), options); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to restore container %v", ctr.ID())
+ } else {
+ fmt.Println(ctr.ID())
+ }
+ }
+ return lastError
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 9ca823760..50cff9fa0 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -537,3 +537,75 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er
}
return <-errChan
}
+
+// Checkpoint one or more containers
+func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues, options libpod.ContainerCheckpointOptions) error {
+ var lastError error
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ return err
+ }
+ if c.All {
+ // We dont have a great way to get all the running containers, so need to get all and then
+ // check status on them bc checkpoint considers checkpointing a stopped container an error
+ var runningIds []string
+ for _, id := range ids {
+ ctr, err := r.LookupContainer(id)
+ if err != nil {
+ return err
+ }
+ if ctr.state.State == libpod.ContainerStateRunning {
+ runningIds = append(runningIds, id)
+ }
+ }
+ ids = runningIds
+ }
+
+ for _, id := range ids {
+ if _, err := iopodman.ContainerCheckpoint().Call(r.Conn, id, options.Keep, options.KeepRunning, options.TCPEstablished); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to checkpoint container %v", id)
+ } else {
+ fmt.Println(id)
+ }
+ }
+ return lastError
+}
+
+// Restore one or more containers
+func (r *LocalRuntime) Restore(c *cliconfig.RestoreValues, options libpod.ContainerCheckpointOptions) error {
+ var lastError error
+ ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs)
+ if err != nil {
+ return err
+ }
+ if c.All {
+ // We dont have a great way to get all the exited containers, so need to get all and then
+ // check status on them bc checkpoint considers restoring a running container an error
+ var exitedIDs []string
+ for _, id := range ids {
+ ctr, err := r.LookupContainer(id)
+ if err != nil {
+ return err
+ }
+ if ctr.state.State != libpod.ContainerStateRunning {
+ exitedIDs = append(exitedIDs, id)
+ }
+ }
+ ids = exitedIDs
+ }
+
+ for _, id := range ids {
+ if _, err := iopodman.ContainerRestore().Call(r.Conn, id, options.Keep, options.TCPEstablished); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to restore container %v", id)
+ } else {
+ fmt.Println(id)
+ }
+ }
+ return lastError
+}
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index d45bdb56d..6aafed550 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -7,6 +7,7 @@ import (
"context"
"io"
"io/ioutil"
+ "k8s.io/api/core/v1"
"os"
"text/template"
@@ -404,27 +405,7 @@ func (r *LocalRuntime) Diff(c *cliconfig.DiffValues, to string) ([]archive.Chang
return r.Runtime.GetDiff("", to)
}
-// func (r *LocalRuntime) joinContainerOrCreateRootlessUserNS(ctr *libpod.Container) (bool, int, error) {
-// if os.Geteuid() == 0 {
-// return false, 0, nil
-// }
-// s, err := ctr.State()
-// if err != nil {
-// return false, -1, err
-// }
-// opts := rootless.Opts{
-// Argument: ctr.ID(),
-// }
-// if s == libpod.ContainerStateRunning || s == libpod.ContainerStatePaused {
-// data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile)
-// if err != nil {
-// return false, -1, errors.Wrapf(err, "Container %s cannot read conmon PID file %q", ctr.ID(), ctr.Config().ConmonPidFile)
-// }
-// conmonPid, err := strconv.Atoi(string(data))
-// if err != nil {
-// return false, -1, errors.Wrapf(err, "Container %s cannot parse PID %q", ctr.ID(), data)
-// }
-// return rootless.JoinDirectUserAndMountNSWithOpts(uint(conmonPid), &opts)
-// }
-// return rootless.BecomeRootInUserNSWithOpts(&opts)
-// }
+// GenerateKube creates kubernetes email from containers and pods
+func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) {
+ return shared.GenerateKube(c.InputArgs[0], c.Service, r.Runtime)
+}
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 807a9ad8f..71f7380db 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -5,9 +5,11 @@ package adapter
import (
"bufio"
"context"
+ "encoding/json"
"fmt"
"io"
"io/ioutil"
+ v1 "k8s.io/api/core/v1"
"os"
"strings"
"text/template"
@@ -858,3 +860,20 @@ func stringToChangeType(change string) archive.ChangeType {
return archive.ChangeModify
}
}
+
+// GenerateKube creates kubernetes email from containers and pods
+func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) {
+ var (
+ pod v1.Pod
+ service v1.Service
+ )
+ reply, err := iopodman.GenerateKube().Call(r.Conn, c.InputArgs[0], c.Service)
+ if err != nil {
+ return nil, nil, errors.Wrap(err, "unable to create kubernetes YAML")
+ }
+ if err := json.Unmarshal([]byte(reply.Pod), &pod); err != nil {
+ return nil, nil, err
+ }
+ err = json.Unmarshal([]byte(reply.Service), &service)
+ return &pod, &service, err
+}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 9cb79ed4d..d6a2793a7 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -16,6 +16,8 @@
#include <sys/types.h>
#include <sys/prctl.h>
#include <dirent.h>
+#include <termios.h>
+#include <sys/ioctl.h>
static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces";
static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone";
@@ -178,6 +180,11 @@ reexec_userns_join (int userns, int mountns)
_exit (EXIT_FAILURE);
}
+ if (isatty (1) && ioctl (1, TIOCSCTTY, 0) == -1) {
+ fprintf (stderr, "cannot ioctl(TIOCSCTTY): %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
+
if (setns (userns, 0) < 0)
{
fprintf (stderr, "cannot setns: %s\n", strerror (errno));
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 1d1b1713d..2c99f41a4 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -28,6 +28,10 @@ extern int reexec_userns_join(int userns, int mountns);
*/
import "C"
+const (
+ numSig = 65 // max number of signals
+)
+
func runInUser() error {
os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done")
return nil
@@ -283,7 +287,15 @@ func BecomeRootInUserNS() (bool, int, error) {
c := make(chan os.Signal, 1)
- gosignal.Notify(c)
+ signals := []os.Signal{}
+ for sig := 0; sig < numSig; sig++ {
+ if sig == int(syscall.SIGTSTP) {
+ continue
+ }
+ signals = append(signals, syscall.Signal(sig))
+ }
+
+ gosignal.Notify(c, signals...)
defer gosignal.Reset()
go func() {
for s := range c {
diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go
new file mode 100644
index 000000000..bc600c397
--- /dev/null
+++ b/pkg/varlinkapi/generate.go
@@ -0,0 +1,30 @@
+// +build varlink
+
+package varlinkapi
+
+import (
+ "encoding/json"
+ "github.com/containers/libpod/cmd/podman/shared"
+ iopodman "github.com/containers/libpod/cmd/podman/varlink"
+)
+
+// GenerateKube ...
+func (i *LibpodAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error {
+ pod, serv, err := shared.GenerateKube(name, service, i.Runtime)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ podB, err := json.Marshal(pod)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ servB, err := json.Marshal(serv)
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+
+ return call.ReplyGenerateKube(iopodman.KubePodService{
+ Pod: string(podB),
+ Service: string(servB),
+ })
+}