diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/rootless/rootless_linux.c | 35 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 166 | ||||
-rw-r--r-- | pkg/varlinkapi/pods.go | 15 |
3 files changed, 215 insertions, 1 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 279a03d3f..acc5d6b2a 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -12,6 +12,7 @@ #include <fcntl.h> #include <sys/wait.h> #include <string.h> +#include <stdbool.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"; @@ -186,6 +187,18 @@ reexec_in_user_namespace (int ready) pid_t ppid = getpid (); char **argv; char uid[16]; + char *listen_fds = NULL; + char *listen_pid = NULL; + bool do_socket_activation = false; + + listen_pid = getenv("LISTEN_PID"); + listen_fds = getenv("LISTEN_FDS"); + + if (listen_pid != NULL && listen_fds != NULL) { + if (strtol(listen_pid, NULL, 10) == getpid()) { + do_socket_activation = true; + } + } sprintf (uid, "%d", geteuid ()); @@ -197,8 +210,22 @@ reexec_in_user_namespace (int ready) check_proc_sys_userns_file (_max_user_namespaces); check_proc_sys_userns_file (_unprivileged_user_namespaces); } - if (pid) + if (pid) { + if (do_socket_activation) { + long num_fds; + num_fds = strtol(listen_fds, NULL, 10); + if (num_fds != LONG_MIN && num_fds != LONG_MAX) { + long i; + for (i = 0; i < num_fds; i++) { + close(3+i); + } + } + unsetenv("LISTEN_PID"); + unsetenv("LISTEN_FDS"); + unsetenv("LISTEN_FDNAMES"); + } return pid; + } argv = get_cmd_line_args (ppid); if (argv == NULL) @@ -207,6 +234,12 @@ reexec_in_user_namespace (int ready) _exit (EXIT_FAILURE); } + if (do_socket_activation) { + char s[32]; + sprintf(s, "%d", getpid()); + setenv("LISTEN_PID", s, true); + } + setenv ("_LIBPOD_USERNS_CONFIGURED", "init", 1); setenv ("_LIBPOD_ROOTLESS_UID", uid, 1); diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index d12ab97ab..a27bdb9e5 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -736,3 +736,169 @@ func (i *LibpodAPI) ImagesPrune(call iopodman.VarlinkCall, all bool) error { } return call.ReplyImagesPrune(prunedImages) } + +// ImageSave .... +func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageSaveOptions) error { + newImage, err := i.Runtime.ImageRuntime().NewFromLocal(options.Name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + // Determine if we are dealing with a tarball or dir + var output string + outputToDir := false + if options.Format == "oci-archive" || options.Format == "docker-archive" { + tempfile, err := ioutil.TempFile("", "varlink_send") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + output = tempfile.Name() + tempfile.Close() + } else { + var err error + outputToDir = true + output, err = ioutil.TempDir("", "varlink_send") + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + } + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + if call.WantsMore() { + call.Continues = true + } + + saveOutput := bytes.NewBuffer([]byte{}) + c := make(chan error) + go func() { + err := newImage.Save(getContext(), options.Name, options.Format, output, options.MoreTags, options.Quiet, options.Compress) + c <- err + close(c) + }() + var log []string + done := false + for { + line, err := saveOutput.ReadString('\n') + if err == nil { + log = append(log, line) + continue + } else if err == io.EOF { + select { + case err := <-c: + if err != nil { + logrus.Errorf("reading of output during save failed for %s", newImage.ID()) + return call.ReplyErrorOccurred(err.Error()) + } + done = true + default: + if !call.WantsMore() { + time.Sleep(1 * time.Second) + break + } + br := iopodman.MoreResponse{ + Logs: log, + } + call.ReplyImageSave(br) + log = []string{} + } + } else { + return call.ReplyErrorOccurred(err.Error()) + } + if done { + break + } + } + call.Continues = false + + sendfile := output + // Image has been saved to `output` + if outputToDir { + // If the output is a directory, we need to tar up the directory to send it back + //Create a tempfile for the directory tarball + outputFile, err := ioutil.TempFile("", "varlink_save_dir") + if err != nil { + return err + } + defer outputFile.Close() + if err := utils.TarToFilesystem(output, outputFile); err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + sendfile = outputFile.Name() + } + br := iopodman.MoreResponse{ + Logs: log, + Id: sendfile, + } + return call.ReplyPushImage(br) +} + +// LoadImage ... +func (i *LibpodAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string, deleteInputFile, quiet bool) error { + var ( + names string + writer io.Writer + err error + ) + if !quiet { + writer = os.Stderr + } + + if call.WantsMore() { + call.Continues = true + } + output := bytes.NewBuffer([]byte{}) + + c := make(chan error) + go func() { + names, err = i.Runtime.LoadImage(getContext(), name, inputFile, writer, "") + c <- err + close(c) + }() + + var log []string + done := false + for { + line, err := output.ReadString('\n') + if err == nil { + log = append(log, line) + continue + } else if err == io.EOF { + select { + case err := <-c: + if err != nil { + logrus.Error(err) + return call.ReplyErrorOccurred(err.Error()) + } + done = true + default: + if !call.WantsMore() { + time.Sleep(1 * time.Second) + break + } + br := iopodman.MoreResponse{ + Logs: log, + } + call.ReplyLoadImage(br) + log = []string{} + } + } else { + return call.ReplyErrorOccurred(err.Error()) + } + if done { + break + } + } + call.Continues = false + + br := iopodman.MoreResponse{ + Logs: log, + Id: names, + } + if deleteInputFile { + if err := os.Remove(inputFile); err != nil { + logrus.Errorf("unable to delete input file %s", inputFile) + } + } + return call.ReplyLoadImage(br) +} diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go index 6e758786a..1dd864d03 100644 --- a/pkg/varlinkapi/pods.go +++ b/pkg/varlinkapi/pods.go @@ -2,6 +2,7 @@ package varlinkapi import ( "encoding/json" + "github.com/containers/libpod/libpod/adapter/shortcuts" "github.com/containers/libpod/pkg/rootless" "syscall" @@ -271,3 +272,17 @@ func (i *LibpodAPI) GetPodStats(call iopodman.VarlinkCall, name string) error { } return call.ReplyGetPodStats(pod.ID(), containersStats) } + +// GetPodsByContext returns a slice of pod ids based on all, latest, or a list +func (i *LibpodAPI) GetPodsByContext(call iopodman.VarlinkCall, all, latest bool, input []string) error { + var podids []string + + pods, err := shortcuts.GetPodsByContext(all, latest, input, i.Runtime) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + for _, p := range pods { + podids = append(podids, p.ID()) + } + return call.ReplyGetPodsByContext(podids) +} |