summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go2
-rw-r--r--pkg/adapter/network.go147
-rw-r--r--pkg/adapter/pods.go2
-rw-r--r--pkg/adapter/runtime.go5
-rw-r--r--pkg/adapter/runtime_remote.go7
-rw-r--r--pkg/cgroups/cgroups.go73
-rw-r--r--pkg/cgroups/systemd.go23
-rw-r--r--pkg/hooks/hooks.go3
-rw-r--r--pkg/network/config.go4
-rw-r--r--pkg/network/network.go26
-rw-r--r--pkg/rootless/rootless_linux.c14
-rw-r--r--pkg/spec/storage.go9
-rw-r--r--pkg/util/mountOpts.go3
-rw-r--r--pkg/util/utils_windows.go12
-rw-r--r--pkg/varlinkapi/containers.go9
15 files changed, 297 insertions, 42 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index b712bd9aa..45a9a54a3 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -342,7 +342,7 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode
if err := ctr.Start(ctx, c.IsSet("pod")); err != nil {
// This means the command did not exist
exitCode = 127
- if strings.Contains(err.Error(), "permission denied") {
+ if strings.Contains(err.Error(), "permission denied") || strings.Contains(err.Error(), "file not found") {
exitCode = 126
}
return exitCode, err
diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go
new file mode 100644
index 000000000..cf3a1dfdd
--- /dev/null
+++ b/pkg/adapter/network.go
@@ -0,0 +1,147 @@
+// +build !remoteclient
+
+package adapter
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "text/tabwriter"
+
+ "github.com/containernetworking/cni/libcni"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/pkg/network"
+ "github.com/pkg/errors"
+)
+
+func getCNIConfDir(r *LocalRuntime) (string, error) {
+ config, err := r.GetConfig()
+ if err != nil {
+ return "", err
+ }
+ configPath := config.CNIConfigDir
+
+ if len(config.CNIConfigDir) < 1 {
+ configPath = network.CNIConfigDir
+ }
+ return configPath, nil
+}
+
+// NetworkList displays summary information about CNI networks
+func (r *LocalRuntime) NetworkList(cli *cliconfig.NetworkListValues) error {
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ networks, err := network.LoadCNIConfsFromDir(cniConfigPath)
+ if err != nil {
+ return err
+ }
+ // quiet means we only print the network names
+ if cli.Quiet {
+ for _, cniNetwork := range networks {
+ fmt.Println(cniNetwork.Name)
+ }
+ return nil
+ }
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
+ if _, err := fmt.Fprintln(w, "NAME\tVERSION\tPLUGINS"); err != nil {
+ return err
+ }
+ for _, cniNetwork := range networks {
+ if _, err := fmt.Fprintf(w, "%s\t%s\t%s\n", cniNetwork.Name, cniNetwork.CNIVersion, getCNIPlugins(cniNetwork)); err != nil {
+ return err
+ }
+ }
+ return w.Flush()
+}
+
+// NetworkInspect displays the raw CNI configuration for one
+// or more CNI networks
+func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error {
+ var (
+ rawCNINetworks []map[string]interface{}
+ )
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ for _, name := range cli.InputArgs {
+ b, err := readRawCNIConfByName(name, cniConfigPath)
+ if err != nil {
+ return err
+ }
+ rawList := make(map[string]interface{})
+ if err := json.Unmarshal(b, &rawList); err != nil {
+ return fmt.Errorf("error parsing configuration list: %s", err)
+ }
+ rawCNINetworks = append(rawCNINetworks, rawList)
+ }
+ out, err := json.MarshalIndent(rawCNINetworks, "", "\t")
+ if err != nil {
+ return err
+ }
+ fmt.Printf("%s\n", out)
+ return nil
+}
+
+// NetworkRemove deletes one or more CNI networks
+func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error {
+ cniConfigPath, err := getCNIConfDir(r)
+ if err != nil {
+ return err
+ }
+ for _, name := range cli.InputArgs {
+ cniPath, err := getCNIConfigPathByName(name, cniConfigPath)
+ if err != nil {
+ return err
+ }
+ if err := os.Remove(cniPath); err != nil {
+ return err
+ }
+ fmt.Printf("Deleted: %s\n", name)
+ }
+ return nil
+}
+
+// getCNIConfigPathByName finds a CNI network by name and
+// returns its configuration file path
+func getCNIConfigPathByName(name, cniConfigPath string) (string, error) {
+ files, err := libcni.ConfFiles(cniConfigPath, []string{".conflist"})
+ if err != nil {
+ return "", err
+ }
+ for _, confFile := range files {
+ conf, err := libcni.ConfListFromFile(confFile)
+ if err != nil {
+ return "", err
+ }
+ if conf.Name == name {
+ return confFile, nil
+ }
+ }
+ return "", errors.Errorf("unable to find network configuration for %s", name)
+}
+
+// readRawCNIConfByName reads the raw CNI configuration for a CNI
+// network by name
+func readRawCNIConfByName(name, cniConfigPath string) ([]byte, error) {
+ confFile, err := getCNIConfigPathByName(name, cniConfigPath)
+ if err != nil {
+ return nil, err
+ }
+ b, err := ioutil.ReadFile(confFile)
+ return b, err
+}
+
+// getCNIPlugins returns a list of plugins that a given network
+// has in the form of a string
+func getCNIPlugins(list *libcni.NetworkConfigList) string {
+ var plugins []string
+ for _, plug := range list.Plugins {
+ plugins = append(plugins, plug.Network.Type)
+ }
+ return strings.Join(plugins, ",")
+}
diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go
index 66588ce26..1dd72babf 100644
--- a/pkg/adapter/pods.go
+++ b/pkg/adapter/pods.go
@@ -708,6 +708,8 @@ func kubeContainerToCreateConfig(ctx context.Context, containerYAML v1.Container
return nil, errors.Errorf("No command specified in container YAML or as CMD or ENTRYPOINT in this image for %s", containerConfig.Name)
}
+ containerConfig.UserCommand = containerConfig.Command
+
containerConfig.StopSignal = 15
// If the user does not pass in ID mappings, just set to basics
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index 61db65a9d..ba988aaf7 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -289,9 +289,12 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti
options.CommonBuildOpts = commonOpts
options.SystemContext = systemContext
- if c.Flag("runtime").Changed {
+ if c.GlobalFlags.Runtime != "" {
+ options.Runtime = c.GlobalFlags.Runtime
+ } else {
options.Runtime = r.GetOCIRuntimePath()
}
+
if c.Quiet {
options.ReportWriter = ioutil.Discard
}
diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go
index 39ea88131..420c9d0bb 100644
--- a/pkg/adapter/runtime_remote.go
+++ b/pkg/adapter/runtime_remote.go
@@ -10,6 +10,7 @@ import (
"io"
"io/ioutil"
"os"
+ "path/filepath"
"strings"
"text/template"
"time"
@@ -69,6 +70,12 @@ func GetRuntime(ctx context.Context, c *cliconfig.PodmanCommand) (*LocalRuntime,
cmd: c.GlobalFlags,
}
configPath := remoteclientconfig.GetConfigFilePath()
+ // Check if the basedir for configPath exists and if not, create it.
+ if _, err := os.Stat(filepath.Dir(configPath)); os.IsNotExist(err) {
+ if mkdirErr := os.MkdirAll(filepath.Dir(configPath), 0750); mkdirErr != nil {
+ return nil, mkdirErr
+ }
+ }
if len(c.GlobalFlags.RemoteConfigFilePath) > 0 {
configPath = c.GlobalFlags.RemoteConfigFilePath
customConfig = true
diff --git a/pkg/cgroups/cgroups.go b/pkg/cgroups/cgroups.go
index f2c6b548e..085718855 100644
--- a/pkg/cgroups/cgroups.go
+++ b/pkg/cgroups/cgroups.go
@@ -10,6 +10,8 @@ import (
"strconv"
"strings"
+ systemdDbus "github.com/coreos/go-systemd/dbus"
+ "github.com/godbus/dbus"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -352,7 +354,56 @@ func (c *CgroupControl) CreateSystemdUnit(path string) error {
if !c.systemd {
return fmt.Errorf("the cgroup controller is not using systemd")
}
- return systemdCreate(path)
+
+ conn, err := systemdDbus.New()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ return systemdCreate(path, conn)
+}
+
+// GetUserConnection returns an user connection to D-BUS
+func GetUserConnection(uid int) (*systemdDbus.Conn, error) {
+ return systemdDbus.NewConnection(func() (*dbus.Conn, error) {
+ return dbusAuthConnection(uid, dbus.SessionBusPrivate)
+ })
+}
+
+// CreateSystemdUserUnit creates the systemd cgroup for the specified user
+func (c *CgroupControl) CreateSystemdUserUnit(path string, uid int) error {
+ if !c.systemd {
+ return fmt.Errorf("the cgroup controller is not using systemd")
+ }
+
+ conn, err := GetUserConnection(uid)
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ return systemdCreate(path, conn)
+}
+
+func dbusAuthConnection(uid int, createBus func(opts ...dbus.ConnOption) (*dbus.Conn, error)) (*dbus.Conn, error) {
+ conn, err := createBus()
+ if err != nil {
+ return nil, err
+ }
+
+ methods := []dbus.Auth{dbus.AuthExternal(strconv.Itoa(uid))}
+
+ err = conn.Auth(methods)
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ if err := conn.Hello(); err != nil {
+ return nil, err
+ }
+
+ return conn, nil
}
// Delete cleans a cgroup
@@ -386,10 +437,11 @@ func rmDirRecursively(path string) error {
return nil
}
-// DeleteByPath deletes the specified cgroup path
-func (c *CgroupControl) DeleteByPath(path string) error {
+// DeleteByPathConn deletes the specified cgroup path using the specified
+// dbus connection if needed.
+func (c *CgroupControl) DeleteByPathConn(path string, conn *systemdDbus.Conn) error {
if c.systemd {
- return systemdDestroy(path)
+ return systemdDestroyConn(path, conn)
}
if c.cgroup2 {
return rmDirRecursively(filepath.Join(cgroupRoot, c.path))
@@ -413,6 +465,19 @@ func (c *CgroupControl) DeleteByPath(path string) error {
return lastError
}
+// DeleteByPath deletes the specified cgroup path
+func (c *CgroupControl) DeleteByPath(path string) error {
+ if c.systemd {
+ conn, err := systemdDbus.New()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+ return c.DeleteByPathConn(path, conn)
+ }
+ return c.DeleteByPathConn(path, nil)
+}
+
// Update updates the cgroups
func (c *CgroupControl) Update(resources *spec.LinuxResources) error {
for _, h := range handlers {
diff --git a/pkg/cgroups/systemd.go b/pkg/cgroups/systemd.go
index e72e456bc..b8e6db156 100644
--- a/pkg/cgroups/systemd.go
+++ b/pkg/cgroups/systemd.go
@@ -9,13 +9,7 @@ import (
"github.com/godbus/dbus"
)
-func systemdCreate(path string) error {
- c, err := systemdDbus.New()
- if err != nil {
- return err
- }
- defer c.Close()
-
+func systemdCreate(path string, c *systemdDbus.Conn) error {
slice, name := filepath.Split(path)
slice = strings.TrimSuffix(slice, "/")
@@ -43,7 +37,7 @@ func systemdCreate(path string) error {
}
ch := make(chan string)
- _, err = c.StartTransientUnit(name, "replace", properties, ch)
+ _, err := c.StartTransientUnit(name, "replace", properties, ch)
if err != nil {
lastError = err
continue
@@ -55,7 +49,7 @@ func systemdCreate(path string) error {
}
/*
- systemdDestroy is copied from containerd/cgroups/systemd.go file, that
+ systemdDestroyConn is copied from containerd/cgroups/systemd.go file, that
has the following license:
Copyright The containerd Authors.
@@ -72,18 +66,11 @@ func systemdCreate(path string) error {
See the License for the specific language governing permissions and
limitations under the License.
*/
-
-func systemdDestroy(path string) error {
- c, err := systemdDbus.New()
- if err != nil {
- return err
- }
- defer c.Close()
-
+func systemdDestroyConn(path string, c *systemdDbus.Conn) error {
name := filepath.Base(path)
ch := make(chan string)
- _, err = c.StopUnit(name, "replace", ch)
+ _, err := c.StopUnit(name, "replace", ch)
if err != nil {
return err
}
diff --git a/pkg/hooks/hooks.go b/pkg/hooks/hooks.go
index b962ffa5c..0d26bf4af 100644
--- a/pkg/hooks/hooks.go
+++ b/pkg/hooks/hooks.go
@@ -4,6 +4,7 @@ package hooks
import (
"context"
"fmt"
+ "os"
"sort"
"strings"
"sync"
@@ -56,7 +57,7 @@ func New(ctx context.Context, directories []string, extensionStages []string) (m
for _, dir := range directories {
err = ReadDir(dir, manager.extensionStages, manager.hooks)
- if err != nil {
+ if err != nil && !os.IsNotExist(err) {
return nil, err
}
}
diff --git a/pkg/network/config.go b/pkg/network/config.go
new file mode 100644
index 000000000..d282f66b6
--- /dev/null
+++ b/pkg/network/config.go
@@ -0,0 +1,4 @@
+package network
+
+// CNIConfigDir is the path where CNI config files exist
+const CNIConfigDir = "/etc/cni/net.d"
diff --git a/pkg/network/network.go b/pkg/network/network.go
new file mode 100644
index 000000000..9d04340a3
--- /dev/null
+++ b/pkg/network/network.go
@@ -0,0 +1,26 @@
+package network
+
+import (
+ "sort"
+
+ "github.com/containernetworking/cni/libcni"
+)
+
+// LoadCNIConfsFromDir loads all the CNI configurations from a dir
+func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
+ var configs []*libcni.NetworkConfigList
+ files, err := libcni.ConfFiles(dir, []string{".conflist"})
+ if err != nil {
+ return nil, err
+ }
+ sort.Strings(files)
+
+ for _, confFile := range files {
+ conf, err := libcni.ConfListFromFile(confFile)
+ if err != nil {
+ return nil, err
+ }
+ configs = append(configs, conf)
+ }
+ return configs, nil
+}
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 19b76f387..94933ddd0 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -137,7 +137,7 @@ get_cmd_line_args (pid_t pid)
{
allocated += 512;
char *tmp = realloc (buffer, allocated);
- if (buffer == NULL)
+ if (tmp == NULL)
{
free (buffer);
return NULL;
@@ -276,7 +276,7 @@ static void __attribute__((constructor)) init()
return;
}
- r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf)));
+ r = TEMP_FAILURE_RETRY (read (fd, buf, sizeof (buf) - 1));
close (fd);
if (r < 0)
{
@@ -457,6 +457,11 @@ create_pause_process (const char *pause_pid_file_path, char **argv)
}
r = TEMP_FAILURE_RETRY (write (p[1], "0", 1));
+ if (r < 0)
+ {
+ fprintf (stderr, "cannot write to pipe: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
close (p[1]);
_exit (EXIT_SUCCESS);
@@ -811,6 +816,11 @@ reexec_in_user_namespace (int ready, char *pause_pid_file_path, char *file_to_re
}
ret = TEMP_FAILURE_RETRY (write (ready, "0", 1));
+ if (ret < 0)
+ {
+ fprintf (stderr, "cannot write to ready pipe: %s\n", strerror (errno));
+ _exit (EXIT_FAILURE);
+ }
close (ready);
if (sigprocmask (SIG_SETMASK, &oldsigset, NULL) < 0)
diff --git a/pkg/spec/storage.go b/pkg/spec/storage.go
index e0bb48a9c..b634f4cac 100644
--- a/pkg/spec/storage.go
+++ b/pkg/spec/storage.go
@@ -168,14 +168,14 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
"/run": false,
}
if config.ReadOnlyRootfs && config.ReadOnlyTmpfs {
- options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup", "size=65536k"}
+ options := []string{"rw", "rprivate", "nosuid", "nodev", "tmpcopyup"}
for dest := range readonlyTmpfs {
if _, ok := baseMounts[dest]; ok {
continue
}
localOpts := options
if dest == "/run" {
- localOpts = append(localOpts, "noexec")
+ localOpts = append(localOpts, "noexec", "size=65536k")
}
baseMounts[dest] = spec.Mount{
Destination: dest,
@@ -238,11 +238,6 @@ func (config *CreateConfig) parseVolumes(runtime *libpod.Runtime) ([]spec.Mount,
// Conflicts are resolved simply - the last container specified wins.
// Container names may be suffixed by mount options after a colon.
func (config *CreateConfig) getVolumesFrom(runtime *libpod.Runtime) (map[string]spec.Mount, map[string]*libpod.ContainerNamedVolume, error) {
- // TODO: This can probably be disabled now
- if os.Geteuid() != 0 {
- return nil, nil, nil
- }
-
// Both of these are maps of mount destination to mount type.
// We ensure that each destination is only mounted to once in this way.
finalMounts := make(map[string]spec.Mount)
diff --git a/pkg/util/mountOpts.go b/pkg/util/mountOpts.go
index 40c99384d..9b2c734c0 100644
--- a/pkg/util/mountOpts.go
+++ b/pkg/util/mountOpts.go
@@ -92,9 +92,6 @@ func ProcessTmpfsOptions(options []string) ([]string, error) {
if !foundWrite {
baseOpts = append(baseOpts, "rw")
}
- if !foundSize {
- baseOpts = append(baseOpts, "size=65536k")
- }
if !foundProp {
baseOpts = append(baseOpts, "rprivate")
}
diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go
index e7b2a272e..e781e6717 100644
--- a/pkg/util/utils_windows.go
+++ b/pkg/util/utils_windows.go
@@ -6,29 +6,31 @@ import (
"github.com/pkg/errors"
)
+var errNotImplemented = errors.New("not yet implemented")
+
// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode.
func IsCgroup2UnifiedMode() (bool, error) {
- return false, errors.New("this function is not implemented for windows")
+ return false, errors.Wrap(errNotImplemented, "IsCgroup2Unified")
}
// GetContainerPidInformationDescriptors returns a string slice of all supported
// format descriptors of GetContainerPidInformation.
func GetContainerPidInformationDescriptors() ([]string, error) {
- return nil, errors.New("this function is not implemented for windows")
+ return nil, errors.Wrap(errNotImplemented, "GetContainerPidInformationDescriptors")
}
// GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for
// the pause process
func GetRootlessPauseProcessPidPath() (string, error) {
- return "", errors.New("this function is not implemented for windows")
+ return "", errors.Wrap(errNotImplemented, "GetRootlessPauseProcessPidPath")
}
// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir() (string, error) {
- return "", errors.New("this function is not implemented for windows")
+ return "", errors.Wrap(errNotImplemented, "GetRootlessRuntimeDir")
}
// GetRootlessConfigHomeDir returns the config home directory when running as non root
func GetRootlessConfigHomeDir() (string, error) {
- return "", errors.New("this function is not implemented for windows")
+ return "", errors.Wrap(errNotImplemented, "GetRootlessConfigHomeDir")
}
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index bb66ff962..c7aa5233f 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -19,6 +19,8 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/adapter/shortcuts"
+ "github.com/containers/libpod/pkg/cgroups"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/varlinkapi/virtwriter"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
@@ -317,6 +319,13 @@ func (i *LibpodAPI) ExportContainer(call iopodman.VarlinkCall, name, outPath str
// GetContainerStats ...
func (i *LibpodAPI) GetContainerStats(call iopodman.VarlinkCall, name string) error {
+ cgroupv2, err := cgroups.IsCgroup2UnifiedMode()
+ if err != nil {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if rootless.IsRootless() && !cgroupv2 {
+ return call.ReplyErrRequiresCgroupsV2ForRootless("rootless containers cannot report container stats")
+ }
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())