Upgrade containerd to v1.3.3-k3s1

pull/1323/head
Erik Wilson 2020-01-20 16:17:03 -07:00
parent d8cf1edf65
commit 39d146bb90
25 changed files with 242 additions and 113 deletions

2
go.mod
View File

@ -7,7 +7,7 @@ replace (
github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83 github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83
github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601 github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601
github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
github.com/containerd/containerd => github.com/rancher/containerd v1.3.0-k3s.5 github.com/containerd/containerd => github.com/rancher/containerd v1.3.3-k3s1
github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02 github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02
github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.3 github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.3
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c

4
go.sum
View File

@ -705,8 +705,8 @@ github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:
github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 h1:83l9gPhYtgxODlZKU0Odq4pQuDcMZEVgAh364+PV3OU= github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 h1:83l9gPhYtgxODlZKU0Odq4pQuDcMZEVgAh364+PV3OU=
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk= github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk=
github.com/rancher/containerd v1.3.0-k3s.5 h1:r5GheXz59KQpEdYPxRd53vfFhipnQG/g3MI5NkNPDQI= github.com/rancher/containerd v1.3.3-k3s1 h1:j8NGZdXKsZd2ne0XQg6OBfMJ/NkY/Qri6QhscGrJp2M=
github.com/rancher/containerd v1.3.0-k3s.5/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM= github.com/rancher/containerd v1.3.3-k3s1/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM=
github.com/rancher/cri v1.3.0-k3s.3 h1:j/Sq2LMyg6gBn2MS1j5dEudpdL+UYVH7ubbewUCXkS0= github.com/rancher/cri v1.3.0-k3s.3 h1:j/Sq2LMyg6gBn2MS1j5dEudpdL+UYVH7ubbewUCXkS0=
github.com/rancher/cri v1.3.0-k3s.3/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY= github.com/rancher/cri v1.3.0-k3s.3/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg= github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg=

View File

@ -7,12 +7,13 @@ clone_folder: c:\gopath\src\github.com\containerd\containerd
branches: branches:
only: only:
- master - master
- /release\/.*/
environment: environment:
GOPATH: C:\gopath GOPATH: C:\gopath
CGO_ENABLED: 1 CGO_ENABLED: 1
matrix: matrix:
- GO_VERSION: 1.12.12 - GO_VERSION: 1.12.15
before_build: before_build:
- choco install -y mingw --version 5.3.0 - choco install -y mingw --version 5.3.0

View File

@ -10,11 +10,11 @@ os:
- linux - linux
go: go:
- "1.12.12" - "1.12.15"
env: env:
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic - TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic - TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic TRAVIS_RELEASE=yes
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic - TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0 - TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0
@ -59,9 +59,9 @@ install:
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-runc ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-runc ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-cni ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-cni ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.12.tar.gz -O /tmp/criu.tar.gz ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.13.tar.gz -O /tmp/criu.tar.gz ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then tar -C /tmp/ -zxf /tmp/criu.tar.gz ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then tar -C /tmp/ -zxf /tmp/criu.tar.gz ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.12 && sudo make install-criu ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.13 && sudo make install-criu ; fi
- cd $TRAVIS_BUILD_DIR - cd $TRAVIS_BUILD_DIR
before_script: before_script:
@ -83,9 +83,9 @@ script:
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration EXTRA_TESTFLAGS=-no-criu ; fi
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759 # Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration ; fi - if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration EXTRA_TESTFLAGS=-no-criu ; fi
- | - |
if [ "$TRAVIS_GOOS" = "linux" ]; then if [ "$TRAVIS_GOOS" = "linux" ]; then
sudo mkdir -p /etc/containerd sudo mkdir -p /etc/containerd
@ -107,8 +107,7 @@ after_success:
- bash <(curl -s https://codecov.io/bash) -F linux - bash <(curl -s https://codecov.io/bash) -F linux
before_deploy: before_deploy:
- make release - if [ "$TRAVIS_RELEASE" = "yes" ]; then make release cri-release; fi
- if [ "$TRAVIS_GOOS" = "linux" ]; then make cri-release; fi
deploy: deploy:
- provider: releases - provider: releases

View File

@ -80,6 +80,11 @@ TEST_REQUIRES_ROOT_PACKAGES=$(filter \
done | sort -u) \ done | sort -u) \
) )
ifdef SKIPTESTS
PACKAGES:=$(filter-out ${SKIPTESTS},${PACKAGES})
TEST_REQUIRES_ROOT_PACKAGES:=$(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES})
endif
# Project binaries. # Project binaries.
COMMANDS=ctr containerd containerd-stress COMMANDS=ctr containerd containerd-stress
MANPAGES=ctr.1 containerd.1 containerd-config.1 containerd-config.toml.5 MANPAGES=ctr.1 containerd.1 containerd-config.1 containerd-config.toml.5
@ -111,7 +116,7 @@ GO_GCFLAGS=$(shell \
BINARIES=$(addprefix bin/,$(COMMANDS)) BINARIES=$(addprefix bin/,$(COMMANDS))
# Flags passed to `go test` # Flags passed to `go test`
TESTFLAGS ?= $(TESTFLAGS_RACE) TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS)
TESTFLAGS_PARALLEL ?= 8 TESTFLAGS_PARALLEL ?= 8
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man genman .PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man genman

View File

@ -42,6 +42,7 @@ var (
registerServiceFlag bool registerServiceFlag bool
unregisterServiceFlag bool unregisterServiceFlag bool
runServiceFlag bool runServiceFlag bool
logFileFlag string
kernel32 = windows.NewLazySystemDLL("kernel32.dll") kernel32 = windows.NewLazySystemDLL("kernel32.dll")
setStdHandle = kernel32.NewProc("SetStdHandle") setStdHandle = kernel32.NewProc("SetStdHandle")
@ -52,6 +53,8 @@ var (
service *handler service *handler
) )
const defaultServiceName = "containerd"
// serviceFlags returns an array of flags for configuring containerd to run // serviceFlags returns an array of flags for configuring containerd to run
// as a Windows service under control of SCM. // as a Windows service under control of SCM.
func serviceFlags() []cli.Flag { func serviceFlags() []cli.Flag {
@ -59,7 +62,7 @@ func serviceFlags() []cli.Flag {
cli.StringFlag{ cli.StringFlag{
Name: "service-name", Name: "service-name",
Usage: "Set the Windows service name", Usage: "Set the Windows service name",
Value: "containerd", Value: defaultServiceName,
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "register-service", Name: "register-service",
@ -74,14 +77,18 @@ func serviceFlags() []cli.Flag {
Usage: "", Usage: "",
Hidden: true, Hidden: true,
}, },
cli.StringFlag{
Name: "log-file",
Usage: "Path to the containerd log file",
},
} }
} }
// applyPlatformFlags applies platform-specific flags. // applyPlatformFlags applies platform-specific flags.
func applyPlatformFlags(context *cli.Context) { func applyPlatformFlags(context *cli.Context) {
serviceNameFlag = context.GlobalString("service-name")
if s := context.GlobalString("service-name"); s != "" { if serviceNameFlag == "" {
serviceNameFlag = s serviceNameFlag = defaultServiceName
} }
for _, v := range []struct { for _, v := range []struct {
name string name string
@ -102,6 +109,7 @@ func applyPlatformFlags(context *cli.Context) {
} { } {
*v.d = context.GlobalBool(v.name) *v.d = context.GlobalBool(v.name)
} }
logFileFlag = context.GlobalString("log-file")
} }
type handler struct { type handler struct {
@ -243,7 +251,15 @@ func registerUnregisterService(root string) (bool, error) {
return true, err return true, err
} }
logrus.SetOutput(ioutil.Discard) logOutput := ioutil.Discard
if logFileFlag != "" {
f, err := os.OpenFile(logFileFlag, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return true, errors.Wrapf(err, "open log file %q", logFileFlag)
}
logOutput = f
}
logrus.SetOutput(logOutput)
} }
return false, nil return false, nil
} }

View File

@ -209,6 +209,8 @@ func (p *parser) field() (string, error) {
return s, nil return s, nil
case tokenQuoted: case tokenQuoted:
return p.unquote(pos, s, false) return p.unquote(pos, s, false)
case tokenIllegal:
return "", p.mkerr(pos, p.scanner.err)
} }
return "", p.mkerr(pos, "expected field or quoted") return "", p.mkerr(pos, "expected field or quoted")
@ -228,6 +230,8 @@ func (p *parser) operator() (operator, error) {
default: default:
return 0, p.mkerr(pos, "unsupported operator %q", s) return 0, p.mkerr(pos, "unsupported operator %q", s)
} }
case tokenIllegal:
return 0, p.mkerr(pos, p.scanner.err)
} }
return 0, p.mkerr(pos, `expected an operator ("=="|"!="|"~=")`) return 0, p.mkerr(pos, `expected an operator ("=="|"!="|"~=")`)
@ -241,6 +245,8 @@ func (p *parser) value(allowAltQuotes bool) (string, error) {
return s, nil return s, nil
case tokenQuoted: case tokenQuoted:
return p.unquote(pos, s, allowAltQuotes) return p.unquote(pos, s, allowAltQuotes)
case tokenIllegal:
return "", p.mkerr(pos, p.scanner.err)
} }
return "", p.mkerr(pos, "expected value or quoted") return "", p.mkerr(pos, "expected value or quoted")

View File

@ -17,7 +17,6 @@
package filters package filters
import ( import (
"fmt"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
@ -64,6 +63,7 @@ type scanner struct {
pos int pos int
ppos int // bounds the current rune in the string ppos int // bounds the current rune in the string
value bool value bool
err string
} }
func (s *scanner) init(input string) { func (s *scanner) init(input string) {
@ -82,12 +82,14 @@ func (s *scanner) next() rune {
s.ppos += w s.ppos += w
if r == utf8.RuneError { if r == utf8.RuneError {
if w > 0 { if w > 0 {
s.error("rune error")
return tokenIllegal return tokenIllegal
} }
return tokenEOF return tokenEOF
} }
if r == 0 { if r == 0 {
s.error("unexpected null")
return tokenIllegal return tokenIllegal
} }
@ -114,7 +116,9 @@ chomp:
case ch == tokenEOF: case ch == tokenEOF:
case ch == tokenIllegal: case ch == tokenIllegal:
case isQuoteRune(ch): case isQuoteRune(ch):
s.scanQuoted(ch) if !s.scanQuoted(ch) {
return pos, tokenIllegal, s.input[pos:s.ppos]
}
return pos, tokenQuoted, s.input[pos:s.ppos] return pos, tokenQuoted, s.input[pos:s.ppos]
case isSeparatorRune(ch): case isSeparatorRune(ch):
s.value = false s.value = false
@ -172,54 +176,64 @@ func (s *scanner) scanValue() {
} }
} }
func (s *scanner) scanQuoted(quote rune) { func (s *scanner) scanQuoted(quote rune) bool {
var illegal bool
ch := s.next() // read character after quote ch := s.next() // read character after quote
for ch != quote { for ch != quote {
if ch == '\n' || ch < 0 { if ch == '\n' || ch < 0 {
s.error("literal not terminated") s.error("quoted literal not terminated")
return return false
} }
if ch == '\\' { if ch == '\\' {
ch = s.scanEscape(quote) var legal bool
ch, legal = s.scanEscape(quote)
if !legal {
illegal = true
}
} else { } else {
ch = s.next() ch = s.next()
} }
} }
return !illegal
} }
func (s *scanner) scanEscape(quote rune) rune { func (s *scanner) scanEscape(quote rune) (ch rune, legal bool) {
ch := s.next() // read character after '/' ch = s.next() // read character after '/'
switch ch { switch ch {
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote: case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
// nothing to do // nothing to do
ch = s.next() ch = s.next()
legal = true
case '0', '1', '2', '3', '4', '5', '6', '7': case '0', '1', '2', '3', '4', '5', '6', '7':
ch = s.scanDigits(ch, 8, 3) ch, legal = s.scanDigits(ch, 8, 3)
case 'x': case 'x':
ch = s.scanDigits(s.next(), 16, 2) ch, legal = s.scanDigits(s.next(), 16, 2)
case 'u': case 'u':
ch = s.scanDigits(s.next(), 16, 4) ch, legal = s.scanDigits(s.next(), 16, 4)
case 'U': case 'U':
ch = s.scanDigits(s.next(), 16, 8) ch, legal = s.scanDigits(s.next(), 16, 8)
default: default:
s.error("illegal char escape") s.error("illegal escape sequence")
} }
return ch return
} }
func (s *scanner) scanDigits(ch rune, base, n int) rune { func (s *scanner) scanDigits(ch rune, base, n int) (rune, bool) {
for n > 0 && digitVal(ch) < base { for n > 0 && digitVal(ch) < base {
ch = s.next() ch = s.next()
n-- n--
} }
if n > 0 { if n > 0 {
s.error("illegal char escape") s.error("illegal numeric escape sequence")
return ch, false
} }
return ch return ch, true
} }
func (s *scanner) error(msg string) { func (s *scanner) error(msg string) {
fmt.Println("error fixme", msg) if s.err == "" {
s.err = msg
}
} }
func digitVal(ch rune) int { func digitVal(ch rune) int {

View File

@ -21,6 +21,8 @@ import (
"context" "context"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strings"
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
"github.com/containerd/containerd/archive" "github.com/containerd/containerd/archive"
@ -48,6 +50,15 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
if err != nil { if err != nil {
return err return err
} }
var binDir, libDir string
if runtime.GOOS == "windows" {
binDir = "Files\\bin"
libDir = "Files\\lib"
} else {
binDir = "bin"
libDir = "lib"
}
for _, layer := range manifest.Layers { for _, layer := range manifest.Layers {
ra, err := cs.ReaderAt(ctx, layer) ra, err := cs.ReaderAt(ctx, layer)
if err != nil { if err != nil {
@ -60,9 +71,14 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
} }
if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) { if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) {
d := filepath.Dir(hdr.Name) d := filepath.Dir(hdr.Name)
result := d == "bin" result := d == binDir
if config.Libs { if config.Libs {
result = result || d == "lib" result = result || d == libDir
}
if runtime.GOOS == "windows" {
hdr.Name = strings.Replace(hdr.Name, "Files", "", 1)
} }
if result && !config.Replace { if result && !config.Replace {
if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil { if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil {

View File

@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) { func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
return nil, errors.Errorf("cannot exec in a deleted state") return nil, errors.Errorf("cannot exec in a deleted state")
} }
func (s *deletedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -96,7 +96,6 @@ func (e *execProcess) setExited(status int) {
e.status = status e.status = status
e.exited = time.Now() e.exited = time.Now()
e.parent.Platform.ShutdownConsole(context.Background(), e.console) e.parent.Platform.ShutdownConsole(context.Background(), e.console)
e.pid.set(StoppedPID)
close(e.waitBlock) close(e.waitBlock)
} }
@ -147,7 +146,7 @@ func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
switch { switch {
case pid == 0: case pid == 0:
return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created") return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created")
case pid < 0: case !e.exited.IsZero():
return errors.Wrapf(errdefs.ErrNotFound, "process already finished") return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
default: default:
if err := unix.Kill(pid, syscall.Signal(sig)); err != nil { if err := unix.Kill(pid, syscall.Signal(sig)); err != nil {
@ -261,17 +260,5 @@ func (e *execProcess) Status(ctx context.Context) (string, error) {
} }
e.mu.Lock() e.mu.Lock()
defer e.mu.Unlock() defer e.mu.Unlock()
// if we don't have a pid(pid=0) then the exec process has just been created return e.execState.Status(ctx)
if e.pid.get() == 0 {
return "created", nil
}
if e.pid.get() == StoppedPID {
return "stopped", nil
}
// if we have a pid and it can be signaled, the process is running
if err := unix.Kill(e.pid.get(), 0); err == nil {
return "running", nil
}
// else if we have a pid but it can nolonger be signaled, it has stopped
return "stopped", nil
} }

View File

@ -31,6 +31,7 @@ type execState interface {
Delete(context.Context) error Delete(context.Context) error
Kill(context.Context, uint32, bool) error Kill(context.Context, uint32, bool) error
SetExited(int) SetExited(int)
Status(context.Context) (string, error)
} }
type execCreatedState struct { type execCreatedState struct {
@ -82,6 +83,10 @@ func (s *execCreatedState) SetExited(status int) {
} }
} }
func (s *execCreatedState) Status(ctx context.Context) (string, error) {
return "created", nil
}
type execRunningState struct { type execRunningState struct {
p *execProcess p *execProcess
} }
@ -120,6 +125,10 @@ func (s *execRunningState) SetExited(status int) {
} }
} }
func (s *execRunningState) Status(ctx context.Context) (string, error) {
return "running", nil
}
type execStoppedState struct { type execStoppedState struct {
p *execProcess p *execProcess
} }
@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
func (s *execStoppedState) SetExited(status int) { func (s *execStoppedState) SetExited(status int) {
// no op // no op
} }
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -56,15 +56,17 @@ type Init struct {
WorkDir string WorkDir string
id string id string
Bundle string Bundle string
console console.Console console console.Console
Platform stdio.Platform Platform stdio.Platform
io *processIO io *processIO
runtime *runc.Runc runtime *runc.Runc
// pausing preserves the pausing state.
pausing *atomicBool
status int status int
exited time.Time exited time.Time
pid safePid pid int
closers []io.Closer closers []io.Closer
stdin io.Closer stdin io.Closer
stdio stdio.Stdio stdio stdio.Stdio
@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
p := &Init{ p := &Init{
id: id, id: id,
runtime: runtime, runtime: runtime,
pausing: new(atomicBool),
stdio: stdio, stdio: stdio,
status: 0, status: 0,
waitBlock: make(chan struct{}), waitBlock: make(chan struct{}),
@ -113,8 +116,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
pio *processIO pio *processIO
pidFile = newPidFile(p.Bundle) pidFile = newPidFile(p.Bundle)
) )
p.pid.Lock()
defer p.pid.Unlock()
if r.Terminal { if r.Terminal {
if socket, err = runc.NewTempConsoleSocket(); err != nil { if socket, err = runc.NewTempConsoleSocket(); err != nil {
@ -170,7 +171,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
if err != nil { if err != nil {
return errors.Wrap(err, "failed to retrieve OCI runtime container pid") return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
} }
p.pid.pid = pid p.pid = pid
return nil return nil
} }
@ -216,7 +217,7 @@ func (p *Init) ID() string {
// Pid of the process // Pid of the process
func (p *Init) Pid() int { func (p *Init) Pid() int {
return p.pid.get() return p.pid
} }
// ExitStatus of the process // ExitStatus of the process
@ -237,17 +238,14 @@ func (p *Init) ExitedAt() time.Time {
// Status of the process // Status of the process
func (p *Init) Status(ctx context.Context) (string, error) { func (p *Init) Status(ctx context.Context) (string, error) {
if p.pausing.get() {
return "pausing", nil
}
p.mu.Lock() p.mu.Lock()
defer p.mu.Unlock() defer p.mu.Unlock()
c, err := p.runtime.State(ctx, p.id) return p.initState.Status(ctx)
if err != nil {
if strings.Contains(err.Error(), "does not exist") {
return "stopped", nil
}
return "", p.runtimeError(err, "OCI runtime state failed")
}
return c.Status, nil
} }
// Start the init process // Start the init process
@ -275,7 +273,6 @@ func (p *Init) setExited(status int) {
p.exited = time.Now() p.exited = time.Now()
p.status = status p.status = status
p.Platform.ShutdownConsole(context.Background(), p.console) p.Platform.ShutdownConsole(context.Background(), p.console)
p.pid.set(StoppedPID)
close(p.waitBlock) close(p.waitBlock)
} }

View File

@ -37,6 +37,7 @@ type initState interface {
Exec(context.Context, string, *ExecConfig) (Process, error) Exec(context.Context, string, *ExecConfig) (Process, error)
Kill(context.Context, uint32, bool) error Kill(context.Context, uint32, bool) error
SetExited(int) SetExited(int)
Status(context.Context) (string, error)
} }
type createdState struct { type createdState struct {
@ -103,6 +104,10 @@ func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
return s.p.exec(ctx, path, r) return s.p.exec(ctx, path, r)
} }
func (s *createdState) Status(ctx context.Context) (string, error) {
return "created", nil
}
type createdCheckpointState struct { type createdCheckpointState struct {
p *Init p *Init
opts *runc.RestoreOpts opts *runc.RestoreOpts
@ -142,9 +147,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
p := s.p p := s.p
sio := p.stdio sio := p.stdio
p.pid.Lock()
defer p.pid.Unlock()
var ( var (
err error err error
socket *runc.Socket socket *runc.Socket
@ -184,7 +186,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
if err != nil { if err != nil {
return errors.Wrap(err, "failed to retrieve OCI runtime container pid") return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
} }
p.pid.pid = pid p.pid = pid
return s.transition("running") return s.transition("running")
} }
@ -211,6 +213,10 @@ func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecC
return nil, errors.Errorf("cannot exec in a created state") return nil, errors.Errorf("cannot exec in a created state")
} }
func (s *createdCheckpointState) Status(ctx context.Context) (string, error) {
return "created", nil
}
type runningState struct { type runningState struct {
p *Init p *Init
} }
@ -228,6 +234,13 @@ func (s *runningState) transition(name string) error {
} }
func (s *runningState) Pause(ctx context.Context) error { func (s *runningState) Pause(ctx context.Context) error {
s.p.pausing.set(true)
// NOTE "pausing" will be returned in the short window
// after `transition("paused")`, before `pausing` is reset
// to false. That doesn't break the state machine, just
// delays the "paused" state a little bit.
defer s.p.pausing.set(false)
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil { if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
return s.p.runtimeError(err, "OCI runtime pause failed") return s.p.runtimeError(err, "OCI runtime pause failed")
} }
@ -271,6 +284,10 @@ func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
return s.p.exec(ctx, path, r) return s.p.exec(ctx, path, r)
} }
func (s *runningState) Status(ctx context.Context) (string, error) {
return "running", nil
}
type pausedState struct { type pausedState struct {
p *Init p *Init
} }
@ -335,6 +352,10 @@ func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Pro
return nil, errors.Errorf("cannot exec in a paused state") return nil, errors.Errorf("cannot exec in a paused state")
} }
func (s *pausedState) Status(ctx context.Context) (string, error) {
return "paused", nil
}
type stoppedState struct { type stoppedState struct {
p *Init p *Init
} }
@ -387,3 +408,7 @@ func (s *stoppedState) SetExited(status int) {
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) { func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
return nil, errors.Errorf("cannot exec in a stopped state") return nil, errors.Errorf("cannot exec in a stopped state")
} }
func (s *stoppedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -27,6 +27,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/errdefs"
@ -38,8 +39,6 @@ import (
const ( const (
// RuncRoot is the path to the root runc state directory // RuncRoot is the path to the root runc state directory
RuncRoot = "/run/containerd/runc" RuncRoot = "/run/containerd/runc"
// StoppedPID is the pid assigned after a container has run and stopped
StoppedPID = -1
// InitPidFile name of the file that contains the init pid // InitPidFile name of the file that contains the init pid
InitPidFile = "init.pid" InitPidFile = "init.pid"
) )
@ -56,10 +55,18 @@ func (s *safePid) get() int {
return s.pid return s.pid
} }
func (s *safePid) set(pid int) { type atomicBool int32
s.Lock()
s.pid = pid func (ab *atomicBool) set(b bool) {
s.Unlock() if b {
atomic.StoreInt32((*int32)(ab), 1)
} else {
atomic.StoreInt32((*int32)(ab), 0)
}
}
func (ab *atomicBool) get() bool {
return atomic.LoadInt32((*int32)(ab)) == 1
} }
// TODO(mlaventure): move to runc package? // TODO(mlaventure): move to runc package?

View File

@ -189,9 +189,8 @@ func Parse(specifier string) (specs.Platform, error) {
if isKnownOS(p.OS) { if isKnownOS(p.OS) {
// picks a default architecture // picks a default architecture
p.Architecture = runtime.GOARCH p.Architecture = runtime.GOARCH
if p.Architecture == "arm" { if p.Architecture == "arm" && cpuVariant != "v7" {
// TODO(stevvooe): Resolve arm variant, if not v6 (default) p.Variant = cpuVariant
return specs.Platform{}, errors.Wrapf(errdefs.ErrNotImplemented, "arm support not fully implemented")
} }
return p, nil return p, nil

View File

@ -70,6 +70,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
} }
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks) unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
defer func() { defer func() {
if retErr != nil {
// Forcibly stop the unpacker if there is
// an error.
eg.Cancel()
}
if err := eg.Wait(); err != nil { if err := eg.Wait(); err != nil {
if retErr == nil { if retErr == nil {
retErr = errors.Wrap(err, "unpack") retErr = errors.Wrap(err, "unpack")

View File

@ -316,11 +316,12 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
s.eventSendMu.Unlock() s.eventSendMu.Unlock()
return nil, errdefs.ToGRPC(err) return nil, errdefs.ToGRPC(err)
} }
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
logrus.WithError(err).Error("add cg to OOM monitor")
}
switch r.ExecID { switch r.ExecID {
case "": case "":
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
logrus.WithError(err).Error("add cg to OOM monitor")
}
s.send(&eventstypes.TaskStart{ s.send(&eventstypes.TaskStart{
ContainerID: container.ID, ContainerID: container.ID,
Pid: uint32(p.Pid()), Pid: uint32(p.Pid()),
@ -348,15 +349,11 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
if err != nil { if err != nil {
return nil, errdefs.ToGRPC(err) return nil, errdefs.ToGRPC(err)
} }
// if we deleted our init task, close the platform and send the task delete event // if we deleted an init task, send the task delete event
if r.ExecID == "" { if r.ExecID == "" {
s.mu.Lock() s.mu.Lock()
delete(s.containers, r.ID) delete(s.containers, r.ID)
hasContainers := len(s.containers) > 0
s.mu.Unlock() s.mu.Unlock()
if s.platform != nil && !hasContainers {
s.platform.Close()
}
s.send(&eventstypes.TaskDelete{ s.send(&eventstypes.TaskDelete{
ContainerID: container.ID, ContainerID: container.ID,
Pid: uint32(p.Pid()), Pid: uint32(p.Pid()),
@ -600,6 +597,11 @@ func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*pt
} }
s.cancel() s.cancel()
close(s.events) close(s.events)
if s.platform != nil {
s.platform.Close()
}
return empty, nil return empty, nil
} }

View File

@ -115,7 +115,7 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ
return nil return nil
}, req.Filters...); err != nil { }, req.Filters...); err != nil {
return err return errdefs.ToGRPC(err)
} }
if len(buffer) > 0 { if len(buffer) > 0 {

View File

@ -20,7 +20,6 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -42,22 +41,20 @@ func init() {
InitFn: func(ic *plugin.InitContext) (interface{}, error) { InitFn: func(ic *plugin.InitContext) (interface{}, error) {
path := ic.Config.(*Config).Path path := ic.Config.(*Config).Path
ic.Meta.Exports["path"] = path ic.Meta.Exports["path"] = path
bin := filepath.Join(path, "bin") bin := filepath.Join(path, "bin")
if err := os.MkdirAll(bin, 0711); err != nil { if err := os.MkdirAll(bin, 0711); err != nil {
return nil, err return nil, err
} }
if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", bin, os.Getenv("PATH"))); err != nil { if err := os.Setenv("PATH", fmt.Sprintf("%s%c%s", bin, os.PathListSeparator, os.Getenv("PATH"))); err != nil {
return nil, errors.Wrapf(err, "set binary image directory in path %s", bin) return nil, errors.Wrapf(err, "set binary image directory in path %s", bin)
} }
if runtime.GOOS != "windows" {
lib := filepath.Join(path, "lib") lib := filepath.Join(path, "lib")
if err := os.MkdirAll(lib, 0711); err != nil { if err := os.MkdirAll(lib, 0711); err != nil {
return nil, err return nil, err
} }
if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s:%s", os.Getenv("LD_LIBRARY_PATH"), lib)); err != nil { if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s%c%s", lib, os.PathListSeparator, os.Getenv("LD_LIBRARY_PATH"))); err != nil {
return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib) return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib)
}
} }
return &manager{}, nil return &manager{}, nil
}, },

View File

@ -297,7 +297,7 @@ func Remove(ctx context.Context, key string) (string, snapshots.Kind, error) {
} }
if err := readSnapshot(sbkt, &id, &si); err != nil { if err := readSnapshot(sbkt, &id, &si); err != nil {
errors.Wrapf(err, "failed to read snapshot %s", key) return errors.Wrapf(err, "failed to read snapshot %s", key)
} }
if pbkt != nil { if pbkt != nil {

View File

@ -186,8 +186,32 @@ func (u *unpacker) unpack(ctx context.Context, config ocispec.Descriptor, layers
return nil return nil
} }
func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(images.Handler) images.Handler, *errgroup.Group) { type errGroup struct {
eg, uctx := errgroup.WithContext(uctx) *errgroup.Group
cancel context.CancelFunc
}
func newErrGroup(ctx context.Context) (*errGroup, context.Context) {
ctx, cancel := context.WithCancel(ctx)
eg, ctx := errgroup.WithContext(ctx)
return &errGroup{
Group: eg,
cancel: cancel,
}, ctx
}
func (e *errGroup) Cancel() {
e.cancel()
}
func (e *errGroup) Wait() error {
err := e.Group.Wait()
e.cancel()
return err
}
func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(images.Handler) images.Handler, *errGroup) {
eg, uctx := newErrGroup(uctx)
return func(f images.Handler) images.Handler { return func(f images.Handler) images.Handler {
var ( var (
lock sync.Mutex lock sync.Mutex
@ -234,7 +258,19 @@ func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(im
update := !schema1 update := !schema1
lock.Unlock() lock.Unlock()
if update { if update {
u.updateCh <- desc select {
case <-uctx.Done():
// Do not send update if unpacker is not running.
default:
select {
case u.updateCh <- desc:
case <-uctx.Done():
// Do not send update if unpacker is not running.
}
}
// Checking ctx.Done() prevents the case that unpacker
// exits unexpectedly, but update continues to be generated,
// and eventually fills up updateCh and blocks forever.
} }
} }
return children, nil return children, nil

View File

@ -51,7 +51,7 @@ github.com/cpuguy83/go-md2man v1.0.10
github.com/russross/blackfriday v1.5.2 github.com/russross/blackfriday v1.5.2
# cri dependencies # cri dependencies
github.com/containerd/cri 5d49e7e51b43e36a6b9c4386257c7d08c602237f # release/1.3 github.com/containerd/cri b1bef15fbeb6c6f0569b67322acfa74ca3597755 # release/1.3
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1 github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
github.com/containernetworking/cni v0.7.1 github.com/containernetworking/cni v0.7.1
github.com/containernetworking/plugins v0.7.6 github.com/containernetworking/plugins v0.7.6

View File

@ -21,7 +21,7 @@ var (
Package = "github.com/containerd/containerd" Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time. // Version holds the complete version number. Filled in at linking time.
Version = "1.3.0+unknown" Version = "1.3.2+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build // Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time. // the program at linking time.

2
vendor/modules.txt vendored
View File

@ -151,7 +151,7 @@ github.com/container-storage-interface/spec/lib/go/csi
github.com/containerd/cgroups github.com/containerd/cgroups
# github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50 # github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
github.com/containerd/console github.com/containerd/console
# github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/rancher/containerd v1.3.0-k3s.5 # github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69 => github.com/rancher/containerd v1.3.3-k3s1
github.com/containerd/containerd github.com/containerd/containerd
github.com/containerd/containerd/api/events github.com/containerd/containerd/api/events
github.com/containerd/containerd/api/services/containers/v1 github.com/containerd/containerd/api/services/containers/v1