diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/checkpoint_restore.go | 1 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 5 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 7 | ||||
-rw-r--r-- | pkg/namespaces/namespaces.go | 57 | ||||
-rw-r--r-- | pkg/spec/config_linux.go | 41 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 19 | ||||
-rw-r--r-- | pkg/spec/spec.go | 27 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 54 | ||||
-rw-r--r-- | pkg/varlinkapi/util.go | 2 |
9 files changed, 180 insertions, 33 deletions
diff --git a/pkg/adapter/checkpoint_restore.go b/pkg/adapter/checkpoint_restore.go index ec1464fb1..533e9e3a2 100644 --- a/pkg/adapter/checkpoint_restore.go +++ b/pkg/adapter/checkpoint_restore.go @@ -58,6 +58,7 @@ func crImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, input stri "checkpoint", "artifacts", "ctr.log", + "rootfs-diff.tar", "network.status", }, } diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 86e9c0266..7e2384e18 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -524,6 +524,10 @@ func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues) error { KeepRunning: c.LeaveRunning, TCPEstablished: c.TcpEstablished, TargetFile: c.Export, + IgnoreRootfs: c.IgnoreRootfs, + } + if c.Export == "" && c.IgnoreRootfs { + return errors.Errorf("--ignore-rootfs can only be used with --export") } if c.All { containers, err = r.Runtime.GetRunningContainers() @@ -560,6 +564,7 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues) TCPEstablished: c.TcpEstablished, TargetFile: c.Import, Name: c.Name, + IgnoreRootfs: c.IgnoreRootfs, } filterFuncs = append(filterFuncs, func(c *libpod.Container) bool { diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index 5836d0788..fc23381a4 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -493,6 +493,7 @@ func (r *LocalRuntime) Ps(c *cliconfig.PsValues, opts shared.PsOptions) ([]share NoTrunc: &c.NoTrunct, Pod: &c.Pod, Quiet: &c.Quiet, + Size: &c.Size, Sort: &c.Sort, Sync: &c.Sync, } @@ -668,6 +669,9 @@ func (r *LocalRuntime) Checkpoint(c *cliconfig.CheckpointValues) error { if c.Export != "" { return errors.New("the remote client does not support exporting checkpoints") } + if c.IgnoreRootfs { + return errors.New("the remote client does not support --ignore-rootfs") + } var lastError error ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs) @@ -708,6 +712,9 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues) if c.Import != "" { return errors.New("the remote client does not support importing checkpoints") } + if c.IgnoreRootfs { + return errors.New("the remote client does not support --ignore-rootfs") + } var lastError error ids, err := iopodman.GetContainersByContext().Call(r.Conn, c.All, c.Latest, c.InputArgs) diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go index ec9276344..7ed95bd0f 100644 --- a/pkg/namespaces/namespaces.go +++ b/pkg/namespaces/namespaces.go @@ -4,6 +4,63 @@ import ( "strings" ) +// CgroupMode represents cgroup mode in the container. +type CgroupMode string + +// IsHost indicates whether the container uses the host's cgroup. +func (n CgroupMode) IsHost() bool { + return n == "host" +} + +// IsNS indicates a cgroup namespace passed in by path (ns:<path>) +func (n CgroupMode) IsNS() bool { + return strings.HasPrefix(string(n), "ns:") +} + +// NS gets the path associated with a ns:<path> cgroup ns +func (n CgroupMode) NS() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + +// IsContainer indicates whether the container uses a new cgroup namespace. +func (n CgroupMode) IsContainer() bool { + parts := strings.SplitN(string(n), ":", 2) + return len(parts) > 1 && parts[0] == "container" +} + +// Container returns the name of the container whose cgroup namespace is going to be used. +func (n CgroupMode) Container() string { + parts := strings.SplitN(string(n), ":", 2) + if len(parts) > 1 { + return parts[1] + } + return "" +} + +// IsPrivate indicates whether the container uses the a private cgroup. +func (n CgroupMode) IsPrivate() bool { + return n == "private" +} + +// Valid indicates whether the Cgroup namespace is valid. +func (n CgroupMode) Valid() bool { + parts := strings.Split(string(n), ":") + switch mode := parts[0]; mode { + case "", "host", "private", "ns": + case "container": + if len(parts) != 2 || parts[1] == "" { + return false + } + default: + return false + } + return true +} + // UsernsMode represents userns mode in the container. type UsernsMode string diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 9f6a4a058..a84e9a72f 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -8,6 +8,7 @@ import ( "path/filepath" "strings" + "github.com/containers/libpod/pkg/rootless" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" spec "github.com/opencontainers/runtime-spec/specs-go" @@ -118,8 +119,44 @@ func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error { return err } g.ClearLinuxDevices() - for _, d := range hostDevices { - g.AddDevice(Device(d)) + + if rootless.IsRootless() { + mounts := make(map[string]interface{}) + for _, m := range g.Mounts() { + mounts[m.Destination] = true + } + newMounts := []spec.Mount{} + for _, d := range hostDevices { + devMnt := spec.Mount{ + Destination: d.Path, + Type: TypeBind, + Source: d.Path, + Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"}, + } + if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") { + continue + } + if _, found := mounts[d.Path]; found { + continue + } + st, err := os.Stat(d.Path) + if err != nil { + if err == unix.EPERM { + continue + } + return errors.Wrapf(err, "stat %s", d.Path) + } + // Skip devices that the user has not access to. + if st.Mode()&0007 == 0 { + continue + } + newMounts = append(newMounts, devMnt) + } + g.Config.Mounts = append(newMounts, g.Config.Mounts...) + } else { + for _, d := range hostDevices { + g.AddDevice(Device(d)) + } } // Add resources device - need to clear the existing one first. diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 0042ed401..1fb1f829b 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -63,6 +63,7 @@ type CreateConfig struct { CapDrop []string // cap-drop CidFile string ConmonPidFile string + Cgroupns string CgroupParent string // cgroup-parent Command []string Detach bool // detach @@ -101,6 +102,7 @@ type CreateConfig struct { NetworkAlias []string //network-alias PidMode namespaces.PidMode //pid Pod string //pod + CgroupMode namespaces.CgroupMode //cgroup PortBindings nat.PortMap Privileged bool //privileged Publish []string //publish @@ -268,6 +270,23 @@ func (c *CreateConfig) getContainerCreateOptions(runtime *libpod.Runtime, pod *l options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, string(c.NetMode), networks)) } + if c.CgroupMode.IsNS() { + ns := c.CgroupMode.NS() + if ns == "" { + return nil, errors.Errorf("invalid empty user-defined network namespace") + } + _, err := os.Stat(ns) + if err != nil { + return nil, err + } + } else if c.CgroupMode.IsContainer() { + connectedCtr, err := runtime.LookupContainer(c.CgroupMode.Container()) + if err != nil { + return nil, errors.Wrapf(err, "container %q not found", c.CgroupMode.Container()) + } + options = append(options, libpod.WithCgroupNSFrom(connectedCtr)) + } + if c.PidMode.IsContainer() { connectedCtr, err := runtime.LookupContainer(c.PidMode.Container()) if err != nil { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 41054633f..824c99025 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -264,10 +264,8 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM // If privileged, we need to add all the host devices to the // spec. We do not add the user provided ones because we are // already adding them all. - if !rootless.IsRootless() { - if err := config.AddPrivilegedDevices(&g); err != nil { - return nil, err - } + if err := config.AddPrivilegedDevices(&g); err != nil { + return nil, err } } else { for _, devicePath := range config.Devices { @@ -325,6 +323,10 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM if err := addIpcNS(config, &g); err != nil { return nil, err } + + if err := addCgroupNS(config, &g); err != nil { + return nil, err + } configSpec := g.Config // HANDLE CAPABILITIES @@ -622,6 +624,23 @@ func addIpcNS(config *CreateConfig, g *generate.Generator) error { return nil } +func addCgroupNS(config *CreateConfig, g *generate.Generator) error { + cgroupMode := config.CgroupMode + if cgroupMode.IsNS() { + return g.AddOrReplaceLinuxNamespace(string(spec.CgroupNamespace), NS(string(cgroupMode))) + } + if cgroupMode.IsHost() { + return g.RemoveLinuxNamespace(spec.CgroupNamespace) + } + if cgroupMode.IsPrivate() { + return g.AddOrReplaceLinuxNamespace(spec.CgroupNamespace, "") + } + if cgroupMode.IsContainer() { + logrus.Debug("Using container cgroup mode") + } + return nil +} + func addRlimits(config *CreateConfig, g *generate.Generator) error { var ( kernelMax uint64 = 1048576 diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index 700e02b0c..6f6909fac 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -65,32 +65,34 @@ func (i *LibpodAPI) Ps(call iopodman.VarlinkCall, opts iopodman.PsOpts) error { for _, ctr := range psContainerOutputs { container := iopodman.PsContainer{ - Id: ctr.ID, - Image: ctr.Image, - Command: ctr.Command, - Created: ctr.Created, - Ports: ctr.Ports, - Names: ctr.Names, - IsInfra: ctr.IsInfra, - Status: ctr.Status, - State: ctr.State.String(), - PidNum: int64(ctr.Pid), - RootFsSize: ctr.Size.RootFsSize, - RwSize: ctr.Size.RwSize, - Pod: ctr.Pod, - CreatedAt: ctr.CreatedAt.Format(time.RFC3339Nano), - ExitedAt: ctr.ExitedAt.Format(time.RFC3339Nano), - StartedAt: ctr.StartedAt.Format(time.RFC3339Nano), - Labels: ctr.Labels, - NsPid: ctr.PID, - Cgroup: ctr.Cgroup, - Ipc: ctr.Cgroup, - Mnt: ctr.MNT, - Net: ctr.NET, - PidNs: ctr.PIDNS, - User: ctr.User, - Uts: ctr.UTS, - Mounts: ctr.Mounts, + Id: ctr.ID, + Image: ctr.Image, + Command: ctr.Command, + Created: ctr.Created, + Ports: ctr.Ports, + Names: ctr.Names, + IsInfra: ctr.IsInfra, + Status: ctr.Status, + State: ctr.State.String(), + PidNum: int64(ctr.Pid), + Pod: ctr.Pod, + CreatedAt: ctr.CreatedAt.Format(time.RFC3339Nano), + ExitedAt: ctr.ExitedAt.Format(time.RFC3339Nano), + StartedAt: ctr.StartedAt.Format(time.RFC3339Nano), + Labels: ctr.Labels, + NsPid: ctr.PID, + Cgroup: ctr.Cgroup, + Ipc: ctr.Cgroup, + Mnt: ctr.MNT, + Net: ctr.NET, + PidNs: ctr.PIDNS, + User: ctr.User, + Uts: ctr.UTS, + Mounts: ctr.Mounts, + } + if ctr.Size != nil { + container.RootFsSize = ctr.Size.RootFsSize + container.RwSize = ctr.Size.RwSize } containers = append(containers, container) } diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go index e8f74e6aa..d3a41f7ab 100644 --- a/pkg/varlinkapi/util.go +++ b/pkg/varlinkapi/util.go @@ -191,7 +191,7 @@ func makePsOpts(inOpts iopodman.PsOpts) shared.PsOptions { Latest: derefBool(inOpts.Latest), NoTrunc: derefBool(inOpts.NoTrunc), Pod: derefBool(inOpts.Pod), - Size: true, + Size: derefBool(inOpts.Size), Sort: derefString(inOpts.Sort), Namespace: true, Sync: derefBool(inOpts.Sync), |