2016-04-28 22:30:50 +08:00
|
|
|
// +build linux
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
|
2016-05-30 18:56:10 +08:00
|
|
|
"github.com/docker/go-units"
|
2016-04-28 22:30:50 +08:00
|
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
2016-06-07 02:45:46 +08:00
|
|
|
"github.com/urfave/cli"
|
2016-04-28 22:30:50 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func u64Ptr(i uint64) *uint64 { return &i }
|
|
|
|
func u16Ptr(i uint16) *uint16 { return &i }
|
|
|
|
|
|
|
|
var updateCommand = cli.Command{
|
|
|
|
Name: "update",
|
|
|
|
Usage: "update container resource constraints",
|
2016-05-09 19:04:25 +08:00
|
|
|
ArgsUsage: `<container-id>`,
|
2016-04-28 22:30:50 +08:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "resources, r",
|
|
|
|
Value: "",
|
2016-05-28 13:33:57 +08:00
|
|
|
Usage: `path to the file containing the resources to update or '-' to read from the standard input
|
2016-04-28 22:30:50 +08:00
|
|
|
|
|
|
|
The accepted format is as follow (unchanged values can be omitted):
|
|
|
|
|
|
|
|
{
|
|
|
|
"memory": {
|
|
|
|
"limit": 0,
|
|
|
|
"reservation": 0,
|
|
|
|
"swap": 0,
|
2016-05-25 16:01:03 +08:00
|
|
|
"kernel": 0,
|
|
|
|
"kernelTCP": 0
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
"cpu": {
|
|
|
|
"shares": 0,
|
|
|
|
"quota": 0,
|
|
|
|
"period": 0,
|
|
|
|
"cpus": "",
|
|
|
|
"mems": ""
|
|
|
|
},
|
|
|
|
"blockIO": {
|
|
|
|
"blkioWeight": 0
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-05-09 19:04:25 +08:00
|
|
|
Note: if data is to be read from a file or the standard input, all
|
2016-04-28 22:30:50 +08:00
|
|
|
other options are ignored.
|
|
|
|
`,
|
|
|
|
},
|
|
|
|
|
|
|
|
cli.IntFlag{
|
|
|
|
Name: "blkio-weight",
|
2016-05-28 13:33:57 +08:00
|
|
|
Usage: "Specifies per cgroup weight, range is from 10 to 1000",
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "cpu-period",
|
2016-05-28 13:33:57 +08:00
|
|
|
Usage: "CPU period to be used for hardcapping (in usecs). 0 to use system default",
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "cpu-quota",
|
2016-05-28 13:33:57 +08:00
|
|
|
Usage: "CPU hardcap limit (in usecs). Allowed cpu time in a given period",
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "cpu-share",
|
|
|
|
Usage: "CPU shares (relative weight vs. other containers)",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "cpuset-cpus",
|
|
|
|
Usage: "CPU(s) to use",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "cpuset-mems",
|
|
|
|
Usage: "Memory node(s) to use",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "kernel-memory",
|
2016-05-09 23:14:29 +08:00
|
|
|
Usage: "Kernel memory limit (in bytes)",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "kernel-memory-tcp",
|
2016-04-28 22:30:50 +08:00
|
|
|
Usage: "Kernel memory limit (in bytes) for tcp buffer",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "memory",
|
|
|
|
Usage: "Memory limit (in bytes)",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "memory-reservation",
|
|
|
|
Usage: "Memory reservation or soft_limit (in bytes)",
|
|
|
|
},
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "memory-swap",
|
2016-05-28 10:22:06 +08:00
|
|
|
Usage: "Total memory usage (memory + swap); set '-1' to enable unlimited swap",
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
},
|
2016-05-10 13:58:09 +08:00
|
|
|
Action: func(context *cli.Context) error {
|
2016-04-28 22:30:50 +08:00
|
|
|
container, err := getContainer(context)
|
|
|
|
if err != nil {
|
2016-05-10 13:58:09 +08:00
|
|
|
return err
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
r := specs.Resources{
|
|
|
|
Memory: &specs.Memory{
|
|
|
|
Limit: u64Ptr(0),
|
|
|
|
Reservation: u64Ptr(0),
|
|
|
|
Swap: u64Ptr(0),
|
|
|
|
Kernel: u64Ptr(0),
|
2016-05-09 23:14:29 +08:00
|
|
|
KernelTCP: u64Ptr(0),
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
CPU: &specs.CPU{
|
|
|
|
Shares: u64Ptr(0),
|
|
|
|
Quota: u64Ptr(0),
|
|
|
|
Period: u64Ptr(0),
|
|
|
|
Cpus: sPtr(""),
|
|
|
|
Mems: sPtr(""),
|
|
|
|
},
|
|
|
|
BlockIO: &specs.BlockIO{
|
|
|
|
Weight: u16Ptr(0),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
config := container.Config()
|
|
|
|
|
|
|
|
if in := context.String("resources"); in != "" {
|
|
|
|
var (
|
|
|
|
f *os.File
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
switch in {
|
|
|
|
case "-":
|
|
|
|
f = os.Stdin
|
|
|
|
default:
|
|
|
|
f, err = os.Open(in)
|
|
|
|
if err != nil {
|
2016-05-10 13:58:09 +08:00
|
|
|
return err
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
err = json.NewDecoder(f).Decode(&r)
|
|
|
|
if err != nil {
|
2016-05-10 13:58:09 +08:00
|
|
|
return err
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if val := context.Int("blkio-weight"); val != 0 {
|
|
|
|
r.BlockIO.Weight = u16Ptr(uint16(val))
|
|
|
|
}
|
|
|
|
if val := context.String("cpuset-cpus"); val != "" {
|
|
|
|
r.CPU.Cpus = &val
|
|
|
|
}
|
|
|
|
if val := context.String("cpuset-mems"); val != "" {
|
|
|
|
r.CPU.Mems = &val
|
|
|
|
}
|
|
|
|
|
|
|
|
for opt, dest := range map[string]*uint64{
|
2016-05-30 18:56:10 +08:00
|
|
|
"cpu-period": r.CPU.Period,
|
|
|
|
"cpu-quota": r.CPU.Quota,
|
|
|
|
"cpu-share": r.CPU.Shares,
|
|
|
|
} {
|
|
|
|
if val := context.String(opt); val != "" {
|
|
|
|
var err error
|
|
|
|
*dest, err = strconv.ParseUint(val, 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("invalid value for %s: %s", opt, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for opt, dest := range map[string]*uint64{
|
2016-04-28 22:30:50 +08:00
|
|
|
"kernel-memory": r.Memory.Kernel,
|
2016-05-09 23:14:29 +08:00
|
|
|
"kernel-memory-tcp": r.Memory.KernelTCP,
|
2016-04-28 22:30:50 +08:00
|
|
|
"memory": r.Memory.Limit,
|
|
|
|
"memory-reservation": r.Memory.Reservation,
|
|
|
|
"memory-swap": r.Memory.Swap,
|
|
|
|
} {
|
|
|
|
if val := context.String(opt); val != "" {
|
2016-05-30 18:56:10 +08:00
|
|
|
v, err := units.RAMInBytes(val)
|
2016-04-28 22:30:50 +08:00
|
|
|
if err != nil {
|
2016-05-10 13:58:09 +08:00
|
|
|
return fmt.Errorf("invalid value for %s: %s", opt, err)
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
2016-05-30 18:56:10 +08:00
|
|
|
*dest = uint64(v)
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the value
|
|
|
|
config.Cgroups.Resources.BlkioWeight = *r.BlockIO.Weight
|
|
|
|
config.Cgroups.Resources.CpuPeriod = int64(*r.CPU.Period)
|
|
|
|
config.Cgroups.Resources.CpuQuota = int64(*r.CPU.Quota)
|
|
|
|
config.Cgroups.Resources.CpuShares = int64(*r.CPU.Shares)
|
|
|
|
config.Cgroups.Resources.CpusetCpus = *r.CPU.Cpus
|
|
|
|
config.Cgroups.Resources.CpusetMems = *r.CPU.Mems
|
|
|
|
config.Cgroups.Resources.KernelMemory = int64(*r.Memory.Kernel)
|
2016-05-09 23:14:29 +08:00
|
|
|
config.Cgroups.Resources.KernelMemoryTCP = int64(*r.Memory.KernelTCP)
|
2016-04-28 22:30:50 +08:00
|
|
|
config.Cgroups.Resources.Memory = int64(*r.Memory.Limit)
|
|
|
|
config.Cgroups.Resources.MemoryReservation = int64(*r.Memory.Reservation)
|
|
|
|
config.Cgroups.Resources.MemorySwap = int64(*r.Memory.Swap)
|
|
|
|
|
|
|
|
if err := container.Set(config); err != nil {
|
2016-05-10 13:58:09 +08:00
|
|
|
return err
|
2016-04-28 22:30:50 +08:00
|
|
|
}
|
2016-05-10 13:58:09 +08:00
|
|
|
return nil
|
2016-04-28 22:30:50 +08:00
|
|
|
},
|
|
|
|
}
|