mirror of
https://github.com/containers/podman
synced 2024-10-19 08:44:11 +00:00
Merge pull request #10716 from cdoern/podFlags
Podman Pod Create --cpus and --cpuset-cpus flags
This commit is contained in:
commit
3f3feaa015
|
@ -222,7 +222,6 @@ func createInit(c *cobra.Command) error {
|
|||
}
|
||||
cliVals.Env = env
|
||||
}
|
||||
|
||||
if c.Flag("cgroups").Changed && cliVals.CGroupsMode == "split" && registry.IsRemote() {
|
||||
return errors.Errorf("the option --cgroups=%q is not supported in remote mode", cliVals.CGroupsMode)
|
||||
}
|
||||
|
@ -292,6 +291,8 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
|
|||
Net: netOpts,
|
||||
CreateCommand: os.Args,
|
||||
Hostname: s.ContainerBasicConfig.Hostname,
|
||||
Cpus: cliVals.CPUS,
|
||||
CpusetCpus: cliVals.CPUSetCPUs,
|
||||
}
|
||||
// Unset config values we passed to the pod to prevent them being used twice for the container and pod.
|
||||
s.ContainerBasicConfig.Hostname = ""
|
||||
|
|
|
@ -5,9 +5,13 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/common/pkg/sysinfo"
|
||||
"github.com/containers/podman/v3/cmd/podman/common"
|
||||
"github.com/containers/podman/v3/cmd/podman/parse"
|
||||
"github.com/containers/podman/v3/cmd/podman/registry"
|
||||
|
@ -16,6 +20,7 @@ import (
|
|||
"github.com/containers/podman/v3/pkg/errorhandling"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -55,6 +60,14 @@ func init() {
|
|||
|
||||
common.DefineNetFlags(createCommand)
|
||||
|
||||
cpusetflagName := "cpuset-cpus"
|
||||
flags.StringVar(&createOptions.CpusetCpus, cpusetflagName, "", "CPUs in which to allow execution")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cpusetflagName, completion.AutocompleteDefault)
|
||||
|
||||
cpusflagName := "cpus"
|
||||
flags.Float64Var(&createOptions.Cpus, cpusflagName, 0.000, "set amount of CPUs for the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cpusflagName, completion.AutocompleteDefault)
|
||||
|
||||
cgroupParentflagName := "cgroup-parent"
|
||||
flags.StringVar(&createOptions.CGroupParent, cgroupParentflagName, "", "Set parent cgroup for the pod")
|
||||
_ = createCommand.RegisterFlagCompletionFunc(cgroupParentflagName, completion.AutocompleteDefault)
|
||||
|
@ -185,6 +198,46 @@ func create(cmd *cobra.Command, args []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
numCPU := sysinfo.NumCPU()
|
||||
if numCPU == 0 {
|
||||
numCPU = runtime.NumCPU()
|
||||
}
|
||||
if createOptions.Cpus > float64(numCPU) {
|
||||
createOptions.Cpus = float64(numCPU)
|
||||
}
|
||||
copy := createOptions.CpusetCpus
|
||||
cpuSet := createOptions.Cpus
|
||||
if cpuSet == 0 {
|
||||
cpuSet = float64(sysinfo.NumCPU())
|
||||
}
|
||||
ret, err := parsers.ParseUintList(copy)
|
||||
copy = ""
|
||||
if err != nil {
|
||||
errors.Wrapf(err, "could not parse list")
|
||||
}
|
||||
var vals []int
|
||||
for ind, val := range ret {
|
||||
if val {
|
||||
vals = append(vals, ind)
|
||||
}
|
||||
}
|
||||
sort.Ints(vals)
|
||||
for ind, core := range vals {
|
||||
if core > int(cpuSet) {
|
||||
if copy == "" {
|
||||
copy = "0-" + strconv.Itoa(int(cpuSet))
|
||||
createOptions.CpusetCpus = copy
|
||||
break
|
||||
} else {
|
||||
createOptions.CpusetCpus = copy
|
||||
break
|
||||
}
|
||||
} else if ind != 0 {
|
||||
copy += "," + strconv.Itoa(core)
|
||||
} else {
|
||||
copy = "" + strconv.Itoa(core)
|
||||
}
|
||||
}
|
||||
response, err := registry.ContainerEngine().PodCreate(context.Background(), createOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -23,6 +23,22 @@ Add a host to the /etc/hosts file shared between all containers in the pod.
|
|||
|
||||
Path to cgroups under which the cgroup for the pod will be created. If the path is not absolute, the path is considered to be relative to the cgroups path of the init process. Cgroups will be created if they do not already exist.
|
||||
|
||||
#### **--cpus**=*amount*
|
||||
|
||||
Set the total number of CPUs delegated to the pod. Default is 0.000 which indicates that there is no limit on computation power.
|
||||
|
||||
#### **--cpuset-cpus**=*amount*
|
||||
|
||||
Limit the CPUs to support execution. First CPU is numbered 0. Unlike --cpus this is of type string and parsed as a list of numbers
|
||||
|
||||
Format is 0-3,0,1
|
||||
|
||||
Examples of the List Format:
|
||||
|
||||
0-4,9 # bits 0, 1, 2, 3, 4, and 9 set
|
||||
0-2,7,12-14 # bits 0, 1, 2, 7, 12, 13, and 14 set
|
||||
|
||||
|
||||
#### **--dns**=*ipaddr*
|
||||
|
||||
Set custom DNS servers in the /etc/resolv.conf file that will be shared between all containers in the pod. A special option, "none" is allowed which disables creation of /etc/resolv.conf for the pod.
|
||||
|
|
|
@ -131,6 +131,5 @@ func (c *Container) validate() error {
|
|||
if c.config.User == "" && (c.config.Spec.Process.User.UID != 0 || c.config.Spec.Process.User.GID != 0) {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "please set User explicitly via WithUser() instead of in OCI spec directly")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -51,6 +51,12 @@ type InspectPodData struct {
|
|||
// Containers gives a brief summary of all containers in the pod and
|
||||
// their current status.
|
||||
Containers []InspectPodContainerInfo `json:"Containers,omitempty"`
|
||||
// CPUPeriod contains the CPU period of the pod
|
||||
CPUPeriod uint64 `json:"cpu_period,omitempty"`
|
||||
// CPUQuota contains the CPU quota of the pod
|
||||
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
||||
// CPUSetCPUs contains linux specific CPU data for the pod
|
||||
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
|
||||
}
|
||||
|
||||
// InspectPodInfraConfig contains the configuration of the pod's infra
|
||||
|
@ -91,6 +97,12 @@ type InspectPodInfraConfig struct {
|
|||
Networks []string
|
||||
// NetworkOptions are additional options for each network
|
||||
NetworkOptions map[string][]string
|
||||
// CPUPeriod contains the CPU period of the pod
|
||||
CPUPeriod uint64 `json:"cpu_period,omitempty"`
|
||||
// CPUQuota contains the CPU quota of the pod
|
||||
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
||||
// CPUSetCPUs contains linux specific CPU data for the container
|
||||
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
|
||||
}
|
||||
|
||||
// InspectPodContainerInfo contains information on a container in a pod.
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/containers/storage"
|
||||
"github.com/containers/storage/pkg/idtools"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/runtime-tools/generate"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
@ -559,7 +560,6 @@ func WithMaxLogSize(limit int64) CtrCreateOption {
|
|||
if ctr.valid {
|
||||
return define.ErrRuntimeFinalized
|
||||
}
|
||||
|
||||
ctr.config.LogSize = limit
|
||||
|
||||
return nil
|
||||
|
@ -867,7 +867,6 @@ func WithMountNSFrom(nsCtr *Container) CtrCreateOption {
|
|||
if err := checkDependencyContainer(nsCtr, ctr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctr.config.MountNsCtr = nsCtr.ID()
|
||||
|
||||
return nil
|
||||
|
@ -2359,3 +2358,42 @@ func WithVolatile() CtrCreateOption {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodCPUPAQ takes the given cpu period and quota and inserts them in the proper place.
|
||||
func WithPodCPUPAQ(period uint64, quota int64) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if pod.CPUPeriod() != 0 && pod.CPUQuota() != 0 {
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
} else {
|
||||
pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{
|
||||
Period: &period,
|
||||
Quota: "a,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// WithPodCPUSetCPUS computes and sets the Cpus linux resource string which determines the amount of cores, from those available, we are allowed to execute on
|
||||
func WithPodCPUSetCPUs(inp string) PodCreateOption {
|
||||
return func(pod *Pod) error {
|
||||
if pod.valid {
|
||||
return define.ErrPodFinalized
|
||||
}
|
||||
if pod.ResourceLim().CPU.Period != nil {
|
||||
pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
|
||||
} else {
|
||||
pod.config.InfraContainer.ResourceLimits = &specs.LinuxResources{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU = &specs.LinuxCPU{}
|
||||
pod.config.InfraContainer.ResourceLimits.CPU.Cpus = inp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package libpod
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/libpod/lock"
|
||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -110,6 +112,7 @@ type InfraContainerConfig struct {
|
|||
InfraCommand []string `json:"infraCommand,omitempty"`
|
||||
Slirp4netns bool `json:"slirp4netns,omitempty"`
|
||||
NetworkOptions map[string][]string `json:"network_options,omitempty"`
|
||||
ResourceLimits *specs.LinuxResources `json:"resource_limits,omitempty"`
|
||||
}
|
||||
|
||||
// ID retrieves the pod's ID
|
||||
|
@ -128,6 +131,45 @@ func (p *Pod) Namespace() string {
|
|||
return p.config.Namespace
|
||||
}
|
||||
|
||||
// ResourceLim returns the cpuset resource limits for the pod
|
||||
func (p *Pod) ResourceLim() *specs.LinuxResources {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
return nil
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil {
|
||||
return resCopy
|
||||
}
|
||||
empty := &specs.LinuxResources{
|
||||
CPU: &specs.LinuxCPU{},
|
||||
}
|
||||
return empty
|
||||
}
|
||||
|
||||
// CPUPeriod returns the pod CPU period
|
||||
func (p *Pod) CPUPeriod() uint64 {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
return 0
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Period != nil {
|
||||
return *resCopy.CPU.Period
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// CPUQuota returns the pod CPU quota
|
||||
func (p *Pod) CPUQuota() int64 {
|
||||
resCopy := &specs.LinuxResources{}
|
||||
if err := JSONDeepCopy(p.config.InfraContainer.ResourceLimits, resCopy); err != nil {
|
||||
return 0
|
||||
}
|
||||
if resCopy != nil && resCopy.CPU != nil && resCopy.CPU.Quota != nil {
|
||||
return *resCopy.CPU.Quota
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Labels returns the pod's labels
|
||||
func (p *Pod) Labels() map[string]string {
|
||||
labels := make(map[string]string)
|
||||
|
@ -208,7 +250,31 @@ func (p *Pod) CgroupPath() (string, error) {
|
|||
if err := p.updatePod(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if p.state.CgroupPath != "" {
|
||||
return p.state.CgroupPath, nil
|
||||
}
|
||||
if !p.HasInfraContainer() {
|
||||
return "", errors.Wrap(define.ErrNoSuchCtr, "pod has no infra container")
|
||||
}
|
||||
|
||||
id := p.state.InfraContainerID
|
||||
|
||||
if id != "" {
|
||||
ctr, err := p.runtime.state.Container(id)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not get infra")
|
||||
}
|
||||
if ctr != nil {
|
||||
ctr.Start(context.Background(), false)
|
||||
cgroupPath, err := ctr.CGroupPath()
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "could not get container cgroup")
|
||||
}
|
||||
p.state.CgroupPath = cgroupPath
|
||||
p.save()
|
||||
return cgroupPath, nil
|
||||
}
|
||||
}
|
||||
return p.state.CgroupPath, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -538,6 +538,9 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
|
|||
infraConfig.StaticMAC = p.config.InfraContainer.StaticMAC.String()
|
||||
infraConfig.NoManageResolvConf = p.config.InfraContainer.UseImageResolvConf
|
||||
infraConfig.NoManageHosts = p.config.InfraContainer.UseImageHosts
|
||||
infraConfig.CPUPeriod = p.CPUPeriod()
|
||||
infraConfig.CPUQuota = p.CPUQuota()
|
||||
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
||||
|
||||
if len(p.config.InfraContainer.DNSServer) > 0 {
|
||||
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
|
||||
|
@ -581,6 +584,9 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
|
|||
SharedNamespaces: sharesNS,
|
||||
NumContainers: uint(len(containers)),
|
||||
Containers: ctrs,
|
||||
CPUSetCPUs: p.ResourceLim().CPU.Cpus,
|
||||
CPUPeriod: p.CPUPeriod(),
|
||||
CPUQuota: p.CPUQuota(),
|
||||
}
|
||||
|
||||
return &inspectData, nil
|
||||
|
|
|
@ -146,7 +146,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
|
|||
options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
|
||||
}
|
||||
}
|
||||
|
||||
g.SetRootReadonly(true)
|
||||
g.SetProcessArgs(infraCtrCommand)
|
||||
|
||||
|
@ -173,7 +172,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
|
|||
// Ignore mqueue sysctls if not sharing IPC
|
||||
if !p.config.UsePodIPC && strings.HasPrefix(sysctlKey, "fs.mqueue.") {
|
||||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since IPC Namespace for pod is unused", sysctlKey, sysctlVal)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -188,7 +186,6 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
|
|||
logrus.Infof("Sysctl %s=%s ignored in containers.conf, since UTS Namespace for pod is unused", sysctlKey, sysctlVal)
|
||||
continue
|
||||
}
|
||||
|
||||
g.AddLinuxSysctl(sysctlKey, sysctlVal)
|
||||
}
|
||||
|
||||
|
@ -200,7 +197,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
|
|||
if len(p.config.InfraContainer.ConmonPidFile) > 0 {
|
||||
options = append(options, WithConmonPidFile(p.config.InfraContainer.ConmonPidFile))
|
||||
}
|
||||
newRes := new(spec.LinuxResources)
|
||||
newRes.CPU = new(spec.LinuxCPU)
|
||||
newRes.CPU = p.ResourceLim().CPU
|
||||
|
||||
g.Config.Linux.Resources.CPU = newRes.CPU
|
||||
return r.newContainer(ctx, g.Config, options...)
|
||||
}
|
||||
|
||||
|
@ -211,7 +212,6 @@ func (r *Runtime) createInfraContainer(ctx context.Context, p *Pod) (*Container,
|
|||
if !r.valid {
|
||||
return nil, define.ErrRuntimeStopped
|
||||
}
|
||||
|
||||
imageName := p.config.InfraContainer.InfraImage
|
||||
if imageName == "" {
|
||||
imageName = r.config.Engine.InfraImage
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
|
||||
"github.com/containers/podman/v3/libpod/define"
|
||||
"github.com/containers/podman/v3/pkg/specgen"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
type PodKillOptions struct {
|
||||
|
@ -116,13 +118,35 @@ type PodCreateOptions struct {
|
|||
Name string
|
||||
Net *NetOptions
|
||||
Share []string
|
||||
Cpus float64
|
||||
CpusetCpus string
|
||||
}
|
||||
|
||||
type PodCreateReport struct {
|
||||
Id string //nolint
|
||||
}
|
||||
|
||||
func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
|
||||
func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU {
|
||||
cpu := &specs.LinuxCPU{}
|
||||
hasLimits := false
|
||||
|
||||
if p.Cpus != 0 {
|
||||
period, quota := util.CoresToPeriodAndQuota(p.Cpus)
|
||||
cpu.Period = &period
|
||||
cpu.Quota = "a
|
||||
hasLimits = true
|
||||
}
|
||||
if p.CpusetCpus != "" {
|
||||
cpu.Cpus = p.CpusetCpus
|
||||
hasLimits = true
|
||||
}
|
||||
if !hasLimits {
|
||||
return cpu
|
||||
}
|
||||
return cpu
|
||||
}
|
||||
|
||||
func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
||||
// Basic Config
|
||||
s.Name = p.Name
|
||||
s.Hostname = p.Hostname
|
||||
|
@ -156,6 +180,21 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {
|
|||
|
||||
// Cgroup
|
||||
s.CgroupParent = p.CGroupParent
|
||||
|
||||
// Resource config
|
||||
cpuDat := p.CPULimits()
|
||||
if s.ResourceLimits == nil {
|
||||
s.ResourceLimits = &specs.LinuxResources{}
|
||||
s.ResourceLimits.CPU = &specs.LinuxCPU{}
|
||||
}
|
||||
if cpuDat != nil {
|
||||
s.ResourceLimits.CPU = cpuDat
|
||||
if p.Cpus != 0 {
|
||||
s.CPUPeriod = *cpuDat.Period
|
||||
s.CPUQuota = *cpuDat.Quota
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type PodPruneOptions struct {
|
||||
|
|
|
@ -347,7 +347,6 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
|
|||
options = append(options, libpod.WithLogDriver(s.LogConfiguration.Driver))
|
||||
}
|
||||
}
|
||||
|
||||
// Security options
|
||||
if len(s.SelinuxOpts) > 0 {
|
||||
options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
|
||||
|
|
|
@ -54,6 +54,14 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
|
|||
if len(p.Name) > 0 {
|
||||
options = append(options, libpod.WithPodName(p.Name))
|
||||
}
|
||||
if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Period != nil && p.ResourceLimits.CPU.Quota != nil {
|
||||
if *p.ResourceLimits.CPU.Period != 0 || *p.ResourceLimits.CPU.Quota != 0 {
|
||||
options = append(options, libpod.WithPodCPUPAQ((*p.ResourceLimits.CPU.Period), (*p.ResourceLimits.CPU.Quota)))
|
||||
}
|
||||
}
|
||||
if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Cpus != "" {
|
||||
options = append(options, libpod.WithPodCPUSetCPUs(p.ResourceLimits.CPU.Cpus))
|
||||
}
|
||||
if len(p.Hostname) > 0 {
|
||||
options = append(options, libpod.WithPodHostname(p.Hostname))
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package specgen
|
|||
|
||||
import (
|
||||
"net"
|
||||
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
)
|
||||
|
||||
// PodBasicConfig contains basic configuration options for pods.
|
||||
|
@ -155,6 +157,16 @@ type PodSpecGenerator struct {
|
|||
PodBasicConfig
|
||||
PodNetworkConfig
|
||||
PodCgroupConfig
|
||||
PodResourceConfig
|
||||
}
|
||||
|
||||
type PodResourceConfig struct {
|
||||
// ResourceLimits contains linux specific CPU data for the pod
|
||||
ResourceLimits *spec.LinuxResources `json:"resource_limits,omitempty"`
|
||||
// CPU period of the cpuset, determined by --cpus
|
||||
CPUPeriod uint64 `json:"cpu_period,omitempty"`
|
||||
// CPU quota of the cpuset, determined by --cpus
|
||||
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
||||
}
|
||||
|
||||
// NewPodSpecGenerator creates a new pod spec
|
||||
|
|
|
@ -470,6 +470,10 @@ type ContainerResourceConfig struct {
|
|||
// that are used to configure cgroup v2.
|
||||
// Optional.
|
||||
CgroupConf map[string]string `json:"unified,omitempty"`
|
||||
// CPU period of the cpuset, determined by --cpus
|
||||
CPUPeriod uint64 `json:"cpu_period,omitempty"`
|
||||
// CPU quota of the cpuset, determined by --cpus
|
||||
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
||||
}
|
||||
|
||||
// ContainerHealthCheckConfig describes a container healthcheck with attributes
|
||||
|
|
|
@ -5,9 +5,12 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/sysinfo"
|
||||
"github.com/containers/podman/v3/pkg/rootless"
|
||||
"github.com/containers/podman/v3/pkg/util"
|
||||
. "github.com/containers/podman/v3/test/utils"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
@ -515,4 +518,45 @@ ENTRYPOINT ["sleep","99999"]
|
|||
Expect(create.ExitCode()).To(BeZero())
|
||||
})
|
||||
|
||||
It("podman pod create --cpus", func() {
|
||||
podName := "testPod"
|
||||
numCPU := float64(sysinfo.NumCPU())
|
||||
period, quota := util.CoresToPeriodAndQuota(numCPU)
|
||||
numCPUStr := strconv.Itoa(int(numCPU))
|
||||
podCreate := podmanTest.Podman([]string{"pod", "create", "--cpus", numCPUStr, "--name", podName})
|
||||
podCreate.WaitWithDefaultTimeout()
|
||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||
|
||||
contCreate := podmanTest.Podman([]string{"container", "create", "--pod", podName, "alpine"})
|
||||
contCreate.WaitWithDefaultTimeout()
|
||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||
|
||||
podInspect := podmanTest.Podman([]string{"pod", "inspect", podName})
|
||||
podInspect.WaitWithDefaultTimeout()
|
||||
Expect(podInspect.ExitCode()).To(Equal(0))
|
||||
podJSON := podInspect.InspectPodToJSON()
|
||||
Expect(podJSON.CPUPeriod).To(Equal(period))
|
||||
Expect(podJSON.CPUQuota).To(Equal(quota))
|
||||
})
|
||||
|
||||
It("podman pod create --cpuset-cpus", func() {
|
||||
podName := "testPod"
|
||||
ctrName := "testCtr"
|
||||
numCPU := float64(sysinfo.NumCPU())
|
||||
numCPUStr := strconv.Itoa(int(numCPU))
|
||||
in := "0-" + numCPUStr
|
||||
podCreate := podmanTest.Podman([]string{"pod", "create", "--cpuset-cpus", in, "--name", podName})
|
||||
podCreate.WaitWithDefaultTimeout()
|
||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||
|
||||
contCreate := podmanTest.Podman([]string{"container", "create", "--name", ctrName, "--pod", podName, "alpine"})
|
||||
contCreate.WaitWithDefaultTimeout()
|
||||
Expect(podCreate.ExitCode()).To(Equal(0))
|
||||
|
||||
podInspect := podmanTest.Podman([]string{"pod", "inspect", podName})
|
||||
podInspect.WaitWithDefaultTimeout()
|
||||
Expect(podInspect.ExitCode()).To(Equal(0))
|
||||
podJSON := podInspect.InspectPodToJSON()
|
||||
Expect(podJSON.CPUSetCPUs).To(Equal(in))
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue