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 (c *container) Resume() error { args := c.runtimeArgs args = append(args, "resume", c.id) b, err := exec.Command(c.runtime, args...).CombinedOutput() if err != nil { return fmt.Errorf("%s: %q", err.Error(), string(b)) } return nil }
func (d *directProcess) delete() { if d.console != nil { d.console.Close() } d.io.Close() d.Wait() if !d.exec { exec.Command(d.container.runtime, append(d.container.runtimeArgs, "delete", d.container.id)...).Run() } }
func (c *container) Delete() error { err := os.RemoveAll(filepath.Join(c.root, c.id)) args := c.runtimeArgs args = append(args, "delete", c.id) if derr := exec.Command(c.runtime, args...).Run(); err == nil { err = derr } return err }
// cmd runs `apparmor_parser` with the passed arguments. func cmd(dir string, arg ...string) (string, error) { c := exec.Command(binary, arg...) c.Dir = dir output, err := c.CombinedOutput() if err != nil { return "", fmt.Errorf("running `%s %s` failed with output: %s\nerror: %v", c.Path, strings.Join(c.Args, " "), string(output), err) } return string(output), nil }
func (p *process) Start() error { cmd := exec.Command(p.container.shim, p.container.id, p.container.bundle, p.container.runtime, ) cmd.Dir = p.root cmd.SysProcAttr = &syscall.SysProcAttr{ Setpgid: true, } return p.startCmd(cmd) }
func (c *container) Pids() ([]int, error) { args := c.runtimeArgs args = append(args, "ps", "--format=json", c.id) out, err := exec.Command(c.runtime, args...).CombinedOutput() if err != nil { return nil, fmt.Errorf("%s: %q", err.Error(), out) } var pids []int if err := json.Unmarshal(out, &pids); err != nil { return nil, err } return pids, nil }
func (c *container) Checkpoint(cpt Checkpoint, checkpointDir string) error { if checkpointDir == "" { checkpointDir = filepath.Join(c.bundle, "checkpoints") } if err := os.MkdirAll(checkpointDir, 0755); err != nil { return err } path := filepath.Join(checkpointDir, cpt.Name) if err := os.Mkdir(path, 0755); err != nil { return err } f, err := os.Create(filepath.Join(path, "config.json")) if err != nil { return err } cpt.Created = time.Now() err = json.NewEncoder(f).Encode(cpt) f.Close() if err != nil { return err } args := []string{ "checkpoint", "--image-path", path, } add := func(flags ...string) { args = append(args, flags...) } add(c.runtimeArgs...) if !cpt.Exit { add("--leave-running") } if cpt.Shell { add("--shell-job") } if cpt.Tcp { add("--tcp-established") } if cpt.UnixSockets { add("--ext-unix-sk") } add(c.id) out, err := exec.Command(c.runtime, args...).CombinedOutput() if err != nil { return fmt.Errorf("%s: %q", err.Error(), string(out)) } return err }
func (c *container) Stats() (*Stat, error) { now := time.Now() args := c.runtimeArgs args = append(args, "events", "--stats", c.id) out, err := exec.Command(c.runtime, args...).CombinedOutput() if err != nil { return nil, fmt.Errorf("%s: %q", err.Error(), out) } s := struct { Data *Stat `json:"data"` }{} if err := json.Unmarshal(out, &s); err != nil { return nil, err } s.Data.Timestamp = now return s.Data, nil }
// Status implements the runtime Container interface. func (c *container) Status() (State, error) { args := c.runtimeArgs args = append(args, "state", c.id) out, err := exec.Command(c.runtime, args...).CombinedOutput() if err != nil { return "", fmt.Errorf("%s: %q", err.Error(), out) } // We only require the runtime json output to have a top level Status field. var s struct { Status State `json:"status"` } if err := json.Unmarshal(out, &s); err != nil { return "", err } return s.Status, nil }
func xzDecompress(archive io.Reader) (io.ReadCloser, <-chan struct{}, error) { args := []string{"xz", "-d", "-c", "-q"} return cmdStream(exec.Command(args[0], args[1:]...), archive) }
func git(args ...string) ([]byte, error) { return exec.Command("git", args...).CombinedOutput() }
func (d *directProcess) Start() error { cwd, err := filepath.Abs(d.root) if err != nil { return err } stdin, stdout, stderr, err := d.openIO() if err != nil { return nil } checkpoint, err := d.loadCheckpoint(d.container.bundle) if err != nil { return err } logPath := filepath.Join(cwd, "log.json") args := append([]string{ "--log", logPath, "--log-format", "json", }, d.container.runtimeArgs...) if d.exec { args = append(args, "exec", "--process", filepath.Join(cwd, "process.json"), "--console", d.consolePath, ) } else if checkpoint != nil { args = append(args, "restore", "--image-path", filepath.Join(d.container.bundle, "checkpoints", checkpoint.Name), ) add := func(flags ...string) { args = append(args, flags...) } if checkpoint.Shell { add("--shell-job") } if checkpoint.Tcp { add("--tcp-established") } if checkpoint.UnixSockets { add("--ext-unix-sk") } if d.container.noPivotRoot { add("--no-pivot") } } else { args = append(args, "start", "--bundle", d.container.bundle, "--console", d.consolePath, ) if d.container.noPivotRoot { args = append(args, "--no-pivot") } } args = append(args, "-d", "--pid-file", filepath.Join(cwd, "pid"), d.container.id, ) cmd := exec.Command(d.container.runtime, args...) cmd.Dir = d.container.bundle cmd.Stdin = stdin cmd.Stdout = stdout cmd.Stderr = stderr // set the parent death signal to SIGKILL so that if containerd dies the container // process also dies cmd.SysProcAttr = &syscall.SysProcAttr{ Pdeathsig: syscall.SIGKILL, } exitSubscription := subreaper.Subscribe() err = d.startCmd(cmd) if err != nil { subreaper.Unsubscribe(exitSubscription) d.delete() return err } go d.watch(cmd, exitSubscription) return nil }
// ContainerTop lists the processes running inside of the given // container by calling ps with the given args, or with the flags // "-ef" if no args are given. An error is returned if the container // is not found, or is not running, or if there are any problems // running ps, or parsing the output. func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) { if psArgs == "" { psArgs = "-ef" } container, err := daemon.GetContainer(name) if err != nil { return nil, err } if !container.IsRunning() { return nil, errNotRunning{container.ID} } if container.IsRestarting() { return nil, errContainerIsRestarting(container.ID) } pids, err := daemon.containerd.GetPidsForContainer(container.ID) if err != nil { return nil, err } output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output() if err != nil { return nil, fmt.Errorf("Error running ps: %v", err) } procList := &types.ContainerProcessList{} lines := strings.Split(string(output), "\n") procList.Titles = strings.Fields(lines[0]) pidIndex := -1 for i, name := range procList.Titles { if name == "PID" { pidIndex = i } } if pidIndex == -1 { return nil, fmt.Errorf("Couldn't find PID field in ps output") } // loop through the output and extract the PID from each line for _, line := range lines[1:] { if len(line) == 0 { continue } fields := strings.Fields(line) p, err := strconv.Atoi(fields[pidIndex]) if err != nil { return nil, fmt.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err) } for _, pid := range pids { if pid == p { // Make sure number of fields equals number of header titles // merging "overhanging" fields process := fields[:len(procList.Titles)-1] process = append(process, strings.Join(fields[len(procList.Titles)-1:], " ")) procList.Processes = append(procList.Processes, process) } } } daemon.LogContainerEvent(container, "top") return procList, nil }