123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- package runtime
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "strings"
- "syscall"
- "github.com/docker/containerd/specs"
- "github.com/docker/containerd/subreaper/exec"
- "github.com/opencontainers/runc/libcontainer"
- ocs "github.com/opencontainers/runtime-spec/specs-go"
- )
- func (c *container) getLibctContainer() (libcontainer.Container, error) {
- runtimeRoot := "/run/runc"
- // Check that the root wasn't changed
- for _, opt := range c.runtimeArgs {
- if strings.HasPrefix(opt, "--root=") {
- runtimeRoot = strings.TrimPrefix(opt, "--root=")
- break
- }
- }
- f, err := libcontainer.New(runtimeRoot, libcontainer.Cgroupfs)
- if err != nil {
- return nil, err
- }
- return f.Load(c.id)
- }
- func (c *container) OOM() (OOM, error) {
- container, err := c.getLibctContainer()
- if err != nil {
- if lerr, ok := err.(libcontainer.Error); ok {
- // with oom registration sometimes the container can run, exit, and be destroyed
- // faster than we can get the state back so we can just ignore this
- if lerr.Code() == libcontainer.ContainerNotExists {
- return nil, ErrContainerExited
- }
- }
- return nil, err
- }
- state, err := container.State()
- if err != nil {
- return nil, err
- }
- memoryPath := state.CgroupPaths["memory"]
- return c.getMemeoryEventFD(memoryPath)
- }
- func u64Ptr(i uint64) *uint64 { return &i }
- func (c *container) UpdateResources(r *Resource) error {
- sr := ocs.Resources{
- Memory: &ocs.Memory{
- Limit: u64Ptr(uint64(r.Memory)),
- Reservation: u64Ptr(uint64(r.MemoryReservation)),
- Swap: u64Ptr(uint64(r.MemorySwap)),
- Kernel: u64Ptr(uint64(r.KernelMemory)),
- },
- CPU: &ocs.CPU{
- Shares: u64Ptr(uint64(r.CPUShares)),
- Quota: u64Ptr(uint64(r.CPUQuota)),
- Period: u64Ptr(uint64(r.CPUPeriod)),
- Cpus: &r.CpusetCpus,
- Mems: &r.CpusetMems,
- },
- BlockIO: &ocs.BlockIO{
- Weight: &r.BlkioWeight,
- },
- }
- srStr := bytes.NewBuffer(nil)
- if err := json.NewEncoder(srStr).Encode(&sr); err != nil {
- return err
- }
- args := c.runtimeArgs
- args = append(args, "update", "-r", "-", c.id)
- cmd := exec.Command(c.runtime, args...)
- cmd.Stdin = srStr
- b, err := cmd.CombinedOutput()
- if err != nil {
- return fmt.Errorf(string(b))
- }
- return nil
- }
- func getRootIDs(s *specs.Spec) (int, int, error) {
- if s == nil {
- return 0, 0, nil
- }
- var hasUserns bool
- for _, ns := range s.Linux.Namespaces {
- if ns.Type == ocs.UserNamespace {
- hasUserns = true
- break
- }
- }
- if !hasUserns {
- return 0, 0, nil
- }
- uid := hostIDFromMap(0, s.Linux.UIDMappings)
- gid := hostIDFromMap(0, s.Linux.GIDMappings)
- return uid, gid, nil
- }
- func (c *container) getMemeoryEventFD(root string) (*oom, error) {
- f, err := os.Open(filepath.Join(root, "memory.oom_control"))
- if err != nil {
- return nil, err
- }
- fd, _, serr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0)
- if serr != 0 {
- f.Close()
- return nil, serr
- }
- if err := c.writeEventFD(root, int(f.Fd()), int(fd)); err != nil {
- syscall.Close(int(fd))
- f.Close()
- return nil, err
- }
- return &oom{
- root: root,
- id: c.id,
- eventfd: int(fd),
- control: f,
- }, nil
- }
|