diff options
Diffstat (limited to 'cmd/podman/common/specgen.go')
-rw-r--r-- | cmd/podman/common/specgen.go | 138 |
1 files changed, 95 insertions, 43 deletions
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index f8c58f1a4..1fabff378 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -8,12 +8,14 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/image/v5/manifest" "github.com/containers/libpod/cmd/podman/parse" "github.com/containers/libpod/libpod/define" ann "github.com/containers/libpod/pkg/annotations" envLib "github.com/containers/libpod/pkg/env" ns "github.com/containers/libpod/pkg/namespaces" + "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/specgen" systemdGen "github.com/containers/libpod/pkg/systemd/generate" "github.com/containers/libpod/pkg/util" @@ -26,6 +28,16 @@ func getCPULimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) cpu := &specs.LinuxCPU{} hasLimits := false + const cpuPeriod = 100000 + + if c.CPUS > 0 { + quota := int64(c.CPUS * cpuPeriod) + period := uint64(cpuPeriod) + + cpu.Period = &period + cpu.Quota = "a + hasLimits = true + } if c.CPUShares > 0 { cpu.Shares = &c.CPUShares hasLimits = true @@ -116,20 +128,23 @@ func getIOLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) ( return io, nil } -func getPidsLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) (*specs.LinuxPids, error) { +func getPidsLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) *specs.LinuxPids { pids := &specs.LinuxPids{} - hasLimits := false - if c.CGroupsMode == "disabled" && c.PIDsLimit > 0 { - return nil, nil + if c.CGroupsMode == "disabled" && c.PIDsLimit != 0 { + return nil + } + if c.PIDsLimit < 0 { + if rootless.IsRootless() && containerConfig.Engine.CgroupManager != config.SystemdCgroupsManager { + return nil + } + pids.Limit = containerConfig.PidsLimit() + return pids } if c.PIDsLimit > 0 { pids.Limit = c.PIDsLimit - hasLimits = true + return pids } - if !hasLimits { - return nil, nil - } - return pids, nil + return nil } func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) (*specs.LinuxMemory, error) { @@ -142,6 +157,10 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []strin return nil, errors.Wrapf(err, "invalid value for memory") } memory.Limit = &ml + if c.MemorySwap == "" { + limit := 2 * ml + memory.Swap = &(limit) + } hasLimits = true } if m := c.MemoryReservation; len(m) > 0 { @@ -192,7 +211,6 @@ func getMemoryLimits(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []strin func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string) error { var ( err error - //namespaces map[string]string ) // validate flags as needed @@ -234,9 +252,15 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string // We are not handling the Expose flag yet. // s.PortsExpose = c.Expose s.PortMappings = c.Net.PublishPorts - s.PublishImagePorts = c.PublishAll + s.PublishExposedPorts = c.PublishAll s.Pod = c.Pod + expose, err := createExpose(c.Expose) + if err != nil { + return err + } + s.Expose = expose + for k, v := range map[string]*specgen.Namespace{ c.IPC: &s.IpcNS, c.PID: &s.PidNS, @@ -316,15 +340,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string env = envLib.Join(env, fileEnv) } - // env overrides any previous variables - if cmdLineEnv := c.env; len(cmdLineEnv) > 0 { - parsedEnv, err := envLib.ParseSlice(cmdLineEnv) - if err != nil { - return err - } - env = envLib.Join(env, parsedEnv) + parsedEnv, err := envLib.ParseSlice(c.Env) + if err != nil { + return err } - s.Env = env + + s.Env = envLib.Join(env, parsedEnv) // LABEL VARIABLES labels, err := parse.GetAllLabels(c.LabelFile, c.Label) @@ -364,20 +385,20 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.WorkDir = workDir entrypoint := []string{} userCommand := []string{} - if ep := c.Entrypoint; len(ep) > 0 { - // Check if entrypoint specified is json - if err := json.Unmarshal([]byte(c.Entrypoint), &entrypoint); err != nil { - entrypoint = append(entrypoint, ep) + if c.Entrypoint != nil { + if ep := *c.Entrypoint; len(ep) > 0 { + // Check if entrypoint specified is json + if err := json.Unmarshal([]byte(*c.Entrypoint), &entrypoint); err != nil { + entrypoint = append(entrypoint, ep) + } } + s.Entrypoint = entrypoint } - var command []string - s.Entrypoint = entrypoint - // Build the command // If we have an entry point, it goes first - if len(entrypoint) > 0 { + if c.Entrypoint != nil { command = entrypoint } if len(inputCommand) > 0 { @@ -386,9 +407,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string userCommand = append(userCommand, inputCommand...) } - if len(inputCommand) > 0 { + switch { + case len(inputCommand) > 0: s.Command = userCommand - } else { + case c.Entrypoint != nil: + s.Command = []string{} + default: s.Command = command } @@ -400,6 +424,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } s.ShmSize = &shmSize } + s.CNINetworks = c.Net.CNINetworks s.HostAdd = c.Net.AddHosts s.UseImageResolvConf = c.Net.UseImageResolvConf s.DNSServers = c.Net.DNSServers @@ -444,10 +469,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string if err != nil { return err } - s.ResourceLimits.Pids, err = getPidsLimits(s, c, args) - if err != nil { - return err - } + s.ResourceLimits.Pids = getPidsLimits(s, c, args) s.ResourceLimits.CPU, err = getCPULimits(s, c, args) if err != nil { return err @@ -481,11 +503,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.CapDrop = c.CapDrop s.Privileged = c.Privileged s.ReadOnlyFilesystem = c.ReadOnly + s.ConmonPidFile = c.ConmonPIDFile // TODO // ouitside of specgen and oci though // defaults to true, check spec/storage - //s.readon = c.ReadOnlyTmpFS + // s.readon = c.ReadOnlyTmpFS // TODO convert to map? // check if key=value and convert sysmap := make(map[string]string) @@ -498,6 +521,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } s.Sysctl = sysmap + if c.CIDFile != "" { + s.Annotations[define.InspectAnnotationCIDFile] = c.CIDFile + } + for _, opt := range c.SecurityOpt { if opt == "no-new-privileges" { s.ContainerSecurityConfig.NoNewPrivileges = true @@ -511,10 +538,13 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string case "label": // TODO selinux opts and label opts are the same thing s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, con[1]) + s.Annotations[define.InspectAnnotationLabel] = con[1] case "apparmor": s.ContainerSecurityConfig.ApparmorProfile = con[1] + s.Annotations[define.InspectAnnotationApparmor] = con[1] case "seccomp": s.SeccompProfilePath = con[1] + s.Annotations[define.InspectAnnotationSeccomp] = con[1] default: return fmt.Errorf("invalid --security-opt 2: %q", opt) } @@ -528,7 +558,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string // Only add read-only tmpfs mounts in case that we are read-only and the // read-only tmpfs flag has been set. - mounts, volumes, err := parseVolumes(c.Volume, c.Mount, c.TmpFS, (c.ReadOnlyTmpFS && c.ReadOnly)) + mounts, volumes, err := parseVolumes(c.Volume, c.Mount, c.TmpFS, c.ReadOnlyTmpFS && c.ReadOnly) if err != nil { return err } @@ -536,12 +566,12 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Volumes = volumes // TODO any idea why this was done - //devices := rtc.Containers.Devices + // devices := rtc.Containers.Devices // TODO conflict on populate? // - //if c.Changed("device") { + // if c.Changed("device") { // devices = append(devices, c.StringSlice("device")...) - //} + // } for _, dev := range c.Devices { s.Devices = append(s.Devices, specs.LinuxDevice{Path: dev}) @@ -553,7 +583,7 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string // initpath s.Stdin = c.Interactive // quiet - //DeviceCgroupRules: c.StringSlice("device-cgroup-rule"), + // DeviceCgroupRules: c.StringSlice("device-cgroup-rule"), // Rlimits/Ulimits for _, u := range c.Ulimit { @@ -573,10 +603,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Rlimits = append(s.Rlimits, rl) } - //Tmpfs: c.StringArray("tmpfs"), + // Tmpfs: c.StringArray("tmpfs"), // TODO how to handle this? - //Syslog: c.Bool("syslog"), + // Syslog: c.Bool("syslog"), logOpts := make(map[string]string) for _, o := range c.LogOptions { @@ -597,12 +627,34 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Name = c.Name s.OOMScoreAdj = &c.OOMScoreAdj - s.RestartPolicy = c.Restart + if c.Restart != "" { + splitRestart := strings.Split(c.Restart, ":") + switch len(splitRestart) { + case 1: + // No retries specified + case 2: + if strings.ToLower(splitRestart[0]) != "on-failure" { + return errors.Errorf("restart policy retries can only be specified with on-failure restart policy") + } + retries, err := strconv.Atoi(splitRestart[1]) + if err != nil { + return errors.Wrapf(err, "error parsing restart policy retry count") + } + if retries < 0 { + return errors.Errorf("must specify restart policy retry count as a number greater than 0") + } + var retriesUint uint = uint(retries) + s.RestartRetries = &retriesUint + default: + return errors.Errorf("invalid restart policy: may specify retries at most once") + } + s.RestartPolicy = splitRestart[0] + } s.Remove = c.Rm s.StopTimeout = &c.StopTimeout // TODO where should we do this? - //func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) { + // func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) { return nil } |