Package init
This commit is contained in:
commit
6138d366d1
1
VERSION-openeuler
Normal file
1
VERSION-openeuler
Normal file
@ -0,0 +1 @@
|
||||
18.09.0.100
|
||||
44
apply-patches
Executable file
44
apply-patches
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) Huawei Technologies Co., Ltd. 2018-2019. All rights reserved.
|
||||
# Description: This shell script is used to apply patches for the project
|
||||
# Author: jingrui@huawei.com
|
||||
# Create: 2019-03-02
|
||||
|
||||
set -ex
|
||||
|
||||
pkg=docker-ce-18.09.0
|
||||
cwd=$PWD
|
||||
src=$cwd/$pkg
|
||||
|
||||
tar -xzvf $pkg.tar.gz
|
||||
|
||||
cd $src
|
||||
git init
|
||||
git add .
|
||||
git config user.name 'build'
|
||||
git config user.email 'build@obs.com'
|
||||
git commit -m 'init build'
|
||||
cd $cwd
|
||||
|
||||
series=$cwd/series.conf
|
||||
while IPF= read -r line
|
||||
do
|
||||
if [[ "$line" =~ ^patch* ]]; then
|
||||
echo git apply $cwd/$line
|
||||
cd $src && git apply $cwd/$line
|
||||
fi
|
||||
done <"$series"
|
||||
|
||||
cd $cwd
|
||||
|
||||
if [ "$1" == "selinux" ]; then
|
||||
cp -rf $src/components/engine/contrib/selinux-euleros/docker-engine-selinux/* .
|
||||
else
|
||||
cp -rf $src/* .
|
||||
cp -rf VERSION-openeuler $cwd/components/cli/
|
||||
cp -rf VERSION-openeuler $cwd/components/engine/
|
||||
fi
|
||||
mv $src/.git $src/git
|
||||
|
||||
|
||||
BIN
docker-ce-18.09.0.tar.gz
Executable file
BIN
docker-ce-18.09.0.tar.gz
Executable file
Binary file not shown.
202
docker-engine-openeuler.spec
Normal file
202
docker-engine-openeuler.spec
Normal file
@ -0,0 +1,202 @@
|
||||
Name: docker-engine
|
||||
Version: 18.09.0
|
||||
Release: 100
|
||||
Summary: The open-source application container engine
|
||||
Group: Tools/Docker
|
||||
|
||||
License: ASL 2.0
|
||||
Source: %{name}.tar.gz
|
||||
|
||||
URL: https://mobyproject.org
|
||||
|
||||
%global is_systemd 1
|
||||
%global debug_package %{nil}
|
||||
|
||||
# required packages for build
|
||||
# most are already in the container (see contrib/builder/rpm/ARCH/generate.sh)
|
||||
BuildRequires: pkgconfig(systemd) golang >= 1.8.3 go-md2man btrfs-progs-devel device-mapper-devel glibc-static libseccomp-devel
|
||||
BuildRequires: libselinux-devel libtool-ltdl-devel pkgconfig selinux-policy selinux-policy-devel sqlite-devel systemd-devel
|
||||
BuildRequires: tar containerd docker-runc docker-proxy
|
||||
|
||||
# required packages on install
|
||||
Requires: /bin/sh iptables libcgroup tar xz device-mapper-libs >= 1.02.90-1 systemd-units
|
||||
|
||||
# conflicting packages
|
||||
Provides: docker
|
||||
Conflicts: docker-io
|
||||
Conflicts: docker-engine-cs
|
||||
|
||||
%description
|
||||
Docker is an open source project to build, ship and run any application as a
|
||||
lightweight container.
|
||||
|
||||
Docker containers are both hardware-agnostic and platform-agnostic. This means
|
||||
they can run anywhere, from your laptop to the largest EC2 compute instance and
|
||||
everything in between - and they don't require you to use a particular
|
||||
language, framework or packaging system. That makes them great building blocks
|
||||
for deploying and scaling web apps, databases, and backend services without
|
||||
depending on a particular stack or provider.
|
||||
|
||||
%prep
|
||||
%autosetup -c -n %{name}
|
||||
|
||||
%build
|
||||
|
||||
./apply-patches
|
||||
|
||||
# build docker engine
|
||||
WORKDIR=$(pwd)
|
||||
GITCOMMIT=$(git rev-parse --short HEAD)
|
||||
export VERSION=$(cat VERSION)
|
||||
export DOCKER_GITCOMMIT=${GITCOMMIT}
|
||||
export AUTO_GOPATH=1
|
||||
export DOCKER_BUILDTAGS="pkcs11 seccomp selinux"
|
||||
cd ${WORKDIR}/components/engine
|
||||
./hack/make.sh dynbinary
|
||||
|
||||
# buid docker cli
|
||||
cd ${WORKDIR}/components/cli
|
||||
mkdir -p .gopath/src/github.com/docker
|
||||
export GOPATH=`pwd`/.gopath
|
||||
ln -sf `pwd` .gopath/src/github.com/docker/cli
|
||||
ln -sf ${WORKDIR}/components/engine .gopath/src/github.com/docker/docker
|
||||
cd .gopath/src/github.com/docker/cli
|
||||
make dynbinary
|
||||
|
||||
# ./man/md2man-all.sh runs outside the build container (if at all), since we don't have go-md2man here
|
||||
./man/md2man-all.sh -q
|
||||
|
||||
rm -rf .gopath
|
||||
cd ${WORKDIR}
|
||||
|
||||
%check
|
||||
./components/engine/bundles/dynbinary-daemon/dockerd -v
|
||||
./components/cli/build/docker -v
|
||||
|
||||
%install
|
||||
# install binary
|
||||
install -d $RPM_BUILD_ROOT/%{_bindir}
|
||||
install -p -m 755 components/engine/bundles/dynbinary-daemon/dockerd $RPM_BUILD_ROOT/%{_bindir}/dockerd
|
||||
|
||||
# install cli
|
||||
install -p -m 755 components/cli/build/docker $RPM_BUILD_ROOT/%{_bindir}/docker
|
||||
|
||||
# install proxy
|
||||
install -p -m 755 /usr/bin/docker-proxy $RPM_BUILD_ROOT/%{_bindir}/docker-proxy
|
||||
|
||||
# install containerd
|
||||
install -p -m 755 /usr/bin/containerd $RPM_BUILD_ROOT/%{_bindir}/containerd
|
||||
install -p -m 755 /usr/bin/containerd-shim $RPM_BUILD_ROOT/%{_bindir}/containerd-shim
|
||||
|
||||
# install runc
|
||||
install -p -m 755 /usr/local/bin/runc $RPM_BUILD_ROOT/%{_bindir}/runc
|
||||
|
||||
# install udev rules
|
||||
install -d $RPM_BUILD_ROOT/%{_sysconfdir}/udev/rules.d
|
||||
install -p -m 644 components/engine/contrib/udev/80-docker.rules $RPM_BUILD_ROOT/%{_sysconfdir}/udev/rules.d/80-docker.rules
|
||||
|
||||
# add init scripts
|
||||
install -d $RPM_BUILD_ROOT/etc/sysconfig
|
||||
install -d $RPM_BUILD_ROOT/%{_initddir}
|
||||
install -p -m 644 components/engine/contrib/init/sysvinit-redhat/docker.sysconfig $RPM_BUILD_ROOT/etc/sysconfig/docker
|
||||
install -p -m 644 components/engine/contrib/init/sysvinit-redhat/docker-network $RPM_BUILD_ROOT/etc/sysconfig/docker-network
|
||||
install -p -m 644 components/engine/contrib/init/sysvinit-redhat/docker-storage $RPM_BUILD_ROOT/etc/sysconfig/docker-storage
|
||||
|
||||
install -d $RPM_BUILD_ROOT/%{_unitdir}
|
||||
install -p -m 644 components/engine/contrib/init/systemd/docker.service $RPM_BUILD_ROOT/%{_unitdir}/docker.service
|
||||
# add bash, zsh, and fish completions
|
||||
install -d $RPM_BUILD_ROOT/usr/share/bash-completion/completions
|
||||
install -d $RPM_BUILD_ROOT/usr/share/zsh/vendor-completions
|
||||
install -d $RPM_BUILD_ROOT/usr/share/fish/vendor_completions.d
|
||||
install -p -m 644 components/cli/contrib/completion/bash/docker $RPM_BUILD_ROOT/usr/share/bash-completion/completions/docker
|
||||
install -p -m 644 components/cli/contrib/completion/zsh/_docker $RPM_BUILD_ROOT/usr/share/zsh/vendor-completions/_docker
|
||||
install -p -m 644 components/cli/contrib/completion/fish/docker.fish $RPM_BUILD_ROOT/usr/share/fish/vendor_completions.d/docker.fish
|
||||
|
||||
# install manpages
|
||||
install -d %{buildroot}%{_mandir}/man1
|
||||
install -p -m 644 components/cli/man/man1/*.1 $RPM_BUILD_ROOT/%{_mandir}/man1
|
||||
install -d %{buildroot}%{_mandir}/man5
|
||||
install -p -m 644 components/cli/man/man5/*.5 $RPM_BUILD_ROOT/%{_mandir}/man5
|
||||
install -d %{buildroot}%{_mandir}/man8
|
||||
install -p -m 644 components/cli/man/man8/*.8 $RPM_BUILD_ROOT/%{_mandir}/man8
|
||||
|
||||
# add vimfiles
|
||||
install -d $RPM_BUILD_ROOT/usr/share/vim/vimfiles/doc
|
||||
install -d $RPM_BUILD_ROOT/usr/share/vim/vimfiles/ftdetect
|
||||
install -d $RPM_BUILD_ROOT/usr/share/vim/vimfiles/syntax
|
||||
install -p -m 644 components/engine/contrib/syntax/vim/doc/dockerfile.txt $RPM_BUILD_ROOT/usr/share/vim/vimfiles/doc/dockerfile.txt
|
||||
install -p -m 644 components/engine/contrib/syntax/vim/ftdetect/dockerfile.vim $RPM_BUILD_ROOT/usr/share/vim/vimfiles/ftdetect/dockerfile.vim
|
||||
install -p -m 644 components/engine/contrib/syntax/vim/syntax/dockerfile.vim $RPM_BUILD_ROOT/usr/share/vim/vimfiles/syntax/dockerfile.vim
|
||||
|
||||
# add nano
|
||||
install -d $RPM_BUILD_ROOT/usr/share/nano
|
||||
install -p -m 644 components/engine/contrib/syntax/nano/Dockerfile.nanorc $RPM_BUILD_ROOT/usr/share/nano/Dockerfile.nanorc
|
||||
|
||||
# list files owned by the package here
|
||||
%files
|
||||
%doc components/engine/AUTHORS components/engine/CHANGELOG.md components/engine/CONTRIBUTING.md components/engine/LICENSE components/engine/MAINTAINERS components/engine/NOTICE components/engine/README.md
|
||||
/%{_bindir}/docker
|
||||
/%{_bindir}/dockerd
|
||||
/%{_bindir}/containerd
|
||||
/%{_bindir}/docker-proxy
|
||||
/%{_bindir}/containerd-shim
|
||||
/%{_bindir}/runc
|
||||
/%{_sysconfdir}/udev/rules.d/80-docker.rules
|
||||
%if 0%{?is_systemd}
|
||||
/%{_unitdir}/docker.service
|
||||
%else
|
||||
/%{_initddir}/docker
|
||||
%endif
|
||||
/usr/share/bash-completion/completions/docker
|
||||
/usr/share/zsh/vendor-completions/_docker
|
||||
/usr/share/fish/vendor_completions.d/docker.fish
|
||||
%doc
|
||||
/%{_mandir}/man1/*
|
||||
/%{_mandir}/man5/*
|
||||
/%{_mandir}/man8/*
|
||||
|
||||
%config(noreplace,missingok) /etc/sysconfig/docker
|
||||
%config(noreplace,missingok) /etc/sysconfig/docker-storage
|
||||
%config(noreplace,missingok) /etc/sysconfig/docker-network
|
||||
|
||||
/usr/share/vim/vimfiles/doc/dockerfile.txt
|
||||
/usr/share/vim/vimfiles/ftdetect/dockerfile.vim
|
||||
/usr/share/vim/vimfiles/syntax/dockerfile.vim
|
||||
/usr/share/nano/Dockerfile.nanorc
|
||||
|
||||
%post
|
||||
if ! getent group docker > /dev/null; then
|
||||
groupadd --system docker
|
||||
fi
|
||||
%if 0%{?is_systemd}
|
||||
#%systemd_post docker
|
||||
systemctl enable docker
|
||||
systemctl start docker
|
||||
%else
|
||||
# This adds the proper /etc/rc*.d links for the script
|
||||
/sbin/chkconfig --add docker
|
||||
%endif
|
||||
if ! getent group docker > /dev/null; then
|
||||
groupadd --system docker
|
||||
fi
|
||||
|
||||
%preun
|
||||
%if 0%{?is_systemd}
|
||||
%systemd_preun docker
|
||||
%else
|
||||
if [ $1 -eq 0 ] ; then
|
||||
/sbin/service docker stop >/dev/null 2>&1
|
||||
/sbin/chkconfig --del docker
|
||||
fi
|
||||
%endif
|
||||
|
||||
%postun
|
||||
%if 0%{?is_systemd}
|
||||
%systemd_postun_with_restart docker
|
||||
%else
|
||||
if [ "$1" -ge "1" ] ; then
|
||||
/sbin/service docker condrestart >/dev/null 2>&1 || :
|
||||
fi
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
616
patch/0001-pause-move-pause-function-to-docker.patch
Normal file
616
patch/0001-pause-move-pause-function-to-docker.patch
Normal file
@ -0,0 +1,616 @@
|
||||
From 7e41c5cf67a5deaa542d3907a257adf6ae6c976b Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:07:09 +0800
|
||||
Subject: [PATCH 001/111] pause: move pause function to docker
|
||||
|
||||
reason: The origin pause function has a long callstack from
|
||||
docker->containerd->runc,it is waste a lot of time.
|
||||
Now we move this function to docker, docker will update freeze
|
||||
cgroup directly.
|
||||
|
||||
Change-Id: I8c26d5b4ed71fb30563db0d4e77167b5b68ccad9
|
||||
Signed-off-by: Wentao Zhang <zhangwentao234@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/container/container.go | 1 +
|
||||
components/engine/daemon/daemon.go | 53 ++++++
|
||||
components/engine/daemon/freezer/cgroup_fs.go | 94 +++++++++
|
||||
.../engine/daemon/freezer/cgroup_systemd.go | 59 ++++++
|
||||
components/engine/daemon/freezer/freezer.go | 179 ++++++++++++++++++
|
||||
components/engine/daemon/oci_linux.go | 1 +
|
||||
components/engine/daemon/pause.go | 19 +-
|
||||
components/engine/daemon/unpause.go | 17 +-
|
||||
.../engine/libcontainerd/utils_linux.go | 25 +++
|
||||
.../engine/libcontainerd/utils_windows.go | 7 +-
|
||||
10 files changed, 449 insertions(+), 6 deletions(-)
|
||||
create mode 100644 components/engine/daemon/freezer/cgroup_fs.go
|
||||
create mode 100644 components/engine/daemon/freezer/cgroup_systemd.go
|
||||
create mode 100644 components/engine/daemon/freezer/freezer.go
|
||||
create mode 100644 components/engine/libcontainerd/utils_linux.go
|
||||
|
||||
diff --git a/components/engine/container/container.go b/components/engine/container/container.go
|
||||
index 6a5907c34b..f74676f7ee 100644
|
||||
--- a/components/engine/container/container.go
|
||||
+++ b/components/engine/container/container.go
|
||||
@@ -106,6 +106,7 @@ type Container struct {
|
||||
// Fields here are specific to Windows
|
||||
NetworkSharedContainerID string `json:"-"`
|
||||
SharedEndpointList []string `json:"-"`
|
||||
+ CgroupParent string
|
||||
}
|
||||
|
||||
// NewBaseContainer creates a new container with its
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index a307863017..8d6b4d8546 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/docker/docker/daemon/discovery"
|
||||
"github.com/docker/docker/daemon/events"
|
||||
"github.com/docker/docker/daemon/exec"
|
||||
+ "github.com/docker/docker/daemon/freezer"
|
||||
"github.com/docker/docker/daemon/images"
|
||||
"github.com/docker/docker/daemon/logger"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
@@ -197,6 +198,53 @@ func (daemon *Daemon) NewResolveOptionsFunc() resolver.ResolveOptionsFunc {
|
||||
}
|
||||
}
|
||||
|
||||
+func (daemon *Daemon) updatePauseStatus(c *container.Container) error {
|
||||
+ if !daemon.IsNativeRuntime(c.HostConfig.Runtime) {
|
||||
+ return nil
|
||||
+ }
|
||||
+
|
||||
+ // update docker pause status.
|
||||
+ // for old container, CgroupParent may be empty.
|
||||
+ if c.CgroupParent == "" {
|
||||
+ spec, err := libcontainerd.LoadContainerSpec(filepath.Join(daemon.configStore.ExecRoot, "libcontainerd"), c.ID)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ c.CgroupParent = spec.Linux.CgroupsPath
|
||||
+ }
|
||||
+
|
||||
+ if !c.IsRunning() {
|
||||
+ c.Paused = false
|
||||
+ return nil
|
||||
+ }
|
||||
+
|
||||
+ useSystemd := UsingSystemd(daemon.configStore)
|
||||
+ freeze, err := freezer.New(c.ID, c.CgroupParent, useSystemd)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ paused, err := freeze.IsPaused()
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ c.Paused = paused
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) IsNativeRuntime(runtime string) bool {
|
||||
+ // For the containers which created by old docker (do not support multi-runtime)
|
||||
+ // c.HostConfig.Runtime may be empty. just use the default runtime.
|
||||
+ if runtime == "" {
|
||||
+ runtime = daemon.configStore.GetDefaultRuntimeName()
|
||||
+ }
|
||||
+ rt := daemon.configStore.GetRuntime(runtime)
|
||||
+ if rt != nil && filepath.Base(rt.Path) == DefaultRuntimeBinary {
|
||||
+ return true
|
||||
+ }
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
func (daemon *Daemon) restore() error {
|
||||
containers := make(map[string]*container.Container)
|
||||
|
||||
@@ -244,6 +292,11 @@ func (daemon *Daemon) restore() error {
|
||||
delete(containers, id)
|
||||
continue
|
||||
}
|
||||
+
|
||||
+ if err := daemon.updatePauseStatus(c); err != nil {
|
||||
+ logrus.Errorf("Failed to update pause status for container %s: %s", c.ID, err)
|
||||
+ }
|
||||
+
|
||||
if err := daemon.Register(c); err != nil {
|
||||
logrus.Errorf("Failed to register container %s: %s", c.ID, err)
|
||||
delete(containers, id)
|
||||
diff --git a/components/engine/daemon/freezer/cgroup_fs.go b/components/engine/daemon/freezer/cgroup_fs.go
|
||||
new file mode 100644
|
||||
index 0000000000..5822c3a659
|
||||
--- /dev/null
|
||||
+++ b/components/engine/daemon/freezer/cgroup_fs.go
|
||||
@@ -0,0 +1,94 @@
|
||||
+package freezer
|
||||
+
|
||||
+import (
|
||||
+ "fmt"
|
||||
+ "os"
|
||||
+ "path/filepath"
|
||||
+ "sync"
|
||||
+
|
||||
+ "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
+ "github.com/opencontainers/runc/libcontainer/configs"
|
||||
+ "github.com/opencontainers/runc/libcontainer/utils"
|
||||
+)
|
||||
+
|
||||
+// The absolute path to the root of the cgroup hierarchies.
|
||||
+var cgroupRootLock sync.Mutex
|
||||
+var cgroupRoot string
|
||||
+
|
||||
+func fsCgroupPath(subsystem string, c *configs.Cgroup) (string, error) {
|
||||
+ rawRoot, err := getCgroupRoot()
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ if (c.Name != "" || c.Parent != "") && c.Path != "" {
|
||||
+ return "", fmt.Errorf("cgroup: either Path or Name and Parent should be used")
|
||||
+ }
|
||||
+
|
||||
+ // XXX: Do not remove this code. Path safety is important! -- cyphar
|
||||
+ cgPath := utils.CleanPath(c.Path)
|
||||
+ cgParent := utils.CleanPath(c.Parent)
|
||||
+ cgName := utils.CleanPath(c.Name)
|
||||
+
|
||||
+ innerPath := cgPath
|
||||
+ if innerPath == "" {
|
||||
+ innerPath = filepath.Join(cgParent, cgName)
|
||||
+ }
|
||||
+
|
||||
+ mnt, root, err := cgroups.FindCgroupMountpointAndRoot(subsystem)
|
||||
+ // If we didn't mount the subsystem, there is no point we make the path.
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ // If the cgroup name/path is absolute do not look relative to the cgroup of the init process.
|
||||
+ if filepath.IsAbs(innerPath) {
|
||||
+ // Sometimes subsystems can be mounted together as 'cpu,cpuacct'.
|
||||
+ return filepath.Join(rawRoot, filepath.Base(mnt), innerPath), nil
|
||||
+ }
|
||||
+
|
||||
+ parentPath, err := parentPath(subsystem, mnt, root)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ return filepath.Join(parentPath, innerPath), nil
|
||||
+}
|
||||
+
|
||||
+func parentPath(subsystem, mountpoint, root string) (string, error) {
|
||||
+ // Use GetThisCgroupDir instead of GetInitCgroupDir, because the creating
|
||||
+ // process could in container and shared pid namespace with host, and
|
||||
+ // /proc/1/cgroup could point to whole other world of cgroups.
|
||||
+ initPath, err := cgroups.GetOwnCgroup(subsystem)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ // This is needed for nested containers, because in /proc/self/cgroup we
|
||||
+ // see pathes from host, which don't exist in container.
|
||||
+ relDir, err := filepath.Rel(root, initPath)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ return filepath.Join(mountpoint, relDir), nil
|
||||
+}
|
||||
+
|
||||
+func getCgroupRoot() (string, error) {
|
||||
+ cgroupRootLock.Lock()
|
||||
+ defer cgroupRootLock.Unlock()
|
||||
+
|
||||
+ if cgroupRoot != "" {
|
||||
+ return cgroupRoot, nil
|
||||
+ }
|
||||
+
|
||||
+ root, err := cgroups.FindCgroupMountpointDir()
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ if _, err := os.Stat(root); err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ cgroupRoot = root
|
||||
+ return cgroupRoot, nil
|
||||
+}
|
||||
diff --git a/components/engine/daemon/freezer/cgroup_systemd.go b/components/engine/daemon/freezer/cgroup_systemd.go
|
||||
new file mode 100644
|
||||
index 0000000000..4a05d04910
|
||||
--- /dev/null
|
||||
+++ b/components/engine/daemon/freezer/cgroup_systemd.go
|
||||
@@ -0,0 +1,59 @@
|
||||
+package freezer
|
||||
+
|
||||
+import (
|
||||
+ "fmt"
|
||||
+ "path/filepath"
|
||||
+ "strings"
|
||||
+
|
||||
+ "github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
+ "github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
+ "github.com/opencontainers/runc/libcontainer/configs"
|
||||
+)
|
||||
+
|
||||
+var (
|
||||
+ systemdEnabledChecked = false
|
||||
+ systemdEnabled = false
|
||||
+)
|
||||
+
|
||||
+func SystemdEnabled() bool {
|
||||
+ if systemdEnabledChecked {
|
||||
+ return systemdEnabled
|
||||
+ }
|
||||
+ systemdEnabledChecked = true
|
||||
+ systemdEnabled = systemd.UseSystemd()
|
||||
+ return systemdEnabled
|
||||
+}
|
||||
+
|
||||
+func systemdCgroupPath(subsystem string, c *configs.Cgroup) (string, error) {
|
||||
+ mountpoint, err := cgroups.FindCgroupMountpoint(subsystem)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ initPath, err := cgroups.GetInitCgroup(subsystem)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+ // if pid 1 is systemd 226 or later, it will be in init.scope, not the root
|
||||
+ initPath = strings.TrimSuffix(filepath.Clean(initPath), "init.scope")
|
||||
+
|
||||
+ slice := "system.slice"
|
||||
+ if c.Parent != "" {
|
||||
+ slice = c.Parent
|
||||
+ }
|
||||
+
|
||||
+ slice, err = systemd.ExpandSlice(slice)
|
||||
+ if err != nil {
|
||||
+ return "", err
|
||||
+ }
|
||||
+
|
||||
+ return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
|
||||
+}
|
||||
+
|
||||
+func getUnitName(c *configs.Cgroup) string {
|
||||
+ // by default, we create a scope unless the user explicitly asks for a slice.
|
||||
+ if !strings.HasSuffix(c.Name, ".slice") {
|
||||
+ return fmt.Sprintf("%s-%s.scope", c.ScopePrefix, c.Name)
|
||||
+ }
|
||||
+ return c.Name
|
||||
+}
|
||||
diff --git a/components/engine/daemon/freezer/freezer.go b/components/engine/daemon/freezer/freezer.go
|
||||
new file mode 100644
|
||||
index 0000000000..774f5c21ed
|
||||
--- /dev/null
|
||||
+++ b/components/engine/daemon/freezer/freezer.go
|
||||
@@ -0,0 +1,179 @@
|
||||
+package freezer
|
||||
+
|
||||
+import (
|
||||
+ "bytes"
|
||||
+ "fmt"
|
||||
+ "io/ioutil"
|
||||
+ "os"
|
||||
+ "path/filepath"
|
||||
+ "strings"
|
||||
+ "sync"
|
||||
+ "time"
|
||||
+
|
||||
+ "github.com/opencontainers/runc/libcontainer/configs"
|
||||
+ "github.com/opencontainers/runc/libcontainer/utils"
|
||||
+)
|
||||
+
|
||||
+// Freezer is the interface which could be used to pause/resume container,
|
||||
+// And it could be used to get the real container paused status of a container too.
|
||||
+type Freezer interface {
|
||||
+ // Pause will set the container to pause state by writing freeze cgroup.
|
||||
+ Pause() error
|
||||
+
|
||||
+ // Resume will set the container to running state by writing freeze cgroup.
|
||||
+ Resume() error
|
||||
+
|
||||
+ // IsPaused will return if the container is paused or not by reading cgroup information.
|
||||
+ IsPaused() (bool, error)
|
||||
+}
|
||||
+
|
||||
+func writeFile(dir, file, data string) error {
|
||||
+ // Normally dir should not be empty, one case is that cgroup subsystem
|
||||
+ // is not mounted, we will get empty dir, and we want it fail here.
|
||||
+ if dir == "" {
|
||||
+ return fmt.Errorf("no such directory for %s", file)
|
||||
+ }
|
||||
+ if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700); err != nil {
|
||||
+ return fmt.Errorf("failed to write %v to %v: %v", data, file, err)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func readFile(dir, file string) (string, error) {
|
||||
+ data, err := ioutil.ReadFile(filepath.Join(dir, file))
|
||||
+ return string(data), err
|
||||
+}
|
||||
+
|
||||
+// New will create a Freezer interface for caller
|
||||
+func New(cid, cgroupParent string, useSystemdCgroup bool) (Freezer, error) {
|
||||
+ if useSystemdCgroup && !SystemdEnabled() {
|
||||
+ return nil, fmt.Errorf("systemd cgroup flag passed, but systemd support for managing cgroups is not available")
|
||||
+ }
|
||||
+ cgroupConfig, err := prepareCgroupConfig(cid, cgroupParent, useSystemdCgroup)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+
|
||||
+ return newFreezer(useSystemdCgroup, cgroupConfig)
|
||||
+}
|
||||
+
|
||||
+func prepareCgroupConfig(cid, cgroupsPath string, useSystemdCgroup bool) (*configs.Cgroup, error) {
|
||||
+ var myCgroupPath string
|
||||
+ c := &configs.Cgroup{
|
||||
+ Resources: &configs.Resources{},
|
||||
+ }
|
||||
+ if cgroupsPath != "" {
|
||||
+ myCgroupPath = utils.CleanPath(cgroupsPath)
|
||||
+ if useSystemdCgroup {
|
||||
+ myCgroupPath = cgroupsPath
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if useSystemdCgroup {
|
||||
+ if myCgroupPath == "" {
|
||||
+ c.Parent = "system.slice"
|
||||
+ c.ScopePrefix = "runc"
|
||||
+ c.Name = cid
|
||||
+ } else {
|
||||
+ // Parse the path from expected "slice:prefix:name"
|
||||
+ // for e.g. "system.slice:docker:1234"
|
||||
+ parts := strings.Split(myCgroupPath, ":")
|
||||
+ if len(parts) != 3 {
|
||||
+ return nil, fmt.Errorf("expected cgroupsPath to be of format \"slice:prefix:name\" for systemd cgroups")
|
||||
+ }
|
||||
+ c.Parent = parts[0]
|
||||
+ c.ScopePrefix = parts[1]
|
||||
+ c.Name = parts[2]
|
||||
+ }
|
||||
+ } else {
|
||||
+ if myCgroupPath == "" {
|
||||
+ c.Name = cid
|
||||
+ }
|
||||
+ c.Path = myCgroupPath
|
||||
+ }
|
||||
+ return c, nil
|
||||
+}
|
||||
+
|
||||
+func newFreezer(useSystemdCgroup bool, cgroup *configs.Cgroup) (Freezer, error) {
|
||||
+ var err error
|
||||
+ var path string
|
||||
+
|
||||
+ if useSystemdCgroup {
|
||||
+ path, err = systemdCgroupPath("freezer", cgroup)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ } else {
|
||||
+ path, err = fsCgroupPath("freezer", cgroup)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ }
|
||||
+ return &freezer{path: path}, nil
|
||||
+}
|
||||
+
|
||||
+type freezer struct {
|
||||
+ sync.Mutex
|
||||
+ path string
|
||||
+}
|
||||
+
|
||||
+// Pause will set the container to pause state by writing freeze cgroup.
|
||||
+func (f *freezer) Pause() error {
|
||||
+ f.Lock()
|
||||
+ defer f.Unlock()
|
||||
+
|
||||
+ if err := f.updateCgroup(string(configs.Frozen)); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ tasks, err := readFile(f.path, "tasks")
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("failed to check container cgroup task status: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ if strings.TrimSpace(tasks) == "" {
|
||||
+ return fmt.Errorf("error: no tasks running in freeze cgroup")
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+// Resume will set the container to running state by writing freeze cgroup.
|
||||
+func (f *freezer) Resume() error {
|
||||
+ f.Lock()
|
||||
+ defer f.Unlock()
|
||||
+ return f.updateCgroup(string(configs.Thawed))
|
||||
+}
|
||||
+
|
||||
+// IsPaused will return if the container is paused or not by reading cgroup information.
|
||||
+func (f *freezer) IsPaused() (bool, error) {
|
||||
+ f.Lock()
|
||||
+ defer f.Unlock()
|
||||
+
|
||||
+ data, err := readFile(f.path, "freezer.state")
|
||||
+ if err != nil {
|
||||
+ // If freezer cgroup is not mounted, the container would just be not paused.
|
||||
+ if os.IsNotExist(err) {
|
||||
+ return false, nil
|
||||
+ }
|
||||
+ return false, fmt.Errorf("failed to check container status: %v", err)
|
||||
+ }
|
||||
+ return bytes.Equal(bytes.TrimSpace([]byte(data)), []byte("FROZEN")), nil
|
||||
+}
|
||||
+
|
||||
+func (f *freezer) updateCgroup(state string) error {
|
||||
+ if err := writeFile(f.path, "freezer.state", state); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ for {
|
||||
+ newState, err := readFile(f.path, "freezer.state")
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ if strings.TrimSpace(newState) == state {
|
||||
+ break
|
||||
+ }
|
||||
+ time.Sleep(1 * time.Millisecond)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||||
index 7611fc054d..864d22fbcb 100644
|
||||
--- a/components/engine/daemon/oci_linux.go
|
||||
+++ b/components/engine/daemon/oci_linux.go
|
||||
@@ -711,6 +711,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
||||
cgroupsPath = filepath.Join(parent, c.ID)
|
||||
}
|
||||
s.Linux.CgroupsPath = cgroupsPath
|
||||
+ c.CgroupParent = cgroupsPath
|
||||
|
||||
if err := setResources(&s, c.HostConfig.Resources); err != nil {
|
||||
return nil, fmt.Errorf("linux runtime spec resources: %v", err)
|
||||
diff --git a/components/engine/daemon/pause.go b/components/engine/daemon/pause.go
|
||||
index be6ec1b92a..972baa961f 100644
|
||||
--- a/components/engine/daemon/pause.go
|
||||
+++ b/components/engine/daemon/pause.go
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
+ "github.com/docker/docker/daemon/freezer"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -38,8 +39,22 @@ func (daemon *Daemon) containerPause(container *container.Container) error {
|
||||
return errContainerIsRestarting(container.ID)
|
||||
}
|
||||
|
||||
- if err := daemon.containerd.Pause(context.Background(), container.ID); err != nil {
|
||||
- return fmt.Errorf("Cannot pause container %s: %s", container.ID, err)
|
||||
+ if daemon.IsNativeRuntime(container.HostConfig.Runtime) {
|
||||
+ freezer, err := freezer.New(container.ID, container.CgroupParent, UsingSystemd(daemon.configStore))
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("Failed to create freezer for container %s: %v", container.ID, err)
|
||||
+ }
|
||||
+
|
||||
+ if err := freezer.Pause(); err != nil {
|
||||
+ return fmt.Errorf("Cannot pause container %s: %v", container.ID, err)
|
||||
+ }
|
||||
+
|
||||
+ container.Paused = true
|
||||
+ daemon.LogContainerEvent(container, "pause")
|
||||
+ } else {
|
||||
+ if err := daemon.containerd.Pause(context.Background(), container.ID); err != nil {
|
||||
+ return fmt.Errorf("Cannot pause container %s: %s", container.ID, err)
|
||||
+ }
|
||||
}
|
||||
|
||||
container.Paused = true
|
||||
diff --git a/components/engine/daemon/unpause.go b/components/engine/daemon/unpause.go
|
||||
index 27648ae72e..4a8225258f 100644
|
||||
--- a/components/engine/daemon/unpause.go
|
||||
+++ b/components/engine/daemon/unpause.go
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/docker/container"
|
||||
+ "github.com/docker/docker/daemon/freezer"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@@ -27,8 +28,20 @@ func (daemon *Daemon) containerUnpause(container *container.Container) error {
|
||||
return fmt.Errorf("Container %s is not paused", container.ID)
|
||||
}
|
||||
|
||||
- if err := daemon.containerd.Resume(context.Background(), container.ID); err != nil {
|
||||
- return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
+ if daemon.IsNativeRuntime(container.HostConfig.Runtime) {
|
||||
+ freezer, err := freezer.New(container.ID, container.CgroupParent, UsingSystemd(daemon.configStore))
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("Failed to create freezer for container %s: %v", container.ID, err)
|
||||
+ }
|
||||
+ if err := freezer.Resume(); err != nil {
|
||||
+ return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
+ }
|
||||
+ container.Paused = false
|
||||
+ daemon.LogContainerEvent(container, "unpause")
|
||||
+ } else {
|
||||
+ if err := daemon.containerd.Resume(context.Background(), container.ID); err != nil {
|
||||
+ return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
+ }
|
||||
}
|
||||
|
||||
container.Paused = false
|
||||
diff --git a/components/engine/libcontainerd/utils_linux.go b/components/engine/libcontainerd/utils_linux.go
|
||||
new file mode 100644
|
||||
index 0000000000..f9b3e64db9
|
||||
--- /dev/null
|
||||
+++ b/components/engine/libcontainerd/utils_linux.go
|
||||
@@ -0,0 +1,25 @@
|
||||
+package libcontainerd
|
||||
+
|
||||
+import (
|
||||
+ "encoding/json"
|
||||
+ "io/ioutil"
|
||||
+ "path/filepath"
|
||||
+
|
||||
+ "github.com/opencontainers/runtime-spec/specs-go"
|
||||
+)
|
||||
+
|
||||
+func LoadContainerSpec(stateDir, id string) (*specs.Spec, error) {
|
||||
+ var spec specs.Spec
|
||||
+ dir, err := filepath.Abs(stateDir)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ dt, err := ioutil.ReadFile(filepath.Join(dir, id, "config.json"))
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ if err := json.Unmarshal(dt, &spec); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ return &spec, nil
|
||||
+}
|
||||
diff --git a/components/engine/libcontainerd/utils_windows.go b/components/engine/libcontainerd/utils_windows.go
|
||||
index aabb9aeaaa..a8ba3629a3 100644
|
||||
--- a/components/engine/libcontainerd/utils_windows.go
|
||||
+++ b/components/engine/libcontainerd/utils_windows.go
|
||||
@@ -1,6 +1,7 @@
|
||||
package libcontainerd // import "github.com/docker/docker/libcontainerd"
|
||||
|
||||
import (
|
||||
+ "fmt"
|
||||
"strings"
|
||||
|
||||
opengcs "github.com/Microsoft/opengcs/client"
|
||||
@@ -19,10 +20,12 @@ func setupEnvironmentVariables(a []string) map[string]string {
|
||||
return r
|
||||
}
|
||||
|
||||
+func LoadContainerSpec(stateDir, id string) (*specs.Spec, error) {
|
||||
+ return nil, fmt.Errorf("not supported")
|
||||
+}
|
||||
+
|
||||
// Apply for the LCOW option is a no-op.
|
||||
func (s *LCOWOption) Apply(interface{}) error {
|
||||
- return nil
|
||||
-}
|
||||
|
||||
// debugGCS is a dirty hack for debugging for Linux Utility VMs. It simply
|
||||
// runs a bunch of commands inside the UVM, but seriously aides in advanced debugging.
|
||||
--
|
||||
2.17.1
|
||||
|
||||
76
patch/0002-pause-docker-pause-set-timeout-30s.patch
Normal file
76
patch/0002-pause-docker-pause-set-timeout-30s.patch
Normal file
@ -0,0 +1,76 @@
|
||||
From fb74bc5ce2a510e38b9a8a83d4524876f1881759 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:11:25 +0800
|
||||
Subject: [PATCH 002/111] pause: docker pause set timeout 30s
|
||||
|
||||
reason:fix docker pause in infinite loop case,when the process in D status
|
||||
libcontainer: cgroups: Write freezer state after every state check
|
||||
This commit ensures we write the expected freezer cgroup state after
|
||||
every state check, in case the state check does not give the expected
|
||||
result. This can happen when a new task is created and prevents the
|
||||
whole cgroup to be FROZEN, leaving the state into FREEZING instead.
|
||||
This patch prevents the case of an infinite loop to happen.
|
||||
Cherry-pick from https://github.com/opencontainers/runc/pull/1610
|
||||
|
||||
Change-Id: Ib5355b9d928c491e120439780c1f03c18aa68b73
|
||||
Signed-off-by: panwenxiang <panwenxiang@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/freezer/freezer.go | 37 +++++++++++++++------
|
||||
1 file changed, 27 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/freezer/freezer.go b/components/engine/daemon/freezer/freezer.go
|
||||
index 774f5c21ed..cd8b3513d7 100644
|
||||
--- a/components/engine/daemon/freezer/freezer.go
|
||||
+++ b/components/engine/daemon/freezer/freezer.go
|
||||
@@ -161,19 +161,36 @@ func (f *freezer) IsPaused() (bool, error) {
|
||||
}
|
||||
|
||||
func (f *freezer) updateCgroup(state string) error {
|
||||
- if err := writeFile(f.path, "freezer.state", state); err != nil {
|
||||
- return err
|
||||
+ curState, err := readFile(f.path, "freezer.state")
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("read current state failed for %#v", err)
|
||||
}
|
||||
+ curState = strings.TrimSpace(curState)
|
||||
|
||||
+ timeout := time.After(30 * time.Second)
|
||||
+ tick := time.Tick(1 * time.Millisecond)
|
||||
for {
|
||||
- newState, err := readFile(f.path, "freezer.state")
|
||||
- if err != nil {
|
||||
- return err
|
||||
- }
|
||||
- if strings.TrimSpace(newState) == state {
|
||||
- break
|
||||
+ select {
|
||||
+ case <-timeout:
|
||||
+ if err := writeFile(f.path, "freezer.state", curState); err != nil {
|
||||
+ return fmt.Errorf("cannot write %s to freezer for %#v", curState, err)
|
||||
+ }
|
||||
+ return fmt.Errorf("update freezer cgroup timeout for 30s")
|
||||
+ case <-tick:
|
||||
+ // In case this loop does not exit because it doesn't get the expected
|
||||
+ // state, let's write again this state, hoping it's going to be properly
|
||||
+ // set this time. Otherwise, this loop could run infinitely, waiting for
|
||||
+ // a state change that would never happen.
|
||||
+ if err := writeFile(f.path, "freezer.state", state); err != nil {
|
||||
+ return fmt.Errorf("cannot write freezer.state for %#v", err)
|
||||
+ }
|
||||
+ newState, err := readFile(f.path, "freezer.state")
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ if strings.TrimSpace(newState) == state {
|
||||
+ return nil
|
||||
+ }
|
||||
}
|
||||
- time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
- return nil
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
From 8a897fcad4bf6d2f4be05bb3075640d65e98ac8e Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:13:24 +0800
|
||||
Subject: [PATCH 003/111] pause: fix integration testing faile about
|
||||
`docker pause` status display
|
||||
|
||||
reason:fix integration testing faile about `docker pause` status display
|
||||
|
||||
Change-Id: I851b29171a33f5eb278800fb0f1e061bebb3745c
|
||||
Signed-off-by: leizhongkai <leizhongkai@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/pause.go | 4 ++++
|
||||
components/engine/daemon/unpause.go | 4 ++++
|
||||
2 files changed, 8 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/pause.go b/components/engine/daemon/pause.go
|
||||
index 972baa961f..6f9d8b0f70 100644
|
||||
--- a/components/engine/daemon/pause.go
|
||||
+++ b/components/engine/daemon/pause.go
|
||||
@@ -50,6 +50,10 @@ func (daemon *Daemon) containerPause(container *container.Container) error {
|
||||
}
|
||||
|
||||
container.Paused = true
|
||||
+ daemon.setStateCounter(container)
|
||||
+ if err := container.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
daemon.LogContainerEvent(container, "pause")
|
||||
} else {
|
||||
if err := daemon.containerd.Pause(context.Background(), container.ID); err != nil {
|
||||
diff --git a/components/engine/daemon/unpause.go b/components/engine/daemon/unpause.go
|
||||
index 4a8225258f..290d2b1d0c 100644
|
||||
--- a/components/engine/daemon/unpause.go
|
||||
+++ b/components/engine/daemon/unpause.go
|
||||
@@ -37,6 +37,10 @@ func (daemon *Daemon) containerUnpause(container *container.Container) error {
|
||||
return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
}
|
||||
container.Paused = false
|
||||
+ daemon.setStateCounter(container)
|
||||
+ if err := container.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
daemon.LogContainerEvent(container, "unpause")
|
||||
} else {
|
||||
if err := daemon.containerd.Resume(context.Background(), container.ID); err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
398
patch/0004-prjquota-support-set-filesystem-quot.patch
Normal file
398
patch/0004-prjquota-support-set-filesystem-quot.patch
Normal file
@ -0,0 +1,398 @@
|
||||
From a8f05692638bf50826ed9533f2a5282e2cde359d Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:13:41 +0800
|
||||
Subject: [PATCH 004/111] prjquota: support set filesystem
|
||||
quota if ext4 support project quota
|
||||
|
||||
reason:Support set filesystem quota if ext4 support project quota
|
||||
|
||||
Change-Id: I99d28f248e758837cbf8b615e673ee7d8e36be7b
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon_unix.go | 19 ++
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 10 +-
|
||||
.../daemon/graphdriver/quota/projectquota.go | 176 +++++++++++++++---
|
||||
.../daemon/graphdriver/vfs/quota_linux.go | 13 +-
|
||||
4 files changed, 191 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index b69eede21c..1b35df4950 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -633,6 +633,25 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
|
||||
}
|
||||
}
|
||||
|
||||
+ if hostConfig.StorageOpt != nil && daemon.imageService.GraphDriverForOS(runtime.GOOS) == "overlay2" {
|
||||
+ _, exist := hostConfig.StorageOpt["size"]
|
||||
+ if exist {
|
||||
+ status := daemon.imageService.LayerStoreStatus()[runtime.GOOS]
|
||||
+ if status[0][0] == "Backing Filesystem" && status[0][1] == "extfs" {
|
||||
+ if hostConfig.Privileged {
|
||||
+ warnings = append(warnings, "filesystem quota for overlay2 over ext4 can't take affect with privileged container")
|
||||
+ } else {
|
||||
+ for _, cap := range hostConfig.CapAdd {
|
||||
+ if cap == "SYS_RESOURCE" {
|
||||
+ warnings = append(warnings, "filesystem quota for overlay2 over ext4 can't take affect with CAP_SYS_RESOURCE")
|
||||
+ break
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
return warnings, nil
|
||||
}
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 6b3236f8f3..36ae182bcd 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -216,16 +216,16 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
|
||||
d.naiveDiff = graphdriver.NewNaiveDiffDriver(d, uidMaps, gidMaps)
|
||||
|
||||
- if backingFs == "xfs" {
|
||||
- // Try to enable project quota support over xfs.
|
||||
- if d.quotaCtl, err = quota.NewControl(home); err == nil {
|
||||
+ if backingFs == "xfs" || backingFs == "extfs" {
|
||||
+ // Try to enable project quota support over xfs and extfs.
|
||||
+ if d.quotaCtl, err = quota.NewControl(home, backingFs); err == nil {
|
||||
projectQuotaSupported = true
|
||||
} else if opts.quota.Size > 0 {
|
||||
return nil, fmt.Errorf("Storage option overlay2.size not supported. Filesystem does not support Project Quota: %v", err)
|
||||
}
|
||||
} else if opts.quota.Size > 0 {
|
||||
// if xfs is not the backing fs then error out if the storage-opt overlay2.size is used.
|
||||
- return nil, fmt.Errorf("Storage Option overlay2.size only supported for backingFS XFS. Found %v", backingFs)
|
||||
+ return nil, fmt.Errorf("Storage Option overlay2.size only supported for backingFS XFS or ext4. Found %v", backingFs)
|
||||
}
|
||||
|
||||
logger.Debugf("backingFs=%s, projectQuotaSupported=%v", backingFs, projectQuotaSupported)
|
||||
@@ -341,7 +341,7 @@ func (d *Driver) Cleanup() error {
|
||||
// file system.
|
||||
func (d *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error {
|
||||
if opts != nil && len(opts.StorageOpt) != 0 && !projectQuotaSupported {
|
||||
- return fmt.Errorf("--storage-opt is supported only for overlay over xfs with 'pquota' mount option")
|
||||
+ return fmt.Errorf("--storage-opt is supported only for overlay over xfs or ext4 with 'pquota' mount option")
|
||||
}
|
||||
|
||||
if opts == nil {
|
||||
diff --git a/components/engine/daemon/graphdriver/quota/projectquota.go b/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
index 93e85823af..7d879eb81d 100644
|
||||
--- a/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
+++ b/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
@@ -38,8 +38,8 @@ struct fsxattr {
|
||||
#ifndef PRJQUOTA
|
||||
#define PRJQUOTA 2
|
||||
#endif
|
||||
-#ifndef XFS_PROJ_QUOTA
|
||||
-#define XFS_PROJ_QUOTA 2
|
||||
+#ifndef PROJ_QUOTA
|
||||
+#define PROJ_QUOTA 2
|
||||
#endif
|
||||
#ifndef Q_XSETPQLIM
|
||||
#define Q_XSETPQLIM QCMD(Q_XSETQLIM, PRJQUOTA)
|
||||
@@ -49,6 +49,28 @@ struct fsxattr {
|
||||
#endif
|
||||
|
||||
const int Q_XGETQSTAT_PRJQUOTA = QCMD(Q_XGETQSTAT, PRJQUOTA);
|
||||
+
|
||||
+#ifndef Q_XGETPQSTAT
|
||||
+#define Q_XGETPQSTAT QCMD(Q_XGETQSTAT, PRJQUOTA)
|
||||
+#endif
|
||||
+
|
||||
+#ifndef Q_SETPQUOTA
|
||||
+#define Q_SETPQUOTA (unsigned int)QCMD(Q_SETQUOTA, PRJQUOTA)
|
||||
+#endif
|
||||
+
|
||||
+#ifndef Q_GETPQUOTA
|
||||
+#define Q_GETPQUOTA (unsigned int)QCMD(Q_GETQUOTA, PRJQUOTA)
|
||||
+#endif
|
||||
+
|
||||
+#define PDQ_ACCT_BIT 4
|
||||
+#define PDQ_ENFD_BIT 5
|
||||
+
|
||||
+#ifndef QUOTA_PDQ_ACCT
|
||||
+#define QUOTA_PDQ_ACCT (1<<PDQ_ACCT_BIT)
|
||||
+#endif
|
||||
+#ifndef QUOTA_PDQ_ENFD
|
||||
+#define QUOTA_PDQ_ENFD (1<<PDQ_ENFD_BIT)
|
||||
+#endif
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
@@ -56,6 +78,8 @@ import (
|
||||
"io/ioutil"
|
||||
"path"
|
||||
"path/filepath"
|
||||
+ "sync"
|
||||
+ "syscall"
|
||||
"unsafe"
|
||||
|
||||
rsystem "github.com/opencontainers/runc/libcontainer/system"
|
||||
@@ -74,6 +98,17 @@ type Control struct {
|
||||
backingFsBlockDev string
|
||||
nextProjectID uint32
|
||||
quotas map[string]uint32
|
||||
+ quotaOps QuotafileOps
|
||||
+ lock sync.Mutex
|
||||
+}
|
||||
+
|
||||
+// QuotafileOps is a interface for quotafile operations
|
||||
+type QuotafileOps interface {
|
||||
+ // SetProjectQuota sets the project quota for project id on block device
|
||||
+ SetProjectQuota(dev string, projectID uint32, quota Quota) error
|
||||
+
|
||||
+ // GetProjectQuota gets the project quota for project id on block device
|
||||
+ GetProjectQuota(dev string, projectID uint32, quota *Quota) error
|
||||
}
|
||||
|
||||
// NewControl - initialize project quota support.
|
||||
@@ -98,7 +133,7 @@ type Control struct {
|
||||
// on it. If that works, continue to scan existing containers to map allocated
|
||||
// project ids.
|
||||
//
|
||||
-func NewControl(basePath string) (*Control, error) {
|
||||
+func NewControl(basePath string, fs string) (*Control, error) {
|
||||
//
|
||||
// If we are running in a user namespace quota won't be supported for
|
||||
// now since makeBackingFsDev() will try to mknod().
|
||||
@@ -141,7 +176,28 @@ func NewControl(basePath string) (*Control, error) {
|
||||
quota := Quota{
|
||||
Size: 0,
|
||||
}
|
||||
- if err := setProjectQuota(backingFsBlockDev, minProjectID, quota); err != nil {
|
||||
+ //
|
||||
+ // Get the quota stat to check whether the system support project quota
|
||||
+ //
|
||||
+ stat, err := getQuotaStat(backingFsBlockDev)
|
||||
+ if err != nil || stat != 2 {
|
||||
+ if err != nil {
|
||||
+ logrus.Warnf("Get quota stat failed with: %v", err)
|
||||
+ }
|
||||
+ return nil, fmt.Errorf("quota isn't supported on your system")
|
||||
+ }
|
||||
+
|
||||
+ var quotaOps QuotafileOps
|
||||
+
|
||||
+ if fs == "xfs" {
|
||||
+ quotaOps = new(XfsQuota)
|
||||
+ } else if fs == "extfs" {
|
||||
+ quotaOps = new(Ext4Quota)
|
||||
+ } else {
|
||||
+ return nil, fmt.Errorf("quota isn't supported for filesystem %q", fs)
|
||||
+ }
|
||||
+
|
||||
+ if err := quotaOps.SetProjectQuota(backingFsBlockDev, minProjectID, quota); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -149,6 +205,7 @@ func NewControl(basePath string) (*Control, error) {
|
||||
backingFsBlockDev: backingFsBlockDev,
|
||||
nextProjectID: minProjectID + 1,
|
||||
quotas: make(map[string]uint32),
|
||||
+ quotaOps: quotaOps,
|
||||
}
|
||||
|
||||
//
|
||||
@@ -167,6 +224,7 @@ func NewControl(basePath string) (*Control, error) {
|
||||
// for that project id
|
||||
func (q *Control) SetQuota(targetPath string, quota Quota) error {
|
||||
|
||||
+ q.lock.Lock()
|
||||
projectID, ok := q.quotas[targetPath]
|
||||
if !ok {
|
||||
projectID = q.nextProjectID
|
||||
@@ -176,26 +234,32 @@ func (q *Control) SetQuota(targetPath string, quota Quota) error {
|
||||
//
|
||||
err := setProjectID(targetPath, projectID)
|
||||
if err != nil {
|
||||
+ q.lock.Lock()
|
||||
return err
|
||||
}
|
||||
|
||||
q.quotas[targetPath] = projectID
|
||||
q.nextProjectID++
|
||||
}
|
||||
+ q.lock.Unlock()
|
||||
|
||||
//
|
||||
// set the quota limit for the container's project id
|
||||
//
|
||||
logrus.Debugf("SetQuota(%s, %d): projectID=%d", targetPath, quota.Size, projectID)
|
||||
- return setProjectQuota(q.backingFsBlockDev, projectID, quota)
|
||||
+ return q.quotaOps.SetProjectQuota(q.backingFsBlockDev, projectID, quota)
|
||||
}
|
||||
|
||||
-// setProjectQuota - set the quota for project id on xfs block device
|
||||
-func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) error {
|
||||
+// XfsQuota is a struct implements quota operations
|
||||
+type XfsQuota struct {
|
||||
+}
|
||||
+
|
||||
+// SetProjectQuota - set the quota for project id on xfs block device
|
||||
+func (q *XfsQuota) SetProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) error {
|
||||
var d C.fs_disk_quota_t
|
||||
d.d_version = C.FS_DQUOT_VERSION
|
||||
d.d_id = C.__u32(projectID)
|
||||
- d.d_flags = C.XFS_PROJ_QUOTA
|
||||
+ d.d_flags = C.PROJ_QUOTA
|
||||
|
||||
d.d_fieldmask = C.FS_DQ_BHARD | C.FS_DQ_BSOFT
|
||||
d.d_blk_hardlimit = C.__u64(quota.Size / 512)
|
||||
@@ -215,20 +279,11 @@ func setProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) er
|
||||
return nil
|
||||
}
|
||||
|
||||
-// GetQuota - get the quota limits of a directory that was configured with SetQuota
|
||||
-func (q *Control) GetQuota(targetPath string, quota *Quota) error {
|
||||
-
|
||||
- projectID, ok := q.quotas[targetPath]
|
||||
- if !ok {
|
||||
- return fmt.Errorf("quota not found for path : %s", targetPath)
|
||||
- }
|
||||
-
|
||||
- //
|
||||
- // get the quota limit for the container's project id
|
||||
- //
|
||||
+// GetProjectQuota gets the project quota for projectID on dev
|
||||
+func (q *XfsQuota) GetProjectQuota(backingFsBlockDev string, projectID uint32, quota *Quota) error {
|
||||
var d C.fs_disk_quota_t
|
||||
|
||||
- var cs = C.CString(q.backingFsBlockDev)
|
||||
+ var cs = C.CString(backingFsBlockDev)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
_, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XGETPQUOTA,
|
||||
@@ -236,13 +291,92 @@ func (q *Control) GetQuota(targetPath string, quota *Quota) error {
|
||||
uintptr(unsafe.Pointer(&d)), 0, 0)
|
||||
if errno != 0 {
|
||||
return fmt.Errorf("Failed to get quota limit for projid %d on %s: %v",
|
||||
- projectID, q.backingFsBlockDev, errno.Error())
|
||||
+ projectID, backingFsBlockDev, errno.Error())
|
||||
}
|
||||
quota.Size = uint64(d.d_blk_hardlimit) * 512
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
+// Ext4Quota is a struct implements quota operations
|
||||
+type Ext4Quota struct {
|
||||
+}
|
||||
+
|
||||
+// SetProjectQuota - set the quota for project id on ext4 block device
|
||||
+func (q *Ext4Quota) SetProjectQuota(backingFsBlockDev string, projectID uint32, quota Quota) error {
|
||||
+ var d C.struct_if_dqblk
|
||||
+ d.dqb_bhardlimit = C.__u64(quota.Size / 1024)
|
||||
+ d.dqb_bsoftlimit = d.dqb_bhardlimit
|
||||
+ d.dqb_valid = C.QIF_LIMITS
|
||||
+
|
||||
+ var cs = C.CString(backingFsBlockDev)
|
||||
+ defer C.free(unsafe.Pointer(cs))
|
||||
+
|
||||
+ _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_SETPQUOTA,
|
||||
+ uintptr(unsafe.Pointer(cs)), uintptr(C.__u32(projectID)),
|
||||
+ uintptr(unsafe.Pointer(&d)), 0, 0)
|
||||
+ if errno != 0 {
|
||||
+ return fmt.Errorf("Failed to set quota limit for projid %d on %s: %v",
|
||||
+ projectID, backingFsBlockDev, errno.Error())
|
||||
+ }
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (q *Ext4Quota) GetProjectQuota(backingFsBlockDev string, projectID uint32, quota *Quota) error {
|
||||
+ var d C.struct_if_dqblk
|
||||
+ d.dqb_valid = C.QIF_USAGE
|
||||
+
|
||||
+ var cs = C.CString(backingFsBlockDev)
|
||||
+ defer C.free(unsafe.Pointer(cs))
|
||||
+
|
||||
+ _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_SETPQUOTA,
|
||||
+ uintptr(unsafe.Pointer(cs)), uintptr(C.__u32(projectID)),
|
||||
+ uintptr(unsafe.Pointer(&d)), 0, 0)
|
||||
+ if errno != 0 {
|
||||
+ return fmt.Errorf("Failed to get quota limit for projid %d on %s: %v",
|
||||
+ projectID, backingFsBlockDev, errno.Error())
|
||||
+ }
|
||||
+
|
||||
+ quota.Size = uint64(d.dqb_bhardlimit) * 1024
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+// getQuotaStat - get the quota stat
|
||||
+// return 2 means quota is on
|
||||
+func getQuotaStat(backingFsBlockDev string) (int, error) {
|
||||
+ var info C.fs_quota_stat_t
|
||||
+
|
||||
+ var cs = C.CString(backingFsBlockDev)
|
||||
+ defer C.free(unsafe.Pointer(cs))
|
||||
+ _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_XGETPQSTAT,
|
||||
+ uintptr(unsafe.Pointer(cs)), 0,
|
||||
+ uintptr(unsafe.Pointer(&info)), 0, 0)
|
||||
+ if errno != 0 {
|
||||
+ return -1, fmt.Errorf("Failed to get quota stat on %s: %v",
|
||||
+ backingFsBlockDev, errno.Error())
|
||||
+ }
|
||||
+
|
||||
+ return int((info.qs_flags&C.QUOTA_PDQ_ACCT)>>C.PDQ_ACCT_BIT + (info.qs_flags&C.QUOTA_PDQ_ENFD)>>C.PDQ_ENFD_BIT), nil
|
||||
+}
|
||||
+
|
||||
+// GetQuota - get the quota limits of a directory that was configured with SetQuota
|
||||
+func (q *Control) GetQuota(targetPath string, quota *Quota) error {
|
||||
+ q.lock.Lock()
|
||||
+ projectID, ok := q.quotas[targetPath]
|
||||
+ q.lock.Unlock()
|
||||
+ if !ok {
|
||||
+ return fmt.Errorf("quota not found for path : %s", targetPath)
|
||||
+ }
|
||||
+
|
||||
+ //
|
||||
+ // get the quota limit for the container's project id
|
||||
+ //
|
||||
+
|
||||
+ return q.quotaOps.GetProjectQuota(q.backingFsBlockDev, projectID, quota)
|
||||
+}
|
||||
+
|
||||
// getProjectID - get the project id of path on xfs
|
||||
func getProjectID(targetPath string) (uint32, error) {
|
||||
dir, err := openDir(targetPath)
|
||||
diff --git a/components/engine/daemon/graphdriver/vfs/quota_linux.go b/components/engine/daemon/graphdriver/vfs/quota_linux.go
|
||||
index 0d5c3a7b98..bb2f571834 100644
|
||||
--- a/components/engine/daemon/graphdriver/vfs/quota_linux.go
|
||||
+++ b/components/engine/daemon/graphdriver/vfs/quota_linux.go
|
||||
@@ -1,6 +1,7 @@
|
||||
package vfs // import "github.com/docker/docker/daemon/graphdriver/vfs"
|
||||
|
||||
import (
|
||||
+ "github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/daemon/graphdriver/quota"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -10,7 +11,17 @@ type driverQuota struct {
|
||||
}
|
||||
|
||||
func setupDriverQuota(driver *Driver) {
|
||||
- if quotaCtl, err := quota.NewControl(driver.home); err == nil {
|
||||
+ // Probe fs type before setting quota, now only supports xfs and extfs
|
||||
+ fsMagic, err := graphdriver.GetFSMagic(driver.home)
|
||||
+ if err != nil {
|
||||
+ return
|
||||
+ }
|
||||
+ fsName, ok := graphdriver.FsNames[fsMagic]
|
||||
+ if !ok {
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ if quotaCtl, err := quota.NewControl(driver.home, fsName); err == nil {
|
||||
driver.quotaCtl = quotaCtl
|
||||
} else if err != quota.ErrQuotaNotSupported {
|
||||
logrus.Warnf("Unable to setup quota: %v\n", err)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
37
patch/0005-prjquota-fix-few-overlay2-quota-problems.patch
Normal file
37
patch/0005-prjquota-fix-few-overlay2-quota-problems.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From b5e205b8d1ea0a62ea8847dc5510a10c65a2573e Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:13:57 +0800
|
||||
Subject: [PATCH 005/111] prjquota: fix few overlay2 quota problems
|
||||
|
||||
reason:fix few overlay2 quota problems
|
||||
|
||||
Change-Id: Id3a7915747c415d56684c291fb0498d04b762c8c
|
||||
Signed-off-by: dengguangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/graphdriver/overlay2/overlay.go | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 36ae182bcd..96f44ba9a1 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -455,6 +455,14 @@ func (d *Driver) parseStorageOpt(storageOpt map[string]string, driver *Driver) e
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ // deal with negative and super large number
|
||||
+ if size < 0 {
|
||||
+ return fmt.Errorf("Illegal storage size(%s): numerical result out of range", val)
|
||||
+ }
|
||||
+ // for overlay (0-1024) means no limit
|
||||
+ if size < 1024 && size > 0 {
|
||||
+ return fmt.Errorf("Illegal storage size:%d, 1024 at least", size)
|
||||
+ }
|
||||
driver.options.quota.Size = uint64(size)
|
||||
default:
|
||||
return fmt.Errorf("Unknown option %s", key)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
From c5a18b46152c4c7016c0c2f0054e276a53f25e1f Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:14:09 +0800
|
||||
Subject: [PATCH 006/111] prjquota: overlay2 quota control backward
|
||||
compability
|
||||
|
||||
reason: In Euleros docker we support default quota control limit
|
||||
for daemon with commit
|
||||
docker: Add options to surport default limit for daemon
|
||||
However in mainstream they have similar commit
|
||||
35903110 Add overlay2.size daemon storage-opt
|
||||
But mainstream uses different api `overlay2.size` compares with
|
||||
`overlay2.basesize`, so adding this backward compability.
|
||||
|
||||
Change-Id: I36a548bd7f1ce6fab6cad24cfb49faa56f7a1fd1
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/graphdriver/overlay2/overlay.go | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 96f44ba9a1..b969582eb3 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -248,6 +248,7 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
||||
return nil, err
|
||||
}
|
||||
case "overlay2.size":
|
||||
+ case "overlay2.basesize":
|
||||
size, err := units.RAMInBytes(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -394,12 +395,16 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
||||
}
|
||||
}()
|
||||
|
||||
- if opts != nil && len(opts.StorageOpt) > 0 {
|
||||
+ if (opts != nil && len(opts.StorageOpt) > 0) || d.options.quota.Size > 0 {
|
||||
driver := &Driver{}
|
||||
if err := d.parseStorageOpt(opts.StorageOpt, driver); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+ if driver.options.quota.Size == 0 && d.options.quota.Size > 0 {
|
||||
+ driver.options.quota.Size = d.options.quota.Size
|
||||
+ }
|
||||
+
|
||||
if driver.options.quota.Size > 0 {
|
||||
// Set container disk quota limit
|
||||
if err := d.quotaCtl.SetQuota(dir, driver.options.quota); err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
319
patch/0007-filelimit-Add-file-fds-limit.patch
Normal file
319
patch/0007-filelimit-Add-file-fds-limit.patch
Normal file
@ -0,0 +1,319 @@
|
||||
From 1e26a8c5d18eb93c2786eff9eeede77f3b8162df Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:14:23 +0800
|
||||
Subject: [PATCH 007/111] filelimit: Add file fds limit
|
||||
|
||||
Change-Id: I4255fc648ad71dcba78fe38fae9d26454e2e41d8
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/opts.go | 3 +++
|
||||
components/cli/contrib/completion/bash/docker | 1 +
|
||||
components/cli/contrib/completion/zsh/_docker | 1 +
|
||||
.../cli/docs/reference/commandline/create.md | 1 +
|
||||
components/cli/docs/reference/commandline/run.md | 1 +
|
||||
components/cli/man/docker-run.1.md | 4 ++++
|
||||
.../vendor/github.com/docker/docker/api/Checklist | 1 +
|
||||
.../docker/api/types/container/host_config.go | 1 +
|
||||
.../engine/api/types/container/host_config.go | 1 +
|
||||
components/engine/daemon/daemon_unix.go | 6 ++++++
|
||||
components/engine/daemon/oci_linux.go | 3 +++
|
||||
.../integration-cli/docker_cli_run_unix_test.go | 10 ++++++++++
|
||||
.../integration-cli/requirements_unix_test.go | 4 ++++
|
||||
components/engine/pkg/sysinfo/sysinfo.go | 6 ++++++
|
||||
components/engine/pkg/sysinfo/sysinfo_linux.go | 15 +++++++++++++++
|
||||
.../opencontainers/runtime-spec/Checklist | 1 +
|
||||
.../runtime-spec/specs-go/config.go | 8 ++++++++
|
||||
17 files changed, 67 insertions(+)
|
||||
create mode 100644 components/cli/vendor/github.com/docker/docker/api/Checklist
|
||||
create mode 100644 components/engine/vendor/github.com/opencontainers/runtime-spec/Checklist
|
||||
|
||||
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||||
index 97906b6722..efb28a2cdf 100644
|
||||
--- a/components/cli/cli/command/container/opts.go
|
||||
+++ b/components/cli/cli/command/container/opts.go
|
||||
@@ -100,6 +100,7 @@ type containerOptions struct {
|
||||
ipv6Address string
|
||||
ipcMode string
|
||||
pidsLimit int64
|
||||
+ filesLimit int64
|
||||
restartPolicy string
|
||||
readonlyRootfs bool
|
||||
loggingDriver string
|
||||
@@ -271,6 +272,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
flags.BoolVar(&copts.oomKillDisable, "oom-kill-disable", false, "Disable OOM Killer")
|
||||
flags.IntVar(&copts.oomScoreAdj, "oom-score-adj", 0, "Tune host's OOM preferences (-1000 to 1000)")
|
||||
flags.Int64Var(&copts.pidsLimit, "pids-limit", 0, "Tune container pids limit (set -1 for unlimited)")
|
||||
+ flags.Int64Var(&copts.filesLimit, "files-limit", 0, "Tune container files limit (set -1 for unlimited)")
|
||||
|
||||
// Low-level execution (cgroups, namespaces, ...)
|
||||
flags.StringVar(&copts.cgroupParent, "cgroup-parent", "", "Optional parent cgroup for the container")
|
||||
@@ -531,6 +533,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
CPURealtimePeriod: copts.cpuRealtimePeriod,
|
||||
CPURealtimeRuntime: copts.cpuRealtimeRuntime,
|
||||
PidsLimit: copts.pidsLimit,
|
||||
+ FilesLimit: copts.filesLimit,
|
||||
BlkioWeight: copts.blkioWeight,
|
||||
BlkioWeightDevice: copts.blkioWeightDevice.GetList(),
|
||||
BlkioDeviceReadBps: copts.deviceReadBps.GetList(),
|
||||
diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker
|
||||
index 44ac8f3e0e..2e2c8cb04f 100644
|
||||
--- a/components/cli/contrib/completion/bash/docker
|
||||
+++ b/components/cli/contrib/completion/bash/docker
|
||||
@@ -1789,6 +1789,7 @@ _docker_container_run_and_create() {
|
||||
--env -e
|
||||
--env-file
|
||||
--expose
|
||||
+ --files-limit
|
||||
--group-add
|
||||
--health-cmd
|
||||
--health-interval
|
||||
diff --git a/components/cli/contrib/completion/zsh/_docker b/components/cli/contrib/completion/zsh/_docker
|
||||
index 94f042204d..cbbdfdb798 100644
|
||||
--- a/components/cli/contrib/completion/zsh/_docker
|
||||
+++ b/components/cli/contrib/completion/zsh/_docker
|
||||
@@ -621,6 +621,7 @@ __docker_container_subcommand() {
|
||||
"($help)--entrypoint=[Overwrite the default entrypoint of the image]:entry point: "
|
||||
"($help)*--env-file=[Read environment variables from a file]:environment file:_files"
|
||||
"($help)*--expose=[Expose a port from the container without publishing it]: "
|
||||
+ "($help)--files-limit[Tune container files limit (set -1 for max)]"
|
||||
"($help)*--group=[Set one or more supplementary user groups for the container]:group:_groups"
|
||||
"($help -h --hostname)"{-h=,--hostname=}"[Container host name]:hostname:_hosts"
|
||||
"($help -i --interactive)"{-i,--interactive}"[Keep stdin open even if not attached]"
|
||||
diff --git a/components/cli/docs/reference/commandline/create.md b/components/cli/docs/reference/commandline/create.md
|
||||
index d585da40ae..5d888183b3 100644
|
||||
--- a/components/cli/docs/reference/commandline/create.md
|
||||
+++ b/components/cli/docs/reference/commandline/create.md
|
||||
@@ -57,6 +57,7 @@ Options:
|
||||
-e, --env value Set environment variables (default [])
|
||||
--env-file value Read in a file of environment variables (default [])
|
||||
--expose value Expose a port or a range of ports (default [])
|
||||
+ --files-limit int Tune container files limit (set -1 for unlimited)
|
||||
--group-add value Add additional groups to join (default [])
|
||||
--health-cmd string Command to run to check health
|
||||
--health-interval duration Time between running the check (ns|us|ms|s|m|h) (default 0s)
|
||||
diff --git a/components/cli/docs/reference/commandline/run.md b/components/cli/docs/reference/commandline/run.md
|
||||
index 08b9f18d68..21b4fdf261 100644
|
||||
--- a/components/cli/docs/reference/commandline/run.md
|
||||
+++ b/components/cli/docs/reference/commandline/run.md
|
||||
@@ -61,6 +61,7 @@ Options:
|
||||
-e, --env value Set environment variables (default [])
|
||||
--env-file value Read in a file of environment variables (default [])
|
||||
--expose value Expose a port or a range of ports (default [])
|
||||
+ --files-limit int Tune container files limit (set -1 for unlimited)
|
||||
--group-add value Add additional groups to join (default [])
|
||||
--health-cmd string Command to run to check health
|
||||
--health-interval duration Time between running the check (ns|us|ms|s|m|h) (default 0s)
|
||||
diff --git a/components/cli/man/docker-run.1.md b/components/cli/man/docker-run.1.md
|
||||
index e03377001d..41f501d5b9 100644
|
||||
--- a/components/cli/man/docker-run.1.md
|
||||
+++ b/components/cli/man/docker-run.1.md
|
||||
@@ -39,6 +39,7 @@ docker-run - Run a command in a new container
|
||||
[**--entrypoint**[=*ENTRYPOINT*]]
|
||||
[**--env-file**[=*[]*]]
|
||||
[**--expose**[=*[]*]]
|
||||
+[**--files-limit**[=*FILES_LIMIT*]]
|
||||
[**--group-add**[=*[]*]]
|
||||
[**-h**|**--hostname**[=*HOSTNAME*]]
|
||||
[**--help**]
|
||||
@@ -315,6 +316,9 @@ that the container listens on the specified network ports at runtime. Docker
|
||||
uses this information to interconnect containers using links and to set up port
|
||||
redirection on the host system.
|
||||
|
||||
+**--files-limit**=""
|
||||
+ Tune the container's files limit. Set `-1` to have max files for the container.
|
||||
+
|
||||
**--group-add**=[]
|
||||
Add additional groups to run as
|
||||
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/Checklist b/components/cli/vendor/github.com/docker/docker/api/Checklist
|
||||
new file mode 100644
|
||||
index 0000000000..9594f235e4
|
||||
--- /dev/null
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/Checklist
|
||||
@@ -0,0 +1 @@
|
||||
+Add FilesLimit to components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go for supporting --files-limit
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
index 4ef26fa6c8..1565b5e091 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
@@ -334,6 +334,7 @@ type Resources struct {
|
||||
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
|
||||
OomKillDisable *bool // Whether to disable OOM Killer or not
|
||||
PidsLimit int64 // Setting pids limit for a container
|
||||
+ FilesLimit int64 // Setting files limit for a container
|
||||
Ulimits []*units.Ulimit // List of ulimits to be set in the container
|
||||
|
||||
// Applicable to Windows
|
||||
diff --git a/components/engine/api/types/container/host_config.go b/components/engine/api/types/container/host_config.go
|
||||
index 4ef26fa6c8..1565b5e091 100644
|
||||
--- a/components/engine/api/types/container/host_config.go
|
||||
+++ b/components/engine/api/types/container/host_config.go
|
||||
@@ -334,6 +334,7 @@ type Resources struct {
|
||||
MemorySwappiness *int64 // Tuning container memory swappiness behaviour
|
||||
OomKillDisable *bool // Whether to disable OOM Killer or not
|
||||
PidsLimit int64 // Setting pids limit for a container
|
||||
+ FilesLimit int64 // Setting files limit for a container
|
||||
Ulimits []*units.Ulimit // List of ulimits to be set in the container
|
||||
|
||||
// Applicable to Windows
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index 1b35df4950..138b8ac544 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -425,6 +425,12 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
|
||||
resources.PidsLimit = 0
|
||||
}
|
||||
|
||||
+ if resources.FilesLimit != 0 && !sysInfo.FilesLimit {
|
||||
+ warnings = append(warnings, "Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
+ logrus.Warnf("Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
+ resources.FilesLimit = 0
|
||||
+ }
|
||||
+
|
||||
// cpu subsystem checks and adjustments
|
||||
if resources.NanoCPUs > 0 && resources.CPUPeriod > 0 {
|
||||
return warnings, fmt.Errorf("Conflicting options: Nano CPUs and CPU Period cannot both be set")
|
||||
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||||
index 864d22fbcb..210d2ad3f6 100644
|
||||
--- a/components/engine/daemon/oci_linux.go
|
||||
+++ b/components/engine/daemon/oci_linux.go
|
||||
@@ -70,6 +70,9 @@ func setResources(s *specs.Spec, r containertypes.Resources) error {
|
||||
Pids: &specs.LinuxPids{
|
||||
Limit: r.PidsLimit,
|
||||
},
|
||||
+ Files: &specs.Files{
|
||||
+ Limit: &r.FilesLimit,
|
||||
+ },
|
||||
}
|
||||
|
||||
if s.Linux.Resources != nil && len(s.Linux.Resources.Devices) > 0 {
|
||||
diff --git a/components/engine/integration-cli/docker_cli_run_unix_test.go b/components/engine/integration-cli/docker_cli_run_unix_test.go
|
||||
index 5f782ee530..a618316d4b 100644
|
||||
--- a/components/engine/integration-cli/docker_cli_run_unix_test.go
|
||||
+++ b/components/engine/integration-cli/docker_cli_run_unix_test.go
|
||||
@@ -1414,6 +1414,16 @@ func (s *DockerSuite) TestRunPIDsLimit(c *check.C) {
|
||||
c.Assert(out, checker.Equals, "4", check.Commentf("setting the pids limit failed"))
|
||||
}
|
||||
|
||||
+// TestRunFilesLimit makes sure the files cgroup is set with --files-limit
|
||||
+func (s *DockerSuite) TestRunFilesLimit(c *check.C) {
|
||||
+ testRequires(c, filesLimit)
|
||||
+ file := "/sys/fs/cgroup/files/files.limit"
|
||||
+ out, _ := dockerCmd(c, "run", "--name", "fileslimit", "--files-limit", "32", "busybox", "cat", file)
|
||||
+ c.Assert(strings.TrimSpace(out), checker.Equals, "32")
|
||||
+ out = inspectField(c, "fileslimit", "HostConfig.FilesLimit")
|
||||
+ c.Assert(out, checker.Equals, "32", check.Commentf("setting the files limit failed"))
|
||||
+}
|
||||
+
|
||||
func (s *DockerSuite) TestRunPrivilegedAllowedDevices(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
|
||||
diff --git a/components/engine/integration-cli/requirements_unix_test.go b/components/engine/integration-cli/requirements_unix_test.go
|
||||
index 7c594f7db4..873c1fbfe2 100644
|
||||
--- a/components/engine/integration-cli/requirements_unix_test.go
|
||||
+++ b/components/engine/integration-cli/requirements_unix_test.go
|
||||
@@ -37,6 +37,10 @@ func pidsLimit() bool {
|
||||
return SysInfo.PidsLimit
|
||||
}
|
||||
|
||||
+func filesLimit() bool {
|
||||
+ return SysInfo.FilesLimit
|
||||
+}
|
||||
+
|
||||
func kernelMemorySupport() bool {
|
||||
return testEnv.DaemonInfo.KernelMemory
|
||||
}
|
||||
diff --git a/components/engine/pkg/sysinfo/sysinfo.go b/components/engine/pkg/sysinfo/sysinfo.go
|
||||
index 0f327d5068..5d9320218c 100644
|
||||
--- a/components/engine/pkg/sysinfo/sysinfo.go
|
||||
+++ b/components/engine/pkg/sysinfo/sysinfo.go
|
||||
@@ -15,6 +15,7 @@ type SysInfo struct {
|
||||
cgroupBlkioInfo
|
||||
cgroupCpusetInfo
|
||||
cgroupPids
|
||||
+ cgroupFiles
|
||||
|
||||
// Whether IPv4 forwarding is supported or not, if this was disabled, networking will not work
|
||||
IPv4ForwardingDisabled bool
|
||||
@@ -102,6 +103,11 @@ type cgroupPids struct {
|
||||
PidsLimit bool
|
||||
}
|
||||
|
||||
+type cgroupFiles struct {
|
||||
+ // Whether Files Limit is supported or not
|
||||
+ FilesLimit bool
|
||||
+}
|
||||
+
|
||||
// IsCpusetCpusAvailable returns `true` if the provided string set is contained
|
||||
// in cgroup's cpuset.cpus set, `false` otherwise.
|
||||
// If error is not nil a parsing error occurred.
|
||||
diff --git a/components/engine/pkg/sysinfo/sysinfo_linux.go b/components/engine/pkg/sysinfo/sysinfo_linux.go
|
||||
index dde5be19bc..c0bf280412 100644
|
||||
--- a/components/engine/pkg/sysinfo/sysinfo_linux.go
|
||||
+++ b/components/engine/pkg/sysinfo/sysinfo_linux.go
|
||||
@@ -40,6 +40,7 @@ func New(quiet bool) *SysInfo {
|
||||
sysInfo.cgroupBlkioInfo = checkCgroupBlkioInfo(cgMounts, quiet)
|
||||
sysInfo.cgroupCpusetInfo = checkCgroupCpusetInfo(cgMounts, quiet)
|
||||
sysInfo.cgroupPids = checkCgroupPids(quiet)
|
||||
+ sysInfo.cgroupFiles = checkCgroupFiles(quiet)
|
||||
}
|
||||
|
||||
_, ok := cgMounts["devices"]
|
||||
@@ -240,6 +241,20 @@ func checkCgroupPids(quiet bool) cgroupPids {
|
||||
}
|
||||
}
|
||||
|
||||
+// checkCgroupPids reads the files information from the pids cgroup mount point.
|
||||
+func checkCgroupFiles(quiet bool) cgroupFiles {
|
||||
+ _, err := cgroups.FindCgroupMountpoint("files")
|
||||
+ if err != nil {
|
||||
+ if !quiet {
|
||||
+ logrus.Warn(err)
|
||||
+ }
|
||||
+ return cgroupFiles{}
|
||||
+ }
|
||||
+ return cgroupFiles{
|
||||
+ FilesLimit: true,
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func cgroupEnabled(mountPoint, name string) bool {
|
||||
_, err := os.Stat(path.Join(mountPoint, name))
|
||||
return err == nil
|
||||
diff --git a/components/engine/vendor/github.com/opencontainers/runtime-spec/Checklist b/components/engine/vendor/github.com/opencontainers/runtime-spec/Checklist
|
||||
new file mode 100644
|
||||
index 0000000000..5b7ba2fab9
|
||||
--- /dev/null
|
||||
+++ b/components/engine/vendor/github.com/opencontainers/runtime-spec/Checklist
|
||||
@@ -0,0 +1 @@
|
||||
+Add struct LinuxFiles to components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go for supporting --files-limit
|
||||
diff --git a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
index f32698cab2..46049b3bfa 100644
|
||||
--- a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
+++ b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
@@ -314,6 +314,12 @@ type LinuxPids struct {
|
||||
Limit int64 `json:"limit"`
|
||||
}
|
||||
|
||||
+// Files for Linux cgroup 'files' resource management (https://lwn.net/Articles/604129/)
|
||||
+type Files struct {
|
||||
+ // Maximum number of open files. Default is "no limit".
|
||||
+ Limit *int64 `json:"limit,omitempty"`
|
||||
+}
|
||||
+
|
||||
// LinuxNetwork identification and priority configuration
|
||||
type LinuxNetwork struct {
|
||||
// Set class identifier for container's network packets
|
||||
@@ -340,6 +346,8 @@ type LinuxResources struct {
|
||||
CPU *LinuxCPU `json:"cpu,omitempty"`
|
||||
// Task resource restriction configuration.
|
||||
Pids *LinuxPids `json:"pids,omitempty"`
|
||||
+ // Files resource restriction configuration.
|
||||
+ Files *Files `json:"files,omitempty"`
|
||||
// BlockIO restriction configuration
|
||||
BlockIO *LinuxBlockIO `json:"blockIO,omitempty"`
|
||||
// Hugetlb limit (in bytes)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
104
patch/0008-filelimit-Ignore-host-kernel-whether-suport-f.patch
Normal file
104
patch/0008-filelimit-Ignore-host-kernel-whether-suport-f.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From 7a965f7491e5f60e27ce1f6c052aa139f80e0744 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:14:42 +0800
|
||||
Subject: [PATCH 008/111] filelimit: Ignore host kernel whether suport
|
||||
files limit when run a secure container
|
||||
|
||||
reason:Ignore host kernel whether suport files limit when run a secure
|
||||
container.
|
||||
|
||||
Change-Id: Iabd2c54492465a8df53375206d5ff600d9da7f6e
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/container.go | 2 +-
|
||||
components/engine/daemon/daemon_unix.go | 15 +++++++++------
|
||||
components/engine/daemon/daemon_windows.go | 6 +++---
|
||||
3 files changed, 13 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index c8e2053970..bd96de2571 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -348,7 +348,7 @@ func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *conta
|
||||
warnings []string
|
||||
)
|
||||
// Now do platform-specific verification
|
||||
- if warnings, err = verifyPlatformContainerSettings(daemon, hostConfig, config, update); err != nil {
|
||||
+ if warnings, err = daemon.verifyPlatformContainerSettings(hostConfig, config, update); err != nil {
|
||||
return warnings, err
|
||||
}
|
||||
if hostConfig.NetworkMode.IsHost() && len(hostConfig.PortBindings) > 0 {
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index 138b8ac544..f4b75055f5 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -350,8 +350,9 @@ func adaptSharedNamespaceContainer(daemon containerGetter, hostConfig *container
|
||||
}
|
||||
}
|
||||
|
||||
-func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
|
||||
+func (daemon *Daemon) verifyContainerResources(hostConfig *containertypes.HostConfig, sysInfo *sysinfo.SysInfo, update bool) ([]string, error) {
|
||||
warnings := []string{}
|
||||
+ resources := &hostConfig.Resources
|
||||
fixMemorySwappiness(resources)
|
||||
|
||||
// memory subsystem checks and adjustments
|
||||
@@ -426,9 +427,11 @@ func verifyContainerResources(resources *containertypes.Resources, sysInfo *sysi
|
||||
}
|
||||
|
||||
if resources.FilesLimit != 0 && !sysInfo.FilesLimit {
|
||||
- warnings = append(warnings, "Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
- logrus.Warnf("Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
- resources.FilesLimit = 0
|
||||
+ if daemon.IsNativeRuntime(hostConfig.Runtime) {
|
||||
+ warnings = append(warnings, "Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
+ logrus.Warnf("Your kernel does not support files limit capabilities, files limit discarded.")
|
||||
+ resources.FilesLimit = 0
|
||||
+ }
|
||||
}
|
||||
|
||||
// cpu subsystem checks and adjustments
|
||||
@@ -580,11 +583,11 @@ func UsingSystemd(config *config.Config) bool {
|
||||
|
||||
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||
// hostconfig and config structures.
|
||||
-func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
+func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
var warnings []string
|
||||
sysInfo := sysinfo.New(true)
|
||||
|
||||
- w, err := verifyContainerResources(&hostConfig.Resources, sysInfo, update)
|
||||
+ w, err := daemon.verifyContainerResources(hostConfig, sysInfo, update)
|
||||
|
||||
// no matter err is nil or not, w could have data in itself.
|
||||
warnings = append(warnings, w...)
|
||||
diff --git a/components/engine/daemon/daemon_windows.go b/components/engine/daemon/daemon_windows.go
|
||||
index 04d3de9924..4812236bc2 100644
|
||||
--- a/components/engine/daemon/daemon_windows.go
|
||||
+++ b/components/engine/daemon/daemon_windows.go
|
||||
@@ -75,7 +75,7 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
|
||||
return nil
|
||||
}
|
||||
|
||||
-func verifyContainerResources(resources *containertypes.Resources, isHyperv bool) ([]string, error) {
|
||||
+func (daemon *Daemon) verifyContainerResources(resources *containertypes.Resources, isHyperv bool) ([]string, error) {
|
||||
warnings := []string{}
|
||||
fixMemorySwappiness(resources)
|
||||
if !isHyperv {
|
||||
@@ -191,10 +191,10 @@ func verifyContainerResources(resources *containertypes.Resources, isHyperv bool
|
||||
|
||||
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||
// hostconfig and config structures.
|
||||
-func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
+func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
warnings := []string{}
|
||||
|
||||
- hyperv := daemon.runAsHyperVContainer(hostConfig)
|
||||
+ hyperv := daemon.daemon.runAsHyperVContainer(hostConfig)
|
||||
if !hyperv && system.IsWindowsClient() && !system.IsIoTCore() {
|
||||
// @engine maintainers. This block should not be removed. It partially enforces licensing
|
||||
// restrictions on Windows. Ping @jhowardmsft if there are concerns or PRs to change this.
|
||||
--
|
||||
2.17.1
|
||||
|
||||
128
patch/0009-healthycheck-add-healthycheck-in-_ping-add-se.patch
Normal file
128
patch/0009-healthycheck-add-healthycheck-in-_ping-add-se.patch
Normal file
@ -0,0 +1,128 @@
|
||||
From c03a609c9bb837d8f361888460c7a605dc1219d6 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:15:11 +0800
|
||||
Subject: [PATCH 009/111] healthycheck: add healthycheck in _ping &
|
||||
add semaphore set info in docker info
|
||||
|
||||
reason: add healthycheck in _ping & add semaphore set info in docker info
|
||||
|
||||
Change-Id: I90b3def5fa8bcf0e21090471c43c6309e58c26aa
|
||||
Signed-off-by: liruilin4 <liruilin4@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../api/server/router/system/backend.go | 1 +
|
||||
.../api/server/router/system/system_routes.go | 2 ++
|
||||
.../daemon/graphdriver/devmapper/driver.go | 7 ++++++
|
||||
components/engine/daemon/info.go | 10 ++++++++
|
||||
components/engine/utils/utils.go | 23 +++++++++++++++++++
|
||||
5 files changed, 43 insertions(+)
|
||||
create mode 100644 components/engine/utils/utils.go
|
||||
|
||||
diff --git a/components/engine/api/server/router/system/backend.go b/components/engine/api/server/router/system/backend.go
|
||||
index f5d2d98101..2ba5ab774b 100644
|
||||
--- a/components/engine/api/server/router/system/backend.go
|
||||
+++ b/components/engine/api/server/router/system/backend.go
|
||||
@@ -19,6 +19,7 @@ type Backend interface {
|
||||
SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{})
|
||||
UnsubscribeFromEvents(chan interface{})
|
||||
AuthenticateToRegistry(ctx context.Context, authConfig *types.AuthConfig) (string, string, error)
|
||||
+ HealthyCheck()
|
||||
}
|
||||
|
||||
// ClusterBackend is all the methods that need to be implemented
|
||||
diff --git a/components/engine/api/server/router/system/system_routes.go b/components/engine/api/server/router/system/system_routes.go
|
||||
index a2ff692de3..f235acc657 100644
|
||||
--- a/components/engine/api/server/router/system/system_routes.go
|
||||
+++ b/components/engine/api/server/router/system/system_routes.go
|
||||
@@ -31,6 +31,8 @@ func (s *systemRouter) pingHandler(ctx context.Context, w http.ResponseWriter, r
|
||||
if bv := builderVersion; bv != "" {
|
||||
w.Header().Set("Builder-Version", string(bv))
|
||||
}
|
||||
+
|
||||
+ s.backend.HealthyCheck()
|
||||
_, err := w.Write([]byte{'O', 'K'})
|
||||
return err
|
||||
}
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/driver.go b/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
index 899b1f8670..623843f852 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
+ "github.com/docker/docker/utils"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -101,6 +102,12 @@ func (d *Driver) Status() [][2]string {
|
||||
if vStr, err := devicemapper.GetLibraryVersion(); err == nil {
|
||||
status = append(status, [2]string{"Library Version", vStr})
|
||||
}
|
||||
+ usz, mni, err := utils.CheckSemSetStat()
|
||||
+ status = append(status, [2]string{"Semaphore Set Used", fmt.Sprintf("%d", usz)})
|
||||
+ status = append(status, [2]string{"Semaphore Set Total", fmt.Sprintf("%d", mni)})
|
||||
+ if err != nil {
|
||||
+ status = append(status, [2]string{"WARNING", fmt.Sprintf("%v", err)})
|
||||
+ }
|
||||
return status
|
||||
}
|
||||
|
||||
diff --git a/components/engine/daemon/info.go b/components/engine/daemon/info.go
|
||||
index bf84342b54..262719d9d1 100644
|
||||
--- a/components/engine/daemon/info.go
|
||||
+++ b/components/engine/daemon/info.go
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"github.com/docker/docker/pkg/sysinfo"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/registry"
|
||||
+ "github.com/docker/docker/utils"
|
||||
"github.com/docker/go-connections/sockets"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -256,3 +257,12 @@ func maskCredentials(rawURL string) string {
|
||||
maskedURL := parsedURL.String()
|
||||
return maskedURL
|
||||
}
|
||||
+
|
||||
+func (daemon *Daemon) HealthyCheck() {
|
||||
+ if daemon.imageService.GraphDriverForOS(runtime.GOOS) == "devicemapper" {
|
||||
+ _, _, err := utils.CheckSemSetStat()
|
||||
+ if err != nil {
|
||||
+ logrus.Warn(err)
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/components/engine/utils/utils.go b/components/engine/utils/utils.go
|
||||
new file mode 100644
|
||||
index 0000000000..75fd409399
|
||||
--- /dev/null
|
||||
+++ b/components/engine/utils/utils.go
|
||||
@@ -0,0 +1,23 @@
|
||||
+package utils
|
||||
+
|
||||
+/*
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/sem.h>
|
||||
+int mysemctl(int cmd, struct seminfo *p){
|
||||
+ return semctl(0, 0, cmd, p);
|
||||
+}
|
||||
+*/
|
||||
+import "C"
|
||||
+import (
|
||||
+ "fmt"
|
||||
+)
|
||||
+
|
||||
+func CheckSemSetStat() (int, int, error) {
|
||||
+ var seminfo *C.struct_seminfo = new(C.struct_seminfo)
|
||||
+ C.mysemctl(C.SEM_INFO, seminfo)
|
||||
+ var err error = nil
|
||||
+ if seminfo.semusz == seminfo.semmni {
|
||||
+ err = fmt.Errorf("system semaphore nums has attached limit: %d", int(seminfo.semusz))
|
||||
+ }
|
||||
+ return int(seminfo.semusz), int(seminfo.semmni), err
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
149
patch/0010-annotation-add-annotation-into-cli-flag.patch
Normal file
149
patch/0010-annotation-add-annotation-into-cli-flag.patch
Normal file
@ -0,0 +1,149 @@
|
||||
From 961d5e98090e4725dca298dde8afb8df54f99f2e Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:15:25 +0800
|
||||
Subject: [PATCH 010/111] annotation: add annotation into cli flag
|
||||
|
||||
reason: add annotation into cli flag
|
||||
|
||||
Change-Id: Ibca64819e6f390c70e8516a1462d8e465fcfe080
|
||||
Signed-off-by: caihaomin <caihaomin@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/opts.go | 7 +++++
|
||||
.../docker/api/types/container/config.go | 1 +
|
||||
.../engine/api/types/container/config.go | 1 +
|
||||
components/engine/api/types/types.go | 28 ++++++++++---------
|
||||
components/engine/daemon/oci_linux.go | 1 +
|
||||
5 files changed, 25 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||||
index efb28a2cdf..af30dfcbf2 100644
|
||||
--- a/components/cli/cli/command/container/opts.go
|
||||
+++ b/components/cli/cli/command/container/opts.go
|
||||
@@ -43,6 +43,7 @@ type containerOptions struct {
|
||||
deviceWriteIOps opts.ThrottledeviceOpt
|
||||
env opts.ListOpts
|
||||
labels opts.ListOpts
|
||||
+ annotation opts.ListOpts
|
||||
deviceCgroupRules opts.ListOpts
|
||||
devices opts.ListOpts
|
||||
ulimits *opts.UlimitOpt
|
||||
@@ -148,6 +149,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
groupAdd: opts.NewListOpts(nil),
|
||||
labels: opts.NewListOpts(nil),
|
||||
labelsFile: opts.NewListOpts(nil),
|
||||
+ annotation: opts.NewListOpts(opts.ValidateEnv),
|
||||
linkLocalIPs: opts.NewListOpts(nil),
|
||||
links: opts.NewListOpts(opts.ValidateLink),
|
||||
loggingOpts: opts.NewListOpts(nil),
|
||||
@@ -173,6 +175,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
flags.BoolVarP(&copts.stdin, "interactive", "i", false, "Keep STDIN open even if not attached")
|
||||
flags.VarP(&copts.labels, "label", "l", "Set meta data on a container")
|
||||
flags.Var(&copts.labelsFile, "label-file", "Read in a line delimited file of labels")
|
||||
+ flags.Var(&copts.annotation, "annotation", "Set annotations on a container")
|
||||
flags.BoolVar(&copts.readonlyRootfs, "read-only", false, "Mount the container's root filesystem as read only")
|
||||
flags.StringVar(&copts.restartPolicy, "restart", "no", "Restart policy to apply when a container exits")
|
||||
flags.StringVar(&copts.stopSignal, "stop-signal", signal.DefaultStopSignal, "Signal to stop a container")
|
||||
@@ -438,6 +441,9 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+ // collect all the annotations for the container
|
||||
+ annotations := copts.annotation.GetAll()
|
||||
+
|
||||
pidMode := container.PidMode(copts.pidMode)
|
||||
if !pidMode.Valid() {
|
||||
return nil, errors.Errorf("--pid: invalid PID mode")
|
||||
@@ -568,6 +574,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
Entrypoint: entrypoint,
|
||||
WorkingDir: copts.workingDir,
|
||||
Labels: opts.ConvertKVStringsToMap(labels),
|
||||
+ Annotations: opts.ConvertKVStringsToMap(annotations),
|
||||
Healthcheck: healthConfig,
|
||||
}
|
||||
if flags.Changed("stop-signal") {
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/container/config.go b/components/cli/vendor/github.com/docker/docker/api/types/container/config.go
|
||||
index 89ad08c234..c28f0b101e 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/api/types/container/config.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/types/container/config.go
|
||||
@@ -63,6 +63,7 @@ type Config struct {
|
||||
MacAddress string `json:",omitempty"` // Mac Address of the container
|
||||
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
|
||||
Labels map[string]string // List of labels set to this container
|
||||
+ Annotations map[string]string // List of annotations set to this container
|
||||
StopSignal string `json:",omitempty"` // Signal to stop a container
|
||||
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
|
||||
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
|
||||
diff --git a/components/engine/api/types/container/config.go b/components/engine/api/types/container/config.go
|
||||
index 89ad08c234..c28f0b101e 100644
|
||||
--- a/components/engine/api/types/container/config.go
|
||||
+++ b/components/engine/api/types/container/config.go
|
||||
@@ -63,6 +63,7 @@ type Config struct {
|
||||
MacAddress string `json:",omitempty"` // Mac Address of the container
|
||||
OnBuild []string // ONBUILD metadata that were defined on the image Dockerfile
|
||||
Labels map[string]string // List of labels set to this container
|
||||
+ Annotations map[string]string // List of annotations set to this container
|
||||
StopSignal string `json:",omitempty"` // Signal to stop a container
|
||||
StopTimeout *int `json:",omitempty"` // Timeout (in seconds) to stop a container
|
||||
Shell strslice.StrSlice `json:",omitempty"` // Shell for shell-form of RUN, CMD, ENTRYPOINT
|
||||
diff --git a/components/engine/api/types/types.go b/components/engine/api/types/types.go
|
||||
index a8fae3ba32..959e9eb447 100644
|
||||
--- a/components/engine/api/types/types.go
|
||||
+++ b/components/engine/api/types/types.go
|
||||
@@ -56,19 +56,20 @@ type ImageMetadata struct {
|
||||
// Container contains response of Engine API:
|
||||
// GET "/containers/json"
|
||||
type Container struct {
|
||||
- ID string `json:"Id"`
|
||||
- Names []string
|
||||
- Image string
|
||||
- ImageID string
|
||||
- Command string
|
||||
- Created int64
|
||||
- Ports []Port
|
||||
- SizeRw int64 `json:",omitempty"`
|
||||
- SizeRootFs int64 `json:",omitempty"`
|
||||
- Labels map[string]string
|
||||
- State string
|
||||
- Status string
|
||||
- HostConfig struct {
|
||||
+ ID string `json:"Id"`
|
||||
+ Names []string
|
||||
+ Image string
|
||||
+ ImageID string
|
||||
+ Command string
|
||||
+ Created int64
|
||||
+ Ports []Port
|
||||
+ SizeRw int64 `json:",omitempty"`
|
||||
+ SizeRootFs int64 `json:",omitempty"`
|
||||
+ Labels map[string]string
|
||||
+ Annotaitons map[string]string
|
||||
+ State string
|
||||
+ Status string
|
||||
+ HostConfig struct {
|
||||
NetworkMode string `json:",omitempty"`
|
||||
}
|
||||
NetworkSettings *SummaryNetworkSettings
|
||||
@@ -188,6 +189,7 @@ type Info struct {
|
||||
NoProxy string
|
||||
Name string
|
||||
Labels []string
|
||||
+ Annotations []string
|
||||
ExperimentalBuild bool
|
||||
ServerVersion string
|
||||
ClusterStore string
|
||||
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||||
index 210d2ad3f6..5018b21f0d 100644
|
||||
--- a/components/engine/daemon/oci_linux.go
|
||||
+++ b/components/engine/daemon/oci_linux.go
|
||||
@@ -846,6 +846,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
||||
s.Process.NoNewPrivileges = c.NoNewPrivileges
|
||||
s.Process.OOMScoreAdj = &c.HostConfig.OomScoreAdj
|
||||
s.Linux.MountLabel = c.MountLabel
|
||||
+ s.Annotations = c.Config.Annotations
|
||||
|
||||
// Set the masked and readonly paths with regard to the host config options if they are set.
|
||||
if c.HostConfig.MaskedPaths != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
288
patch/0011-hookspec-Allow-adding-custom-hooks.patch
Normal file
288
patch/0011-hookspec-Allow-adding-custom-hooks.patch
Normal file
@ -0,0 +1,288 @@
|
||||
From 65c782bb9b0b159f5644395cb291b8741b4400f4 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:15:40 +0800
|
||||
Subject: [PATCH 011/111] hookspec: Allow adding custom hooks
|
||||
|
||||
reason: Add new flag "--hook-spec" which accept a file containing custom hook
|
||||
definitions, custom hooks will be appended to system hooks which means
|
||||
docker will execute its own hook first(libnetwork prestart hook) to make
|
||||
sure everything predefined is working normally, user custom programme
|
||||
can be executed afterwards
|
||||
|
||||
One example hook spec file can be of format:
|
||||
```
|
||||
{
|
||||
"prestart": [
|
||||
{
|
||||
"path": "/bin/ls",
|
||||
"args": ["ls"],
|
||||
"env": []
|
||||
}
|
||||
],
|
||||
"poststart":[],
|
||||
"poststop":[]
|
||||
}
|
||||
```
|
||||
|
||||
Change-Id: Iee6f4e5b56ebf0647304c08c2948d599356192e6
|
||||
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/opts.go | 3 ++
|
||||
.../cli/docs/reference/commandline/create.md | 1 +
|
||||
.../cli/docs/reference/commandline/run.md | 1 +
|
||||
components/cli/man/docker-run.1.md | 28 +++++++++++++++++++
|
||||
.../docker/api/types/container/host_config.go | 1 +
|
||||
.../engine/api/types/container/host_config.go | 1 +
|
||||
components/engine/container/container.go | 4 ++-
|
||||
components/engine/daemon/container.go | 24 ++++++++++++++++
|
||||
components/engine/daemon/daemon_unix.go | 16 +++++++++++
|
||||
components/engine/daemon/oci_linux.go | 6 ++++
|
||||
10 files changed, 84 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||||
index af30dfcbf2..8e07aa77cb 100644
|
||||
--- a/components/cli/cli/command/container/opts.go
|
||||
+++ b/components/cli/cli/command/container/opts.go
|
||||
@@ -111,6 +111,7 @@ type containerOptions struct {
|
||||
stopTimeout int
|
||||
isolation string
|
||||
shmSize opts.MemBytes
|
||||
+ hookSpec string
|
||||
noHealthcheck bool
|
||||
healthCmd string
|
||||
healthInterval time.Duration
|
||||
@@ -283,6 +284,7 @@ func addFlags(flags *pflag.FlagSet) *containerOptions {
|
||||
flags.StringVar(&copts.isolation, "isolation", "", "Container isolation technology")
|
||||
flags.StringVar(&copts.pidMode, "pid", "", "PID namespace to use")
|
||||
flags.Var(&copts.shmSize, "shm-size", "Size of /dev/shm")
|
||||
+ flags.StringVar(&copts.hookSpec, "hook-spec", "", "file containing hook definition(prestart, poststart, poststop)")
|
||||
flags.StringVar(&copts.utsMode, "uts", "", "UTS namespace to use")
|
||||
flags.StringVar(&copts.runtime, "runtime", "", "Runtime to use for this container")
|
||||
|
||||
@@ -619,6 +621,7 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
VolumeDriver: copts.volumeDriver,
|
||||
Isolation: container.Isolation(copts.isolation),
|
||||
ShmSize: copts.shmSize.Value(),
|
||||
+ HookSpec: copts.hookSpec,
|
||||
Resources: resources,
|
||||
Tmpfs: tmpfs,
|
||||
Sysctls: copts.sysctls.GetAll(),
|
||||
diff --git a/components/cli/docs/reference/commandline/create.md b/components/cli/docs/reference/commandline/create.md
|
||||
index 5d888183b3..34cb79a679 100644
|
||||
--- a/components/cli/docs/reference/commandline/create.md
|
||||
+++ b/components/cli/docs/reference/commandline/create.md
|
||||
@@ -66,6 +66,7 @@ Options:
|
||||
--health-start-period duration Start period for the container to initialize before counting retries towards unstable (ns|us|ms|s|m|h) (default 0s)
|
||||
--help Print usage
|
||||
-h, --hostname string Container host name
|
||||
+ --hook-spec File containing hook definition(prestart, poststart, poststop)
|
||||
--init Run an init inside the container that forwards signals and reaps processes
|
||||
-i, --interactive Keep STDIN open even if not attached
|
||||
--io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only)
|
||||
diff --git a/components/cli/docs/reference/commandline/run.md b/components/cli/docs/reference/commandline/run.md
|
||||
index 21b4fdf261..1dc43ddcd9 100644
|
||||
--- a/components/cli/docs/reference/commandline/run.md
|
||||
+++ b/components/cli/docs/reference/commandline/run.md
|
||||
@@ -70,6 +70,7 @@ Options:
|
||||
--health-start-period duration Start period for the container to initialize before counting retries towards unstable (ns|us|ms|s|m|h) (default 0s)
|
||||
--help Print usage
|
||||
-h, --hostname string Container host name
|
||||
+ --hook-spec File containing hook definition(prestart, poststart, poststop)
|
||||
--init Run an init inside the container that forwards signals and reaps processes
|
||||
-i, --interactive Keep STDIN open even if not attached
|
||||
--io-maxbandwidth string Maximum IO bandwidth limit for the system drive (Windows only)
|
||||
diff --git a/components/cli/man/docker-run.1.md b/components/cli/man/docker-run.1.md
|
||||
index 41f501d5b9..b0cbcd2e87 100644
|
||||
--- a/components/cli/man/docker-run.1.md
|
||||
+++ b/components/cli/man/docker-run.1.md
|
||||
@@ -43,6 +43,7 @@ docker-run - Run a command in a new container
|
||||
[**--group-add**[=*[]*]]
|
||||
[**-h**|**--hostname**[=*HOSTNAME*]]
|
||||
[**--help**]
|
||||
+[**--hook-spec**[=*HOOKFILE*]]
|
||||
[**--init**]
|
||||
[**-i**|**--interactive**]
|
||||
[**--ip**[=*IPv4-ADDRESS*]]
|
||||
@@ -330,6 +331,33 @@ redirection on the host system.
|
||||
**--help**
|
||||
Print usage statement
|
||||
|
||||
+**--hook-spec**=""
|
||||
+ Add custom hooks for container
|
||||
+
|
||||
+ With this flag, user can specify a file containing custom hook, an example hook file can be like this:
|
||||
+
|
||||
+```
|
||||
+{
|
||||
+ "prestart": [
|
||||
+ {
|
||||
+ "path": "/usr/libexec/oci/hooks.d/oci-systemd-hook",
|
||||
+ "args": ["oci-systemd-hook", "prestart"],
|
||||
+ "env": ["container=runc"]
|
||||
+ }
|
||||
+ ],
|
||||
+ "poststop":[
|
||||
+ {
|
||||
+ "path": "/usr/libexec/oci/hooks.d/oci-systemd-hook",
|
||||
+ "args": ["oci-systemd-hook", "poststop"],
|
||||
+ "env": ["container=runc"]
|
||||
+ }
|
||||
+ ]
|
||||
+}
|
||||
+```
|
||||
+
|
||||
+ currently it supports three hooks: "prestart", "poststart", "poststop".
|
||||
+ See OCI spec definition for more information about "hooks".
|
||||
+
|
||||
**--init**
|
||||
Run an init inside the container that forwards signals and reaps processes
|
||||
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
index 1565b5e091..701cae55f1 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/types/container/host_config.go
|
||||
@@ -395,6 +395,7 @@ type HostConfig struct {
|
||||
// Applicable to Windows
|
||||
ConsoleSize [2]uint // Initial console size (height,width)
|
||||
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||||
+ HookSpec string // specification file containing custom hook definition
|
||||
|
||||
// Contains container's resources (cgroups, ulimits)
|
||||
Resources
|
||||
diff --git a/components/engine/api/types/container/host_config.go b/components/engine/api/types/container/host_config.go
|
||||
index 1565b5e091..701cae55f1 100644
|
||||
--- a/components/engine/api/types/container/host_config.go
|
||||
+++ b/components/engine/api/types/container/host_config.go
|
||||
@@ -395,6 +395,7 @@ type HostConfig struct {
|
||||
// Applicable to Windows
|
||||
ConsoleSize [2]uint // Initial console size (height,width)
|
||||
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||||
+ HookSpec string // specification file containing custom hook definition
|
||||
|
||||
// Contains container's resources (cgroups, ulimits)
|
||||
Resources
|
||||
diff --git a/components/engine/container/container.go b/components/engine/container/container.go
|
||||
index f74676f7ee..02adc2019a 100644
|
||||
--- a/components/engine/container/container.go
|
||||
+++ b/components/engine/container/container.go
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
"github.com/docker/go-units"
|
||||
agentexec "github.com/docker/swarmkit/agent/exec"
|
||||
+ "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@@ -93,6 +94,8 @@ type Container struct {
|
||||
LogCopier *logger.Copier `json:"-"`
|
||||
restartManager restartmanager.RestartManager
|
||||
attachContext *attachContext
|
||||
+ Hooks specs.Hooks
|
||||
+ CgroupParent string
|
||||
|
||||
// Fields here are specific to Unix platforms
|
||||
AppArmorProfile string
|
||||
@@ -106,7 +109,6 @@ type Container struct {
|
||||
// Fields here are specific to Windows
|
||||
NetworkSharedContainerID string `json:"-"`
|
||||
SharedEndpointList []string `json:"-"`
|
||||
- CgroupParent string
|
||||
}
|
||||
|
||||
// NewBaseContainer creates a new container with its
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index bd96de2571..8e68904b16 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -1,6 +1,7 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
+ "encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
@@ -224,11 +225,34 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||||
return err
|
||||
}
|
||||
|
||||
+ // register hooks to container
|
||||
+ if err := daemon.registerHooks(container, hostConfig); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
runconfig.SetDefaultNetModeIfBlank(hostConfig)
|
||||
container.HostConfig = hostConfig
|
||||
return container.CheckpointTo(daemon.containersReplica)
|
||||
}
|
||||
|
||||
+
|
||||
+func (daemon *Daemon) registerHooks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||
+ if hostConfig.HookSpec == "" {
|
||||
+ return nil
|
||||
+ }
|
||||
+ // the hook spec has already been sanitized, so no need for validation again
|
||||
+ f, err := os.Open(hostConfig.HookSpec)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("open hook spec file error: %v", err)
|
||||
+ }
|
||||
+ defer f.Close()
|
||||
+
|
||||
+ if err = json.NewDecoder(f).Decode(&container.Hooks); err != nil {
|
||||
+ return fmt.Errorf("malformed hook spec, is your spec file in json format? error: %v", err)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
// verifyContainerSettings performs validation of the hostconfig and config
|
||||
// structures.
|
||||
func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index f4b75055f5..ebf4e067fb 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -627,6 +627,22 @@ func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes
|
||||
return warnings, fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if hostConfig.HookSpec != "" {
|
||||
+ hostConfig.HookSpec = filepath.Clean(hostConfig.HookSpec)
|
||||
+ if !filepath.IsAbs(hostConfig.HookSpec) {
|
||||
+ return warnings, fmt.Errorf("Hook spec file must be an absolute path")
|
||||
+ }
|
||||
+ fi, err := os.Stat(hostConfig.HookSpec)
|
||||
+ if err != nil {
|
||||
+ return warnings, fmt.Errorf("stat hook spec file failed: %v", err)
|
||||
+ }
|
||||
+ if !fi.Mode().IsRegular() {
|
||||
+ return warnings, fmt.Errorf("Hook spec file must be a regular text file")
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
if hostConfig.Runtime == "" {
|
||||
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
|
||||
}
|
||||
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||||
index 5018b21f0d..884739c07e 100644
|
||||
--- a/components/engine/daemon/oci_linux.go
|
||||
+++ b/components/engine/daemon/oci_linux.go
|
||||
@@ -818,6 +818,12 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
|
||||
}
|
||||
}
|
||||
|
||||
+ // apppend user custom hooks after system hooks
|
||||
+ // make sure docker's predefined hooks are executed before custom hooks
|
||||
+ s.Hooks.Prestart = append(s.Hooks.Prestart, c.Hooks.Prestart...)
|
||||
+ s.Hooks.Poststart = append(s.Hooks.Poststart, c.Hooks.Poststart...)
|
||||
+ s.Hooks.Poststop = append(s.Hooks.Poststop, c.Hooks.Poststop...)
|
||||
+
|
||||
if apparmor.IsEnabled() {
|
||||
var appArmorProfile string
|
||||
if c.AppArmorProfile != "" {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
82
patch/0012-hookspec-Security-enhancement-for-hooks.patch
Normal file
82
patch/0012-hookspec-Security-enhancement-for-hooks.patch
Normal file
@ -0,0 +1,82 @@
|
||||
From e81d103000ae3213b91ed54410ddb20d911ddc1a Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:15:56 +0800
|
||||
Subject: [PATCH 012/111] hookspec: Security enhancement for hooks
|
||||
|
||||
reason: Currently docker support running hooks with any path, this is insecure.
|
||||
To solve this, we need to restrict path to specified path, e.g.
|
||||
"/var/lib/docker/hooks" or "/var/lib/docker/1000.1000/hooks" if user
|
||||
remap enabled for user ns.
|
||||
|
||||
Change-Id: I9cff78f1a1105dcb4bc0b00c8e6e715904dfb778
|
||||
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/container.go | 37 +++++++++++++++++++++++++++
|
||||
components/engine/daemon/daemon.go | 1 +
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index 8e68904b16..0864443513 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -250,6 +250,43 @@ func (daemon *Daemon) registerHooks(container *container.Container, hostConfig *
|
||||
if err = json.NewDecoder(f).Decode(&container.Hooks); err != nil {
|
||||
return fmt.Errorf("malformed hook spec, is your spec file in json format? error: %v", err)
|
||||
}
|
||||
+
|
||||
+ // hook path must be absolute and must be subdir of XXX
|
||||
+ if err = daemon.validateHook(container); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) validateHook(container *container.Container) error {
|
||||
+ for _, v := range container.Hooks.Prestart {
|
||||
+ if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ }
|
||||
+ for _, v := range container.Hooks.Poststart {
|
||||
+ if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ }
|
||||
+ for _, v := range container.Hooks.Poststop {
|
||||
+ if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) validateHookPath(path string) error {
|
||||
+ // hook path must be absolute and must be subdir of XXX
|
||||
+ path = filepath.Clean(path)
|
||||
+ if !filepath.IsAbs(path) {
|
||||
+ return fmt.Errorf("Hook path %q must be an absolute path", path)
|
||||
+ }
|
||||
+
|
||||
+ if !filepath.HasPrefix(path, daemon.hookStore) {
|
||||
+ return fmt.Errorf("hook program must be put under %q", daemon.hookStore)
|
||||
+ }
|
||||
return nil
|
||||
}
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index 8d6b4d8546..d1f3131c4f 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -95,6 +95,7 @@ type Daemon struct {
|
||||
volumes *volumesservice.VolumesService
|
||||
discoveryWatcher discovery.Reloader
|
||||
root string
|
||||
+ hookStore string
|
||||
seccompEnabled bool
|
||||
apparmorEnabled bool
|
||||
shutdown bool
|
||||
--
|
||||
2.17.1
|
||||
|
||||
31
patch/0013-hookspec-Add-bash-completion-for-hook-spec.patch
Normal file
31
patch/0013-hookspec-Add-bash-completion-for-hook-spec.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From e261cd646bd656db1eae5a3bcb4af59af3423a46 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:16:09 +0800
|
||||
Subject: [PATCH 013/111] hookspec: Add bash completion for
|
||||
--hook-spec
|
||||
|
||||
reason: Add bash completion for --hook-spec
|
||||
|
||||
Change-Id: Ic2cf226576a5437aa69b48edb73737c59f116ae8
|
||||
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/contrib/completion/bash/docker | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker
|
||||
index 2e2c8cb04f..9012988075 100644
|
||||
--- a/components/cli/contrib/completion/bash/docker
|
||||
+++ b/components/cli/contrib/completion/bash/docker
|
||||
@@ -1791,6 +1791,7 @@ _docker_container_run_and_create() {
|
||||
--expose
|
||||
--files-limit
|
||||
--group-add
|
||||
+ --hook-spec
|
||||
--health-cmd
|
||||
--health-interval
|
||||
--health-retries
|
||||
--
|
||||
2.17.1
|
||||
|
||||
367
patch/0014-hookspec-Add-default-hooks-for-all-containers.patch
Normal file
367
patch/0014-hookspec-Add-default-hooks-for-all-containers.patch
Normal file
@ -0,0 +1,367 @@
|
||||
From d6725e951ee958b61af8c32d5c71d79d2e708432 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:16:48 +0800
|
||||
Subject: [PATCH 014/111] hookspec: Add default hooks for all
|
||||
containers
|
||||
|
||||
reason: Add new flag `--hook-spec` for daemon, so that we can specify one json
|
||||
file containing hooks definition for all containers.
|
||||
|
||||
You can also add this into `/etc/docker/daemon.json` daemon config file:
|
||||
|
||||
```
|
||||
{
|
||||
"hook-spec": "/tmp/hookspec.json"
|
||||
}
|
||||
```
|
||||
|
||||
Change-Id: I9263d5a912daeb04621e7d2ec991204333c2b931
|
||||
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/system/info.go | 4 +
|
||||
components/cli/contrib/completion/bash/docker | 1 +
|
||||
.../cli/docs/reference/commandline/dockerd.md | 1 +
|
||||
components/cli/man/dockerd.8.md | 25 ++++-
|
||||
.../docker/docker/api/types/types.go | 1 +
|
||||
components/engine/api/types/types.go | 1 +
|
||||
components/engine/cmd/dockerd/config.go | 1 +
|
||||
components/engine/daemon/config/config.go | 1 +
|
||||
components/engine/daemon/container.go | 94 +++++++++++++++++--
|
||||
components/engine/daemon/daemon.go | 7 ++
|
||||
components/engine/daemon/info.go | 1 +
|
||||
11 files changed, 126 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/system/info.go b/components/cli/cli/command/system/info.go
|
||||
index 92fc2cd3e7..17ccc14aec 100644
|
||||
--- a/components/cli/cli/command/system/info.go
|
||||
+++ b/components/cli/cli/command/system/info.go
|
||||
@@ -204,6 +204,10 @@ func prettyPrintInfo(dockerCli command.Cli, info types.Info) error {
|
||||
}
|
||||
|
||||
fmt.Fprintln(dockerCli.Out(), "Live Restore Enabled:", info.LiveRestoreEnabled)
|
||||
+ if info.HookSpec != "" {
|
||||
+ fmt.Fprintf(dockerCli.Out(), "Default hook spec file: %s", info.HookSpec)
|
||||
+ }
|
||||
+
|
||||
if info.ProductLicense != "" {
|
||||
fmt.Fprintln(dockerCli.Out(), "Product License:", info.ProductLicense)
|
||||
}
|
||||
diff --git a/components/cli/contrib/completion/bash/docker b/components/cli/contrib/completion/bash/docker
|
||||
index 9012988075..64f7fe08dd 100644
|
||||
--- a/components/cli/contrib/completion/bash/docker
|
||||
+++ b/components/cli/contrib/completion/bash/docker
|
||||
@@ -2274,6 +2274,7 @@ _docker_daemon() {
|
||||
--fixed-cidr
|
||||
--fixed-cidr-v6
|
||||
--group -G
|
||||
+ --hook-spec
|
||||
--init-path
|
||||
--insecure-registry
|
||||
--ip
|
||||
diff --git a/components/cli/docs/reference/commandline/dockerd.md b/components/cli/docs/reference/commandline/dockerd.md
|
||||
index 4b50b78b19..bbf6908af3 100644
|
||||
--- a/components/cli/docs/reference/commandline/dockerd.md
|
||||
+++ b/components/cli/docs/reference/commandline/dockerd.md
|
||||
@@ -53,6 +53,7 @@ Options:
|
||||
--fixed-cidr-v6 string IPv6 subnet for fixed IPs
|
||||
-G, --group string Group for the unix socket (default "docker")
|
||||
--help Print usage
|
||||
+ --hook-spec Default hook spec file applied to all containers
|
||||
-H, --host list Daemon socket(s) to connect to (default [])
|
||||
--icc Enable inter-container communication (default true)
|
||||
--init Run an init in the container to forward signals and reap processes
|
||||
diff --git a/components/cli/man/dockerd.8.md b/components/cli/man/dockerd.8.md
|
||||
index 0224035970..d075080e78 100644
|
||||
--- a/components/cli/man/dockerd.8.md
|
||||
+++ b/components/cli/man/dockerd.8.md
|
||||
@@ -38,6 +38,7 @@ dockerd - Enable daemon mode
|
||||
[**-G**|**--group**[=*docker*]]
|
||||
[**-H**|**--host**[=*[]*]]
|
||||
[**--help**]
|
||||
+[**--hook-spec**[=*HOOKFILE*]]
|
||||
[**--icc**[=*true*]]
|
||||
[**--init**[=*false*]]
|
||||
[**--init-path**[=*""*]]
|
||||
@@ -239,7 +240,29 @@ unix://[/path/to/socket] to use.
|
||||
|
||||
**--help**
|
||||
Print usage statement
|
||||
-
|
||||
+
|
||||
+**--hook-spec**=""
|
||||
+ Add default hooks for all containers.
|
||||
+
|
||||
+ With this flag, user can specify a file containing custom hook, an example hook file can be like this:
|
||||
+
|
||||
+ ```
|
||||
+ {
|
||||
+ "prestart": [
|
||||
+ {
|
||||
+ "path": "/var/lib/docker/hooks/myhook",
|
||||
+ "args": ["myhook", "prestart"],
|
||||
+ "env": ["container=runc"]
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ ```
|
||||
+
|
||||
+ Then all the containers will run the default hook `myhook` when start.
|
||||
+
|
||||
+ currently it supports three hooks: "prestart", "poststart", "poststop".
|
||||
+ See OCI spec definition for more information about "hooks".
|
||||
+
|
||||
**--icc**=*true*|*false*
|
||||
Allow unrestricted inter\-container and Docker daemon host communication. If
|
||||
disabled, containers can still be linked together using the **--link** option
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/types.go b/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
index a8fae3ba32..2fb6c5478b 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
@@ -192,6 +192,7 @@ type Info struct {
|
||||
ServerVersion string
|
||||
ClusterStore string
|
||||
ClusterAdvertise string
|
||||
+ HookSpec string
|
||||
Runtimes map[string]Runtime
|
||||
DefaultRuntime string
|
||||
Swarm swarm.Info
|
||||
diff --git a/components/engine/api/types/types.go b/components/engine/api/types/types.go
|
||||
index 959e9eb447..820d513cbb 100644
|
||||
--- a/components/engine/api/types/types.go
|
||||
+++ b/components/engine/api/types/types.go
|
||||
@@ -194,6 +194,7 @@ type Info struct {
|
||||
ServerVersion string
|
||||
ClusterStore string
|
||||
ClusterAdvertise string
|
||||
+ HookSpec string
|
||||
Runtimes map[string]Runtime
|
||||
DefaultRuntime string
|
||||
Swarm swarm.Info
|
||||
diff --git a/components/engine/cmd/dockerd/config.go b/components/engine/cmd/dockerd/config.go
|
||||
index 2c8ed8edb4..6f62b97da8 100644
|
||||
--- a/components/engine/cmd/dockerd/config.go
|
||||
+++ b/components/engine/cmd/dockerd/config.go
|
||||
@@ -56,6 +56,7 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
||||
flags.StringVar(&conf.ClusterAdvertise, "cluster-advertise", "", "Address or interface name to advertise")
|
||||
flags.StringVar(&conf.ClusterStore, "cluster-store", "", "URL of the distributed storage backend")
|
||||
flags.Var(opts.NewNamedMapOpts("cluster-store-opts", conf.ClusterOpts, nil), "cluster-store-opt", "Set cluster store options")
|
||||
+ flags.StringVar(&conf.HookSpec, "hook-spec", "", "Default hook spec file applied to all containers")
|
||||
flags.StringVar(&conf.CorsHeaders, "api-cors-header", "", "Set CORS headers in the Engine API")
|
||||
flags.IntVar(&maxConcurrentDownloads, "max-concurrent-downloads", config.DefaultMaxConcurrentDownloads, "Set the max concurrent downloads for each pull")
|
||||
flags.IntVar(&maxConcurrentUploads, "max-concurrent-uploads", config.DefaultMaxConcurrentUploads, "Set the max concurrent uploads for each push")
|
||||
diff --git a/components/engine/daemon/config/config.go b/components/engine/daemon/config/config.go
|
||||
index 8b2c844a57..2141ce8c54 100644
|
||||
--- a/components/engine/daemon/config/config.go
|
||||
+++ b/components/engine/daemon/config/config.go
|
||||
@@ -124,6 +124,7 @@ type CommonConfig struct {
|
||||
ExecOptions []string `json:"exec-opts,omitempty"`
|
||||
GraphDriver string `json:"storage-driver,omitempty"`
|
||||
GraphOptions []string `json:"storage-opts,omitempty"`
|
||||
+ HookSpec string `json:"hook-spec,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
Mtu int `json:"mtu,omitempty"`
|
||||
NetworkDiagnosticPort int `json:"network-diagnostic-port,omitempty"`
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index 0864443513..8f9f6baf25 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -13,16 +13,19 @@ import (
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/docker/container"
|
||||
+ "github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/daemon/network"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/opts"
|
||||
+ "github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/signal"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/docker/pkg/truncindex"
|
||||
"github.com/docker/docker/runconfig"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
"github.com/docker/go-connections/nat"
|
||||
+ "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/opencontainers/selinux/go-selinux/label"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -226,7 +229,7 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||||
}
|
||||
|
||||
// register hooks to container
|
||||
- if err := daemon.registerHooks(container, hostConfig); err != nil {
|
||||
+ if err := daemon.registerHooks(container, hostConfig.HookSpec); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -235,41 +238,112 @@ func (daemon *Daemon) setHostConfig(container *container.Container, hostConfig *
|
||||
return container.CheckpointTo(daemon.containersReplica)
|
||||
}
|
||||
|
||||
+func (daemon *Daemon) sanitizeHookSpec(spec string) (string, error) {
|
||||
+ if spec != "" {
|
||||
+ spec = filepath.Clean(spec)
|
||||
+ if !filepath.IsAbs(spec) {
|
||||
+ return "", fmt.Errorf("hook spec file must be an absolute path")
|
||||
+ }
|
||||
+ fi, err := os.Stat(spec)
|
||||
+ if err != nil {
|
||||
+ return "", fmt.Errorf("stat hook spec file failed: %v", err)
|
||||
+ }
|
||||
+ if !fi.Mode().IsRegular() {
|
||||
+ return "", fmt.Errorf("hook spec file must be a regular text file")
|
||||
+ }
|
||||
+ }
|
||||
+ return spec, nil
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) initHooks(config *config.Config, rootIdentity idtools.Identity) error {
|
||||
+ // create hook store dir
|
||||
+ var err error
|
||||
+ hookDir := filepath.Join(config.Root, "hooks")
|
||||
+ if err = idtools.MkdirAllAndChown(hookDir, 0700, rootIdentity); err != nil && !os.IsExist(err) {
|
||||
+ return err
|
||||
+ }
|
||||
+ daemon.hookStore = hookDir
|
||||
+
|
||||
+ if config.HookSpec, err = daemon.sanitizeHookSpec(config.HookSpec); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ // setup default hooks
|
||||
+ if err := daemon.registerDaemonHooks(config.HookSpec); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
|
||||
-func (daemon *Daemon) registerHooks(container *container.Container, hostConfig *containertypes.HostConfig) error {
|
||||
- if hostConfig.HookSpec == "" {
|
||||
+func (daemon *Daemon) registerDaemonHooks(hookspec string) error {
|
||||
+ if hookspec == "" {
|
||||
return nil
|
||||
}
|
||||
+
|
||||
// the hook spec has already been sanitized, so no need for validation again
|
||||
- f, err := os.Open(hostConfig.HookSpec)
|
||||
+ f, err := os.Open(hookspec)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open hook spec file error: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
- if err = json.NewDecoder(f).Decode(&container.Hooks); err != nil {
|
||||
+ if err = json.NewDecoder(f).Decode(&daemon.Hooks); err != nil {
|
||||
return fmt.Errorf("malformed hook spec, is your spec file in json format? error: %v", err)
|
||||
}
|
||||
|
||||
// hook path must be absolute and must be subdir of XXX
|
||||
- if err = daemon.validateHook(container); err != nil {
|
||||
+ if err = daemon.validateHook(&daemon.Hooks); err != nil {
|
||||
return err
|
||||
}
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) registerHooks(container *container.Container, hookspec string) error {
|
||||
+ container.Hooks.Prestart = append(container.Hooks.Prestart, daemon.Hooks.Prestart...)
|
||||
+ container.Hooks.Poststart = append(container.Hooks.Poststart, daemon.Hooks.Poststart...)
|
||||
+ container.Hooks.Poststop = append(container.Hooks.Poststop, daemon.Hooks.Poststop...)
|
||||
+ if hookspec == "" {
|
||||
+ return nil
|
||||
+ }
|
||||
+
|
||||
+ // the hook spec has already been sanitized, so no need for validation again
|
||||
+ f, err := os.Open(hookspec)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("open hook spec file error: %v", err)
|
||||
+ }
|
||||
+ defer f.Close()
|
||||
+
|
||||
+ var hooks specs.Hooks
|
||||
+ if err = json.NewDecoder(f).Decode(&hooks); err != nil {
|
||||
+ return fmt.Errorf("malformed hook spec, is your spec file in json format? error: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ container.Hooks.Prestart = append(container.Hooks.Prestart, hooks.Prestart...)
|
||||
+ container.Hooks.Poststart = append(container.Hooks.Poststart, hooks.Poststart...)
|
||||
+ container.Hooks.Poststop = append(container.Hooks.Poststop, hooks.Poststop...)
|
||||
+
|
||||
+ // hook path must be absolute and must be subdir of XXX
|
||||
+ if err = daemon.validateHook(&container.Hooks); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
return nil
|
||||
}
|
||||
|
||||
-func (daemon *Daemon) validateHook(container *container.Container) error {
|
||||
- for _, v := range container.Hooks.Prestart {
|
||||
+func (daemon *Daemon) validateHook(hooks *specs.Hooks) error {
|
||||
+ for _, v := range hooks.Prestart {
|
||||
if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
- for _, v := range container.Hooks.Poststart {
|
||||
+ for _, v := range hooks.Poststart {
|
||||
if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
- for _, v := range container.Hooks.Poststop {
|
||||
+ for _, v := range hooks.Poststop {
|
||||
if err := daemon.validateHookPath(v.Path); err != nil {
|
||||
return err
|
||||
}
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index d1f3131c4f..f7635f27cc 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -67,6 +67,7 @@ import (
|
||||
"github.com/docker/libnetwork"
|
||||
"github.com/docker/libnetwork/cluster"
|
||||
nwconfig "github.com/docker/libnetwork/config"
|
||||
+ "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -109,6 +110,7 @@ type Daemon struct {
|
||||
containerdCli *containerd.Client
|
||||
containerd libcontainerd.Client
|
||||
defaultIsolation containertypes.Isolation // Default isolation mode on Windows
|
||||
+ Hooks specs.Hooks
|
||||
clusterProvider cluster.Provider
|
||||
cluster Cluster
|
||||
genericResources []swarm.GenericResource
|
||||
@@ -997,6 +999,11 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
|
||||
return nil, errors.New("Devices cgroup isn't mounted")
|
||||
}
|
||||
|
||||
+ // setup hooks environment
|
||||
+ if err := d.initHooks(config, rootIDs); err != nil {
|
||||
+ return nil, fmt.Errorf("Failed to register default hooks: %v", err)
|
||||
+ }
|
||||
+
|
||||
d.ID = trustKey.PublicKey().KeyID()
|
||||
d.repository = daemonRepo
|
||||
d.containers = container.NewMemoryStore()
|
||||
diff --git a/components/engine/daemon/info.go b/components/engine/daemon/info.go
|
||||
index 262719d9d1..523a396643 100644
|
||||
--- a/components/engine/daemon/info.go
|
||||
+++ b/components/engine/daemon/info.go
|
||||
@@ -67,6 +67,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
||||
HTTPSProxy: maskCredentials(sockets.GetProxyEnv("https_proxy")),
|
||||
NoProxy: sockets.GetProxyEnv("no_proxy"),
|
||||
LiveRestoreEnabled: daemon.configStore.LiveRestoreEnabled,
|
||||
+ HookSpec: daemon.configStore.HookSpec,
|
||||
Isolation: daemon.defaultIsolation,
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
72
patch/0015-hookspec-add-limit-of-hook-spec-file.patch
Normal file
72
patch/0015-hookspec-add-limit-of-hook-spec-file.patch
Normal file
@ -0,0 +1,72 @@
|
||||
From a6c5e3824b6b8d3a443e1a14136360cc73779296 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:17:06 +0800
|
||||
Subject: [PATCH 015/111] hookspec: add limit of hook spec file
|
||||
|
||||
reason: add limit of hook spec file, to prevent docker daemon OOM.
|
||||
|
||||
Change-Id: I11afebf163de3c401ed4f9b8f30c403f1d15de77
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/container.go | 8 ++++++++
|
||||
components/engine/daemon/daemon_unix.go | 15 ++-------------
|
||||
2 files changed, 10 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index 8f9f6baf25..a8cb950f44 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -30,6 +30,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
+const (
|
||||
+ // hook spec file size limit (in bytes)
|
||||
+ hookSpecSizeLimit = (10 * 1024 * 1024)
|
||||
+)
|
||||
+
|
||||
// GetContainer looks for a container using the provided information, which could be
|
||||
// one of the following inputs from the caller:
|
||||
// - A full container ID, which will exact match a container in daemon's list
|
||||
@@ -251,6 +256,9 @@ func (daemon *Daemon) sanitizeHookSpec(spec string) (string, error) {
|
||||
if !fi.Mode().IsRegular() {
|
||||
return "", fmt.Errorf("hook spec file must be a regular text file")
|
||||
}
|
||||
+ if fi.Size() > hookSpecSizeLimit {
|
||||
+ return "", fmt.Errorf("Hook spec file size must not exceed %d bytes", hookSpecSizeLimit)
|
||||
+ }
|
||||
}
|
||||
return spec, nil
|
||||
}
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index ebf4e067fb..5b390d2db1 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -628,21 +628,10 @@ func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes
|
||||
}
|
||||
}
|
||||
|
||||
- if hostConfig.HookSpec != "" {
|
||||
- hostConfig.HookSpec = filepath.Clean(hostConfig.HookSpec)
|
||||
- if !filepath.IsAbs(hostConfig.HookSpec) {
|
||||
- return warnings, fmt.Errorf("Hook spec file must be an absolute path")
|
||||
- }
|
||||
- fi, err := os.Stat(hostConfig.HookSpec)
|
||||
- if err != nil {
|
||||
- return warnings, fmt.Errorf("stat hook spec file failed: %v", err)
|
||||
- }
|
||||
- if !fi.Mode().IsRegular() {
|
||||
- return warnings, fmt.Errorf("Hook spec file must be a regular text file")
|
||||
- }
|
||||
+ if hostConfig.HookSpec, err = daemon.sanitizeHookSpec(hostConfig.HookSpec); err != nil {
|
||||
+ return warnings, err
|
||||
}
|
||||
|
||||
-
|
||||
if hostConfig.Runtime == "" {
|
||||
hostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
31
patch/0016-hookspec-fix-hooks-nil-pointer-dereference.patch
Normal file
31
patch/0016-hookspec-fix-hooks-nil-pointer-dereference.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From 8dd367f460008bbe1715117610b1eb48cb5b20bf Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:17:23 +0800
|
||||
Subject: [PATCH 016/111] hookspec: fix hooks nil pointer dereference
|
||||
|
||||
reason: merge containerd and runc into one version for docker-1.11.2 and
|
||||
docker-17.06
|
||||
|
||||
Change-Id: I1b0899cf18f2734bb205026b3094f1a3264a695e
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/oci/defaults.go | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/components/engine/oci/defaults.go b/components/engine/oci/defaults.go
|
||||
index 992157b0f5..5e17ea3f38 100644
|
||||
--- a/components/engine/oci/defaults.go
|
||||
+++ b/components/engine/oci/defaults.go
|
||||
@@ -66,6 +66,7 @@ func DefaultLinuxSpec() specs.Spec {
|
||||
},
|
||||
},
|
||||
Root: &specs.Root{},
|
||||
+ Hooks: &specs.Hooks{},
|
||||
}
|
||||
s.Mounts = []specs.Mount{
|
||||
{
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
From fe67259fd158b8193db31fad83f2dc3d3d3bc5c4 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:17:38 +0800
|
||||
Subject: [PATCH 017/111] hookspec: canonicalize hook path before
|
||||
validation
|
||||
|
||||
reason:hook programs must put under hook directory, but if we refer
|
||||
them with a symbolic link path in hookspecs, docker daemon refuse
|
||||
to run. so we just canonicalize path first before check.
|
||||
|
||||
Change-Id: I68d3757f26d7df05eb048e686368eca061cb06a9
|
||||
Signed-off-by: zhangyuyun <zhangyuyun@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/container.go | 13 +++++++++++--
|
||||
1 file changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index a8cb950f44..06a19bb4c8 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -366,8 +366,17 @@ func (daemon *Daemon) validateHookPath(path string) error {
|
||||
return fmt.Errorf("Hook path %q must be an absolute path", path)
|
||||
}
|
||||
|
||||
- if !filepath.HasPrefix(path, daemon.hookStore) {
|
||||
- return fmt.Errorf("hook program must be put under %q", daemon.hookStore)
|
||||
+ realPath, err := filepath.EvalSymlinks(path)
|
||||
+ if err != nil {
|
||||
+ if !strings.Contains(err.Error(), "no such file or directory") {
|
||||
+ return fmt.Errorf("failed to canonicalise path for %s: %s", path, err)
|
||||
+ }
|
||||
+ // for backward compatibility
|
||||
+ realPath = path
|
||||
+ }
|
||||
+
|
||||
+ if !filepath.HasPrefix(realPath, daemon.hookStore) {
|
||||
+ return fmt.Errorf("hook path %q isn't right, hook program must be put under %q", path, daemon.hookStore)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
362
patch/0018-dfx-trylock-add-trylock-and-trylocktimeout-fo.patch
Normal file
362
patch/0018-dfx-trylock-add-trylock-and-trylocktimeout-fo.patch
Normal file
@ -0,0 +1,362 @@
|
||||
From 6a9e68763da72ebc0b9a7e45cd08ce57fe11998f Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:21:56 +0800
|
||||
Subject: [PATCH 018/111] dfx/trylock: add trylock and trylocktimeout
|
||||
for docker inspect
|
||||
|
||||
reason:In order to avoid deadlocks, add trylock and trylocktimeout
|
||||
for docker inspect commmand. The -t/--time is a parameter of
|
||||
docker inspect command, set by user, and the default value
|
||||
is 120s.
|
||||
|
||||
Change-Id: Ie30ff28941624cc595e2a30d453d6f90b265d803
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../cli/cli/command/container/inspect.go | 4 +-
|
||||
components/cli/cli/command/system/inspect.go | 12 ++--
|
||||
.../github.com/docker/docker/client/Checklist | 1 +
|
||||
.../docker/docker/client/container_inspect.go | 4 +-
|
||||
.../docker/docker/client/interface.go | 2 +-
|
||||
.../api/server/router/container/backend.go | 2 +-
|
||||
.../api/server/router/container/inspect.go | 4 +-
|
||||
components/engine/container/state.go | 4 +-
|
||||
.../engine/daemon/cluster/executor/backend.go | 2 +-
|
||||
.../cluster/executor/container/adapter.go | 3 +-
|
||||
components/engine/daemon/inspect.go | 12 ++--
|
||||
components/engine/pkg/trylock/mutex.go | 61 +++++++++++++++++++
|
||||
12 files changed, 93 insertions(+), 18 deletions(-)
|
||||
create mode 100644 components/cli/vendor/github.com/docker/docker/client/Checklist
|
||||
create mode 100644 components/engine/pkg/trylock/mutex.go
|
||||
|
||||
diff --git a/components/cli/cli/command/container/inspect.go b/components/cli/cli/command/container/inspect.go
|
||||
index 4f50e2a080..b77994e896 100644
|
||||
--- a/components/cli/cli/command/container/inspect.go
|
||||
+++ b/components/cli/cli/command/container/inspect.go
|
||||
@@ -13,6 +13,7 @@ type inspectOptions struct {
|
||||
format string
|
||||
size bool
|
||||
refs []string
|
||||
+ time int
|
||||
}
|
||||
|
||||
// newInspectCommand creates a new cobra.Command for `docker container inspect`
|
||||
@@ -32,6 +33,7 @@ func newInspectCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags := cmd.Flags()
|
||||
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
|
||||
flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes")
|
||||
+ flags.IntVarP(&opts.time, "time", "t", 120, "Seconds to wait for inspect timeout")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -41,7 +43,7 @@ func runInspect(dockerCli command.Cli, opts inspectOptions) error {
|
||||
ctx := context.Background()
|
||||
|
||||
getRefFunc := func(ref string) (interface{}, []byte, error) {
|
||||
- return client.ContainerInspectWithRaw(ctx, ref, opts.size)
|
||||
+ return client.ContainerInspectWithRaw(ctx, ref, opts.size, opts.time)
|
||||
}
|
||||
return inspect.Inspect(dockerCli.Out(), opts.refs, opts.format, getRefFunc)
|
||||
}
|
||||
diff --git a/components/cli/cli/command/system/inspect.go b/components/cli/cli/command/system/inspect.go
|
||||
index b49b4b33d3..248f9caad2 100644
|
||||
--- a/components/cli/cli/command/system/inspect.go
|
||||
+++ b/components/cli/cli/command/system/inspect.go
|
||||
@@ -19,6 +19,7 @@ type inspectOptions struct {
|
||||
inspectType string
|
||||
size bool
|
||||
ids []string
|
||||
+ time int
|
||||
}
|
||||
|
||||
// NewInspectCommand creates a new cobra.Command for `docker inspect`
|
||||
@@ -39,6 +40,7 @@ func NewInspectCommand(dockerCli command.Cli) *cobra.Command {
|
||||
flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
|
||||
flags.StringVar(&opts.inspectType, "type", "", "Return JSON for specified type")
|
||||
flags.BoolVarP(&opts.size, "size", "s", false, "Display total file sizes if the type is container")
|
||||
+ flags.IntVarP(&opts.time, "time", "t", 120, "Seconds to wait for inspect timeout")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -47,16 +49,16 @@ func runInspect(dockerCli command.Cli, opts inspectOptions) error {
|
||||
var elementSearcher inspect.GetRefFunc
|
||||
switch opts.inspectType {
|
||||
case "", "container", "image", "node", "network", "service", "volume", "task", "plugin", "secret":
|
||||
- elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType)
|
||||
+ elementSearcher = inspectAll(context.Background(), dockerCli, opts.size, opts.inspectType, opts.time)
|
||||
default:
|
||||
return errors.Errorf("%q is not a valid value for --type", opts.inspectType)
|
||||
}
|
||||
return inspect.Inspect(dockerCli.Out(), opts.ids, opts.format, elementSearcher)
|
||||
}
|
||||
|
||||
-func inspectContainers(ctx context.Context, dockerCli command.Cli, getSize bool) inspect.GetRefFunc {
|
||||
+func inspectContainers(ctx context.Context, dockerCli command.Cli, getSize bool, timeout int) inspect.GetRefFunc {
|
||||
return func(ref string) (interface{}, []byte, error) {
|
||||
- return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize)
|
||||
+ return dockerCli.Client().ContainerInspectWithRaw(ctx, ref, getSize, timeout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +111,7 @@ func inspectSecret(ctx context.Context, dockerCli command.Cli) inspect.GetRefFun
|
||||
}
|
||||
}
|
||||
|
||||
-func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeConstraint string) inspect.GetRefFunc {
|
||||
+func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeConstraint string, timeout int) inspect.GetRefFunc {
|
||||
var inspectAutodetect = []struct {
|
||||
objectType string
|
||||
isSizeSupported bool
|
||||
@@ -119,7 +121,7 @@ func inspectAll(ctx context.Context, dockerCli command.Cli, getSize bool, typeCo
|
||||
{
|
||||
objectType: "container",
|
||||
isSizeSupported: true,
|
||||
- objectInspector: inspectContainers(ctx, dockerCli, getSize),
|
||||
+ objectInspector: inspectContainers(ctx, dockerCli, getSize, timeout),
|
||||
},
|
||||
{
|
||||
objectType: "image",
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/client/Checklist b/components/cli/vendor/github.com/docker/docker/client/Checklist
|
||||
new file mode 100644
|
||||
index 0000000000..9b1682dc41
|
||||
--- /dev/null
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/client/Checklist
|
||||
@@ -0,0 +1 @@
|
||||
+Add trylcok and trylocktimeout for docker inspect commmand.
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/client/container_inspect.go b/components/cli/vendor/github.com/docker/docker/client/container_inspect.go
|
||||
index f453064cf8..b8573fd40b 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/client/container_inspect.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/client/container_inspect.go
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/url"
|
||||
+ "strconv"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
)
|
||||
@@ -27,7 +28,7 @@ func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (ty
|
||||
}
|
||||
|
||||
// ContainerInspectWithRaw returns the container information and its raw representation.
|
||||
-func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) {
|
||||
+func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool, timeout int) (types.ContainerJSON, []byte, error) {
|
||||
if containerID == "" {
|
||||
return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID}
|
||||
}
|
||||
@@ -35,6 +36,7 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri
|
||||
if getSize {
|
||||
query.Set("size", "1")
|
||||
}
|
||||
+ query.Set("t", strconv.Itoa(timeout))
|
||||
serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil)
|
||||
if err != nil {
|
||||
return types.ContainerJSON{}, nil, wrapResponseError(err, serverResp, "container", containerID)
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/client/interface.go b/components/cli/vendor/github.com/docker/docker/client/interface.go
|
||||
index d190f8e58d..b2d5d7bb72 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/client/interface.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/client/interface.go
|
||||
@@ -56,7 +56,7 @@ type ContainerAPIClient interface {
|
||||
ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
|
||||
ContainerExport(ctx context.Context, container string) (io.ReadCloser, error)
|
||||
ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error)
|
||||
- ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error)
|
||||
+ ContainerInspectWithRaw(ctx context.Context, container string, getSize bool, timeout int) (types.ContainerJSON, []byte, error)
|
||||
ContainerKill(ctx context.Context, container, signal string) error
|
||||
ContainerList(ctx context.Context, options types.ContainerListOptions) ([]types.Container, error)
|
||||
ContainerLogs(ctx context.Context, container string, options types.ContainerLogsOptions) (io.ReadCloser, error)
|
||||
diff --git a/components/engine/api/server/router/container/backend.go b/components/engine/api/server/router/container/backend.go
|
||||
index 75ea1d82b7..88fbe71a88 100644
|
||||
--- a/components/engine/api/server/router/container/backend.go
|
||||
+++ b/components/engine/api/server/router/container/backend.go
|
||||
@@ -49,7 +49,7 @@ type stateBackend interface {
|
||||
// monitorBackend includes functions to implement to provide containers monitoring functionality.
|
||||
type monitorBackend interface {
|
||||
ContainerChanges(name string) ([]archive.Change, error)
|
||||
- ContainerInspect(name string, size bool, version string) (interface{}, error)
|
||||
+ ContainerInspect(name string, size bool, version string, timeout int) (interface{}, error)
|
||||
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
|
||||
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
|
||||
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)
|
||||
diff --git a/components/engine/api/server/router/container/inspect.go b/components/engine/api/server/router/container/inspect.go
|
||||
index 5c78d15bc9..cb6eb50251 100644
|
||||
--- a/components/engine/api/server/router/container/inspect.go
|
||||
+++ b/components/engine/api/server/router/container/inspect.go
|
||||
@@ -3,6 +3,7 @@ package container // import "github.com/docker/docker/api/server/router/containe
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
+ "strconv"
|
||||
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
)
|
||||
@@ -12,7 +13,8 @@ func (s *containerRouter) getContainersByName(ctx context.Context, w http.Respon
|
||||
displaySize := httputils.BoolValue(r, "size")
|
||||
|
||||
version := httputils.VersionFromContext(ctx)
|
||||
- json, err := s.backend.ContainerInspect(vars["name"], displaySize, version)
|
||||
+ timeout, _ := strconv.Atoi(r.Form.Get("t"))
|
||||
+ json, err := s.backend.ContainerInspect(vars["name"], displaySize, version, timeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diff --git a/components/engine/container/state.go b/components/engine/container/state.go
|
||||
index 7c2a1ec81c..91ea30a76e 100644
|
||||
--- a/components/engine/container/state.go
|
||||
+++ b/components/engine/container/state.go
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
- "sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
+ "github.com/docker/docker/pkg/trylock"
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
// set the state. Container has an embed, which allows all of the
|
||||
// functions defined against State to run against Container.
|
||||
type State struct {
|
||||
- sync.Mutex
|
||||
+ trylock.TryMutex
|
||||
// Note that `Running` and `Paused` are not mutually exclusive:
|
||||
// When pausing a container (on Linux), the cgroups freezer is used to suspend
|
||||
// all processes in the container. Freezing the process requires the process to
|
||||
diff --git a/components/engine/daemon/cluster/executor/backend.go b/components/engine/daemon/cluster/executor/backend.go
|
||||
index cfbc86ce36..c9ff4503bc 100644
|
||||
--- a/components/engine/daemon/cluster/executor/backend.go
|
||||
+++ b/components/engine/daemon/cluster/executor/backend.go
|
||||
@@ -41,7 +41,7 @@ type Backend interface {
|
||||
ActivateContainerServiceBinding(containerName string) error
|
||||
DeactivateContainerServiceBinding(containerName string) error
|
||||
UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
|
||||
- ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error)
|
||||
+ ContainerInspectCurrent(name string, size bool, timeout int) (*types.ContainerJSON, error)
|
||||
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
|
||||
ContainerRm(name string, config *types.ContainerRmConfig) error
|
||||
ContainerKill(name string, sig uint64) error
|
||||
diff --git a/components/engine/daemon/cluster/executor/container/adapter.go b/components/engine/daemon/cluster/executor/container/adapter.go
|
||||
index 720b8447fc..3743cb6418 100644
|
||||
--- a/components/engine/daemon/cluster/executor/container/adapter.go
|
||||
+++ b/components/engine/daemon/cluster/executor/container/adapter.go
|
||||
@@ -351,7 +351,8 @@ func (c *containerAdapter) start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
|
||||
- cs, err := c.backend.ContainerInspectCurrent(c.container.name(), false)
|
||||
+ timeout := -1
|
||||
+ cs, err := c.backend.ContainerInspectCurrent(c.container.name(), false, timeout)
|
||||
if ctx.Err() != nil {
|
||||
return types.ContainerJSON{}, ctx.Err()
|
||||
}
|
||||
diff --git a/components/engine/daemon/inspect.go b/components/engine/daemon/inspect.go
|
||||
index 45a2154254..be8f6eff71 100644
|
||||
--- a/components/engine/daemon/inspect.go
|
||||
+++ b/components/engine/daemon/inspect.go
|
||||
@@ -19,25 +19,29 @@ import (
|
||||
// ContainerInspect returns low-level information about a
|
||||
// container. Returns an error if the container cannot be found, or if
|
||||
// there is an error getting the data.
|
||||
-func (daemon *Daemon) ContainerInspect(name string, size bool, version string) (interface{}, error) {
|
||||
+func (daemon *Daemon) ContainerInspect(name string, size bool, version string, timeout int) (interface{}, error) {
|
||||
switch {
|
||||
case versions.LessThan(version, "1.20"):
|
||||
return daemon.containerInspectPre120(name)
|
||||
case versions.Equal(version, "1.20"):
|
||||
return daemon.containerInspect120(name)
|
||||
}
|
||||
- return daemon.ContainerInspectCurrent(name, size)
|
||||
+ return daemon.ContainerInspectCurrent(name, size, timeout)
|
||||
}
|
||||
|
||||
// ContainerInspectCurrent returns low-level information about a
|
||||
// container in a most recent api version.
|
||||
-func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error) {
|
||||
+func (daemon *Daemon) ContainerInspectCurrent(name string, size bool, timeout int) (*types.ContainerJSON, error) {
|
||||
container, err := daemon.GetContainer(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
- container.Lock()
|
||||
+ // The unit of timeout is seconds, and the unit of frequency is milliseconds.
|
||||
+ lockTimeoutSuccess := container.TryLockTimeout(timeout, 100)
|
||||
+ if lockTimeoutSuccess == false {
|
||||
+ return nil, fmt.Errorf("Container %s inspect failed due to trylock timeout for %ds.", name, timeout)
|
||||
+ }
|
||||
|
||||
base, err := daemon.getInspectData(container)
|
||||
if err != nil {
|
||||
diff --git a/components/engine/pkg/trylock/mutex.go b/components/engine/pkg/trylock/mutex.go
|
||||
new file mode 100644
|
||||
index 0000000000..18b3c3cca7
|
||||
--- /dev/null
|
||||
+++ b/components/engine/pkg/trylock/mutex.go
|
||||
@@ -0,0 +1,61 @@
|
||||
+package trylock
|
||||
+
|
||||
+import (
|
||||
+ "sync"
|
||||
+ "sync/atomic"
|
||||
+ "time"
|
||||
+ "unsafe"
|
||||
+)
|
||||
+
|
||||
+const mutexLocked = 1 << iota
|
||||
+
|
||||
+// Mutex is simple sync.Mutex + ability to try to Lock.
|
||||
+type TryMutex struct {
|
||||
+ in sync.Mutex
|
||||
+}
|
||||
+
|
||||
+// Lock locks m.
|
||||
+// If the lock is already in use, the calling goroutine
|
||||
+// blocks until the mutex is available.
|
||||
+func (m *TryMutex) Lock() {
|
||||
+ m.in.Lock()
|
||||
+}
|
||||
+
|
||||
+// Unlock unlocks m.
|
||||
+// It is a run-time error if m is not locked on entry to Unlock.
|
||||
+//
|
||||
+// A locked Mutex is not associated with a particular goroutine.
|
||||
+// It is allowed for one goroutine to lock a Mutex and then
|
||||
+// arrange for another goroutine to unlock it.
|
||||
+func (m *TryMutex) Unlock() {
|
||||
+ m.in.Unlock()
|
||||
+}
|
||||
+
|
||||
+// TryLock tries to lock m. It returns true in case of success, false otherwise.
|
||||
+func (m *TryMutex) TryLock() bool {
|
||||
+ return atomic.CompareAndSwapInt32((*int32)(unsafe.Pointer(&m.in)), 0, mutexLocked)
|
||||
+}
|
||||
+
|
||||
+// TryLockTimeout tries to lock m at a certain frequency for a certain period of time.
|
||||
+// It returns true in case of success, false otherwise.
|
||||
+func (m *TryMutex) TryLockTimeout(timeout int, frequency int) bool {
|
||||
+ if timeout <= 0 {
|
||||
+ m.Lock()
|
||||
+ return true
|
||||
+ } else {
|
||||
+ timer := time.After(time.Second * time.Duration(timeout))
|
||||
+ result := false
|
||||
+ for {
|
||||
+ select {
|
||||
+ case <-timer:
|
||||
+ return result
|
||||
+ default:
|
||||
+ }
|
||||
+ result = atomic.CompareAndSwapInt32((*int32)(unsafe.Pointer(&m.in)), 0, mutexLocked)
|
||||
+ if result {
|
||||
+ return result
|
||||
+ }
|
||||
+ time.Sleep(time.Millisecond * time.Duration(frequency))
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 9e05ad46f060ab47559cd1566a95ec579fbc08ac Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:18:35 +0800
|
||||
Subject: [PATCH 019/111] dfx: print container name and id when create
|
||||
done
|
||||
|
||||
reason:print container name and id when create done
|
||||
|
||||
Change-Id: I62932133c2a28e24adb54a40d16e2792a0772185
|
||||
Signed-off-by: dengguangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/create.go | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/components/engine/daemon/create.go b/components/engine/daemon/create.go
|
||||
index 1afb1bebea..565e9dc022 100644
|
||||
--- a/components/engine/daemon/create.go
|
||||
+++ b/components/engine/daemon/create.go
|
||||
@@ -74,6 +74,7 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage
|
||||
return containertypes.ContainerCreateCreatedBody{Warnings: warnings}, err
|
||||
}
|
||||
containerActions.WithValues("create").UpdateSince(start)
|
||||
+ logrus.Infof("Container create done(Name: %s ID: %s)", container.Name, container.ID)
|
||||
|
||||
return containertypes.ContainerCreateCreatedBody{ID: container.ID, Warnings: warnings}, nil
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
441
patch/0020-cleanup-remove-redundant-files-in-graphdriver.patch
Normal file
441
patch/0020-cleanup-remove-redundant-files-in-graphdriver.patch
Normal file
@ -0,0 +1,441 @@
|
||||
From b555ed1bb121b0740665fb0db9f7fea3b339f98c Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:22:22 +0800
|
||||
Subject: [PATCH 020/111] cleanup: remove redundant files in
|
||||
graphdriver and mount dir
|
||||
|
||||
reason:remove redundant files in graphdriver and mount dir
|
||||
|
||||
Change-Id: Ie75b78ac1e288d2c909dcd446636d16b1dd60363
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon.go | 28 ++++++-
|
||||
.../engine/daemon/graphdriver/aufs/aufs.go | 5 ++
|
||||
.../engine/daemon/graphdriver/btrfs/btrfs.go | 5 ++
|
||||
.../daemon/graphdriver/devmapper/driver.go | 5 ++
|
||||
.../engine/daemon/graphdriver/driver.go | 2 +
|
||||
.../daemon/graphdriver/overlay/overlay.go | 5 ++
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 19 +++++
|
||||
components/engine/daemon/graphdriver/proxy.go | 5 ++
|
||||
.../engine/daemon/graphdriver/vfs/driver.go | 5 ++
|
||||
.../engine/daemon/graphdriver/zfs/zfs.go | 5 ++
|
||||
components/engine/daemon/images/service.go | 4 +
|
||||
.../engine/distribution/xfer/download_test.go | 4 +
|
||||
components/engine/layer/layer.go | 1 +
|
||||
components/engine/layer/layer_store.go | 73 +++++++++++++++++++
|
||||
components/engine/pkg/ioutils/fswriters.go | 36 +++++++++
|
||||
components/engine/reference/store.go | 1 +
|
||||
16 files changed, 201 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index f7635f27cc..4546587369 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -262,7 +262,15 @@ func (daemon *Daemon) restore() error {
|
||||
id := v.Name()
|
||||
container, err := daemon.load(id)
|
||||
if err != nil {
|
||||
- logrus.Errorf("Failed to load container %v: %v", id, err)
|
||||
+ logrus.Errorf("Failed to load container %v: %v. Try to remove it", id, err)
|
||||
+ cdir := filepath.Join(daemon.repository, id)
|
||||
+ // to make sure we are not in fd exhausted state
|
||||
+ if !strings.Contains(err.Error(), "too many open files") {
|
||||
+ logrus.Warnf("remove invalid container data: %s", cdir)
|
||||
+ if err := system.EnsureRemoveAll(cdir); err != nil {
|
||||
+ logrus.Warnf("remove %s error: %v", cdir, err)
|
||||
+ }
|
||||
+ }
|
||||
continue
|
||||
}
|
||||
if !system.IsOSSupported(container.OS) {
|
||||
@@ -274,7 +282,12 @@ func (daemon *Daemon) restore() error {
|
||||
if (container.Driver == "" && currentDriverForContainerOS == "aufs") || container.Driver == currentDriverForContainerOS {
|
||||
rwlayer, err := daemon.imageService.GetLayerByID(container.ID, container.OS)
|
||||
if err != nil {
|
||||
- logrus.Errorf("Failed to load container mount %v: %v", id, err)
|
||||
+ logrus.Errorf("Failed to load container mount %v: %v. Try to remove it", id, err)
|
||||
+ cdir := filepath.Join(daemon.repository, id)
|
||||
+ logrus.Warnf("remove invalid container data: %s", cdir)
|
||||
+ if err := system.EnsureRemoveAll(cdir); err != nil {
|
||||
+ logrus.Warnf("remove %s error: %v", cdir, err)
|
||||
+ }
|
||||
continue
|
||||
}
|
||||
container.RWLayer = rwlayer
|
||||
@@ -472,6 +485,17 @@ func (daemon *Daemon) restore() error {
|
||||
}(c)
|
||||
}
|
||||
wg.Wait()
|
||||
+
|
||||
+ containerIDs := make(map[string]struct{})
|
||||
+ for cid, _ := range containers {
|
||||
+ containerIDs[cid] = struct{}{}
|
||||
+ }
|
||||
+
|
||||
+ err = daemon.imageService.LayerStoreForOS(runtime.GOOS).CleanupRedundant(containerIDs)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("cleanup redundant IDs in layerStore failed %s", err)
|
||||
+ }
|
||||
+
|
||||
daemon.netController, err = daemon.initNetworkController(daemon.configStore, activeSandboxes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error initializing network controller: %v", err)
|
||||
diff --git a/components/engine/daemon/graphdriver/aufs/aufs.go b/components/engine/daemon/graphdriver/aufs/aufs.go
|
||||
index 114aa9a615..303138d48a 100644
|
||||
--- a/components/engine/daemon/graphdriver/aufs/aufs.go
|
||||
+++ b/components/engine/daemon/graphdriver/aufs/aufs.go
|
||||
@@ -230,6 +230,11 @@ func (a *Driver) Exists(id string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
// CreateReadWrite creates a layer that is writable for use as a container
|
||||
// file system.
|
||||
func (a *Driver) CreateReadWrite(id, parent string, opts *graphdriver.CreateOpts) error {
|
||||
diff --git a/components/engine/daemon/graphdriver/btrfs/btrfs.go b/components/engine/daemon/graphdriver/btrfs/btrfs.go
|
||||
index 7ce7edef36..d04ce10be9 100644
|
||||
--- a/components/engine/daemon/graphdriver/btrfs/btrfs.go
|
||||
+++ b/components/engine/daemon/graphdriver/btrfs/btrfs.go
|
||||
@@ -167,6 +167,11 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
// Cleanup unmounts the home directory.
|
||||
func (d *Driver) Cleanup() error {
|
||||
err := d.subvolDisableQuota()
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/driver.go b/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
index 623843f852..a56b26bc8f 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/driver.go
|
||||
@@ -126,6 +126,11 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
// Cleanup unmounts a device.
|
||||
func (d *Driver) Cleanup() error {
|
||||
err := d.DeviceSet.Shutdown(d.home)
|
||||
diff --git a/components/engine/daemon/graphdriver/driver.go b/components/engine/daemon/graphdriver/driver.go
|
||||
index a9e1957393..672257a9b5 100644
|
||||
--- a/components/engine/daemon/graphdriver/driver.go
|
||||
+++ b/components/engine/daemon/graphdriver/driver.go
|
||||
@@ -78,6 +78,8 @@ type ProtoDriver interface {
|
||||
// held by the driver, e.g., unmounting all layered filesystems
|
||||
// known to this driver.
|
||||
Cleanup() error
|
||||
+ // GetAll returns all the mountid exists in this driver
|
||||
+ GetAll() []string
|
||||
}
|
||||
|
||||
// DiffDriver is the interface to use to implement graph diffs
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay/overlay.go b/components/engine/daemon/graphdriver/overlay/overlay.go
|
||||
index 08c05e192f..d59a6dfc83 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay/overlay.go
|
||||
@@ -264,6 +264,11 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
// Cleanup any state created by overlay which should be cleaned when daemon
|
||||
// is being shutdown. For now, we just have to unmount the bind mounted
|
||||
// we had created.
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index b969582eb3..7290616bae 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -507,6 +507,25 @@ func (d *Driver) dir(id string) string {
|
||||
return path.Join(d.home, id)
|
||||
}
|
||||
|
||||
+func (d *Driver) GetAll() []string {
|
||||
+ var ids []string
|
||||
+
|
||||
+ fs, err := ioutil.ReadDir(d.home)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("open directory(%s) failed: %s", d.home, err)
|
||||
+ return ids
|
||||
+ }
|
||||
+
|
||||
+ for _, f := range fs {
|
||||
+ if len(f.Name()) >= 64 {
|
||||
+ ids = append(ids, f.Name())
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return ids
|
||||
+
|
||||
+}
|
||||
+
|
||||
func (d *Driver) getLowerDirs(id string) ([]string, error) {
|
||||
var lowersArray []string
|
||||
lowers, err := ioutil.ReadFile(path.Join(d.dir(id), lowerFile))
|
||||
diff --git a/components/engine/daemon/graphdriver/proxy.go b/components/engine/daemon/graphdriver/proxy.go
|
||||
index cb350d8074..6c132d40a8 100644
|
||||
--- a/components/engine/daemon/graphdriver/proxy.go
|
||||
+++ b/components/engine/daemon/graphdriver/proxy.go
|
||||
@@ -91,6 +91,11 @@ func (d *graphDriverProxy) Capabilities() Capabilities {
|
||||
return d.caps
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (d *graphDriverProxy) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
func (d *graphDriverProxy) CreateReadWrite(id, parent string, opts *CreateOpts) error {
|
||||
return d.create("GraphDriver.CreateReadWrite", id, parent, opts)
|
||||
}
|
||||
diff --git a/components/engine/daemon/graphdriver/vfs/driver.go b/components/engine/daemon/graphdriver/vfs/driver.go
|
||||
index 33e6bf6cc9..8c2947d9ee 100644
|
||||
--- a/components/engine/daemon/graphdriver/vfs/driver.go
|
||||
+++ b/components/engine/daemon/graphdriver/vfs/driver.go
|
||||
@@ -64,6 +64,11 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
// Cleanup is used to implement graphdriver.ProtoDriver. There is no cleanup required for this driver.
|
||||
func (d *Driver) Cleanup() error {
|
||||
return nil
|
||||
diff --git a/components/engine/daemon/graphdriver/zfs/zfs.go b/components/engine/daemon/graphdriver/zfs/zfs.go
|
||||
index 8a798778d2..e1e2d0d823 100644
|
||||
--- a/components/engine/daemon/graphdriver/zfs/zfs.go
|
||||
+++ b/components/engine/daemon/graphdriver/zfs/zfs.go
|
||||
@@ -227,6 +227,11 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
+// GetAll not implemented
|
||||
+func (a *Driver) GetAll() []string {
|
||||
+ return []string{}
|
||||
+}
|
||||
+
|
||||
func (d *Driver) cloneFilesystem(name, parentName string) error {
|
||||
snapshotName := fmt.Sprintf("%d", time.Now().Nanosecond())
|
||||
parentDataset := zfs.Dataset{Name: parentName}
|
||||
diff --git a/components/engine/daemon/images/service.go b/components/engine/daemon/images/service.go
|
||||
index e8df5cb649..8d187e2603 100644
|
||||
--- a/components/engine/daemon/images/service.go
|
||||
+++ b/components/engine/daemon/images/service.go
|
||||
@@ -177,6 +177,10 @@ func (i *ImageService) GraphDriverForOS(os string) string {
|
||||
return i.layerStores[os].DriverName()
|
||||
}
|
||||
|
||||
+func (i *ImageService) LayerStoreForOS(os string) layer.Store {
|
||||
+ return i.layerStores[os]
|
||||
+}
|
||||
+
|
||||
// ReleaseLayer releases a layer allowing it to be removed
|
||||
// called from delete.go Daemon.cleanupContainer(), and Daemon.containerExport()
|
||||
func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer, containerOS string) error {
|
||||
diff --git a/components/engine/distribution/xfer/download_test.go b/components/engine/distribution/xfer/download_test.go
|
||||
index 4ab3705af6..91153591ed 100644
|
||||
--- a/components/engine/distribution/xfer/download_test.go
|
||||
+++ b/components/engine/distribution/xfer/download_test.go
|
||||
@@ -150,6 +150,10 @@ func (ls *mockLayerStore) DriverStatus() [][2]string {
|
||||
return [][2]string{}
|
||||
}
|
||||
|
||||
+func (ls *mockLayerStore) CleanupRedundant(cids map[string]struct{}) error {
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
func (ls *mockLayerStore) DriverName() string {
|
||||
return "mock"
|
||||
}
|
||||
diff --git a/components/engine/layer/layer.go b/components/engine/layer/layer.go
|
||||
index d0c7fa8608..425006854d 100644
|
||||
--- a/components/engine/layer/layer.go
|
||||
+++ b/components/engine/layer/layer.go
|
||||
@@ -193,6 +193,7 @@ type Store interface {
|
||||
Cleanup() error
|
||||
DriverStatus() [][2]string
|
||||
DriverName() string
|
||||
+ CleanupRedundant(map[string]struct{}) error
|
||||
}
|
||||
|
||||
// DescribableStore represents a layer store capable of storing
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index bc3e8719fc..6a568e9d9b 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
+ "strings"
|
||||
"sync"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
@@ -460,6 +461,78 @@ func (ls *layerStore) releaseLayer(l *roLayer) ([]Metadata, error) {
|
||||
}
|
||||
}
|
||||
|
||||
+// CleanupRedundant will cleanup useless dirs in image/mount and driver
|
||||
+func (ls *layerStore) CleanupRedundant(cs map[string]struct{}) error {
|
||||
+ cids, err := ls.getAndCleanCacheIDs(cs)
|
||||
+ if err != nil {
|
||||
+ return fmt.Errorf("get cacheIDs failed: %s", err)
|
||||
+ }
|
||||
+
|
||||
+ ids := ls.driver.GetAll()
|
||||
+
|
||||
+ for _, id := range ids {
|
||||
+ if _, ok := cids[id]; !ok {
|
||||
+ logrus.Warnf("remove redundant cacheID: %s", id)
|
||||
+ ls.driver.Remove(id)
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func (ls *layerStore) getAndCleanCacheIDs(cs map[string]struct{}) (map[string]struct{}, error) {
|
||||
+ cids := make(map[string]struct{})
|
||||
+
|
||||
+ ids, mountids, err := ls.store.List()
|
||||
+ if err != nil {
|
||||
+ return cids, fmt.Errorf("failed to get mount list from store: %s", err)
|
||||
+ }
|
||||
+
|
||||
+ for _, id := range ids {
|
||||
+ cid, err := ls.store.GetCacheID(id)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("failed to get cache id for %s: %s", id, err)
|
||||
+ // just return if we are not in fd exhausted state
|
||||
+ if strings.Contains(err.Error(), "too many open files") {
|
||||
+ return cids, err
|
||||
+ }
|
||||
+ continue
|
||||
+ }
|
||||
+ cids[cid] = struct{}{}
|
||||
+ }
|
||||
+
|
||||
+ for _, mid := range mountids {
|
||||
+ // if mid not exist in current container list, just remove it
|
||||
+ if _, ok := cs[mid]; !ok {
|
||||
+ logrus.Warnf("remove redundant mountID: %s", mid)
|
||||
+ ls.store.RemoveMount(mid)
|
||||
+ continue
|
||||
+ }
|
||||
+ mountID, err := ls.store.GetMountID(mid)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("failed to get mount id for %s: %s", mid, err)
|
||||
+ // just return if we are not in fd exhausted state
|
||||
+ if strings.Contains(err.Error(), "too many open files") {
|
||||
+ return cids, err
|
||||
+ }
|
||||
+ } else {
|
||||
+ cids[mountID] = struct{}{}
|
||||
+ }
|
||||
+
|
||||
+ initID, err := ls.store.GetInitID(mid)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("failed to get init id for %s: %s", mid, err)
|
||||
+ // just return if we are not in fd exhausted state
|
||||
+ if strings.Contains(err.Error(), "too many open files") {
|
||||
+ return cids, err
|
||||
+ }
|
||||
+ continue
|
||||
+ }
|
||||
+ cids[initID] = struct{}{}
|
||||
+ }
|
||||
+
|
||||
+ return cids, nil
|
||||
+}
|
||||
+
|
||||
func (ls *layerStore) Release(l Layer) ([]Metadata, error) {
|
||||
ls.layerL.Lock()
|
||||
defer ls.layerL.Unlock()
|
||||
diff --git a/components/engine/pkg/ioutils/fswriters.go b/components/engine/pkg/ioutils/fswriters.go
|
||||
index 534d66ac26..093f11ad8e 100644
|
||||
--- a/components/engine/pkg/ioutils/fswriters.go
|
||||
+++ b/components/engine/pkg/ioutils/fswriters.go
|
||||
@@ -5,6 +5,9 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
+ "strings"
|
||||
+
|
||||
+ "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a
|
||||
@@ -27,6 +30,39 @@ func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
+func CleanupTmpFilesRecursive(rootDir string) {
|
||||
+ var removals []string
|
||||
+ filepath.Walk(rootDir, func(path string, f os.FileInfo, err error) error {
|
||||
+ if strings.HasPrefix(f.Name(), ".tmp-") {
|
||||
+ removals = append(removals, path)
|
||||
+ }
|
||||
+ return nil
|
||||
+ })
|
||||
+
|
||||
+ for _, r := range removals {
|
||||
+ os.RemoveAll(r)
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// CleanupAtomicFile cleanup redundant atomic files
|
||||
+func CleanupAtomicFile(filename string) error {
|
||||
+ baseName := ".tmp-" + filepath.Base(filename)
|
||||
+ dir := filepath.Dir(filename)
|
||||
+ fs, err := ioutil.ReadDir(dir)
|
||||
+ if err != nil {
|
||||
+ logrus.Errorf("open directory(%s) failed: %s", dir, err)
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ for _, f := range fs {
|
||||
+ if strings.Contains(f.Name(), baseName) {
|
||||
+ logrus.Warnf("Remove temporary file: %s", filepath.Join(dir, f.Name()))
|
||||
+ os.RemoveAll(filepath.Join(dir, f.Name()))
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
// AtomicWriteFile atomically writes data to a file named by filename.
|
||||
func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error {
|
||||
f, err := NewAtomicFileWriter(filename, perm)
|
||||
diff --git a/components/engine/reference/store.go b/components/engine/reference/store.go
|
||||
index b01051bf58..e54f772b5e 100644
|
||||
--- a/components/engine/reference/store.go
|
||||
+++ b/components/engine/reference/store.go
|
||||
@@ -81,6 +81,7 @@ func NewReferenceStore(jsonPath string) (Store, error) {
|
||||
Repositories: make(map[string]repository),
|
||||
referencesByIDCache: make(map[digest.Digest]map[string]reference.Named),
|
||||
}
|
||||
+ ioutils.CleanupAtomicFile(abspath)
|
||||
// Load the json file if it exists, otherwise create it.
|
||||
if err := store.reload(); os.IsNotExist(err) {
|
||||
if err := store.save(); err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
125
patch/0021-umask-support-specify-umask.patch
Normal file
125
patch/0021-umask-support-specify-umask.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From 79b46d05b185bf8df96cabb2a121186cd2f121c3 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:22:35 +0800
|
||||
Subject: [PATCH 021/111] umask: support specify umask
|
||||
|
||||
reason: support specify umask.
|
||||
Umask can be 0022 or 0027(default) by specify umask when
|
||||
start container by command `docker create/run` or start
|
||||
daemon by command `dockerd`. For example:
|
||||
$ dockerd --annotation native.umask=normal
|
||||
$ dockerd --annotation native.umask=secure
|
||||
$ docker run --exec-opt native.umask=normal
|
||||
$ docker run --exec-opt native.umask=secure
|
||||
`normal` reparent umask is 0022, `secure`
|
||||
reparent umask is 0027.
|
||||
|
||||
Change-Id: Iba07a884b733b411e5268d7ecaa22b9aa327ac3c
|
||||
Signed-off-by: wangfengtu <wangfengtu@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/create.go | 21 +++++++++++++++-
|
||||
components/engine/daemon/daemon_unix.go | 33 +++++++++++++++++++++++++
|
||||
2 files changed, 53 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/create.go b/components/engine/daemon/create.go
|
||||
index 565e9dc022..fa000c2208 100644
|
||||
--- a/components/engine/daemon/create.go
|
||||
+++ b/components/engine/daemon/create.go
|
||||
@@ -79,6 +79,22 @@ func (daemon *Daemon) containerCreate(params types.ContainerCreateConfig, manage
|
||||
return containertypes.ContainerCreateCreatedBody{ID: container.ID, Warnings: warnings}, nil
|
||||
}
|
||||
|
||||
+func (daemon *Daemon) setUmask(c *containertypes.Config) error {
|
||||
+ // Use option native.umask passed by command create/run if specified,
|
||||
+ // otherwise use daemon's native.umask option.
|
||||
+ if val, ok := c.Annotations["native.umask"]; ok {
|
||||
+ if val != umaskNormal && val != umaskSecure {
|
||||
+ return fmt.Errorf("native.umask option %s not supported", val)
|
||||
+ }
|
||||
+ } else if UsingNormalUmask(daemon.configStore) {
|
||||
+ c.Annotations["native.umask"] = umaskNormal
|
||||
+ } else {
|
||||
+ c.Annotations["native.umask"] = umaskSecure
|
||||
+ }
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
// Create creates a new container from the given configuration with a given name.
|
||||
func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (retC *container.Container, retErr error) {
|
||||
var (
|
||||
@@ -162,8 +178,11 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
|
||||
}
|
||||
container.RWLayer = rwLayer
|
||||
|
||||
- rootIDs := daemon.idMapping.RootPair()
|
||||
+ if err := daemon.setUmask(params.Config); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
|
||||
+ rootIDs := daemon.idMapping.RootPair()
|
||||
if err := idtools.MkdirAndChown(container.Root, 0700, rootIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index 5b390d2db1..8ffdd0009a 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -77,6 +77,10 @@ const (
|
||||
// DefaultRuntimeName is the default runtime to be used by
|
||||
// containerd if none is specified
|
||||
DefaultRuntimeName = "runc"
|
||||
+
|
||||
+ // constant for umasks in containers. normal: 0022, secure(default): 0027
|
||||
+ umaskNormal = "normal"
|
||||
+ umaskSecure = "secure"
|
||||
)
|
||||
|
||||
type containerGetter interface {
|
||||
@@ -581,6 +585,32 @@ func UsingSystemd(config *config.Config) bool {
|
||||
return getCD(config) == cgroupSystemdDriver
|
||||
}
|
||||
|
||||
+// getUmask gets the raw value of the native.umask option, if set.
|
||||
+func getUmask(config *config.Config) string {
|
||||
+ for _, option := range config.ExecOptions {
|
||||
+ key, val, err := parsers.ParseKeyValueOpt(option)
|
||||
+ if err != nil || !strings.EqualFold(key, "native.umask") {
|
||||
+ continue
|
||||
+ }
|
||||
+ return val
|
||||
+ }
|
||||
+ return ""
|
||||
+}
|
||||
+
|
||||
+// VerifyNativeUmask validates native.umask
|
||||
+func VerifyNativeUmask(config *config.Config) error {
|
||||
+ umask := getUmask(config)
|
||||
+ if umask == "" || umask == umaskNormal || umask == umaskSecure {
|
||||
+ return nil
|
||||
+ }
|
||||
+ return fmt.Errorf("native.umask option %s not supported", umask)
|
||||
+}
|
||||
+
|
||||
+// UsingNormalUmask returns true if cli option includes native.umask=normal
|
||||
+func UsingNormalUmask(config *config.Config) bool {
|
||||
+ return getUmask(config) == umaskNormal
|
||||
+}
|
||||
+
|
||||
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||
// hostconfig and config structures.
|
||||
func (daemon *Daemon) verifyPlatformContainerSettings(hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||
@@ -737,6 +767,9 @@ func verifyDaemonSettings(conf *config.Config) error {
|
||||
return fmt.Errorf("cgroup-parent for systemd cgroup should be a valid slice named as \"xxx.slice\"")
|
||||
}
|
||||
}
|
||||
+ if err := VerifyNativeUmask(conf); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
|
||||
if conf.DefaultRuntime == "" {
|
||||
conf.DefaultRuntime = config.StockRuntimeName
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
From 412b8a34a2aa40ddf6f9b507142c4793922cedf5 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 11:22:46 +0800
|
||||
Subject: [PATCH 022/111] umask: fix nil pointer on c.Annotations in
|
||||
setUmask
|
||||
|
||||
reason: c.Annotations should be check before using in setUmask().
|
||||
When "/create" request is sent via restful api, the c.Annotations
|
||||
is nil, so **nil map** happens in setUmask.
|
||||
|
||||
Change-Id: Idafa2d8d1f54c1ebc34a6380d64c1cd7efad0266
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/create.go | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/create.go b/components/engine/daemon/create.go
|
||||
index fa000c2208..b57b01eacc 100644
|
||||
--- a/components/engine/daemon/create.go
|
||||
+++ b/components/engine/daemon/create.go
|
||||
@@ -86,10 +86,15 @@ func (daemon *Daemon) setUmask(c *containertypes.Config) error {
|
||||
if val != umaskNormal && val != umaskSecure {
|
||||
return fmt.Errorf("native.umask option %s not supported", val)
|
||||
}
|
||||
- } else if UsingNormalUmask(daemon.configStore) {
|
||||
- c.Annotations["native.umask"] = umaskNormal
|
||||
} else {
|
||||
- c.Annotations["native.umask"] = umaskSecure
|
||||
+ if c.Annotations == nil {
|
||||
+ c.Annotations = make(map[string]string)
|
||||
+ }
|
||||
+ if UsingNormalUmask(daemon.configStore) {
|
||||
+ c.Annotations["native.umask"] = umaskNormal
|
||||
+ } else {
|
||||
+ c.Annotations["native.umask"] = umaskSecure
|
||||
+ }
|
||||
}
|
||||
|
||||
return nil
|
||||
--
|
||||
2.17.1
|
||||
|
||||
65
patch/0023-prjquota-fix-syscall-bugs-in-projectquota.patch
Normal file
65
patch/0023-prjquota-fix-syscall-bugs-in-projectquota.patch
Normal file
@ -0,0 +1,65 @@
|
||||
From d864d32460063a25ef5a408c596b40555a062646 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 15:02:39 +0800
|
||||
Subject: [PATCH 023/111] prjquota: fix syscall bugs in projectquota
|
||||
|
||||
reason: fix syscall bugs in projectquota, which is introduced
|
||||
when cherry-picked.
|
||||
|
||||
Change-Id: I4496f2b8fcdcd16eb34584b435a9ef9434639cee
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../engine/daemon/graphdriver/quota/projectquota.go | 9 ++++-----
|
||||
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/quota/projectquota.go b/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
index 7d879eb81d..7f2fa2fe70 100644
|
||||
--- a/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
+++ b/components/engine/daemon/graphdriver/quota/projectquota.go
|
||||
@@ -79,7 +79,6 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
- "syscall"
|
||||
"unsafe"
|
||||
|
||||
rsystem "github.com/opencontainers/runc/libcontainer/system"
|
||||
@@ -234,7 +233,7 @@ func (q *Control) SetQuota(targetPath string, quota Quota) error {
|
||||
//
|
||||
err := setProjectID(targetPath, projectID)
|
||||
if err != nil {
|
||||
- q.lock.Lock()
|
||||
+ q.lock.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -312,7 +311,7 @@ func (q *Ext4Quota) SetProjectQuota(backingFsBlockDev string, projectID uint32,
|
||||
var cs = C.CString(backingFsBlockDev)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
- _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_SETPQUOTA,
|
||||
+ _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_SETPQUOTA,
|
||||
uintptr(unsafe.Pointer(cs)), uintptr(C.__u32(projectID)),
|
||||
uintptr(unsafe.Pointer(&d)), 0, 0)
|
||||
if errno != 0 {
|
||||
@@ -330,7 +329,7 @@ func (q *Ext4Quota) GetProjectQuota(backingFsBlockDev string, projectID uint32,
|
||||
var cs = C.CString(backingFsBlockDev)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
- _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_SETPQUOTA,
|
||||
+ _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_GETPQUOTA,
|
||||
uintptr(unsafe.Pointer(cs)), uintptr(C.__u32(projectID)),
|
||||
uintptr(unsafe.Pointer(&d)), 0, 0)
|
||||
if errno != 0 {
|
||||
@@ -350,7 +349,7 @@ func getQuotaStat(backingFsBlockDev string) (int, error) {
|
||||
|
||||
var cs = C.CString(backingFsBlockDev)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
- _, _, errno := syscall.Syscall6(syscall.SYS_QUOTACTL, C.Q_XGETPQSTAT,
|
||||
+ _, _, errno := unix.Syscall6(unix.SYS_QUOTACTL, C.Q_XGETPQSTAT,
|
||||
uintptr(unsafe.Pointer(cs)), 0,
|
||||
uintptr(unsafe.Pointer(&info)), 0, 0)
|
||||
if errno != 0 {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
51
patch/0024-runtime-spec-Compatibility-modifications-fo.patch
Normal file
51
patch/0024-runtime-spec-Compatibility-modifications-fo.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 3de51170031133bcd8d6aefe022d3fd26287c8c0 Mon Sep 17 00:00:00 2001
|
||||
From: leizhongkai <leizhongkai@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 16:45:43 +0800
|
||||
Subject: [PATCH 024/111] runtime-spec: Compatibility modifications
|
||||
for runc-1.0.0-rc3 about `struct LinuxBlockIO`
|
||||
|
||||
reason:Compatibility modifications for runc-1.0.0-rc3 about `struct LinuxBlockIO`
|
||||
|
||||
Change-Id: If2389709d4639b5e9d61a9b853a8f220ef6e3884
|
||||
Signed-off-by: leizhongkai <leizhongkai@huawei.com>
|
||||
---
|
||||
.../runtime-spec/specs-go/config.go | 18 +++++++++---------
|
||||
2 files changed, 10 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
index 46049b3bfa..aab7b8a098 100644
|
||||
--- a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
+++ b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
@@ -256,20 +256,20 @@ type LinuxThrottleDevice struct {
|
||||
|
||||
// LinuxBlockIO for Linux cgroup 'blkio' resource management
|
||||
type LinuxBlockIO struct {
|
||||
- // Specifies per cgroup weight
|
||||
- Weight *uint16 `json:"weight,omitempty"`
|
||||
- // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, CFQ scheduler only
|
||||
- LeafWeight *uint16 `json:"leafWeight,omitempty"`
|
||||
+ // Specifies per cgroup weight, range is from 10 to 1000
|
||||
+ Weight *uint16 `json:"blkioWeight,omitempty"`
|
||||
+ // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, CFQ scheduler only
|
||||
+ LeafWeight *uint16 `json:"blkioLeafWeight,omitempty"`
|
||||
// Weight per cgroup per device, can override BlkioWeight
|
||||
- WeightDevice []LinuxWeightDevice `json:"weightDevice,omitempty"`
|
||||
+ WeightDevice []LinuxWeightDevice `json:"blkioWeightDevice,omitempty"`
|
||||
// IO read rate limit per cgroup per device, bytes per second
|
||||
- ThrottleReadBpsDevice []LinuxThrottleDevice `json:"throttleReadBpsDevice,omitempty"`
|
||||
+ ThrottleReadBpsDevice []LinuxThrottleDevice `json:"blkioThrottleReadBpsDevice,omitempty"`
|
||||
// IO write rate limit per cgroup per device, bytes per second
|
||||
- ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"throttleWriteBpsDevice,omitempty"`
|
||||
+ ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"blkioThrottleWriteBpsDevice,omitempty"`
|
||||
// IO read rate limit per cgroup per device, IO per second
|
||||
- ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"`
|
||||
+ ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleReadIOPSDevice,omitempty"`
|
||||
// IO write rate limit per cgroup per device, IO per second
|
||||
- ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"throttleWriteIOPSDevice,omitempty"`
|
||||
+ ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleWriteIOPSDevice,omitempty"`
|
||||
}
|
||||
|
||||
// LinuxMemory for Linux cgroup 'memory' resource management
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
From d0625f253c9cfd62e043f1799b9f9c2a0e2fdb21 Mon Sep 17 00:00:00 2001
|
||||
From: caihaomin <caihaomin@huawei.com>
|
||||
Date: Sun, 20 Jan 2019 13:59:45 +0800
|
||||
Subject: [PATCH 025/111] resource-limit: enable unlimited usage of
|
||||
memory compoents
|
||||
|
||||
reason:enable unlimited usage of memory compoents
|
||||
|
||||
Change-Id: I24871d1b2ef1fe20277d5e5c721d1297fa5fd6cf
|
||||
Signed-off-by: caihaomin <caihaomin@huawei.com>
|
||||
---
|
||||
components/engine/container/container_unix.go | 2 +-
|
||||
components/engine/daemon/update_linux.go | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/container/container_unix.go b/components/engine/container/container_unix.go
|
||||
index ed664f3eec..5a21b8c483 100644
|
||||
--- a/components/engine/container/container_unix.go
|
||||
+++ b/components/engine/container/container_unix.go
|
||||
@@ -323,7 +323,7 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
||||
if resources.Memory != 0 {
|
||||
// if memory limit smaller than already set memoryswap limit and doesn't
|
||||
// update the memoryswap limit, then error out.
|
||||
- if resources.Memory > cResources.MemorySwap && resources.MemorySwap == 0 {
|
||||
+ if cResources.MemorySwap > 0 && resources.Memory > cResources.MemorySwap && resources.MemorySwap == 0 {
|
||||
return conflictingUpdateOptions("Memory limit should be smaller than already set memoryswap limit, update the memoryswap at the same time")
|
||||
}
|
||||
cResources.Memory = resources.Memory
|
||||
diff --git a/components/engine/daemon/update_linux.go b/components/engine/daemon/update_linux.go
|
||||
index 6a307eabc5..1a6f070b82 100644
|
||||
--- a/components/engine/daemon/update_linux.go
|
||||
+++ b/components/engine/daemon/update_linux.go
|
||||
@@ -46,7 +46,7 @@ func toContainerdResources(resources container.Resources) *libcontainerd.Resourc
|
||||
Kernel: &resources.KernelMemory,
|
||||
}
|
||||
|
||||
- if resources.MemorySwap > 0 {
|
||||
+ if resources.MemorySwap != 0 {
|
||||
r.Memory.Swap = &resources.MemorySwap
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
37
patch/0026-prjquota-use-dockerd-quota-size-when-docker.patch
Normal file
37
patch/0026-prjquota-use-dockerd-quota-size-when-docker.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 0ff4db1fc19ecb6f9dedfaa8d0645a638bb7ab20 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Sat, 19 Jan 2019 17:53:59 +0800
|
||||
Subject: [PATCH 026/111] prjquota: use dockerd quota size when
|
||||
docker not specifies
|
||||
|
||||
reason: if docker run not specifies quota size but dockerd has default
|
||||
size, we should use the default value in dockerd.
|
||||
EulerOS docker 1.11.2 and 17.06 has the same logic. But now, if docker
|
||||
create/run not give --storage-opt, it will panic during parseStorageOpt, so
|
||||
updating the handling logic.
|
||||
|
||||
Change-Id: I52141c7f1caf5a2a4cbd9c00fbe709f09f7a412b
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../engine/daemon/graphdriver/overlay2/overlay.go | 11 ++++++-----
|
||||
1 file changed, 6 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 7290616bae..722d65b11a 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -406,6 +406,11 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
||||
return err
|
||||
}
|
||||
}
|
||||
+ } else if d.options.quota.Size > 0 {
|
||||
+ // docker run not specified quota size, but dockerd does, so limits it also
|
||||
+ if err := d.quotaCtl.SetQuota(dir, d.options.quota); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
|
||||
if err := idtools.MkdirAndChown(path.Join(dir, "diff"), 0755, root); err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
30
patch/0027-oci-add-files_panic_enable-to-masked-path.patch
Normal file
30
patch/0027-oci-add-files_panic_enable-to-masked-path.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From 5370b3b9f2f4adfc10bbc3db5903b1a23e13f6c2 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 00:37:17 +0800
|
||||
Subject: [PATCH 027/111] oci: add files_panic_enable to masked path
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
reason:add files_panic_enable to masked path
|
||||
|
||||
Change-Id: I3d6fb04a1063f64ad52e40cb5debf21c301d829c
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
components/engine/oci/defaults.go | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/components/engine/oci/defaults.go b/components/engine/oci/defaults.go
|
||||
index 5e17ea3f38..e39140b47f 100644
|
||||
--- a/components/engine/oci/defaults.go
|
||||
+++ b/components/engine/oci/defaults.go
|
||||
@@ -123,6 +123,7 @@ func DefaultLinuxSpec() specs.Spec {
|
||||
"/proc/timer_stats",
|
||||
"/proc/sched_debug",
|
||||
"/proc/scsi",
|
||||
+ "/proc/files_panic_enable",
|
||||
"/sys/firmware",
|
||||
},
|
||||
ReadonlyPaths: []string{
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From f81a87edbeb1ddc58d48d36c963f76f0ed6cc04f Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 00:40:29 +0800
|
||||
Subject: [PATCH 028/111] oci: add fdenable fdstat and fdthreshold to
|
||||
masked path
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
reason:add fdenable fdstat and fdthreshold to masked path
|
||||
|
||||
Change-Id: I7b39a4ad9b989ef4b8185e386aa70c2d638efcd9
|
||||
Signed-off-by: caihaomin <caihaomin@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
components/engine/oci/defaults.go | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/components/engine/oci/defaults.go b/components/engine/oci/defaults.go
|
||||
index e39140b47f..de0088c4bb 100644
|
||||
--- a/components/engine/oci/defaults.go
|
||||
+++ b/components/engine/oci/defaults.go
|
||||
@@ -124,6 +124,9 @@ func DefaultLinuxSpec() specs.Spec {
|
||||
"/proc/sched_debug",
|
||||
"/proc/scsi",
|
||||
"/proc/files_panic_enable",
|
||||
+ "/proc/fdthreshold",
|
||||
+ "/proc/fdstat",
|
||||
+ "/proc/fdenable",
|
||||
"/sys/firmware",
|
||||
},
|
||||
ReadonlyPaths: []string{
|
||||
--
|
||||
2.17.1
|
||||
|
||||
43
patch/0029-oci-add-oom_extend-to-proc-masked-path.patch
Normal file
43
patch/0029-oci-add-oom_extend-to-proc-masked-path.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From fe4522af7f1c5dadfeaf8513dd584c66854d612b Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 00:43:55 +0800
|
||||
Subject: [PATCH 029/111] oci: add oom_extend to proc masked path
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
reason:add oom_extend to proc masked path
|
||||
|
||||
Change-Id: I4b9c3dd94b6d68d753e9aad0879949b310fe7180
|
||||
Signed-off-by: dengguangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: Haomin <caihaomin@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
components/engine/oci/defaults.go | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/components/engine/oci/defaults.go b/components/engine/oci/defaults.go
|
||||
index de0088c4bb..74d3fdb2d8 100644
|
||||
--- a/components/engine/oci/defaults.go
|
||||
+++ b/components/engine/oci/defaults.go
|
||||
@@ -116,6 +116,7 @@ func DefaultLinuxSpec() specs.Spec {
|
||||
s.Linux = &specs.Linux{
|
||||
MaskedPaths: []string{
|
||||
"/proc/acpi",
|
||||
+ "/proc/config.gz",
|
||||
"/proc/kcore",
|
||||
"/proc/keys",
|
||||
"/proc/latency_stats",
|
||||
@@ -127,6 +128,10 @@ func DefaultLinuxSpec() specs.Spec {
|
||||
"/proc/fdthreshold",
|
||||
"/proc/fdstat",
|
||||
"/proc/fdenable",
|
||||
+ "/proc/signo",
|
||||
+ "/proc/sig_catch",
|
||||
+ "/proc/kbox",
|
||||
+ "/proc/oom_extend",
|
||||
"/sys/firmware",
|
||||
},
|
||||
ReadonlyPaths: []string{
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 1e9ad6a48e283bcc9850fb1439bf0be6be805010 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 00:49:35 +0800
|
||||
Subject: [PATCH 030/111] restart: fix docker stats blocked while
|
||||
docker daemon restart
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
change closeChan channel from non-buffered channel to 2-buffered channel,
|
||||
because non-blocked channel will be blocked while docker daemon restart
|
||||
|
||||
Change-Id: Ica5dbefc85e463836b55e5d96da522a64a259f64
|
||||
Signed-off-by: jiangpengfei9 <jiangpengfei9@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/stats.go | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/stats.go b/components/cli/cli/command/container/stats.go
|
||||
index 4efcb19e65..1f9e1b8556 100644
|
||||
--- a/components/cli/cli/command/container/stats.go
|
||||
+++ b/components/cli/cli/command/container/stats.go
|
||||
@@ -53,7 +53,7 @@ func NewStatsCommand(dockerCli command.Cli) *cobra.Command {
|
||||
// nolint: gocyclo
|
||||
func runStats(dockerCli command.Cli, opts *statsOptions) error {
|
||||
showAll := len(opts.containers) == 0
|
||||
- closeChan := make(chan error)
|
||||
+ closeChan := make(chan error, 2)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
From 6da7401bff6b59e59f04323fcf2f88115f38ede8 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 16:33:11 +0800
|
||||
Subject: [PATCH 031/111] restart: Incase deadlock when kill the docker
|
||||
CLI and restart
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
the docker daemon is in created stage and last long time, then kill
|
||||
the docker cli and restart docker at the same time, the restart stage will trylock,
|
||||
because the created stage already locked.
|
||||
|
||||
cherry-pick from 1.11.2: 3082432
|
||||
|
||||
the testcase testCE_container_resourced_cpuiso_ABN.023.sh
|
||||
|
||||
current_dir=$(cd `dirname $0` && pwd)
|
||||
source ${COMMON_DIR}/commonlib.sh
|
||||
source ${current_dir}/../common/container_resourced_commonlib.sh
|
||||
resource_managerd_env
|
||||
|
||||
work_dir=`mktemp -d /tmp/testCE_container_resourced_cpuiso_ABN_005.XXXX`
|
||||
bind_cpu=1
|
||||
resource_pid=`ps axu |grep resource-managerd |grep -v grep|awk '{print $2}'`
|
||||
service container-resourced stop
|
||||
service container-resourced start & kill -9 $!
|
||||
container_id=`timeout 10 docker run -itd --hook-spec /etc/docker/resource-hook.json --cpuset-cpus $bind_cpu -e ISOLATION_CORES=$bind_cpu $ubuntu_image bash &`
|
||||
timeout 10 docker restart $container_id
|
||||
fn_check_result_noeq $? 0
|
||||
resource_managerd_env
|
||||
docker restart $container_id
|
||||
fn_check_result $? 0
|
||||
test_cpuset $container_id
|
||||
docker rm -f $container_id
|
||||
rm -rf $work_dir
|
||||
kill_resource_managerd
|
||||
exit $exit_flag
|
||||
Conflicts:
|
||||
daemon/restart.go
|
||||
|
||||
Change-Id: I571f109dc07a7e76df40c544008a97cd497ef8bb
|
||||
Signed-off-by: panwenxiang <panwenxiang@huawei.com>
|
||||
Signed-off-by: lixiang172 <lixiang172@huawei.com>
|
||||
---
|
||||
components/engine/daemon/restart.go | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/restart.go b/components/engine/daemon/restart.go
|
||||
index 0f06dea267..bae665f76b 100644
|
||||
--- a/components/engine/daemon/restart.go
|
||||
+++ b/components/engine/daemon/restart.go
|
||||
@@ -41,7 +41,10 @@ func (daemon *Daemon) containerRestart(container *container.Container, seconds i
|
||||
defer daemon.Unmount(container)
|
||||
}
|
||||
|
||||
- if container.IsRunning() {
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return fmt.Errorf("can't restart a container which is dead or marked for removal")
|
||||
+ }
|
||||
+ if container.Running {
|
||||
// set AutoRemove flag to false before stop so the container won't be
|
||||
// removed during restart process
|
||||
autoRemove := container.HostConfig.AutoRemove
|
||||
--
|
||||
2.17.1
|
||||
|
||||
254
patch/0032-devmapper-Add-udev-event-time-out-to-fix-dock.patch
Normal file
254
patch/0032-devmapper-Add-udev-event-time-out-to-fix-dock.patch
Normal file
@ -0,0 +1,254 @@
|
||||
From e22807e3972f1c168e596fa95a97e2730024824c Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 10:20:44 +0800
|
||||
Subject: [PATCH 032/111] devmapper: Add udev event time out to fix
|
||||
docker stuck on udev wait
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
Add udev event time out to fix docker stuck on udev wait
|
||||
|
||||
Change-Id: I47505140699c0a51f37f4127b761f2a99930466d
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/devmapper/deviceset.go | 28 ++++++---
|
||||
.../engine/pkg/devicemapper/devmapper.go | 57 +++++++++++++------
|
||||
.../pkg/devicemapper/devmapper_wrapper.go | 5 ++
|
||||
3 files changed, 66 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index 5dc01d71d9..af53cf83e6 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -35,13 +35,16 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
- defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
|
||||
- defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
|
||||
- defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
|
||||
- defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
|
||||
- defaultUdevSyncOverride = false
|
||||
- maxDeviceID = 0xffffff // 24 bit, pool limit
|
||||
- deviceIDMapSz = (maxDeviceID + 1) / 8
|
||||
+ defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
|
||||
+ defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
|
||||
+ defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
|
||||
+ defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
|
||||
+ defaultUdevSyncOverride = false
|
||||
+ maxDeviceID = 0xffffff // 24 bit, pool limit
|
||||
+ deviceIDMapSz = (maxDeviceID + 1) / 8
|
||||
+ // The default timeout is 30s from `man systemd-udevd`, we use 35
|
||||
+ // just to make sure the timeout really happened in systemd-udevd
|
||||
+ defaultUdevWaitTimeout = 35
|
||||
driverDeferredRemovalSupport = false
|
||||
enableDeferredRemoval = false
|
||||
enableDeferredDeletion = false
|
||||
@@ -2059,7 +2062,9 @@ func (devices *DeviceSet) issueDiscard(info *devInfo) error {
|
||||
// Should be called with devices.Lock() held.
|
||||
func (devices *DeviceSet) deleteDevice(info *devInfo, syncDelete bool) error {
|
||||
if devices.doBlkDiscard {
|
||||
- devices.issueDiscard(info)
|
||||
+ if err := devices.issueDiscard(info); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
}
|
||||
|
||||
// Try to deactivate device in case it is active.
|
||||
@@ -2651,6 +2656,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
|
||||
|
||||
foundBlkDiscard := false
|
||||
var lvmSetupConfig directLVMConfig
|
||||
+ udevWaitTimeout := int64(defaultUdevWaitTimeout)
|
||||
for _, option := range options {
|
||||
key, val, err := parsers.ParseKeyValueOpt(option)
|
||||
if err != nil {
|
||||
@@ -2800,10 +2806,16 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
|
||||
devicemapper.LogInit(devicemapper.DefaultLogger{
|
||||
Level: int(level),
|
||||
})
|
||||
+ case "dm.udev_wait_timeout":
|
||||
+ udevWaitTimeout, err = strconv.ParseInt(val, 10, 32)
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
default:
|
||||
return nil, fmt.Errorf("devmapper: Unknown option %s", key)
|
||||
}
|
||||
}
|
||||
+ devicemapper.SetUdevWaitTimtout(udevWaitTimeout)
|
||||
|
||||
if err := validateLVMConfig(lvmSetupConfig); err != nil {
|
||||
return nil, err
|
||||
diff --git a/components/engine/pkg/devicemapper/devmapper.go b/components/engine/pkg/devicemapper/devmapper.go
|
||||
index 63243637a7..b384a27f8f 100644
|
||||
--- a/components/engine/pkg/devicemapper/devmapper.go
|
||||
+++ b/components/engine/pkg/devicemapper/devmapper.go
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
+ "time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -59,6 +60,7 @@ var (
|
||||
ErrNilCookie = errors.New("cookie ptr can't be nil")
|
||||
ErrGetBlockSize = errors.New("Can't get block size")
|
||||
ErrUdevWait = errors.New("wait on udev cookie failed")
|
||||
+ ErrUdevWaitTimeout = errors.New("wait on udev cookie time out")
|
||||
ErrSetDevDir = errors.New("dm_set_dev_dir failed")
|
||||
ErrGetLibraryVersion = errors.New("dm_get_library_version failed")
|
||||
ErrCreateRemoveTask = errors.New("Can't create task of type deviceRemove")
|
||||
@@ -71,10 +73,11 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
- dmSawBusy bool
|
||||
- dmSawExist bool
|
||||
- dmSawEnxio bool // No Such Device or Address
|
||||
- dmSawEnoData bool // No data available
|
||||
+ dmSawBusy bool
|
||||
+ dmSawExist bool
|
||||
+ dmSawEnxio bool // No Such Device or Address
|
||||
+ dmSawEnoData bool // No data available
|
||||
+ dmUdevWaitTimeout int64
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -256,13 +259,36 @@ func (t *Task) getNextTarget(next unsafe.Pointer) (nextPtr unsafe.Pointer, start
|
||||
|
||||
// UdevWait waits for any processes that are waiting for udev to complete the specified cookie.
|
||||
func UdevWait(cookie *uint) error {
|
||||
- if res := DmUdevWait(*cookie); res != 1 {
|
||||
- logrus.Debugf("devicemapper: Failed to wait on udev cookie %d, %d", *cookie, res)
|
||||
- return ErrUdevWait
|
||||
+ chError := make(chan error)
|
||||
+ go func() {
|
||||
+ if res := DmUdevWait(*cookie); res != 1 {
|
||||
+ logrus.Debugf("Failed to wait on udev cookie %d", *cookie)
|
||||
+ chError <- ErrUdevWait
|
||||
+ }
|
||||
+ chError <- nil
|
||||
+ }()
|
||||
+ select {
|
||||
+ case err := <-chError:
|
||||
+ return err
|
||||
+ case <-time.After(time.Second * time.Duration(dmUdevWaitTimeout)):
|
||||
+ logrus.Errorf("Failed to wait on udev cookie %d: timeout %v", *cookie, dmUdevWaitTimeout)
|
||||
+ if res := DmUdevComplete(*cookie); res != 1 {
|
||||
+ // This is bad to return here
|
||||
+ logrus.Errorf("Failed to complete udev cookie %d on udev wait timeout", *cookie)
|
||||
+ return ErrUdevWaitTimeout
|
||||
+ }
|
||||
+ // wait DmUdevWait return after DmUdevComplete
|
||||
+ <-chError
|
||||
+ return ErrUdevWaitTimeout
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+// SetUdevWaitTimtout sets udev wait timeout
|
||||
+func SetUdevWaitTimtout(t int64) {
|
||||
+ dmUdevWaitTimeout = t
|
||||
+}
|
||||
+
|
||||
// SetDevDir sets the dev folder for the device mapper library (usually /dev).
|
||||
func SetDevDir(dir string) error {
|
||||
if res := DmSetDevDir(dir); res != 1 {
|
||||
@@ -319,11 +345,11 @@ func RemoveDevice(name string) error {
|
||||
if err := task.setCookie(cookie, 0); err != nil {
|
||||
return fmt.Errorf("devicemapper: Can not set cookie: %s", err)
|
||||
}
|
||||
- defer UdevWait(cookie)
|
||||
|
||||
dmSawBusy = false // reset before the task is run
|
||||
dmSawEnxio = false
|
||||
if err = task.run(); err != nil {
|
||||
+ UdevWait(cookie)
|
||||
if dmSawBusy {
|
||||
return ErrBusy
|
||||
}
|
||||
@@ -333,7 +359,7 @@ func RemoveDevice(name string) error {
|
||||
return fmt.Errorf("devicemapper: Error running RemoveDevice %s", err)
|
||||
}
|
||||
|
||||
- return nil
|
||||
+ return UdevWait(cookie)
|
||||
}
|
||||
|
||||
// RemoveDeviceDeferred is a useful helper for cleaning up a device, but deferred.
|
||||
@@ -470,13 +496,13 @@ func CreatePool(poolName string, dataFile, metadataFile *os.File, poolBlockSize
|
||||
if err := task.setCookie(cookie, flags); err != nil {
|
||||
return fmt.Errorf("devicemapper: Can't set cookie %s", err)
|
||||
}
|
||||
- defer UdevWait(cookie)
|
||||
|
||||
if err := task.run(); err != nil {
|
||||
+ UdevWait(cookie)
|
||||
return fmt.Errorf("devicemapper: Error running deviceCreate (CreatePool) %s", err)
|
||||
}
|
||||
|
||||
- return nil
|
||||
+ return UdevWait(cookie)
|
||||
}
|
||||
|
||||
// ReloadPool is the programmatic example of "dmsetup reload".
|
||||
@@ -656,13 +682,13 @@ func ResumeDevice(name string) error {
|
||||
if err := task.setCookie(cookie, 0); err != nil {
|
||||
return fmt.Errorf("devicemapper: Can't set cookie %s", err)
|
||||
}
|
||||
- defer UdevWait(cookie)
|
||||
|
||||
if err := task.run(); err != nil {
|
||||
+ UdevWait(cookie)
|
||||
return fmt.Errorf("devicemapper: Error running deviceResume %s", err)
|
||||
}
|
||||
|
||||
- return nil
|
||||
+ return UdevWait(cookie)
|
||||
}
|
||||
|
||||
// CreateDevice creates a device with the specified poolName with the specified device id.
|
||||
@@ -760,13 +786,12 @@ func activateDevice(poolName string, name string, deviceID int, size uint64, ext
|
||||
return fmt.Errorf("devicemapper: Can't set cookie %s", err)
|
||||
}
|
||||
|
||||
- defer UdevWait(cookie)
|
||||
-
|
||||
if err := task.run(); err != nil {
|
||||
+ UdevWait(cookie)
|
||||
return fmt.Errorf("devicemapper: Error running deviceCreate (ActivateDevice) %s", err)
|
||||
}
|
||||
|
||||
- return nil
|
||||
+ return UdevWait(cookie)
|
||||
}
|
||||
|
||||
// CreateSnapDeviceRaw creates a snapshot device. Caller needs to suspend and resume the origin device if it is active.
|
||||
diff --git a/components/engine/pkg/devicemapper/devmapper_wrapper.go b/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
index 0b88f49695..77cd674a09 100644
|
||||
--- a/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
+++ b/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
@@ -77,6 +77,7 @@ var (
|
||||
DmTaskSetRo = dmTaskSetRoFct
|
||||
DmTaskSetSector = dmTaskSetSectorFct
|
||||
DmUdevWait = dmUdevWaitFct
|
||||
+ DmUdevComplete = dmUdevCompleteFct
|
||||
DmUdevSetSyncSupport = dmUdevSetSyncSupportFct
|
||||
DmUdevGetSyncSupport = dmUdevGetSyncSupportFct
|
||||
DmCookieSupported = dmCookieSupportedFct
|
||||
@@ -227,6 +228,10 @@ func dmUdevWaitFct(cookie uint) int {
|
||||
return int(C.dm_udev_wait(C.uint32_t(cookie)))
|
||||
}
|
||||
|
||||
+func dmUdevCompleteFct(cookie uint) int {
|
||||
+ return int(C.dm_udev_complete(C.uint32_t(cookie)))
|
||||
+}
|
||||
+
|
||||
func dmCookieSupportedFct() int {
|
||||
return int(C.dm_cookie_supported())
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
224
patch/0033-devmapper-Fix-devicemapper-issue-power-off-th.patch
Normal file
224
patch/0033-devmapper-Fix-devicemapper-issue-power-off-th.patch
Normal file
@ -0,0 +1,224 @@
|
||||
From 72f9e0c4d0d907a036d25c9dfeea9c0baddddc3e Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 10:37:50 +0800
|
||||
Subject: [PATCH 033/111] devmapper: Fix devicemapper issue: power off
|
||||
the VM while loading a image, couldn't load it after VM bootup
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick from 28991928c4 | * Fix devicemapper issue: power off the VM while
|
||||
loading a image, couldn't load it after VM bootup
|
||||
|
||||
Issue Description:
|
||||
While running loading image test, power off or restart the VM, and then
|
||||
there are
|
||||
some chances that we can not load the image. And "Error running
|
||||
deviceCreate (createSnapDevice) dm_task_run failed" will be reported.
|
||||
|
||||
Reproduce Steps:
|
||||
> 1. run `docker load -i xxx.tar`
|
||||
> 2. virsh restart VM; # restart the VM.
|
||||
> 3. After startup, run `docker load -i xxx.tar`, will fail to import
|
||||
> the image
|
||||
|
||||
Analysis:
|
||||
From syslog, we found that docker was executing "Umount Device" then VM
|
||||
powered restart. And found
|
||||
two failure reasons:
|
||||
> 1. Rollback operation only remove the device on DM thin pool, not
|
||||
> remove the device in memory
|
||||
> 2. TransactionData or metadata not flushed to Disk.
|
||||
|
||||
Solution:
|
||||
> 1. Rollback operation for DM, should remove the devices cache in DM
|
||||
> driver.
|
||||
> 2. When restore layers and images, check whether the device exists in
|
||||
> graphdriver.
|
||||
If desen't, remove the layer( and the metadata) and do not load the
|
||||
image.
|
||||
|
||||
Issue link:
|
||||
#203
|
||||
|
||||
Signed-off-by: Wentao Zhang <zhangwentao234@huawei.com>
|
||||
|
||||
Conflicts:
|
||||
image/store.go
|
||||
layer/layer_store.go
|
||||
|
||||
Change-Id: If3bfbf0d0ed8f950cfd5934fc25fac892481275c
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/devmapper/deviceset.go | 38 +++++++------------
|
||||
components/engine/image/store.go | 3 +-
|
||||
components/engine/layer/layer_store.go | 15 +++++++-
|
||||
3 files changed, 28 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index af53cf83e6..0675b2eacd 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
- "io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -23,6 +22,7 @@ import (
|
||||
"github.com/docker/docker/pkg/devicemapper"
|
||||
"github.com/docker/docker/pkg/dmesg"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
+ "github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/loopback"
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
@@ -306,6 +306,10 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
|
||||
return filename, nil
|
||||
}
|
||||
|
||||
+func (devices *DeviceSet) removeDeviceMap(hash string) {
|
||||
+ delete(devices.Devices, hash)
|
||||
+}
|
||||
+
|
||||
func (devices *DeviceSet) allocateTransactionID() uint64 {
|
||||
devices.OpenTransactionID = devices.TransactionID + 1
|
||||
return devices.OpenTransactionID
|
||||
@@ -328,28 +332,9 @@ func (devices *DeviceSet) removeMetadata(info *devInfo) error {
|
||||
|
||||
// Given json data and file path, write it to disk
|
||||
func (devices *DeviceSet) writeMetaFile(jsonData []byte, filePath string) error {
|
||||
- tmpFile, err := ioutil.TempFile(devices.metadataDir(), ".tmp")
|
||||
- if err != nil {
|
||||
- return fmt.Errorf("devmapper: Error creating metadata file: %s", err)
|
||||
- }
|
||||
-
|
||||
- n, err := tmpFile.Write(jsonData)
|
||||
- if err != nil {
|
||||
- return fmt.Errorf("devmapper: Error writing metadata to %s: %s", tmpFile.Name(), err)
|
||||
- }
|
||||
- if n < len(jsonData) {
|
||||
- return io.ErrShortWrite
|
||||
+ if err := ioutils.AtomicWriteFile(filePath, jsonData, 0600); err != nil {
|
||||
+ return fmt.Errorf("devmapper: Error writing metadata to %s: %s", filePath, err)
|
||||
}
|
||||
- if err := tmpFile.Sync(); err != nil {
|
||||
- return fmt.Errorf("devmapper: Error syncing metadata file %s: %s", tmpFile.Name(), err)
|
||||
- }
|
||||
- if err := tmpFile.Close(); err != nil {
|
||||
- return fmt.Errorf("devmapper: Error closing metadata file %s: %s", tmpFile.Name(), err)
|
||||
- }
|
||||
- if err := os.Rename(tmpFile.Name(), filePath); err != nil {
|
||||
- return fmt.Errorf("devmapper: Error committing metadata file %s: %s", tmpFile.Name(), err)
|
||||
- }
|
||||
-
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -483,7 +468,7 @@ func (devices *DeviceSet) unregisterDevice(hash string) error {
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
- delete(devices.Devices, hash)
|
||||
+ devices.removeDeviceMap(hash)
|
||||
|
||||
if err := devices.removeMetadata(info); err != nil {
|
||||
logrus.WithField("storage-driver", "devicemapper").Debugf("Error removing metadata: %s", err)
|
||||
@@ -509,7 +494,7 @@ func (devices *DeviceSet) registerDevice(id int, hash string, size uint64, trans
|
||||
|
||||
if err := devices.saveMetadata(info); err != nil {
|
||||
// Try to remove unused device
|
||||
- delete(devices.Devices, hash)
|
||||
+ devices.removeDeviceMap(hash)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1173,7 +1158,7 @@ func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error {
|
||||
|
||||
if err := devices.saveMetadata(info); err != nil {
|
||||
// Try to remove unused device
|
||||
- delete(devices.Devices, info.Hash)
|
||||
+ devices.removeDeviceMap(info.Hash)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1401,6 +1386,8 @@ func (devices *DeviceSet) rollbackTransaction() error {
|
||||
devices.markDeviceIDFree(devices.DeviceID)
|
||||
}
|
||||
|
||||
+ devices.removeDeviceMap(dinfo.Hash)
|
||||
+
|
||||
if err := devices.removeTransactionMetaData(); err != nil {
|
||||
logger.Errorf("Unable to remove transaction meta file %s: %s", devices.transactionMetaFile(), err)
|
||||
}
|
||||
@@ -1482,6 +1469,7 @@ func (devices *DeviceSet) closeTransaction() error {
|
||||
logrus.WithField("storage-driver", "devicemapper").Debug("Failed to close Transaction")
|
||||
return err
|
||||
}
|
||||
+
|
||||
return nil
|
||||
}
|
||||
|
||||
diff --git a/components/engine/image/store.go b/components/engine/image/store.go
|
||||
index 1a8a8a2451..b078a2627a 100644
|
||||
--- a/components/engine/image/store.go
|
||||
+++ b/components/engine/image/store.go
|
||||
@@ -81,8 +81,9 @@ func (is *store) restore() error {
|
||||
}
|
||||
l, err = is.lss[img.OperatingSystem()].Get(chainID)
|
||||
if err != nil {
|
||||
+ logrus.Errorf("layer does not exist, not restoring image %v, %v, %s", dgst, chainID, img.OperatingSystem())
|
||||
+ // If the layer doesn't exist, return nil to ignore this image.
|
||||
if err == layer.ErrLayerDoesNotExist {
|
||||
- logrus.Errorf("layer does not exist, not restoring image %v, %v, %s", dgst, chainID, img.OperatingSystem())
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 6a568e9d9b..351f787b87 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -105,7 +105,7 @@ func newStoreFromGraphDriver(root string, driver graphdriver.Driver, os string)
|
||||
for _, id := range ids {
|
||||
l, err := ls.loadLayer(id)
|
||||
if err != nil {
|
||||
- logrus.Debugf("Failed to load layer %s: %s", id, err)
|
||||
+ logrus.Warnf("Failed to load layer %s: %s", id, err)
|
||||
continue
|
||||
}
|
||||
if l.parent != nil {
|
||||
@@ -126,11 +126,17 @@ func (ls *layerStore) Driver() graphdriver.Driver {
|
||||
return ls.driver
|
||||
}
|
||||
|
||||
-func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
|
||||
+func (ls *layerStore) loadLayer(layer ChainID) (l *roLayer, err error) {
|
||||
cl, ok := ls.layerMap[layer]
|
||||
if ok {
|
||||
return cl, nil
|
||||
}
|
||||
+ defer func() {
|
||||
+ // If failed to load the layer, remove the layer metadata.
|
||||
+ if err != nil {
|
||||
+ ls.store.Remove(layer)
|
||||
+ }
|
||||
+ }()
|
||||
|
||||
diff, err := ls.store.GetDiffID(layer)
|
||||
if err != nil {
|
||||
@@ -147,6 +153,11 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
|
||||
return nil, fmt.Errorf("failed to get cache id for %s: %s", layer, err)
|
||||
}
|
||||
|
||||
+ // Check whether the layer exists in graphdriver here.
|
||||
+ if exist := ls.driver.Exists(cacheID); !exist {
|
||||
+ return nil, fmt.Errorf("cacheID %s for layer %s does not exists in graphdriver", cacheID, layer)
|
||||
+ }
|
||||
+
|
||||
parent, err := ls.store.GetParent(layer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get parent for %s: %s", layer, err)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
From 2e0fda9de03efe4f399a35c52cac2444b5518709 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 16:43:39 +0800
|
||||
Subject: [PATCH 035/111] restart: reject to restart container when
|
||||
removing it
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
concurrence of restart and remove a container may cause
|
||||
that container info is still saved in memdb while container is actually
|
||||
already removed.
|
||||
|
||||
cherry-pick from 1.11.2: f7eeafa
|
||||
Conflicts:
|
||||
daemon/restart.go
|
||||
|
||||
Change-Id: Ic9be384c908f49697c87f6b51ffcb1968f38d6cc
|
||||
Signed-off-by: liruilin4 <liruilin4@huawei.com>
|
||||
Signed-off-by: lixiang172 <lixiang172@huawei.com>
|
||||
---
|
||||
components/engine/daemon/restart.go | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/restart.go b/components/engine/daemon/restart.go
|
||||
index bae665f76b..2c441de873 100644
|
||||
--- a/components/engine/daemon/restart.go
|
||||
+++ b/components/engine/daemon/restart.go
|
||||
@@ -55,6 +55,11 @@ func (daemon *Daemon) containerRestart(container *container.Container, seconds i
|
||||
container.HostConfig.AutoRemove = autoRemove
|
||||
// containerStop will write HostConfig to disk, we shall restore AutoRemove
|
||||
// in disk too
|
||||
+ // if rm running concurrently, the container may be already removed now. we should not
|
||||
+ // save it to disk
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return fmt.Errorf("can't restart a container which is dead or marked for removal")
|
||||
+ }
|
||||
if toDiskErr := daemon.checkpointAndSave(container); toDiskErr != nil {
|
||||
logrus.Errorf("Write container to disk error: %v", toDiskErr)
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From af5045eb5d9cc84afeace447e2bf3e1571866f4d Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 9 Jan 2019 16:52:39 +0800
|
||||
Subject: [PATCH 036/111] restart: do not reset container restartCount
|
||||
on boot
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
when daemon restart, container's RestartCount will be reseted to 0
|
||||
this is cherry-picked from docker
|
||||
commit:3bffccc719bf8237ce78af8b88aaa7757f43795a
|
||||
Signed-off-by: dengguangxing <dengguangxing@huawei.com>
|
||||
|
||||
cherry-pick from 1.11.2: d5292e3
|
||||
|
||||
Conflicts:
|
||||
daemon/daemon.go
|
||||
|
||||
Change-Id: I2276e9d075b593b74e4b17c0f8e48a2dec3e6f4c
|
||||
Signed-off-by: xueshaojia <xueshaojia@huawei.com>
|
||||
Signed-off-by: lixiang172 <lixiang172@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon.go | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index 4546587369..a058688dd3 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -532,7 +532,7 @@ func (daemon *Daemon) restore() error {
|
||||
|
||||
// Make sure networks are available before starting
|
||||
daemon.waitForNetworks(c)
|
||||
- if err := daemon.containerStart(c, "", "", true); err != nil {
|
||||
+ if err := daemon.containerStart(c, "", "", false); err != nil {
|
||||
logrus.Errorf("Failed to start container %s: %s", c.ID, err)
|
||||
}
|
||||
close(chNotify)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
From 5f82c47f5f08655e325610a9430a4e891c71857a Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 13:58:17 +0800
|
||||
Subject: [PATCH 037/111] config: Add --liver-restore to OPTIION to
|
||||
enable live restore by default
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
this commit copy latest file from docker-1.11.2
|
||||
|
||||
cherry-pick from
|
||||
c9846ccea8 | * Add --liver-restore to OPTIION to enable live restore by
|
||||
default
|
||||
|
||||
Change-Id: I9c52a81d1bb06f2abb090bbd048cbf2dbc44956a
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../init/sysvinit-redhat/docker.sysconfig | 19 ++++++++++++++-----
|
||||
1 file changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/components/engine/contrib/init/sysvinit-redhat/docker.sysconfig b/components/engine/contrib/init/sysvinit-redhat/docker.sysconfig
|
||||
index 0864b3d77f..234acad1dd 100644
|
||||
--- a/components/engine/contrib/init/sysvinit-redhat/docker.sysconfig
|
||||
+++ b/components/engine/contrib/init/sysvinit-redhat/docker.sysconfig
|
||||
@@ -1,7 +1,16 @@
|
||||
# /etc/sysconfig/docker
|
||||
-#
|
||||
-# Other arguments to pass to the docker daemon process
|
||||
-# These will be parsed by the sysv initscript and appended
|
||||
-# to the arguments list passed to docker daemon
|
||||
|
||||
-other_args=""
|
||||
+# Modify these options if you want to change the way the docker daemon runs
|
||||
+OPTIONS='--live-restore'
|
||||
+
|
||||
+DOCKER_CERT_PATH=/etc/docker
|
||||
+
|
||||
+# If you have a registry secured with https but do not have proper certs
|
||||
+# distributed, you can tell docker to not look for full authorization by
|
||||
+# adding the registry to the INSECURE_REGISTRY line and uncommenting it.
|
||||
+# INSECURE_REGISTRY='--insecure-registry'
|
||||
+
|
||||
+# Location used for temporary files, such as those created by
|
||||
+# docker load and build operations. Default is /var/lib/docker/tmp
|
||||
+# Can be overridden by setting the following environment variable.
|
||||
+# DOCKER_TMPDIR=/var/tmp
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
From 42da0fd120db6f5b34c523212b54b88e8837efa6 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 14:09:59 +0800
|
||||
Subject: [PATCH 038/111] devmapper: devicemapper: ignore error when
|
||||
remove a device which does not exist
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick from
|
||||
e91268fda7 | * devicemapper: ignore error when remove a device which
|
||||
does not exist
|
||||
|
||||
Conflicts:
|
||||
daemon/graphdriver/devmapper/deviceset.go
|
||||
pkg/devicemapper/devmapper.go
|
||||
|
||||
Change-Id: Ia1d33d78e4d7000c6e4bd54ec203800a0234cae5
|
||||
Signed-off-by: Liu Hua <sdu.liu@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../engine/daemon/graphdriver/devmapper/deviceset.go | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index 0675b2eacd..be48d92e8d 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -2137,6 +2137,13 @@ func (devices *DeviceSet) deactivateDeviceMode(info *devInfo, deferredRemove boo
|
||||
|
||||
if deferredRemove {
|
||||
err = devicemapper.RemoveDeviceDeferred(info.Name())
|
||||
+ if err != nil {
|
||||
+ if err == devicemapper.ErrEnxio {
|
||||
+ logrus.Warnf("devmapper: device %s has gone", info.Name())
|
||||
+ return nil
|
||||
+ }
|
||||
+ return err
|
||||
+ }
|
||||
} else {
|
||||
err = devices.removeDevice(info.Name())
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
361
patch/0039-restart-Remove-redundant-Mounts-when-start-do.patch
Normal file
361
patch/0039-restart-Remove-redundant-Mounts-when-start-do.patch
Normal file
@ -0,0 +1,361 @@
|
||||
From 49a3cd1ceb6956bd7787135a7938543d64d30638 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 14:02:32 +0800
|
||||
Subject: [PATCH 039/111] restart: -- Remove redundant Mounts when
|
||||
start docker daemon
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
merge from
|
||||
b192ce147d * Remove redundant Mounts when start docker daemon
|
||||
8b031c9488 * devicemapper: remove redundant mountpoint when docker
|
||||
restart
|
||||
9a3c14633e * Revert "devicemapper: remove redundant mountpoint when
|
||||
docker restart"
|
||||
7bbda93537 * devicemapper: remove redundant mountpoint when docker
|
||||
restart
|
||||
0be4e475d7 * remove redundant containers/xxx/shm mountpoint
|
||||
d4adbe2bf7 * Remove redundant overlay2 mountpoints
|
||||
|
||||
---
|
||||
Remove redundant Mounts when start docker daemon
|
||||
|
||||
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
---
|
||||
devicemapper: remove redundant mountpoint when docker restart
|
||||
|
||||
Modify the regexp patterns in `getIdPatterns` in order to match
|
||||
`/var/lib/docker/devicemapper/mnt/xxx-init`.
|
||||
|
||||
Fix #254
|
||||
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
---
|
||||
Revert "devicemapper: remove redundant mountpoint when docker restart"
|
||||
|
||||
With this commit, daemon will restart with error:
|
||||
```
|
||||
level=error msg="devmapper: Error unmounting device
|
||||
0019325b1b09c75da1c9c97dcffdc024498d318b2c148e4ebe67b1cda4ac446e:
|
||||
devmapper: Unknown device
|
||||
0019325b1b09c75da1c9c97dcffdc024498d318b2c148e4ebe67b1cda4ac446e"
|
||||
```
|
||||
Here, the redundant device is `xxx-init` not `xxx`.
|
||||
|
||||
This reverts commit 8b031c9488236a9a808be7aed4cce69786dec010.
|
||||
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
---
|
||||
devicemapper: remove redundant mountpoint when docker restart
|
||||
|
||||
Modify the regexp patterns in `getIdPatterns` in order to match
|
||||
`/var/lib/docker/devicemapper/mnt/xxx-init`.
|
||||
|
||||
Fix #254
|
||||
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
---
|
||||
remove redundant containers/xxx/shm mountpoint
|
||||
|
||||
fix problems caused by killing docker daemon when running a container
|
||||
once restarted, docker ps shows container in created status but failed
|
||||
to rm it with `container/xxx/shm device or resource busy`
|
||||
|
||||
|
||||
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
|
||||
---
|
||||
Remove redundant overlay2 mountpoints
|
||||
|
||||
Modify the regexp patterns in `getIdPatterns` in order to match
|
||||
/var/lib/docker/overlay2/xxx/merged.
|
||||
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
---
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
|
||||
Change-Id: I4859d9cca731477fc64be6772d8c4b89a000f1b5
|
||||
---
|
||||
components/engine/daemon/daemon.go | 6 +
|
||||
components/engine/daemon/daemon_unix.go | 132 ++++++++++++++++++
|
||||
components/engine/daemon/daemon_unix_test.go | 29 ++++
|
||||
components/engine/daemon/daemon_windows.go | 4 +
|
||||
components/engine/daemon/images/service.go | 4 +
|
||||
.../engine/distribution/xfer/download_test.go | 4 +
|
||||
components/engine/layer/layer.go | 1 +
|
||||
components/engine/layer/layer_store.go | 4 +
|
||||
8 files changed, 184 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index a058688dd3..b207709f7c 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -486,6 +486,12 @@ func (daemon *Daemon) restore() error {
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
+ err = daemon.removeRedundantMounts(containers)
|
||||
+ if err != nil {
|
||||
+ // just print error info
|
||||
+ logrus.Errorf("removeRedundantMounts failed %v", err)
|
||||
+ }
|
||||
+
|
||||
containerIDs := make(map[string]struct{})
|
||||
for cid, _ := range containers {
|
||||
containerIDs[cid] = struct{}{}
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index 8ffdd0009a..d4a32a0b25 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
+ "regexp"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
@@ -1587,3 +1588,134 @@ func (daemon *Daemon) setupSeccompProfile() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
+
|
||||
+func getIdPatterns(id string) (regexps []*regexp.Regexp) {
|
||||
+ var patterns []string
|
||||
+ if id == "" {
|
||||
+ id = "(?P<id>[0-9a-f]{64})"
|
||||
+ }
|
||||
+ patterns = append(patterns, "aufs/mnt/"+id+"(-init)?"+"$", "overlay/"+id+"(-init)?"+"/merged$", "overlay2/"+id+"(-init)?"+"/merged$", "zfs/graph/"+id+"(-init)?"+"$", "devicemapper/mnt/"+id+"(-init)?"+"$")
|
||||
+ for _, p := range patterns {
|
||||
+ r, err := regexp.Compile(p)
|
||||
+ if err == nil {
|
||||
+ regexps = append(regexps, r)
|
||||
+ }
|
||||
+ }
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
+func getContainerMountId(path string) (bool, string) {
|
||||
+ regs := getIdPatterns("")
|
||||
+ for _, reg := range regs {
|
||||
+ ret := reg.FindStringSubmatch(path)
|
||||
+ if len(ret) == 3 {
|
||||
+ if ret[2] == "" {
|
||||
+ return false, ret[1]
|
||||
+ } else {
|
||||
+ return true, ret[1]
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return false, ""
|
||||
+}
|
||||
+
|
||||
+func isContainerMount(path string) (bool, string) {
|
||||
+ var regs []*regexp.Regexp
|
||||
+ var patterns []string
|
||||
+ var id = "(?P<id>[0-9a-f]{64})"
|
||||
+
|
||||
+ // TODO: fill in patterns with other mounts info
|
||||
+ patterns = append(patterns, "containers/"+id+"/shm$")
|
||||
+ for _, p := range patterns {
|
||||
+ r, err := regexp.Compile(p)
|
||||
+ if err == nil {
|
||||
+ regs = append(regs, r)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ for _, reg := range regs {
|
||||
+ ret := reg.FindStringSubmatch(path)
|
||||
+ if len(ret) == 2 {
|
||||
+ return true, ret[1]
|
||||
+ }
|
||||
+ }
|
||||
+ return false, ""
|
||||
+}
|
||||
+
|
||||
+func (daemon *Daemon) removeRedundantMounts(containers map[string]*container.Container) error {
|
||||
+ var (
|
||||
+ isShmMount, isInitdev bool
|
||||
+ id string
|
||||
+ redundantMounts = map[string]bool{}
|
||||
+ )
|
||||
+
|
||||
+ // Get redundant Mounts
|
||||
+ f, err := os.Open("/proc/self/mountinfo")
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ defer f.Close()
|
||||
+
|
||||
+ activeContainers := map[string]string{}
|
||||
+ for _, c := range containers {
|
||||
+ if c.IsRunning() && !c.IsRestarting() {
|
||||
+ activeContainers[c.ID] = c.ID
|
||||
+ if mountid, err := daemon.imageService.GetLayerMountID(c.ID, c.OS); err == nil {
|
||||
+ activeContainers[mountid] = c.ID
|
||||
+ logrus.Debugf("removeRedundantMounts, mountid %s, containerID %s\n", mountid, c.ID)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ root := filepath.Join(daemon.root, daemon.imageService.GraphDriverForOS(runtime.GOOS))
|
||||
+ scanner := bufio.NewScanner(f)
|
||||
+ for scanner.Scan() {
|
||||
+ text := scanner.Text()
|
||||
+ fields := strings.Split(text, " ")
|
||||
+ if len(fields) < 5 {
|
||||
+ return fmt.Errorf("%s", "/proc/self/mountinfo format err")
|
||||
+ }
|
||||
+ path := fields[4]
|
||||
+ if !strings.HasPrefix(path, daemon.root) || path == root {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ isShmMount, id = isContainerMount(path)
|
||||
+ if !isShmMount {
|
||||
+ isInitdev, id = getContainerMountId(path)
|
||||
+ }
|
||||
+ if id == "" {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if _, ok := activeContainers[id]; !ok {
|
||||
+ if isShmMount {
|
||||
+ redundantMounts[path] = true
|
||||
+ } else {
|
||||
+ if isInitdev {
|
||||
+ id = fmt.Sprintf("%s-init", id)
|
||||
+ }
|
||||
+ redundantMounts[id] = false
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ if err := scanner.Err(); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ // Remove redundant Mounts
|
||||
+ for path, shm := range redundantMounts {
|
||||
+ var (
|
||||
+ err error
|
||||
+ )
|
||||
+ logrus.Debugf("Umount legacy mountpoint [%s]", path)
|
||||
+ if shm {
|
||||
+ err = mount.Unmount(path)
|
||||
+ } else {
|
||||
+ err = daemon.imageService.DriverPut(runtime.GOOS, path)
|
||||
+ }
|
||||
+ if err != nil {
|
||||
+ logrus.Debugf("Umount legacy mountpoint: %s failed with %s", path, err)
|
||||
+ }
|
||||
+ }
|
||||
+ return err
|
||||
+}
|
||||
diff --git a/components/engine/daemon/daemon_unix_test.go b/components/engine/daemon/daemon_unix_test.go
|
||||
index 36c6030988..d9bba54a93 100644
|
||||
--- a/components/engine/daemon/daemon_unix_test.go
|
||||
+++ b/components/engine/daemon/daemon_unix_test.go
|
||||
@@ -266,3 +266,32 @@ func TestNetworkOptions(t *testing.T) {
|
||||
t.Fatal("Expected networkOptions error, got nil")
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestGetContainerMountId(t *testing.T) {
|
||||
+ id := "56e143922c405419a38b23bfbccc92284f35525e3f2ad7011ea904501ccd1219"
|
||||
+
|
||||
+ id1 := getContainerMountId("/var/lib/docker/aufs/mnt/" + id)
|
||||
+ if id1 != id {
|
||||
+ t.Fatalf("Expected container mount id [%s], but got [%s]", id, id1)
|
||||
+ }
|
||||
+
|
||||
+ id1 = getContainerMountId("/var/lib/docker/devicemapper/mnt/" + id)
|
||||
+ if id1 != id {
|
||||
+ t.Fatalf("Expected container mount id [%s], but got [%s]", id, id1)
|
||||
+ }
|
||||
+
|
||||
+ id1 = getContainerMountId("/var/lib/docker/overlay/" + id + "/merged")
|
||||
+ if id1 != id {
|
||||
+ t.Fatalf("Expected container mount id [%s], but got [%s]", id, id1)
|
||||
+ }
|
||||
+
|
||||
+ id1 = getContainerMountId("/var/lib/docker/zfs/graph/" + id)
|
||||
+ if id1 != id {
|
||||
+ t.Fatalf("Expected container mount id [%s], but got [%s]", id, id1)
|
||||
+ }
|
||||
+
|
||||
+ id1 = getContainerMountId("/var/lib/docker/devicemapper_err/mnt" + id)
|
||||
+ if id1 != "" {
|
||||
+ t.Fatalf("Expected a empty container mount id, but got [%s]", id1)
|
||||
+ }
|
||||
+}
|
||||
diff --git a/components/engine/daemon/daemon_windows.go b/components/engine/daemon/daemon_windows.go
|
||||
index 4812236bc2..9d895b3dfa 100644
|
||||
--- a/components/engine/daemon/daemon_windows.go
|
||||
+++ b/components/engine/daemon/daemon_windows.go
|
||||
@@ -657,3 +657,7 @@ func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error {
|
||||
|
||||
func setupResolvConf(config *config.Config) {
|
||||
}
|
||||
+
|
||||
+func (daemon *Daemon) removeRedundantMounts(containers map[string]*container.Container) error {
|
||||
+ return nil
|
||||
+}
|
||||
diff --git a/components/engine/daemon/images/service.go b/components/engine/daemon/images/service.go
|
||||
index 8d187e2603..e43a4c6651 100644
|
||||
--- a/components/engine/daemon/images/service.go
|
||||
+++ b/components/engine/daemon/images/service.go
|
||||
@@ -193,6 +193,10 @@ func (i *ImageService) ReleaseLayer(rwlayer layer.RWLayer, containerOS string) e
|
||||
return nil
|
||||
}
|
||||
|
||||
+func (i *ImageService) DriverPut(os string, path string) error {
|
||||
+ return i.layerStores[os].DriverPut(path)
|
||||
+}
|
||||
+
|
||||
// LayerDiskUsage returns the number of bytes used by layer stores
|
||||
// called from disk_usage.go
|
||||
func (i *ImageService) LayerDiskUsage(ctx context.Context) (int64, error) {
|
||||
diff --git a/components/engine/distribution/xfer/download_test.go b/components/engine/distribution/xfer/download_test.go
|
||||
index 91153591ed..c4c4aefba9 100644
|
||||
--- a/components/engine/distribution/xfer/download_test.go
|
||||
+++ b/components/engine/distribution/xfer/download_test.go
|
||||
@@ -146,6 +146,10 @@ func (ls *mockLayerStore) Cleanup() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+func (ls *mockLayerStore) DriverPut(id string) error {
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
func (ls *mockLayerStore) DriverStatus() [][2]string {
|
||||
return [][2]string{}
|
||||
}
|
||||
diff --git a/components/engine/layer/layer.go b/components/engine/layer/layer.go
|
||||
index 425006854d..cb13c98d0b 100644
|
||||
--- a/components/engine/layer/layer.go
|
||||
+++ b/components/engine/layer/layer.go
|
||||
@@ -191,6 +191,7 @@ type Store interface {
|
||||
ReleaseRWLayer(RWLayer) ([]Metadata, error)
|
||||
|
||||
Cleanup() error
|
||||
+ DriverPut(id string) error
|
||||
DriverStatus() [][2]string
|
||||
DriverName() string
|
||||
CleanupRedundant(map[string]struct{}) error
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 351f787b87..5decb0bdce 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -807,6 +807,10 @@ func (ls *layerStore) Cleanup() error {
|
||||
return ls.driver.Cleanup()
|
||||
}
|
||||
|
||||
+func (ls *layerStore) DriverPut(id string) error {
|
||||
+ return ls.driver.Put(id)
|
||||
+}
|
||||
+
|
||||
func (ls *layerStore) DriverStatus() [][2]string {
|
||||
return ls.driver.Status()
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
166
patch/0040-devmapper-devicemapper-add-API-GetDeviceList.patch
Normal file
166
patch/0040-devmapper-devicemapper-add-API-GetDeviceList.patch
Normal file
@ -0,0 +1,166 @@
|
||||
From 9df99e9c4b27a3ccfae5f9b5b285784aeaaf1ac9 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Mon, 7 Jan 2019 13:36:04 +0800
|
||||
Subject: [PATCH 040/111] devmapper: devicemapper: add API
|
||||
GetDeviceList
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick from 58fa445402 * devicemapper: add API GetDeviceList
|
||||
|
||||
Change-Id: Ia52611b75f12179bbe2e718e1b8575f0825d5dd7
|
||||
Signed-off-by: Wang Long <long.wanglong@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../engine/pkg/devicemapper/devmapper.go | 21 ++++++
|
||||
.../pkg/devicemapper/devmapper_wrapper.go | 67 +++++++++++++++++++
|
||||
2 files changed, 88 insertions(+)
|
||||
|
||||
diff --git a/components/engine/pkg/devicemapper/devmapper.go b/components/engine/pkg/devicemapper/devmapper.go
|
||||
index b384a27f8f..06ddc3e96b 100644
|
||||
--- a/components/engine/pkg/devicemapper/devmapper.go
|
||||
+++ b/components/engine/pkg/devicemapper/devmapper.go
|
||||
@@ -55,6 +55,7 @@ var (
|
||||
ErrTaskGetDeps = errors.New("dm_task_get_deps failed")
|
||||
ErrTaskGetInfo = errors.New("dm_task_get_info failed")
|
||||
ErrTaskGetDriverVersion = errors.New("dm_task_get_driver_version failed")
|
||||
+ ErrTaskGetNames = errors.New("dm_task_get_names failed")
|
||||
ErrTaskDeferredRemove = errors.New("dm_task_deferred_remove failed")
|
||||
ErrTaskSetCookie = errors.New("dm_task_set_cookie failed")
|
||||
ErrNilCookie = errors.New("cookie ptr can't be nil")
|
||||
@@ -241,6 +242,14 @@ func (t *Task) getInfoWithDeferred() (*Info, error) {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
+func (t *Task) getDeviceList() ([]string, error) {
|
||||
+ res := DmTaskGetNames(t.unmanaged)
|
||||
+ if res == nil {
|
||||
+ return nil, ErrTaskGetNames
|
||||
+ }
|
||||
+ return res, nil
|
||||
+}
|
||||
+
|
||||
func (t *Task) getDriverVersion() (string, error) {
|
||||
res := DmTaskGetDriverVersion(t.unmanaged)
|
||||
if res == "" {
|
||||
@@ -569,6 +578,18 @@ func GetInfoWithDeferred(name string) (*Info, error) {
|
||||
return task.getInfoWithDeferred()
|
||||
}
|
||||
|
||||
+// GetDevices get all device name
|
||||
+func GetDeviceList() ([]string, error) {
|
||||
+ task := TaskCreate(deviceList)
|
||||
+ if task == nil {
|
||||
+ return nil, fmt.Errorf("devicemapper: Can't create deviceList task")
|
||||
+ }
|
||||
+ if err := task.run(); err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
+ return task.getDeviceList()
|
||||
+}
|
||||
+
|
||||
// GetDriverVersion is the programmatic example of "dmsetup version".
|
||||
// It outputs version information of the driver.
|
||||
func GetDriverVersion() (string, error) {
|
||||
diff --git a/components/engine/pkg/devicemapper/devmapper_wrapper.go b/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
index 77cd674a09..3b00a3b54b 100644
|
||||
--- a/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
+++ b/components/engine/pkg/devicemapper/devmapper_wrapper.go
|
||||
@@ -6,6 +6,9 @@ package devicemapper // import "github.com/docker/docker/pkg/devicemapper"
|
||||
#define _GNU_SOURCE
|
||||
#include <libdevmapper.h>
|
||||
#include <linux/fs.h> // FIXME: present only for BLKGETSIZE64, maybe we can remove it?
|
||||
+#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
|
||||
// FIXME: Can't we find a way to do the logging in pure Go?
|
||||
extern void DevmapperLogCallback(int level, char *file, int line, int dm_errno_or_class, char *str);
|
||||
@@ -32,6 +35,51 @@ static void log_with_errno_init()
|
||||
{
|
||||
dm_log_with_errno_init(log_cb);
|
||||
}
|
||||
+
|
||||
+// FIXME: how to use dm_task_get_names directly
|
||||
+static char **local_dm_task_get_names(struct dm_task *dmt, unsigned int *size) {
|
||||
+ struct dm_names *ns, *ns1;
|
||||
+ unsigned next = 0;
|
||||
+ char **result;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (!(ns = dm_task_get_names(dmt)))
|
||||
+ return NULL;
|
||||
+
|
||||
+ // No devices found
|
||||
+ if (!ns->dev)
|
||||
+ return NULL;
|
||||
+
|
||||
+ // calucate the total devices
|
||||
+ ns1 = ns;
|
||||
+ *size = 0;
|
||||
+ do {
|
||||
+ ns1 = (struct dm_names *)((char *) ns1 + next);
|
||||
+ (*size)++;
|
||||
+ next = ns1->next;
|
||||
+ } while (next);
|
||||
+
|
||||
+ result = malloc(sizeof(char *)* (*size));
|
||||
+ if (!result)
|
||||
+ return NULL;
|
||||
+
|
||||
+ next = 0;
|
||||
+ do {
|
||||
+ ns = (struct dm_names *)((char *) ns + next);
|
||||
+ result[i++] = strdup(ns->name);
|
||||
+ next = ns->next;
|
||||
+ } while (next);
|
||||
+
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+void free_devices_names(char **names, unsigned int size) {
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < size; i++)
|
||||
+ free(names[i]);
|
||||
+ free(names);
|
||||
+}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -69,6 +117,7 @@ var (
|
||||
DmTaskGetDeps = dmTaskGetDepsFct
|
||||
DmTaskGetInfo = dmTaskGetInfoFct
|
||||
DmTaskGetDriverVersion = dmTaskGetDriverVersionFct
|
||||
+ DmTaskGetNames = dmTaskGetNamesFct
|
||||
DmTaskRun = dmTaskRunFct
|
||||
DmTaskSetAddNode = dmTaskSetAddNodeFct
|
||||
DmTaskSetCookie = dmTaskSetCookieFct
|
||||
@@ -190,6 +239,24 @@ func dmTaskGetInfoFct(task *cdmTask, info *Info) int {
|
||||
return int(C.dm_task_get_info((*C.struct_dm_task)(task), &Cinfo))
|
||||
}
|
||||
|
||||
+func dmTaskGetNamesFct(task *cdmTask) []string {
|
||||
+ var res []string
|
||||
+ var names []*C.char
|
||||
+ len := C.uint(0)
|
||||
+ Cnames := C.local_dm_task_get_names((*C.struct_dm_task)(task), &len)
|
||||
+ defer C.free_devices_names(Cnames, len)
|
||||
+
|
||||
+ hdr := (*reflect.SliceHeader)(unsafe.Pointer(&names))
|
||||
+ hdr.Cap = int(len)
|
||||
+ hdr.Len = int(len)
|
||||
+ hdr.Data = uintptr(unsafe.Pointer(Cnames))
|
||||
+
|
||||
+ for _, name := range names {
|
||||
+ res = append(res, C.GoString(name))
|
||||
+ }
|
||||
+ return res
|
||||
+}
|
||||
+
|
||||
func dmTaskGetDriverVersionFct(task *cdmTask) string {
|
||||
buffer := C.malloc(128)
|
||||
defer C.free(buffer)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
From 544b5be235f9a34a5c75a936549bf6d6f2280339 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 15:22:26 +0800
|
||||
Subject: [PATCH 041/111] devmapper: devmapper: remove broken device
|
||||
when start daemon
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick from
|
||||
6104c8e237 | * devmapper: remove broken device when start daemon
|
||||
|
||||
When use `kill -9 docker-daemon-pid` to stop docker, It may casue that
|
||||
the status of devicemapper devices inconsisitent. eg, we can see the
|
||||
device info use `dmsetup status` command, but the device does not exist
|
||||
in `/dev/mapper` directory.
|
||||
|
||||
At next time docker start, it will start failed or load container
|
||||
failed.
|
||||
|
||||
This patch add a check when docker start in `initDevmapper` function.
|
||||
First, we find all devmapper devices in the system. Then If the device
|
||||
name has a prefix with `docker-{major}:{minor}-{inode}` and the length
|
||||
is equal to zero, we use `devicemapper.RemoveDevice` remove the device.
|
||||
|
||||
|
||||
Change-Id: I7eccf4e9539751d615b953abf94951b7e94153d1
|
||||
Signed-off-by: Wang Long <long.wanglong@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/devmapper/deviceset.go | 23 +++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index be48d92e8d..b3e142e2ba 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -1732,6 +1732,29 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
|
||||
devices.devicePrefix = fmt.Sprintf("docker-%d:%d-%d", major(st.Dev), minor(st.Dev), st.Ino)
|
||||
logger.Debugf("Generated prefix: %s", devices.devicePrefix)
|
||||
|
||||
+ deviceNames, err := devicemapper.GetDeviceList()
|
||||
+ if err != nil {
|
||||
+ logrus.Debugf("devmapper: Failed to get device list: %s", err)
|
||||
+ }
|
||||
+
|
||||
+ for _, name := range deviceNames {
|
||||
+ if !strings.HasPrefix(name, devices.devicePrefix) {
|
||||
+ continue
|
||||
+ }
|
||||
+ _, length, _, _, err := devicemapper.GetStatus(name)
|
||||
+ if err != nil {
|
||||
+ logrus.Warnf("devmapper: get device status(%s): %s", name, err)
|
||||
+ continue
|
||||
+ }
|
||||
+ // remove broken device
|
||||
+ if length == 0 {
|
||||
+ if err := devicemapper.RemoveDevice(name); err != nil {
|
||||
+ logrus.Warnf("devmapper: remove broken device(%s): %s", name, err)
|
||||
+ }
|
||||
+ logrus.Debugf("devmapper: remove broken device: %s", name)
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
// Check for the existence of the thin-pool device
|
||||
poolExists, err := devices.thinPoolExists(devices.getPoolName())
|
||||
if err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
137
patch/0042-oci-Cannot-join-own-pid-ipc-namespace.patch
Normal file
137
patch/0042-oci-Cannot-join-own-pid-ipc-namespace.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 50c51324293064e12e99da9dfbb3554ab1255f51 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 15:30:42 +0800
|
||||
Subject: [PATCH 042/111] oci: Cannot join own pid/ipc namespace
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
Change-Id: I34a0d97a4196d509d80d20f262f3fbac555e0745
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../daemon/container_operations_unix.go | 20 +++++++++-----
|
||||
components/engine/daemon/oci_linux.go | 2 +-
|
||||
.../integration-cli/docker_cli_run_test.go | 27 +++++++++++++++++++
|
||||
3 files changed, 42 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/container_operations_unix.go b/components/engine/daemon/container_operations_unix.go
|
||||
index 9953c7f3fd..2cc2b2e3cd 100644
|
||||
--- a/components/engine/daemon/container_operations_unix.go
|
||||
+++ b/components/engine/daemon/container_operations_unix.go
|
||||
@@ -58,13 +58,17 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
|
||||
return env, nil
|
||||
}
|
||||
|
||||
-func (daemon *Daemon) getIpcContainer(id string) (*container.Container, error) {
|
||||
- errMsg := "can't join IPC of container " + id
|
||||
+func (daemon *Daemon) getIpcContainer(cc *container.Container) (*container.Container, error) {
|
||||
+ containerID := cc.HostConfig.IpcMode.Container()
|
||||
+ errMsg := "can't join IPC of container " + containerID
|
||||
// Check the container exists
|
||||
- container, err := daemon.GetContainer(id)
|
||||
+ container, err := daemon.GetContainer(containerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, errMsg)
|
||||
}
|
||||
+ if container.ID == cc.ID {
|
||||
+ return nil, fmt.Errorf("cannot join own ipc namespace")
|
||||
+ }
|
||||
// Check the container is running and not restarting
|
||||
if err := daemon.checkContainer(container, containerIsRunning, containerIsNotRestarting); err != nil {
|
||||
return nil, errors.Wrap(err, errMsg)
|
||||
@@ -81,12 +85,16 @@ func (daemon *Daemon) getIpcContainer(id string) (*container.Container, error) {
|
||||
return container, nil
|
||||
}
|
||||
|
||||
-func (daemon *Daemon) getPidContainer(container *container.Container) (*container.Container, error) {
|
||||
- containerID := container.HostConfig.PidMode.Container()
|
||||
+func (daemon *Daemon) getPidContainer(cc *container.Container) (*container.Container, error) {
|
||||
+ containerID := cc.HostConfig.PidMode.Container()
|
||||
container, err := daemon.GetContainer(containerID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot join PID of a non running container: %s", containerID)
|
||||
}
|
||||
+ if container.ID == cc.ID {
|
||||
+ return nil, fmt.Errorf("cannot join own pid namespace")
|
||||
+ }
|
||||
+
|
||||
return container, daemon.checkContainer(container, containerIsRunning, containerIsNotRestarting)
|
||||
}
|
||||
|
||||
@@ -109,7 +117,7 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
||||
|
||||
switch {
|
||||
case ipcMode.IsContainer():
|
||||
- ic, err := daemon.getIpcContainer(ipcMode.Container())
|
||||
+ ic, err := daemon.getIpcContainer(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diff --git a/components/engine/daemon/oci_linux.go b/components/engine/daemon/oci_linux.go
|
||||
index 884739c07e..f5270bd545 100644
|
||||
--- a/components/engine/daemon/oci_linux.go
|
||||
+++ b/components/engine/daemon/oci_linux.go
|
||||
@@ -256,7 +256,7 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error
|
||||
switch {
|
||||
case ipcMode.IsContainer():
|
||||
ns := specs.LinuxNamespace{Type: "ipc"}
|
||||
- ic, err := daemon.getIpcContainer(ipcMode.Container())
|
||||
+ ic, err := daemon.getIpcContainer(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diff --git a/components/engine/integration-cli/docker_cli_run_test.go b/components/engine/integration-cli/docker_cli_run_test.go
|
||||
index 4f55c05aeb..4a137c6159 100644
|
||||
--- a/components/engine/integration-cli/docker_cli_run_test.go
|
||||
+++ b/components/engine/integration-cli/docker_cli_run_test.go
|
||||
@@ -2323,6 +2323,15 @@ func (s *DockerSuite) TestRunModeIpcContainerNotExists(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
+func (s *DockerSuite) TestJoinOwnIpcNamespace(c *check.C) {
|
||||
+ // Not applicable on Windows as uses Unix-specific capabilities
|
||||
+ testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
+ _, _, err := dockerCmdWithError("run", "-d", "--name", "testipc", "--ipc", "container:testipc", "busybox", "top")
|
||||
+ if err == nil {
|
||||
+ c.Fatalf("Join own ipc namespace is not permitted")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func (s *DockerSuite) TestRunModeIpcContainerNotRunning(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux)
|
||||
@@ -2383,6 +2392,15 @@ func (s *DockerSuite) TestRunModePIDContainerNotRunning(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
+func (s *DockerSuite) TestJoinOwnPidNamespace(c *check.C) {
|
||||
+ // Not applicable on Windows as uses Unix-specific capabilities
|
||||
+ testRequires(c, DaemonIsLinux)
|
||||
+ _, _, err := dockerCmdWithError("run", "-d", "--name", "testpid", "--pid", "container:testpid", "busybox", "top")
|
||||
+ if err == nil {
|
||||
+ c.Fatalf("Join own pid namespace is not permitted")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func (s *DockerSuite) TestRunMountShmMqueueFromHost(c *check.C) {
|
||||
// Not applicable on Windows as uses Unix-specific capabilities
|
||||
testRequires(c, SameHostDaemon, DaemonIsLinux, NotUserNamespace)
|
||||
@@ -2621,6 +2639,15 @@ func (s *DockerSuite) TestRunNetContainerWhichHost(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
+func (s *DockerSuite) TestJoinOwnNetNamespace(c *check.C) {
|
||||
+ // Not applicable on Windows as uses Unix-specific capabilities
|
||||
+ testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
+ _, _, err := dockerCmdWithError("run", "-d", "--name", "testnet", "--net", "container:testnet", "busybox", "top")
|
||||
+ if err == nil {
|
||||
+ c.Fatalf("Join own net namespace is not permitted")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func (s *DockerSuite) TestRunAllowPortRangeThroughPublish(c *check.C) {
|
||||
// TODO Windows. This may be possible to enable in the future. However,
|
||||
// Windows does not currently support --expose, or populate the network
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
From f70a2648621ab1463299eabecda8e8c7584831c3 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 16:01:36 +0800
|
||||
Subject: [PATCH 043/111] docker: Make sure the pid exist in pidfile
|
||||
is docker
|
||||
|
||||
reason: cherry-pick commits to docker-18.09.
|
||||
|
||||
cherry-pick from
|
||||
b4714e3321 | * Make sure the pid exist in pidfile is docker
|
||||
|
||||
|
||||
Because of the recycling of used PIDs policy in kernel,
|
||||
it could be possible that the process died with pidfile existing
|
||||
and when the process boot next time, the pid in pidfile has been assigned
|
||||
to another process, this would make the process can't be boot again without
|
||||
removing the pidfile manually.
|
||||
|
||||
Change-Id: I237566682716733174900cd4dc76ce74ff9f4195
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/pkg/pidfile/pidfile.go | 30 +++++++++++++++++++++++-
|
||||
1 file changed, 29 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/pkg/pidfile/pidfile.go b/components/engine/pkg/pidfile/pidfile.go
|
||||
index 0617a89e5f..485c00138b 100644
|
||||
--- a/components/engine/pkg/pidfile/pidfile.go
|
||||
+++ b/components/engine/pkg/pidfile/pidfile.go
|
||||
@@ -4,6 +4,7 @@
|
||||
package pidfile // import "github.com/docker/docker/pkg/pidfile"
|
||||
|
||||
import (
|
||||
+ "bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -19,12 +20,39 @@ type PIDFile struct {
|
||||
path string
|
||||
}
|
||||
|
||||
+// isSameApplication check whether the pid exist in pidfile
|
||||
+// is the the same application we are going to run.
|
||||
+func isSameApplication(pid int) (bool, error) {
|
||||
+ path := filepath.Join("/proc", strconv.Itoa(pid), "status")
|
||||
+ file, err := os.Open(path)
|
||||
+ if err != nil {
|
||||
+ return false, err
|
||||
+ }
|
||||
+ defer file.Close()
|
||||
+ sc := bufio.NewScanner(file)
|
||||
+ for sc.Scan() {
|
||||
+ lens := strings.Split(sc.Text(), ":")
|
||||
+ if len(lens) == 2 && strings.TrimSpace(lens[0]) == "Name" {
|
||||
+ if strings.TrimSpace(lens[1]) == os.Args[0] {
|
||||
+ return true, nil
|
||||
+ }
|
||||
+ return false, nil
|
||||
+ }
|
||||
+ }
|
||||
+ if err := sc.Err(); err != nil {
|
||||
+ return false, err
|
||||
+ }
|
||||
+ return false, nil
|
||||
+}
|
||||
+
|
||||
func checkPIDFileAlreadyExists(path string) error {
|
||||
if pidByte, err := ioutil.ReadFile(path); err == nil {
|
||||
pidString := strings.TrimSpace(string(pidByte))
|
||||
if pid, err := strconv.Atoi(pidString); err == nil {
|
||||
if processExists(pid) {
|
||||
- return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
|
||||
+ if same, err := isSameApplication(pid); same || (err != nil && !os.IsNotExist(err)) {
|
||||
+ return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
|
||||
+ }
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
From 75d53c469ea6115db0386155262565a8aa15556d Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 16:04:37 +0800
|
||||
Subject: [PATCH 044/111] plugin: Fix plugin security bug caused by
|
||||
unchecked plugin name
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick from 48c9622f82 | * plugin,bugfix: Fix plugin security bug
|
||||
caused by unchecked plugin name
|
||||
|
||||
Docker may activate plugins outside plugin directory if plugin name
|
||||
contains string like "../../". This patch fix this bug by checking the
|
||||
combined plugin path before use it.
|
||||
|
||||
fix issue docker/docker#268
|
||||
|
||||
Change-Id: Icff8b24e50fc92721149267bc8c29a8652046d8a
|
||||
Signed-off-by: majiuyue <majiuyue@huawei.com>
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/pkg/plugins/discovery.go | 27 ++++++++++++++++------
|
||||
components/engine/pkg/plugins/plugins.go | 2 +-
|
||||
2 files changed, 21 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/components/engine/pkg/plugins/discovery.go b/components/engine/pkg/plugins/discovery.go
|
||||
index 4b79bd29ad..51f1d8ebea 100644
|
||||
--- a/components/engine/pkg/plugins/discovery.go
|
||||
+++ b/components/engine/pkg/plugins/discovery.go
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
+ // ErrForbidden plugin sock/spec outside allowed location
|
||||
+ ErrForbidden = errors.New("plugin outside allowed location")
|
||||
// ErrNotFound plugin not found
|
||||
ErrNotFound = errors.New("plugin not found")
|
||||
socketsPath = "/run/docker/plugins"
|
||||
@@ -82,7 +84,10 @@ func Scan() ([]string, error) {
|
||||
|
||||
// Plugin returns the plugin registered with the given name (or returns an error).
|
||||
func (l *localRegistry) Plugin(name string) (*Plugin, error) {
|
||||
- socketpaths := pluginPaths(socketsPath, name, ".sock")
|
||||
+ socketpaths, err := pluginPaths(socketsPath, name, ".sock")
|
||||
+ if err != nil {
|
||||
+ return nil, ErrForbidden
|
||||
+ }
|
||||
|
||||
for _, p := range socketpaths {
|
||||
if fi, err := os.Stat(p); err == nil && fi.Mode()&os.ModeSocket != 0 {
|
||||
@@ -92,8 +97,10 @@ func (l *localRegistry) Plugin(name string) (*Plugin, error) {
|
||||
|
||||
var txtspecpaths []string
|
||||
for _, p := range specsPaths {
|
||||
- txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".spec")...)
|
||||
- txtspecpaths = append(txtspecpaths, pluginPaths(p, name, ".json")...)
|
||||
+ for _, ext := range []string{".spec", ".json"} {
|
||||
+ paths, _ := pluginPaths(p, name, ext)
|
||||
+ txtspecpaths = append(txtspecpaths, paths...)
|
||||
+ }
|
||||
}
|
||||
|
||||
for _, p := range txtspecpaths {
|
||||
@@ -146,9 +153,15 @@ func readPluginJSONInfo(name, path string) (*Plugin, error) {
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
-func pluginPaths(base, name, ext string) []string {
|
||||
- return []string{
|
||||
- filepath.Join(base, name+ext),
|
||||
- filepath.Join(base, name, name+ext),
|
||||
+func pluginPaths(base, name, ext string) ([]string, error) {
|
||||
+ paths := []string{
|
||||
+ filepath.Clean(filepath.Join(base, name+ext)),
|
||||
+ filepath.Clean(filepath.Join(base, name, name+ext)),
|
||||
+ }
|
||||
+ for _, p := range paths {
|
||||
+ if !strings.HasPrefix(p, base) {
|
||||
+ return nil, ErrForbidden
|
||||
+ }
|
||||
}
|
||||
+ return paths, nil
|
||||
}
|
||||
diff --git a/components/engine/pkg/plugins/plugins.go b/components/engine/pkg/plugins/plugins.go
|
||||
index 6962079df9..8a6fbeda29 100644
|
||||
--- a/components/engine/pkg/plugins/plugins.go
|
||||
+++ b/components/engine/pkg/plugins/plugins.go
|
||||
@@ -208,7 +208,7 @@ func loadWithRetry(name string, retry bool) (*Plugin, error) {
|
||||
for {
|
||||
pl, err := registry.Plugin(name)
|
||||
if err != nil {
|
||||
- if !retry {
|
||||
+ if !retry || err == ErrForbidden {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
122
patch/0045-overlay-safely-remove-overlay-layer-directory.patch
Normal file
122
patch/0045-overlay-safely-remove-overlay-layer-directory.patch
Normal file
@ -0,0 +1,122 @@
|
||||
From d2901f9efd4b1b26c995ea1c61663a14bc9c55d6 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 3 Jan 2019 16:25:23 +0800
|
||||
Subject: [PATCH 045/111] overlay: safely remove overlay layer
|
||||
directory
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
merge from
|
||||
0af3bf355a * safely remove overlay layer directory
|
||||
e2b1d6827b * docker: add link string validation
|
||||
|
||||
---
|
||||
safely remove overlay layer directory
|
||||
|
||||
do not recover link if the format is illegal
|
||||
do not remove illegal link string
|
||||
|
||||
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
|
||||
---
|
||||
docker: add link string validation
|
||||
|
||||
validate link string with restrict reqirements, not just stringLen.
|
||||
Shukui Yang
|
||||
|
||||
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
|
||||
Change-Id: Ie4f47b942c7e89bd6632d310c1cb34533ed5726b
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 30 +++++++++++++++++--
|
||||
.../daemon/graphdriver/overlay2/randomid.go | 7 +++++
|
||||
2 files changed, 34 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 722d65b11a..773d5232cc 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -419,6 +419,10 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
||||
}
|
||||
|
||||
lid := generateID(idLength)
|
||||
+ if !verifyID(lid, idLength) {
|
||||
+ // this should never happen
|
||||
+ return fmt.Errorf("[overlay2], generated link string(%s) illegal", lid)
|
||||
+ }
|
||||
if err := os.Symlink(path.Join("..", id, "diff"), path.Join(d.home, linkDir, lid)); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -491,6 +495,9 @@ func (d *Driver) getLower(parent string) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
+ if !verifyID(string(parentLink), idLength) {
|
||||
+ return "", fmt.Errorf("illegal link string: %s", parentLink)
|
||||
+ }
|
||||
lowers := []string{path.Join(linkDir, string(parentLink))}
|
||||
|
||||
parentLower, err := ioutil.ReadFile(path.Join(parentDir, lowerFile))
|
||||
@@ -570,7 +577,7 @@ func (d *Driver) Remove(id string) error {
|
||||
dir := d.dir(id)
|
||||
lid, err := ioutil.ReadFile(path.Join(dir, "link"))
|
||||
if err == nil {
|
||||
- if len(lid) == 0 {
|
||||
+ if !verifyID(string(lid), idLength) {
|
||||
logrus.WithField("storage-driver", "overlay2").Errorf("refusing to remove empty link for layer %v", id)
|
||||
} else if err := os.RemoveAll(path.Join(d.home, linkDir, string(lid))); err != nil {
|
||||
logrus.WithField("storage-driver", "overlay2").Debugf("Failed to remove link: %v", err)
|
||||
@@ -703,8 +710,25 @@ func (d *Driver) Put(id string) error {
|
||||
|
||||
// Exists checks to see if the id is already mounted.
|
||||
func (d *Driver) Exists(id string) bool {
|
||||
- _, err := os.Stat(d.dir(id))
|
||||
- return err == nil
|
||||
+ _, rerr := os.Stat(d.dir(id))
|
||||
+ if rerr == nil {
|
||||
+ lstr, err := ioutil.ReadFile(path.Join(d.dir(id), "link"))
|
||||
+ // link is valid
|
||||
+ if err == nil && verifyID(string(lstr), idLength) {
|
||||
+ // check symlink
|
||||
+ _, rerr = os.Stat(path.Join(d.home, linkDir, string(lstr)))
|
||||
+ if rerr != nil {
|
||||
+ os.RemoveAll(path.Join(d.home, linkDir, string(lstr)))
|
||||
+
|
||||
+ logrus.Infof("[overlay2]: symlink (%s) is missing, create a new one", lstr)
|
||||
+ if rerr = os.Symlink(path.Join("..", id, "diff"), path.Join(d.home, linkDir, string(lstr))); rerr != nil {
|
||||
+ return false
|
||||
+ }
|
||||
+ }
|
||||
+ return true
|
||||
+ }
|
||||
+ }
|
||||
+ return false
|
||||
}
|
||||
|
||||
// isParent determines whether the given parent is the direct parent of the
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/randomid.go b/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
index 842c06127f..933d9fccb6 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
+ "regexp"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -79,3 +80,9 @@ func retryOnError(err error) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
+
|
||||
+func verifyID(id string, l int) bool {
|
||||
+ regstr := fmt.Sprintf("^[A-Z0-9]{%d}$", l)
|
||||
+ rgxp := regexp.MustCompile(regstr)
|
||||
+ return rgxp.MatchString(id)
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 024a67b1d7ccfa85bba14318cd4fbbe78ecc8b7e Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 10 Jan 2019 00:17:01 +0800
|
||||
Subject: [PATCH 046/111] debug: add more error info when dial
|
||||
docker.sock fail
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
add more error info when dial docker.sock fail
|
||||
|
||||
cherry-pick from 1.11.2: 91c7491
|
||||
|
||||
Change-Id: I3c7219d44be752ecde92479f03c0e2cee3ccb4a0
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
components/engine/client/request.go | 15 ++++++++++++---
|
||||
1 file changed, 12 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/client/request.go b/components/engine/client/request.go
|
||||
index a19d62aa52..855b84d6ac 100644
|
||||
--- a/components/engine/client/request.go
|
||||
+++ b/components/engine/client/request.go
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
+ "regexp"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -156,11 +157,19 @@ func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResp
|
||||
|
||||
if err, ok := err.(net.Error); ok {
|
||||
if err.Timeout() {
|
||||
- return serverResp, ErrorConnectionFailed(cli.host)
|
||||
+ return serverResp, fmt.Errorf("Cannot connect to the Docker daemon failed for timeout.")
|
||||
}
|
||||
if !err.Temporary() {
|
||||
- if strings.Contains(err.Error(), "connection refused") || strings.Contains(err.Error(), "dial unix") {
|
||||
- return serverResp, ErrorConnectionFailed(cli.host)
|
||||
+ if strings.Contains(err.Error(), "dial unix") {
|
||||
+ var err2 error
|
||||
+ r, rerr := regexp.Compile("dial unix.*")
|
||||
+ if rerr != nil {
|
||||
+ err2 = fmt.Errorf("Cannot connect to the Docker daemon failed for dial unix.")
|
||||
+ } else {
|
||||
+ rbytes := r.Find([]byte(err.Error()))
|
||||
+ err2 = fmt.Errorf("Cannot connect to the Docker daemon failed for %s", string(rbytes))
|
||||
+ }
|
||||
+ return serverResp, err2
|
||||
}
|
||||
}
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
59
patch/0047-docker-fix-panic-slice-bounds-out-of-range.patch
Normal file
59
patch/0047-docker-fix-panic-slice-bounds-out-of-range.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 8483caa076b11f33e9a4c578b8aefce127468e66 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Fri, 11 Jan 2019 12:18:27 +0800
|
||||
Subject: [PATCH 047/111] docker: fix panic slice bounds out of range
|
||||
|
||||
reason: fix panic
|
||||
|
||||
panic: runtime error: slice bounds out of range
|
||||
|
||||
goroutine 1 [running]:
|
||||
github.com/docker/docker/daemon.parseInitVersion(0xc4209da600, 0x22, 0x22, 0x600, 0xc4209da600, 0x22, 0x28, 0x0)
|
||||
/go/src/github.com/docker/docker/daemon/info_unix.go:163 +0x3ce
|
||||
github.com/docker/docker/daemon.(*Daemon).fillPlatformInfo(0xc4206e21e0, 0xc42009cc00, 0xc42081d220)
|
||||
/go/src/github.com/docker/docker/daemon/info_unix.go:68 +0x115f
|
||||
github.com/docker/docker/daemon.(*Daemon).SystemInfo(0xc4206e21e0, 0x0, 0x0, 0xc42020d3c0)
|
||||
/go/src/github.com/docker/docker/daemon/info.go:75 +0x7e8
|
||||
github.com/docker/docker/daemon.NewDaemon(0x55b515ace080, 0xc4201ab400, 0xc4207c5400, 0xc4207602d0, 0x0, 0x0, 0x0)
|
||||
/go/src/github.com/docker/docker/daemon/daemon.go:1080 +0x2c87
|
||||
main.(*DaemonCli).start(0xc420727260, 0xc42016f6e0, 0x0, 0x0)
|
||||
/go/src/github.com/docker/docker/cmd/dockerd/daemon.go:180 +0x74f
|
||||
main.runDaemon(0xc42016f6e0, 0xc420194600, 0x0)
|
||||
/go/src/github.com/docker/docker/cmd/dockerd/docker_unix.go:7 +0x47
|
||||
main.newDaemonCommand.func1(0xc42076d680, 0xc420190d80, 0x0, 0x8, 0x0, 0x0)
|
||||
/go/src/github.com/docker/docker/cmd/dockerd/docker.go:29 +0x5d
|
||||
github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).execute(0xc42076d680, 0xc42003a0a0, 0x8, 0x8, 0xc42076d680, 0xc42003a0a0)
|
||||
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:762 +0x46a
|
||||
github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).ExecuteC(0xc42076d680, 0x55b515aa3350, 0x55b51565f0c0, 0x55b515aa3360)
|
||||
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:852 +0x30c
|
||||
github.com/docker/docker/vendor/github.com/spf13/cobra.(*Command).Execute(0xc42076d680, 0xc42000e020, 0x55b5138f336f)
|
||||
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:800 +0x2d
|
||||
main.main()
|
||||
/go/src/github.com/docker/docker/cmd/dockerd/docker.go:70 +0xa2
|
||||
|
||||
Change-Id: Iafadb0c9215e1840c084637ebc96f5ef4d004cbd
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/info_unix.go | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/info_unix.go b/components/engine/daemon/info_unix.go
|
||||
index 55b6c6e79b..c53804edec 100644
|
||||
--- a/components/engine/daemon/info_unix.go
|
||||
+++ b/components/engine/daemon/info_unix.go
|
||||
@@ -160,7 +160,11 @@ func parseInitVersion(v string) (types.Commit, error) {
|
||||
gitParts := strings.Split(parts[1], ".")
|
||||
if len(gitParts) == 2 && gitParts[0] == "git" {
|
||||
version.ID = gitParts[1]
|
||||
- version.Expected = dockerversion.InitCommitID[0:len(version.ID)]
|
||||
+ n := len(dockerversion.InitCommitID)
|
||||
+ if n > len(version.ID) {
|
||||
+ n = len(version.ID)
|
||||
+ }
|
||||
+ version.Expected = dockerversion.InitCommitID[0:n]
|
||||
}
|
||||
}
|
||||
if version.ID == "" && strings.HasPrefix(parts[0], "tini version ") {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
36
patch/0048-docker-check-metadata-when-load-layer.patch
Normal file
36
patch/0048-docker-check-metadata-when-load-layer.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 7eb6d78447ed19a19c57331cb63e58097d29caeb Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Tue, 8 Jan 2019 18:19:16 +0800
|
||||
Subject: [PATCH 048/111] docker: check metadata when load layer
|
||||
|
||||
reason:check metadata when load layer
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 41795d7 check metadata when load layer
|
||||
|
||||
Change-Id: Ia1734172a33d0ebe29ddb4b76d207da2981a137a
|
||||
Signed-off-by: Liu Hua <sdu.liu@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/layer/layer_store.go | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 5decb0bdce..f22e9c666c 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -193,6 +193,11 @@ func (ls *layerStore) loadLayer(layer ChainID) (l *roLayer, err error) {
|
||||
return nil, err
|
||||
}
|
||||
cl.parent = p
|
||||
+ } else {
|
||||
+ _, err := ls.driver.GetMetadata(cacheID)
|
||||
+ if err != nil {
|
||||
+ return nil, fmt.Errorf("cacheID %s for layer %s does not have metadata ", cacheID, layer)
|
||||
+ }
|
||||
}
|
||||
|
||||
ls.layerMap[cl.chainID] = cl
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
From 652be7c8c259c25adaed10f6f121a7d18283daa0 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Tue, 8 Jan 2019 19:08:25 +0800
|
||||
Subject: [PATCH 049/111] cleanup: cleanup useless netns file in
|
||||
/var/run/docker/netns
|
||||
|
||||
reason:killing daemon would left useless netns file.
|
||||
try to clean them up during daemon restore according to
|
||||
activesandboxes
|
||||
|
||||
cherrt-pick from docker 1.11.2:
|
||||
- e657d09 cleanup useless netns file in /var/run/docker/netns
|
||||
|
||||
Change-Id: I4bfff028a1ad2df9a42456b9f181db87d63c7cd7
|
||||
Signed-off-by: dengguangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
.../docker/libnetwork/controller.go | 2 ++
|
||||
.../docker/libnetwork/osl/namespace_linux.go | 33 +++++++++++++++++++
|
||||
2 files changed, 35 insertions(+)
|
||||
|
||||
diff --git a/components/engine/vendor/github.com/docker/libnetwork/controller.go b/components/engine/vendor/github.com/docker/libnetwork/controller.go
|
||||
index 2896011dbf..95013d31d3 100644
|
||||
--- a/components/engine/vendor/github.com/docker/libnetwork/controller.go
|
||||
+++ b/components/engine/vendor/github.com/docker/libnetwork/controller.go
|
||||
@@ -247,6 +247,8 @@ func New(cfgOptions ...config.Option) (NetworkController, error) {
|
||||
c.sandboxCleanup(c.cfg.ActiveSandboxes)
|
||||
c.cleanupLocalEndpoints()
|
||||
c.networkCleanup()
|
||||
+ osl.NetnsFileCleanup(c.cfg.ActiveSandboxes)
|
||||
+
|
||||
|
||||
if err := c.startExternalKeyListener(); err != nil {
|
||||
return nil, err
|
||||
diff --git a/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go b/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
|
||||
index bfc5d31a53..f97b286bcd 100644
|
||||
--- a/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
|
||||
+++ b/components/engine/vendor/github.com/docker/libnetwork/osl/namespace_linux.go
|
||||
@@ -586,6 +586,39 @@ func (n *networkNamespace) Restore(ifsopt map[string][]IfaceOption, routes []*ty
|
||||
return nil
|
||||
}
|
||||
|
||||
+func NetnsFileCleanup(activeSandboxes map[string]interface{}) {
|
||||
+ maxLen := 12
|
||||
+ dir, err := ioutil.ReadDir(prefix)
|
||||
+ if err != nil {
|
||||
+ logrus.Warnf("failed to open %s for netns cleanup: %s", prefix, err)
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ activeSandboxesMap := make(map[string]string)
|
||||
+ // shorten active sandboxes id to 12 char
|
||||
+ for ac, _ := range activeSandboxes {
|
||||
+ shortid := ac[:maxLen]
|
||||
+ activeSandboxesMap[shortid] = shortid
|
||||
+ }
|
||||
+
|
||||
+ for _, v := range dir {
|
||||
+ id := v.Name()
|
||||
+ // skip if id length is not 12, like default
|
||||
+ if len(id) != maxLen {
|
||||
+ continue
|
||||
+ }
|
||||
+
|
||||
+ if _, ok := activeSandboxesMap[id]; !ok {
|
||||
+ path := filepath.Join(prefix, id)
|
||||
+ // cleanup netns file if not active
|
||||
+ syscall.Unmount(path, syscall.MNT_DETACH)
|
||||
+ if err := os.Remove(path); err != nil {
|
||||
+ logrus.Warnf("Failed to cleanup netns file %s: %s", path, err)
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Checks whether IPv6 needs to be enabled/disabled on the loopback interface
|
||||
func (n *networkNamespace) checkLoV6() {
|
||||
var (
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 415f93f45004d4082d3a7bcfdee122b584cd2e57 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Tue, 8 Jan 2019 19:34:41 +0800
|
||||
Subject: [PATCH 050/111] volume: Make v.opts to nil if opts.json is
|
||||
null
|
||||
|
||||
reason:Make v.opts to nil if opts.json is null
|
||||
|
||||
cherry-pick from docker 1.11.2:
|
||||
- 1b9344b Make v.opts to nil if opts.json is null
|
||||
|
||||
Change-Id: I59d6ebb41cbb908d72beb4f9f6c645cb7ae2c4ba
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/volume/local/local.go | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/components/engine/volume/local/local.go b/components/engine/volume/local/local.go
|
||||
index 7190de9ed6..2e865815a9 100644
|
||||
--- a/components/engine/volume/local/local.go
|
||||
+++ b/components/engine/volume/local/local.go
|
||||
@@ -89,6 +89,13 @@ func New(scope string, rootIdentity idtools.Identity) (*Root, error) {
|
||||
v.opts = &opts
|
||||
}
|
||||
|
||||
+ // For the local volumes created without options,
|
||||
+ // the opts.json is null, so all the value in v.opts is null
|
||||
+ // We should make v.opts to nil to avoid v.mount
|
||||
+ if v.opts != nil && v.opts.MountType == "" && v.opts.MountOpts == "" && v.opts.MountDevice == "" {
|
||||
+ v.opts = nil
|
||||
+ }
|
||||
+
|
||||
// unmount anything that may still be mounted (for example, from an unclean shutdown)
|
||||
mount.Unmount(v.path)
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
102
patch/0051-docker-fix-panic-when-load-maliciously-image.patch
Normal file
102
patch/0051-docker-fix-panic-when-load-maliciously-image.patch
Normal file
@ -0,0 +1,102 @@
|
||||
From 1fe0a4bfad5d7fa418f4e726211f4f037e59cfee Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Tue, 8 Jan 2019 19:47:28 +0800
|
||||
Subject: [PATCH 051/111] docker: fix panic when load maliciously
|
||||
image
|
||||
|
||||
reason:fix oom panic when load maliciously modified image with
|
||||
huge size manifest files
|
||||
|
||||
cherry-pick from docker 1.11.2:
|
||||
- bbe29c3 fix panic when load maliciously image
|
||||
|
||||
Change-Id: I2525e492fac31c33d3ba7275c95b570322a05025
|
||||
Signed-off-by: leizhongkai <leizhongkai@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/image/tarexport/load.go | 28 +++++++++++++++++++
|
||||
.../engine/image/tarexport/tarexport.go | 1 +
|
||||
2 files changed, 29 insertions(+)
|
||||
|
||||
diff --git a/components/engine/image/tarexport/load.go b/components/engine/image/tarexport/load.go
|
||||
index 786214383e..b9f8f7e3ac 100644
|
||||
--- a/components/engine/image/tarexport/load.go
|
||||
+++ b/components/engine/image/tarexport/load.go
|
||||
@@ -49,6 +49,11 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+
|
||||
+ if err = checkJsonFileSize(manifestPath); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
manifestFile, err := os.Open(manifestPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@@ -72,6 +77,9 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ if err = checkJsonFileSize(configPath); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
config, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -246,6 +254,11 @@ func (l *tarexporter) legacyLoad(tmpDir string, outStream io.Writer, progressOut
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+
|
||||
+ if err = checkJsonFileSize(repositoriesPath); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
repositoriesFile, err := os.Open(repositoriesPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -286,6 +299,9 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
+ if err = checkJsonFileSize(configPath); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
imageJSON, err := ioutil.ReadFile(configPath)
|
||||
if err != nil {
|
||||
logrus.Debugf("Error reading json: %v", err)
|
||||
@@ -413,6 +429,18 @@ func checkValidParent(img, parent *image.Image) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
+func checkJsonFileSize(path string) error {
|
||||
+ fileInfo, err := os.Stat(path)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ fileSize := fileInfo.Size()
|
||||
+ if fileSize > maxJsonFileSize {
|
||||
+ return fmt.Errorf("%s is too large", filepath.Base(path))
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
func checkCompatibleOS(imageOS string) error {
|
||||
// always compatible if the images OS matches the host OS; also match an empty image OS
|
||||
if imageOS == runtime.GOOS || imageOS == "" {
|
||||
diff --git a/components/engine/image/tarexport/tarexport.go b/components/engine/image/tarexport/tarexport.go
|
||||
index beff668cd8..f23fe6f8bb 100644
|
||||
--- a/components/engine/image/tarexport/tarexport.go
|
||||
+++ b/components/engine/image/tarexport/tarexport.go
|
||||
@@ -13,6 +13,7 @@ const (
|
||||
legacyConfigFileName = "json"
|
||||
legacyVersionFileName = "VERSION"
|
||||
legacyRepositoriesFileName = "repositories"
|
||||
+ maxJsonFileSize = (10 * 1024 * 1024)
|
||||
)
|
||||
|
||||
type manifestItem struct {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
194
patch/0052-docker-Lock-the-RWLayer-while-committing-expo.patch
Normal file
194
patch/0052-docker-Lock-the-RWLayer-while-committing-expo.patch
Normal file
@ -0,0 +1,194 @@
|
||||
From 568c9501d56ccff1806253f9e2289fdd5c002231 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Thu, 17 Jan 2019 20:03:14 +0800
|
||||
Subject: [PATCH 052/111] docker: Lock the RWLayer while
|
||||
committing/exporting
|
||||
|
||||
reason:Add a rw mutex to `mountLayer/roLayer/emptyLayer` and introduce
|
||||
new methods `RLockRWLayer()` and `RUnlockRWLayer()` to `RWLayer`.
|
||||
Now the rw layer of the container would be locked to block removal of
|
||||
that layer.
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 2923a77c Lock the RWLayer while committing/exporting
|
||||
|
||||
Change-Id: I11d6dcb60a23fe3516cebaed36d19aabaa863769
|
||||
Signed-off-by: Yuanhong Peng <pengyuanhong@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/commit.go | 2 ++
|
||||
components/engine/daemon/export.go | 2 ++
|
||||
components/engine/layer/empty.go | 13 ++++++++++++-
|
||||
components/engine/layer/layer.go | 7 +++++++
|
||||
components/engine/layer/layer_store.go | 2 ++
|
||||
components/engine/layer/mounted_layer.go | 10 ++++++++++
|
||||
components/engine/layer/ro_layer.go | 10 ++++++++++
|
||||
7 files changed, 45 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/commit.go b/components/engine/daemon/commit.go
|
||||
index 0f6f440514..fc7d2782ef 100644
|
||||
--- a/components/engine/daemon/commit.go
|
||||
+++ b/components/engine/daemon/commit.go
|
||||
@@ -155,6 +155,8 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
|
||||
return "", err
|
||||
}
|
||||
|
||||
+ container.RWLayer.RLockRWLayer()
|
||||
+ defer container.RWLayer.RUnlockRWLayer()
|
||||
id, err := daemon.imageService.CommitImage(backend.CommitConfig{
|
||||
Author: c.Author,
|
||||
Comment: c.Comment,
|
||||
diff --git a/components/engine/daemon/export.go b/components/engine/daemon/export.go
|
||||
index 27bc35967d..ebd2d75f40 100644
|
||||
--- a/components/engine/daemon/export.go
|
||||
+++ b/components/engine/daemon/export.go
|
||||
@@ -34,6 +34,8 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
|
||||
return errdefs.Conflict(err)
|
||||
}
|
||||
|
||||
+ container.RWLayer.RLockRWLayer()
|
||||
+ defer container.RWLayer.RUnlockRWLayer()
|
||||
data, err := daemon.containerExport(container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
diff --git a/components/engine/layer/empty.go b/components/engine/layer/empty.go
|
||||
index c81c702140..16a49a7abd 100644
|
||||
--- a/components/engine/layer/empty.go
|
||||
+++ b/components/engine/layer/empty.go
|
||||
@@ -6,13 +6,16 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
+ "sync"
|
||||
)
|
||||
|
||||
// DigestSHA256EmptyTar is the canonical sha256 digest of empty tar file -
|
||||
// (1024 NULL bytes)
|
||||
const DigestSHA256EmptyTar = DiffID("sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef")
|
||||
|
||||
-type emptyLayer struct{}
|
||||
+type emptyLayer struct {
|
||||
+ sync.RWMutex
|
||||
+}
|
||||
|
||||
// EmptyLayer is a layer that corresponds to empty tar.
|
||||
var EmptyLayer = &emptyLayer{}
|
||||
@@ -55,6 +58,14 @@ func (el *emptyLayer) Metadata() (map[string]string, error) {
|
||||
return make(map[string]string), nil
|
||||
}
|
||||
|
||||
+func (el *emptyLayer) RLockRWLayer() {
|
||||
+ el.RLock()
|
||||
+}
|
||||
+
|
||||
+func (el *emptyLayer) RUnlockRWLayer() {
|
||||
+ el.RUnlock()
|
||||
+}
|
||||
+
|
||||
// IsEmpty returns true if the layer is an EmptyLayer
|
||||
func IsEmpty(diffID DiffID) bool {
|
||||
return diffID == DigestSHA256EmptyTar
|
||||
diff --git a/components/engine/layer/layer.go b/components/engine/layer/layer.go
|
||||
index cb13c98d0b..e35a13135b 100644
|
||||
--- a/components/engine/layer/layer.go
|
||||
+++ b/components/engine/layer/layer.go
|
||||
@@ -145,6 +145,13 @@ type RWLayer interface {
|
||||
|
||||
// Metadata returns the low level metadata for the mutable layer
|
||||
Metadata() (map[string]string, error)
|
||||
+
|
||||
+ // RLockRWLayer locks the RWLayer to block unmounting/removal
|
||||
+ // of that layer
|
||||
+ RLockRWLayer()
|
||||
+
|
||||
+ // RUnlockRWLayer unlocks the RWLayer
|
||||
+ RUnlockRWLayer()
|
||||
}
|
||||
|
||||
// Metadata holds information about a
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index f22e9c666c..7c80a29645 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -666,6 +666,8 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
|
||||
return []Metadata{}, nil
|
||||
}
|
||||
|
||||
+ m.Lock()
|
||||
+ defer m.Unlock()
|
||||
if err := m.deleteReference(l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diff --git a/components/engine/layer/mounted_layer.go b/components/engine/layer/mounted_layer.go
|
||||
index d6858c662c..66711d6cf7 100644
|
||||
--- a/components/engine/layer/mounted_layer.go
|
||||
+++ b/components/engine/layer/mounted_layer.go
|
||||
@@ -2,6 +2,7 @@ package layer // import "github.com/docker/docker/layer"
|
||||
|
||||
import (
|
||||
"io"
|
||||
+ "sync"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
@@ -16,6 +17,7 @@ type mountedLayer struct {
|
||||
layerStore *layerStore
|
||||
|
||||
references map[RWLayer]*referencedRWLayer
|
||||
+ sync.RWMutex
|
||||
}
|
||||
|
||||
func (ml *mountedLayer) cacheParent() string {
|
||||
@@ -58,6 +60,14 @@ func (ml *mountedLayer) Metadata() (map[string]string, error) {
|
||||
return ml.layerStore.driver.GetMetadata(ml.mountID)
|
||||
}
|
||||
|
||||
+func (ml *mountedLayer) RLockRWLayer() {
|
||||
+ ml.RLock()
|
||||
+}
|
||||
+
|
||||
+func (ml *mountedLayer) RUnlockRWLayer() {
|
||||
+ ml.RUnlock()
|
||||
+}
|
||||
+
|
||||
func (ml *mountedLayer) getReference() RWLayer {
|
||||
ref := &referencedRWLayer{
|
||||
mountedLayer: ml,
|
||||
diff --git a/components/engine/layer/ro_layer.go b/components/engine/layer/ro_layer.go
|
||||
index 3555e8b027..59bcf17d18 100644
|
||||
--- a/components/engine/layer/ro_layer.go
|
||||
+++ b/components/engine/layer/ro_layer.go
|
||||
@@ -3,6 +3,7 @@ package layer // import "github.com/docker/docker/layer"
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
+ "sync"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@@ -19,6 +20,7 @@ type roLayer struct {
|
||||
|
||||
referenceCount int
|
||||
references map[Layer]struct{}
|
||||
+ sync.RWMutex
|
||||
}
|
||||
|
||||
// TarStream for roLayer guarantees that the data that is produced is the exact
|
||||
@@ -92,6 +94,14 @@ func (rl *roLayer) Metadata() (map[string]string, error) {
|
||||
return rl.layerStore.driver.GetMetadata(rl.cacheID)
|
||||
}
|
||||
|
||||
+func (rl *roLayer) RLockRWLayer() {
|
||||
+ rl.RLock()
|
||||
+}
|
||||
+
|
||||
+func (rl *roLayer) RUnlockRWLayer() {
|
||||
+ rl.RUnlock()
|
||||
+}
|
||||
+
|
||||
type referencedCacheLayer struct {
|
||||
*roLayer
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,46 @@
|
||||
From 2afc35ae4a34d70007bccb971d1f074574a3e282 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Thu, 17 Jan 2019 20:13:18 +0800
|
||||
Subject: [PATCH 053/111] docker: remove init layer when no space to
|
||||
create RW layer
|
||||
|
||||
reason:remove init layer when no space to create RW layer
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 24d00cf remove init layer when no space to create RW layer
|
||||
|
||||
Change-Id: I3ef9fa1073c12242f5f56997883fe831d9497a9a
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/layer/layer_store.go | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 7c80a29645..20c0195b79 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -598,6 +598,20 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWL
|
||||
// Release parent chain if error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
+ m.Lock()
|
||||
+ if err := ls.driver.Remove(m.mountID); err != nil {
|
||||
+ logrus.Errorf("Error removing mounted layer during create rw layer %s: %s", m.name, err)
|
||||
+ }
|
||||
+ if m.initID != "" {
|
||||
+ if err := ls.driver.Remove(m.initID); err != nil {
|
||||
+ logrus.Errorf("Error removing init layer during create rw layer %s: %s", m.name, err)
|
||||
+ }
|
||||
+ }
|
||||
+ if err := ls.store.RemoveMount(m.name); err != nil {
|
||||
+ logrus.Errorf("Error removing mount metadata during create rw layer %s: %s", m.name, err)
|
||||
+ }
|
||||
+ m.Unlock()
|
||||
+
|
||||
ls.layerL.Lock()
|
||||
ls.releaseLayer(p)
|
||||
ls.layerL.Unlock()
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,78 @@
|
||||
From 1fb61b2addb6043e8403a613b4229c20070f8bfe Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 17:38:47 +0800
|
||||
Subject: [PATCH 054/111] docker: remove init layer if fails in
|
||||
initMount
|
||||
|
||||
reason:remove init layer if fails in initMount
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 673c733 remove init layer if fails in initMount
|
||||
during initMount, operation could fails after device
|
||||
created, it should be removed during rollback
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
-------
|
||||
- 424970f fix metadata file deleted mistakely
|
||||
fix devicemapper metadata file "base" be deleted mistakely
|
||||
Signed-off-by: leizhongkai <leizhongkai@huawei.com>
|
||||
|
||||
Change-Id: Ieb40a8cfd3272abf28bfb046d77ecb61aea02bfa
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/layer/layer_store.go | 22 +++++++++++++++-------
|
||||
1 file changed, 15 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 20c0195b79..cbb1ee4a19 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -599,16 +599,16 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWL
|
||||
defer func() {
|
||||
if err != nil {
|
||||
m.Lock()
|
||||
- if err := ls.driver.Remove(m.mountID); err != nil {
|
||||
- logrus.Errorf("Error removing mounted layer during create rw layer %s: %s", m.name, err)
|
||||
+ if deferErr := ls.driver.Remove(m.mountID); deferErr != nil {
|
||||
+ logrus.Errorf("Error removing mounted layer during create rw layer %s: %s", m.name, deferErr)
|
||||
}
|
||||
if m.initID != "" {
|
||||
- if err := ls.driver.Remove(m.initID); err != nil {
|
||||
- logrus.Errorf("Error removing init layer during create rw layer %s: %s", m.name, err)
|
||||
+ if deferErr := ls.driver.Remove(m.initID); deferErr != nil {
|
||||
+ logrus.Errorf("Error removing init layer during create rw layer %s: %s", m.name, deferErr)
|
||||
}
|
||||
}
|
||||
- if err := ls.store.RemoveMount(m.name); err != nil {
|
||||
- logrus.Errorf("Error removing mount metadata during create rw layer %s: %s", m.name, err)
|
||||
+ if deferErr := ls.store.RemoveMount(m.name); deferErr != nil {
|
||||
+ logrus.Errorf("Error removing mount metadata during create rw layer %s: %s", m.name, deferErr)
|
||||
}
|
||||
m.Unlock()
|
||||
|
||||
@@ -743,7 +743,7 @@ func (ls *layerStore) saveMount(mount *mountedLayer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
-func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) {
|
||||
+func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (id string, err error) {
|
||||
// Use "<graph-id>-init" to maintain compatibility with graph drivers
|
||||
// which are expecting this layer with this special name. If all
|
||||
// graph drivers can be updated to not rely on knowing about this layer
|
||||
@@ -758,6 +758,14 @@ func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc Mou
|
||||
if err := ls.driver.CreateReadWrite(initID, parent, createOpts); err != nil {
|
||||
return "", err
|
||||
}
|
||||
+ defer func() {
|
||||
+ if err != nil {
|
||||
+ if deferErr := ls.driver.Remove(initID); deferErr != nil {
|
||||
+ logrus.Errorf("Error removing init layer during init mount %s: %s", initID, deferErr)
|
||||
+ }
|
||||
+ }
|
||||
+ }()
|
||||
+
|
||||
p, err := ls.driver.Get(initID, "")
|
||||
if err != nil {
|
||||
return "", err
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,84 @@
|
||||
From 04094d4f0ca583bf2a3eccc390515840ad322853 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Thu, 17 Jan 2019 20:45:45 +0800
|
||||
Subject: [PATCH 055/111] docker: range checking for memory and
|
||||
memory.swap
|
||||
|
||||
reason:range checking for memory and memory.swap, avoid overflow
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 3dd33a7 range checking for memory and memory.swap
|
||||
|
||||
Change-Id: I1736627a3f847decd36117f307a4919707908b32
|
||||
Signed-off-by: stella <zhangyu235@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/cli/vendor/github.com/docker/go-units/size.go | 4 ++++
|
||||
components/engine/daemon/daemon_unix.go | 5 ++++-
|
||||
.../engine/vendor/github.com/docker/go-units/Checklist | 1 +
|
||||
components/engine/vendor/github.com/docker/go-units/size.go | 4 ++++
|
||||
4 files changed, 13 insertions(+), 1 deletion(-)
|
||||
create mode 100644 components/engine/vendor/github.com/docker/go-units/Checklist
|
||||
|
||||
diff --git a/components/cli/vendor/github.com/docker/go-units/size.go b/components/cli/vendor/github.com/docker/go-units/size.go
|
||||
index 85f6ab0715..2b47b662ba 100644
|
||||
--- a/components/cli/vendor/github.com/docker/go-units/size.go
|
||||
+++ b/components/cli/vendor/github.com/docker/go-units/size.go
|
||||
@@ -104,5 +104,9 @@ func parseSize(sizeStr string, uMap unitMap) (int64, error) {
|
||||
size *= float64(mul)
|
||||
}
|
||||
|
||||
+ if int64(size) < 0 {
|
||||
+ return -1, fmt.Errorf("%s converted to int64 overflowed!", sizeStr)
|
||||
+ }
|
||||
+
|
||||
return int64(size), nil
|
||||
}
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index d4a32a0b25..e48dfcd1ef 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -65,7 +65,7 @@ const (
|
||||
linuxMinCPUShares = 2
|
||||
linuxMaxCPUShares = 262144
|
||||
platformSupported = true
|
||||
- // It's not kernel limit, we want this 4M limit to supply a reasonable functional container
|
||||
+ // It's not kernel limit, we want this 4MB limit to supply a reasonable functional container
|
||||
linuxMinMemory = 4194304
|
||||
// constants for remapped root settings
|
||||
defaultIDSpecifier = "default"
|
||||
@@ -293,6 +293,9 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
|
||||
if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 {
|
||||
// By default, MemorySwap is set to twice the size of Memory.
|
||||
hostConfig.MemorySwap = hostConfig.Memory * 2
|
||||
+ if hostConfig.MemorySwap < 0 {
|
||||
+ return fmt.Errorf("invalid memory swap! The memory swap is double of memory, and should be less than the maximum of int64.")
|
||||
+ }
|
||||
}
|
||||
if hostConfig.ShmSize == 0 {
|
||||
hostConfig.ShmSize = config.DefaultShmSize
|
||||
diff --git a/components/engine/vendor/github.com/docker/go-units/Checklist b/components/engine/vendor/github.com/docker/go-units/Checklist
|
||||
new file mode 100644
|
||||
index 0000000000..6b3f1461e8
|
||||
--- /dev/null
|
||||
+++ b/components/engine/vendor/github.com/docker/go-units/Checklist
|
||||
@@ -0,0 +1 @@
|
||||
+add value range checking when converting units
|
||||
\ No newline at end of file
|
||||
diff --git a/components/engine/vendor/github.com/docker/go-units/size.go b/components/engine/vendor/github.com/docker/go-units/size.go
|
||||
index 85f6ab0715..2b47b662ba 100644
|
||||
--- a/components/engine/vendor/github.com/docker/go-units/size.go
|
||||
+++ b/components/engine/vendor/github.com/docker/go-units/size.go
|
||||
@@ -104,5 +104,9 @@ func parseSize(sizeStr string, uMap unitMap) (int64, error) {
|
||||
size *= float64(mul)
|
||||
}
|
||||
|
||||
+ if int64(size) < 0 {
|
||||
+ return -1, fmt.Errorf("%s converted to int64 overflowed!", sizeStr)
|
||||
+ }
|
||||
+
|
||||
return int64(size), nil
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
132
patch/0056-docker-check-cpuset.cpu-and-cpuset.mem.patch
Normal file
132
patch/0056-docker-check-cpuset.cpu-and-cpuset.mem.patch
Normal file
@ -0,0 +1,132 @@
|
||||
From e894ad0fa1c84d1a01afc47ccc52c3556121bbcd Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Tue, 8 Jan 2019 20:17:21 +0800
|
||||
Subject: [PATCH 056/111] docker: check cpuset.cpu and cpuset.mem
|
||||
|
||||
reason:check cpuset.cpu and cpuset.mem
|
||||
|
||||
cherry-pick from docker 1.11.2:
|
||||
- 1c769f0 check cpuset.cpu and cpuset.mem
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
-----
|
||||
- 782f78f check cpuset.cpu and cpuset.mem
|
||||
Signed-off-by: wangyi45 <wangyi45@huawei.com>
|
||||
|
||||
Change-Id: If21cad2023d737d03ba3d4a83e62d11fb2297945
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon_unix.go | 2 +
|
||||
components/engine/pkg/sysinfo/sysinfo.go | 64 +++++++++++++++++++++++-
|
||||
2 files changed, 65 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index e48dfcd1ef..b20c66e27b 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -499,6 +499,7 @@ func (daemon *Daemon) verifyContainerResources(hostConfig *containertypes.HostCo
|
||||
}
|
||||
cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(resources.CpusetCpus)
|
||||
if err != nil {
|
||||
+ logrus.Errorf("Checking cpuset.cpus got %#v", err.Error())
|
||||
return warnings, errors.Wrapf(err, "Invalid value %s for cpuset cpus", resources.CpusetCpus)
|
||||
}
|
||||
if !cpusAvailable {
|
||||
@@ -506,6 +507,7 @@ func (daemon *Daemon) verifyContainerResources(hostConfig *containertypes.HostCo
|
||||
}
|
||||
memsAvailable, err := sysInfo.IsCpusetMemsAvailable(resources.CpusetMems)
|
||||
if err != nil {
|
||||
+ logrus.Errorf("Checking cpuset.mems got %#v", err.Error())
|
||||
return warnings, errors.Wrapf(err, "Invalid value %s for cpuset mems", resources.CpusetMems)
|
||||
}
|
||||
if !memsAvailable {
|
||||
diff --git a/components/engine/pkg/sysinfo/sysinfo.go b/components/engine/pkg/sysinfo/sysinfo.go
|
||||
index 5d9320218c..7ea1be5daf 100644
|
||||
--- a/components/engine/pkg/sysinfo/sysinfo.go
|
||||
+++ b/components/engine/pkg/sysinfo/sysinfo.go
|
||||
@@ -1,6 +1,12 @@
|
||||
package sysinfo // import "github.com/docker/docker/pkg/sysinfo"
|
||||
|
||||
-import "github.com/docker/docker/pkg/parsers"
|
||||
+import (
|
||||
+ "fmt"
|
||||
+ "strconv"
|
||||
+ "strings"
|
||||
+
|
||||
+ "github.com/docker/docker/pkg/parsers"
|
||||
+)
|
||||
|
||||
// SysInfo stores information about which features a kernel supports.
|
||||
// TODO Windows: Factor out platform specific capabilities.
|
||||
@@ -123,6 +129,13 @@ func (c cgroupCpusetInfo) IsCpusetMemsAvailable(provided string) (bool, error) {
|
||||
}
|
||||
|
||||
func isCpusetListAvailable(provided, available string) (bool, error) {
|
||||
+ if err := checkCPU(provided, available); err != nil {
|
||||
+ if strings.Contains(err.Error(), "invalid format") {
|
||||
+ return false, err
|
||||
+ }
|
||||
+ return false, nil
|
||||
+ }
|
||||
+
|
||||
parsedAvailable, err := parsers.ParseUintList(available)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -147,6 +160,55 @@ func isCpusetListAvailable(provided, available string) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
+func checkCPU(provided, available string) error {
|
||||
+ if provided == "" {
|
||||
+ return nil
|
||||
+ }
|
||||
+
|
||||
+ maxAvailable, err := maxCPU(available)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ maxRequest, err := maxCPU(provided)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ if maxRequest > maxAvailable {
|
||||
+ return fmt.Errorf("invalid maxRequest is %d, max available: %d", maxRequest, maxAvailable)
|
||||
+ }
|
||||
+
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
+func maxCPU(cores string) (int, error) {
|
||||
+ var max int
|
||||
+ split := strings.Split(cores, ",")
|
||||
+ errInvalidFormat := fmt.Errorf("invalid format: %s", cores)
|
||||
+ for _, r := range split {
|
||||
+ if !strings.Contains(r, "-") {
|
||||
+ v, err := strconv.Atoi(r)
|
||||
+ if err != nil {
|
||||
+ return max, errInvalidFormat
|
||||
+ }
|
||||
+ if v > max {
|
||||
+ max = v
|
||||
+ }
|
||||
+ } else {
|
||||
+ split := strings.SplitN(r, "-", 2)
|
||||
+ end, err := strconv.Atoi(split[1])
|
||||
+ if err != nil {
|
||||
+ return max, errInvalidFormat
|
||||
+ }
|
||||
+ if end > max {
|
||||
+ max = end
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return max, nil
|
||||
+}
|
||||
+
|
||||
// Returns bit count of 1, used by NumCPU
|
||||
func popcnt(x uint64) (n byte) {
|
||||
x -= (x >> 1) & 0x5555555555555555
|
||||
--
|
||||
2.17.1
|
||||
|
||||
55
patch/0057-docker-Ignore-ToDisk-error-in-StateChanged.patch
Normal file
55
patch/0057-docker-Ignore-ToDisk-error-in-StateChanged.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From 241fc5d726e63e995d3518b734e18efff76284ac Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 11:07:06 +0800
|
||||
Subject: [PATCH 057/111] docker: Ignore ToDisk error in StateChanged
|
||||
|
||||
reason:If container is started normally, but failed to save
|
||||
state to disk due to error "no space left on device",
|
||||
then container can not be stopped, because container's
|
||||
infomation in libcontainerd is cleaned up when error
|
||||
occurred(so it can not process event 'exit').
|
||||
|
||||
We can ignore ToDisk error in StateChanged, it only
|
||||
change status of container. Status is correct if docker
|
||||
daemon not restart, because right status exists in memory.
|
||||
If docker daemon restart, it will restore these status
|
||||
using status of containerd, so status is also correct.
|
||||
|
||||
This fix can break consistency of status in memory and
|
||||
disk, but considering there is no space in disk, it is
|
||||
not a big problem in this situation. Status in disk can
|
||||
recover if disk have space and if ToDisk is written
|
||||
again(for example, status changed).
|
||||
|
||||
Fix issuse #322
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 5eb9015 Ignore ToDisk error in StateChanged
|
||||
|
||||
Change-Id: Ifbdbffac06d1d739b03ea13962fb2d1fde7b5b3e
|
||||
Signed-off-by: Fengtu Wang <wangfengtu@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/monitor.go | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go
|
||||
index 9b4452d7ef..807cdcaa89 100644
|
||||
--- a/components/engine/daemon/monitor.go
|
||||
+++ b/components/engine/daemon/monitor.go
|
||||
@@ -154,7 +154,11 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
|
||||
daemon.initHealthMonitor(c)
|
||||
|
||||
if err := c.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
- return err
|
||||
+ // If return err, container can not be stopped, see issue #322 for detail.
|
||||
+ // Ignore error is safe, because if daemon not restart, status in memory is
|
||||
+ // correct, and if daemon restart, it will restore status using status in
|
||||
+ // containerd, so status in memory is also correct.
|
||||
+ logrus.Debugf("Set status %v to disk failed: %v", e, err)
|
||||
}
|
||||
daemon.LogContainerEvent(c, "start")
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From ee64a0b5fd645d1765b0c50cbaab76c17bab9b28 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 14:46:21 +0800
|
||||
Subject: [PATCH 058/111] cleanup: cleanup incompleted device while
|
||||
docker startup
|
||||
|
||||
cleanup incompleted device while docker startup
|
||||
|
||||
Change-Id: I9a9a96c655b61ac132fa7ed101dc9953c1bb613d
|
||||
Signed-off-by: Wentao Zhang <zhangwentao234@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/graphdriver/devmapper/deviceset.go | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index b3e142e2ba..f4dc589c6e 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -1753,6 +1753,12 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
|
||||
}
|
||||
logrus.Debugf("devmapper: remove broken device: %s", name)
|
||||
}
|
||||
+ if _, err := os.Stat(filepath.Join("/dev/mapper/", name)); err != nil {
|
||||
+ if err := devicemapper.RemoveDevice(name); err != nil {
|
||||
+ logrus.Warnf("devmapper: remove incompelete device(%s): %v", name, err)
|
||||
+ }
|
||||
+ logrus.Debugf("devmapper: remove incompelete device: %s", name)
|
||||
+ }
|
||||
}
|
||||
|
||||
// Check for the existence of the thin-pool device
|
||||
--
|
||||
2.17.1
|
||||
|
||||
110
patch/0059-overlay2-avoid-middle-state-while-removing-im.patch
Normal file
110
patch/0059-overlay2-avoid-middle-state-while-removing-im.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From ef238d650231f8346078536b6133f147df11283a Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 19:21:39 +0800
|
||||
Subject: [PATCH 059/111] overlay2: avoid middle state while removing
|
||||
images under overlay2
|
||||
|
||||
reason:avoid middle state while removing images under overlay2
|
||||
|
||||
kill -9 daemon while rmi images may cause some inconsistent state
|
||||
of that image
|
||||
|
||||
if image symlink is removed but the id directory remained. daemon
|
||||
restart and load again, the images look fine but create container
|
||||
with it will error out:
|
||||
`docker: Error response from daemon: error creating overlay
|
||||
mount to /var/lib/docker/overlay2/xxx-init/merged:
|
||||
no such file or directory`
|
||||
|
||||
This patch move symlink removal after directory removal, and check
|
||||
link file state while daemon restore, to clean up stale links.
|
||||
|
||||
Change-Id: I44328bc2261c9ec73bcdcbed3d741e569cd4a834
|
||||
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 40 ++++++++++++++++---
|
||||
1 file changed, 34 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 773d5232cc..cf8993e9f3 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -229,6 +229,8 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
return nil, fmt.Errorf("Storage Option overlay2.size only supported for backingFS XFS or ext4. Found %v", backingFs)
|
||||
}
|
||||
|
||||
+ d.cleanupLinkDir()
|
||||
+
|
||||
// figure out whether "index=off" option is recognized by the kernel
|
||||
_, err = os.Stat("/sys/module/overlay/parameters/index")
|
||||
switch {
|
||||
@@ -245,6 +247,19 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
return d, nil
|
||||
}
|
||||
|
||||
+func (d *Driver) cleanupLinkDir() {
|
||||
+ filepath.Walk(path.Join(d.home, linkDir), func(path string, f os.FileInfo, err error) error {
|
||||
+ if _, serr := filepath.EvalSymlinks(path); serr != nil {
|
||||
+ logrus.Warnf("[overlay2]: remove invalid symlink: %s", path)
|
||||
+ os.RemoveAll(path)
|
||||
+ }
|
||||
+ // always return nil, to walk all the symlink
|
||||
+ return nil
|
||||
+ })
|
||||
+
|
||||
+ return
|
||||
+}
|
||||
+
|
||||
func parseOptions(options []string) (*overlayOptions, error) {
|
||||
o := &overlayOptions{}
|
||||
for _, option := range options {
|
||||
@@ -575,8 +590,11 @@ func (d *Driver) Remove(id string) error {
|
||||
d.locker.Lock(id)
|
||||
defer d.locker.Unlock(id)
|
||||
dir := d.dir(id)
|
||||
- lid, err := ioutil.ReadFile(path.Join(dir, "link"))
|
||||
- if err == nil {
|
||||
+ lid, lerr := ioutil.ReadFile(path.Join(dir, "link"))
|
||||
+ if err := system.EnsureRemoveAll(dir); err != nil && !os.IsNotExist(err) {
|
||||
+ return err
|
||||
+ }
|
||||
+ if lerr == nil {
|
||||
if !verifyID(string(lid), idLength) {
|
||||
logrus.WithField("storage-driver", "overlay2").Errorf("refusing to remove empty link for layer %v", id)
|
||||
} else if err := os.RemoveAll(path.Join(d.home, linkDir, string(lid))); err != nil {
|
||||
@@ -568,9 +586,6 @@ func (d *Driver) Remove(id string) error {
|
||||
}
|
||||
}
|
||||
|
||||
- if err := system.EnsureRemoveAll(dir); err != nil && !os.IsNotExist(err) {
|
||||
- return err
|
||||
- }
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -710,7 +725,20 @@ func (d *Driver) Put(id string) error {
|
||||
|
||||
// Exists checks to see if the id is already mounted.
|
||||
func (d *Driver) Exists(id string) bool {
|
||||
- _, rerr := os.Stat(d.dir(id))
|
||||
+ var rerr error
|
||||
+ defer func() {
|
||||
+ if rerr != nil {
|
||||
+ logrus.Warnf("layer(%s) not exist: %s", id, rerr)
|
||||
+ d.Remove(id)
|
||||
+ }
|
||||
+ }()
|
||||
+
|
||||
+ // check if the id directory exist and is valid
|
||||
+ // check if link file exist and get link string from it
|
||||
+ // check if symlink file exist
|
||||
+ // if symlink not exist, create a new one and update link file
|
||||
+ // any steps failed ,we will return false and remove this id layer
|
||||
+ _, rerr = os.Stat(d.dir(id))
|
||||
if rerr == nil {
|
||||
lstr, err := ioutil.ReadFile(path.Join(d.dir(id), "link"))
|
||||
// link is valid
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,90 @@
|
||||
From 42d1e785f2343323822db35966412fdcfce87989 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 15:55:51 +0800
|
||||
Subject: [PATCH 060/111] debug: Add check when execute docker {cp,
|
||||
export, diff}
|
||||
|
||||
reason:If a container is in Dead or RemovalInProgress state,it should return err for tip.
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 903a5de Add check when execute docker {cp, export, diff}
|
||||
|
||||
Change-Id: Idf441bf7d194cc61c618c20c0e6ef8b339e81191
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/archive.go | 13 +++++++++++++
|
||||
components/engine/daemon/changes.go | 5 +++++
|
||||
2 files changed, 18 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/archive.go b/components/engine/daemon/archive.go
|
||||
index 9c7971b56e..f1b715d9ae 100644
|
||||
--- a/components/engine/daemon/archive.go
|
||||
+++ b/components/engine/daemon/archive.go
|
||||
@@ -1,6 +1,7 @@
|
||||
package daemon // import "github.com/docker/docker/daemon"
|
||||
|
||||
import (
|
||||
+ "fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -77,6 +78,10 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return nil, fmt.Errorf("can't stat file from a container which is dead or marked for removal")
|
||||
+ }
|
||||
+
|
||||
// Make sure an online file-system operation is permitted.
|
||||
if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
|
||||
return nil, errdefs.System(err)
|
||||
@@ -102,6 +107,10 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return nil, nil, fmt.Errorf("can't copy file from a container which is dead or marked for removal")
|
||||
+ }
|
||||
+
|
||||
// Make sure an online file-system operation is permitted.
|
||||
if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
|
||||
return nil, nil, errdefs.System(err)
|
||||
@@ -130,6 +139,10 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, copyUIDGID, noOve
|
||||
return err
|
||||
}
|
||||
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return fmt.Errorf("can't copy to a container which is dead or marked for removal")
|
||||
+ }
|
||||
+
|
||||
// Make sure an online file-system operation is permitted.
|
||||
if err := daemon.isOnlineFSOperationPermitted(container); err != nil {
|
||||
return errdefs.System(err)
|
||||
diff --git a/components/engine/daemon/changes.go b/components/engine/daemon/changes.go
|
||||
index 70b3f6b943..55575a96bd 100644
|
||||
--- a/components/engine/daemon/changes.go
|
||||
+++ b/components/engine/daemon/changes.go
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
+ "fmt"
|
||||
)
|
||||
|
||||
// ContainerChanges returns a list of container fs changes
|
||||
@@ -16,6 +17,10 @@ func (daemon *Daemon) ContainerChanges(name string) ([]archive.Change, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+ if container.RemovalInProgress || container.Dead {
|
||||
+ return nil, fmt.Errorf("can't diff a container which is dead or marked for removal")
|
||||
+ }
|
||||
+
|
||||
if runtime.GOOS == "windows" && container.IsRunning() {
|
||||
return nil, errors.New("Windows does not support diff of a running container")
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From 3b24c397492b921ce00f9786c8f6dd22cf2bb420 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 21:31:47 +0800
|
||||
Subject: [PATCH 061/111] docker: check seccomp file size(max:10M)
|
||||
before read into memory
|
||||
|
||||
reason:when seccomp file size is not limited, docker may result in memory OOM
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 3660784 check seccomp file size(max:10M) before read into memory
|
||||
|
||||
Change-Id: I6289b2e84e5aaf6d876e689c842f9d18acaf6814
|
||||
Signed-off-by: xueshaojia <xueshaojia@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/opts.go | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||||
index 8e07aa77cb..cbbc110f9c 100644
|
||||
--- a/components/cli/cli/command/container/opts.go
|
||||
+++ b/components/cli/cli/command/container/opts.go
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
+ "os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -27,6 +28,8 @@ var (
|
||||
deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
||||
)
|
||||
|
||||
+const seccompFileMaxSize = 10 * 1024 * 1024
|
||||
+
|
||||
// containerOptions is a data object with all the options for creating a container
|
||||
type containerOptions struct {
|
||||
attach opts.ListOpts
|
||||
@@ -726,6 +729,11 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) {
|
||||
}
|
||||
}
|
||||
if con[0] == "seccomp" && con[1] != "unconfined" {
|
||||
+ if fileInfo, err := os.Stat(con[1]); err != nil {
|
||||
+ return securityOpts, fmt.Errorf("stat seccomp profile (%s) failed: %v", con[1], err)
|
||||
+ } else if fileInfo.Size() > seccompFileMaxSize {
|
||||
+ return securityOpts, fmt.Errorf("stat seccomp profile (%s) failed: size exceed limit %dM", con[1], seccompFileMaxSize/1024/1024)
|
||||
+ }
|
||||
f, err := ioutil.ReadFile(con[1])
|
||||
if err != nil {
|
||||
return securityOpts, errors.Errorf("opening seccomp profile (%s) failed: %v", con[1], err)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,87 @@
|
||||
From e065d6675c95e37144284f2ee5af3f7e326f9efe Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 18 Jan 2019 22:11:29 +0800
|
||||
Subject: [PATCH 062/111] docker: check file size before reading
|
||||
"envfile" and "labelfile", in case OOM
|
||||
|
||||
reason:check file size before reading "envfile" and "labelfile", in case OOM
|
||||
|
||||
Cherry-pick from docker 1.11.2:
|
||||
- 931660a check file size before reading "envfile" and "labelfile", in case OOM
|
||||
|
||||
Change-Id: I32bc7951565d0e6e720cf7d9f1d53f8709ebc8b3
|
||||
Signed-off-by: panwenxiang <panwenxiang@huawei.com>
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/opts.go | 28 +++++++++++++++++---
|
||||
1 file changed, 25 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/opts.go b/components/cli/cli/command/container/opts.go
|
||||
index cbbc110f9c..a1bf2be79a 100644
|
||||
--- a/components/cli/cli/command/container/opts.go
|
||||
+++ b/components/cli/cli/command/container/opts.go
|
||||
@@ -28,7 +28,7 @@ var (
|
||||
deviceCgroupRuleRegexp = regexp.MustCompile(`^[acb] ([0-9]+|\*):([0-9]+|\*) [rwm]{1,3}$`)
|
||||
)
|
||||
|
||||
-const seccompFileMaxSize = 10 * 1024 * 1024
|
||||
+const fileMaxSize = 10 * 1024 * 1024
|
||||
|
||||
// containerOptions is a data object with all the options for creating a container
|
||||
type containerOptions struct {
|
||||
@@ -435,12 +435,20 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
}
|
||||
|
||||
// collect all the environment variables for the container
|
||||
+ err = checkFileSizeValid(copts.envFile.GetAll())
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
envVariables, err := opts.ReadKVEnvStrings(copts.envFile.GetAll(), copts.env.GetAll())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// collect all the labels for the container
|
||||
+ err = checkFileSizeValid(copts.envFile.GetAll())
|
||||
+ if err != nil {
|
||||
+ return nil, err
|
||||
+ }
|
||||
labels, err := opts.ReadKVStrings(copts.labelsFile.GetAll(), copts.labels.GetAll())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -692,6 +700,20 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
+// check file size
|
||||
+func checkFileSizeValid(files []string) error {
|
||||
+ for _, ef := range files {
|
||||
+ fileInfo, err := os.Stat(ef)
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ if fileInfo.Size() > fileMaxSize {
|
||||
+ return fmt.Errorf("check (%s) file size is %d, size exceed limit %d ", ef, fileInfo.Size(), fileMaxSize)
|
||||
+ }
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
func parsePortOpts(publishOpts []string) ([]string, error) {
|
||||
optsList := []string{}
|
||||
for _, publish := range publishOpts {
|
||||
@@ -731,8 +753,8 @@ func parseSecurityOpts(securityOpts []string) ([]string, error) {
|
||||
if con[0] == "seccomp" && con[1] != "unconfined" {
|
||||
if fileInfo, err := os.Stat(con[1]); err != nil {
|
||||
return securityOpts, fmt.Errorf("stat seccomp profile (%s) failed: %v", con[1], err)
|
||||
- } else if fileInfo.Size() > seccompFileMaxSize {
|
||||
- return securityOpts, fmt.Errorf("stat seccomp profile (%s) failed: size exceed limit %dM", con[1], seccompFileMaxSize/1024/1024)
|
||||
+ } else if fileInfo.Size() > fileMaxSize {
|
||||
+ return securityOpts, fmt.Errorf("stat seccomp profile (%s) failed: size exceed limit %dM", con[1], fileMaxSize/1024/1024)
|
||||
}
|
||||
f, err := ioutil.ReadFile(con[1])
|
||||
if err != nil {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
38
patch/0063-test-fix-umask-make-file-mode-failed.patch
Normal file
38
patch/0063-test-fix-umask-make-file-mode-failed.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From a683efcf5e14acdd40574edeaed6b293b0536867 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Tue, 15 Jan 2019 10:16:25 +0800
|
||||
Subject: [PATCH 063/111] test: fix umask make file mode failed
|
||||
|
||||
reason: set umask to 0022 make sure test added file's mode match expect.
|
||||
|
||||
Change-Id: I258d3d999c82041a16851f438f556746e6477ebf
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/internal/test/fakecontext/context.go | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/components/engine/internal/test/fakecontext/context.go b/components/engine/internal/test/fakecontext/context.go
|
||||
index 8b11da207e..24f326b864 100644
|
||||
--- a/components/engine/internal/test/fakecontext/context.go
|
||||
+++ b/components/engine/internal/test/fakecontext/context.go
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
+ "syscall"
|
||||
|
||||
"github.com/docker/docker/internal/test"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
@@ -96,6 +97,9 @@ func (f *Fake) Add(file, content string) error {
|
||||
}
|
||||
|
||||
func (f *Fake) addFile(file string, content []byte) error {
|
||||
+ mask := syscall.Umask(0022)
|
||||
+ defer syscall.Umask(mask)
|
||||
+
|
||||
fp := filepath.Join(f.Dir, filepath.FromSlash(file))
|
||||
dirpath := filepath.Dir(fp)
|
||||
if dirpath != "." {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
2090
patch/0066-test-skip-swarm-integration-test.patch
Normal file
2090
patch/0066-test-skip-swarm-integration-test.patch
Normal file
File diff suppressed because it is too large
Load Diff
5759
patch/0067-pause-fix-build-missing-dep-packages.patch
Normal file
5759
patch/0067-pause-fix-build-missing-dep-packages.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,54 @@
|
||||
From 634d7c920176c726b8d32d8aee50c8073f4892a3 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Sun, 20 Jan 2019 15:35:57 +0800
|
||||
Subject: [PATCH 068/111] pause: fix docker stop stuck on paused
|
||||
container
|
||||
|
||||
reason: docker-18.09 support docker stop while container is paused.
|
||||
ref 7aed75f09c * Allow stopping of paused container.
|
||||
|
||||
now docker function is moved to docker, so we still have to check
|
||||
container paused status.
|
||||
|
||||
Change-Id: I60731c76808abb5a76daf96c2aba656d73a87e96
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/kill.go | 5 +++++
|
||||
components/engine/daemon/unpause.go | 5 +++++
|
||||
2 files changed, 10 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/kill.go b/components/engine/daemon/kill.go
|
||||
index 3e6457e952..5b2e497604 100644
|
||||
--- a/components/engine/daemon/kill.go
|
||||
+++ b/components/engine/daemon/kill.go
|
||||
@@ -66,6 +66,11 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
||||
|
||||
daemon.stopHealthchecks(container)
|
||||
|
||||
+ // We could unpause the container for them rather than returning this error
|
||||
+ if container.Paused {
|
||||
+ return fmt.Errorf("Container %s is paused. Unpause the container before stopping or killing", container.ID)
|
||||
+ }
|
||||
+
|
||||
if !container.Running {
|
||||
return errNotRunning(container.ID)
|
||||
}
|
||||
diff --git a/components/engine/daemon/unpause.go b/components/engine/daemon/unpause.go
|
||||
index 290d2b1d0c..2d3c056566 100644
|
||||
--- a/components/engine/daemon/unpause.go
|
||||
+++ b/components/engine/daemon/unpause.go
|
||||
@@ -23,6 +23,11 @@ func (daemon *Daemon) containerUnpause(container *container.Container) error {
|
||||
container.Lock()
|
||||
defer container.Unlock()
|
||||
|
||||
+ // We cannot unpause the container which is not running
|
||||
+ if !container.Running {
|
||||
+ return fmt.Errorf("Container %s is not running", container.ID)
|
||||
+ }
|
||||
+
|
||||
// We cannot unpause the container which is not paused
|
||||
if !container.Paused {
|
||||
return fmt.Errorf("Container %s is not paused", container.ID)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
108
patch/0069-pause-fix-log-pause-unpause-event-twice.patch
Normal file
108
patch/0069-pause-fix-log-pause-unpause-event-twice.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From a6db97d2574d509b2077236ff48d70c3469a042e Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Sun, 20 Jan 2019 16:39:08 +0800
|
||||
Subject: [PATCH 069/111] pause: fix log pause/unpause event twice
|
||||
|
||||
reason: fix pause/unpause log event twice
|
||||
|
||||
Change-Id: If136d713afd37806256500d4760d0a344f7c5d92
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/monitor.go | 36 ++++++++++++++++++-----------
|
||||
components/engine/daemon/pause.go | 7 ------
|
||||
components/engine/daemon/unpause.go | 6 -----
|
||||
3 files changed, 22 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go
|
||||
index 807cdcaa89..51159eb76d 100644
|
||||
--- a/components/engine/daemon/monitor.go
|
||||
+++ b/components/engine/daemon/monitor.go
|
||||
@@ -167,28 +167,36 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
- if !c.Paused {
|
||||
- c.Paused = true
|
||||
- daemon.setStateCounter(c)
|
||||
- daemon.updateHealthMonitor(c)
|
||||
- if err := c.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
- return err
|
||||
+ if daemon.IsNativeRuntime(c.HostConfig.Runtime) {
|
||||
+ logrus.Infof("Pause is moved to docker, skip.")
|
||||
+ } else {
|
||||
+ if !c.Paused {
|
||||
+ c.Paused = true
|
||||
+ daemon.setStateCounter(c)
|
||||
+ daemon.updateHealthMonitor(c)
|
||||
+ if err := c.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ daemon.LogContainerEvent(c, "pause")
|
||||
}
|
||||
- daemon.LogContainerEvent(c, "pause")
|
||||
}
|
||||
case libcontainerd.EventResumed:
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
- if c.Paused {
|
||||
- c.Paused = false
|
||||
- daemon.setStateCounter(c)
|
||||
- daemon.updateHealthMonitor(c)
|
||||
+ if daemon.IsNativeRuntime(c.HostConfig.Runtime) {
|
||||
+ logrus.Infof("Pause is moved to docker, skip.")
|
||||
+ } else {
|
||||
+ if c.Paused {
|
||||
+ c.Paused = false
|
||||
+ daemon.setStateCounter(c)
|
||||
+ daemon.updateHealthMonitor(c)
|
||||
|
||||
- if err := c.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
- return err
|
||||
+ if err := c.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+ daemon.LogContainerEvent(c, "unpause")
|
||||
}
|
||||
- daemon.LogContainerEvent(c, "unpause")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
diff --git a/components/engine/daemon/pause.go b/components/engine/daemon/pause.go
|
||||
index 6f9d8b0f70..494aa326d9 100644
|
||||
--- a/components/engine/daemon/pause.go
|
||||
+++ b/components/engine/daemon/pause.go
|
||||
@@ -48,13 +48,6 @@ func (daemon *Daemon) containerPause(container *container.Container) error {
|
||||
if err := freezer.Pause(); err != nil {
|
||||
return fmt.Errorf("Cannot pause container %s: %v", container.ID, err)
|
||||
}
|
||||
-
|
||||
- container.Paused = true
|
||||
- daemon.setStateCounter(container)
|
||||
- if err := container.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- daemon.LogContainerEvent(container, "pause")
|
||||
} else {
|
||||
if err := daemon.containerd.Pause(context.Background(), container.ID); err != nil {
|
||||
return fmt.Errorf("Cannot pause container %s: %s", container.ID, err)
|
||||
diff --git a/components/engine/daemon/unpause.go b/components/engine/daemon/unpause.go
|
||||
index 2d3c056566..a75589b888 100644
|
||||
--- a/components/engine/daemon/unpause.go
|
||||
+++ b/components/engine/daemon/unpause.go
|
||||
@@ -41,12 +41,6 @@ func (daemon *Daemon) containerUnpause(container *container.Container) error {
|
||||
if err := freezer.Resume(); err != nil {
|
||||
return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
}
|
||||
- container.Paused = false
|
||||
- daemon.setStateCounter(container)
|
||||
- if err := container.CheckpointTo(daemon.containersReplica); err != nil {
|
||||
- return err
|
||||
- }
|
||||
- daemon.LogContainerEvent(container, "unpause")
|
||||
} else {
|
||||
if err := daemon.containerd.Resume(context.Background(), container.ID); err != nil {
|
||||
return fmt.Errorf("Cannot unpause container %s: %s", container.ID, err)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
39
patch/0070-test-fix-umask-make-syscall-test-failed.patch
Normal file
39
patch/0070-test-fix-umask-make-syscall-test-failed.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 1bb39edbf403bf31aaece61510b43d9a6e781f7d Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Mon, 21 Jan 2019 17:57:03 +0800
|
||||
Subject: [PATCH 070/111] test: fix umask make syscall-test failed
|
||||
|
||||
reason: set umask 0022 make sure add file's mode to image syscall-test
|
||||
as exepected, so user has permission to exec.
|
||||
|
||||
Change-Id: Iaad1bc328c81b77aa630bcb9f974aeee3a50ecbf
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../engine/integration-cli/fixtures_linux_daemon_test.go | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/components/engine/integration-cli/fixtures_linux_daemon_test.go b/components/engine/integration-cli/fixtures_linux_daemon_test.go
|
||||
index 2387a9ebee..7be3c8b185 100644
|
||||
--- a/components/engine/integration-cli/fixtures_linux_daemon_test.go
|
||||
+++ b/components/engine/integration-cli/fixtures_linux_daemon_test.go
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
+ "syscall"
|
||||
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/internal/test/fixtures/load"
|
||||
@@ -28,6 +29,9 @@ var ensureSyscallTestOnce sync.Once
|
||||
|
||||
func ensureSyscallTest(c *check.C) {
|
||||
var doIt bool
|
||||
+ mask := syscall.Umask(0022)
|
||||
+ defer syscall.Umask(mask)
|
||||
+
|
||||
ensureSyscallTestOnce.Do(func() {
|
||||
doIt = true
|
||||
})
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
From 6a40d11a3bc9be18cb50fb86099ff52a6d459335 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Mon, 21 Jan 2019 18:57:43 +0800
|
||||
Subject: [PATCH 071/111] devmapper: Increace udev wait timeout to
|
||||
185s
|
||||
|
||||
reason: cherry-pick commits to docker-18.09
|
||||
|
||||
cherry-pick e89615bd40c32f95d095c17efaf5258b15543080 from docker-1.11.2
|
||||
|
||||
The default time out of latest systemd-udevd on RTOS and EulerOS
|
||||
is 180s, we use 185s. Even if the time out of systemd-udevd is 30s,
|
||||
set 185s on docker side is also safe, it will just take a longer time
|
||||
to return when time out really happen, we should make sure the timeout
|
||||
on docker side is bigger than the timeout on systemd-udevd.
|
||||
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
|
||||
Change-Id: I05d722f22a0c7728ae1bbe23ab67c567d1694b67
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/graphdriver/devmapper/deviceset.go | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/devmapper/deviceset.go b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
index f4dc589c6e..f5c0b044c4 100644
|
||||
--- a/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
+++ b/components/engine/daemon/graphdriver/devmapper/deviceset.go
|
||||
@@ -42,9 +42,9 @@ var (
|
||||
defaultUdevSyncOverride = false
|
||||
maxDeviceID = 0xffffff // 24 bit, pool limit
|
||||
deviceIDMapSz = (maxDeviceID + 1) / 8
|
||||
- // The default timeout is 30s from `man systemd-udevd`, we use 35
|
||||
- // just to make sure the timeout really happened in systemd-udevd
|
||||
- defaultUdevWaitTimeout = 35
|
||||
+ // The default timeout for latest systemd on RTOS and EulerOS is 180s
|
||||
+ // we use 185s to make sure the timeout really happened.
|
||||
+ defaultUdevWaitTimeout = 185
|
||||
driverDeferredRemovalSupport = false
|
||||
enableDeferredRemoval = false
|
||||
enableDeferredDeletion = false
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
From 59d4dd7fdb0c33dc4c3be2330606ec7724cb368c Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Fri, 11 Jan 2019 17:16:21 +0800
|
||||
Subject: [PATCH 072/111] pause: fix test can not stop paused
|
||||
container failed
|
||||
|
||||
reason: pause function moved to docker and does not support stop paused
|
||||
container. return error message when stop a paused container.
|
||||
|
||||
Change-Id: Ia7b15877980088cdb4eaf9f7e3dd86667df0157b
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/integration/container/pause_test.go | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/integration/container/pause_test.go b/components/engine/integration/container/pause_test.go
|
||||
index 8dd2d784b7..da274c89ce 100644
|
||||
--- a/components/engine/integration/container/pause_test.go
|
||||
+++ b/components/engine/integration/container/pause_test.go
|
||||
@@ -79,9 +79,10 @@ func TestPauseStopPausedContainer(t *testing.T) {
|
||||
assert.NilError(t, err)
|
||||
|
||||
err = client.ContainerStop(ctx, cID, nil)
|
||||
- assert.NilError(t, err)
|
||||
-
|
||||
- poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
+ // assert.NilError(t, err)
|
||||
+ // poll.WaitOn(t, container.IsStopped(ctx, client, cID), poll.WithDelay(100*time.Millisecond))
|
||||
+ assert.Check(t, is.ErrorContains(err, "is paused"))
|
||||
+ client.ContainerUnpause(ctx, cID)
|
||||
}
|
||||
|
||||
func getEventActions(t *testing.T, messages <-chan events.Message, errs <-chan error) []string {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
From 67f1bfcb1df53fcfc044927eda37f0f8b45498dc Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Mon, 21 Jan 2019 22:25:42 +0800
|
||||
Subject: [PATCH 073/111] service: update docker.service with old
|
||||
revision
|
||||
|
||||
reason: use docker.service as the same one used in Euleros docker
|
||||
1.11.2 and 17.06
|
||||
|
||||
Change-Id: I3deb3f3a24d837c98e535550545fd49ea0822629
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../contrib/init/systemd/docker.service | 28 ++++++++-----------
|
||||
1 file changed, 11 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/components/engine/contrib/init/systemd/docker.service b/components/engine/contrib/init/systemd/docker.service
|
||||
index 517463172b..26c0fe648b 100644
|
||||
--- a/components/engine/contrib/init/systemd/docker.service
|
||||
+++ b/components/engine/contrib/init/systemd/docker.service
|
||||
@@ -1,34 +1,28 @@
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine
|
||||
Documentation=https://docs.docker.com
|
||||
-After=network-online.target docker.socket firewalld.service
|
||||
+After=network-online.target firewalld.service
|
||||
Wants=network-online.target
|
||||
-Requires=docker.socket
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
-# the default is not to use systemd for cgroups because the delegate issues still
|
||||
-# exists and systemd currently does not support the cgroup feature set required
|
||||
-# for containers run by docker
|
||||
-ExecStart=/usr/bin/dockerd -H fd://
|
||||
+EnvironmentFile=-/etc/sysconfig/docker
|
||||
+EnvironmentFile=-/etc/sysconfig/docker-storage
|
||||
+EnvironmentFile=-/etc/sysconfig/docker-network
|
||||
+Environment=GOTRACEBACK=crash
|
||||
+
|
||||
+ExecStart=/usr/bin/dockerd $OPTIONS \
|
||||
+ $DOCKER_STORAGE_OPTIONS \
|
||||
+ $DOCKER_NETWORK_OPTIONS \
|
||||
+ $INSECURE_REGISTRY
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
LimitNOFILE=1048576
|
||||
-# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||
-# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||
-LimitNPROC=infinity
|
||||
+LimitNPROC=1048576
|
||||
LimitCORE=infinity
|
||||
-# Uncomment TasksMax if your systemd version supports it.
|
||||
-# Only systemd 226 and above support this version.
|
||||
-#TasksMax=infinity
|
||||
-TimeoutStartSec=0
|
||||
# set delegate yes so that systemd does not reset the cgroups of docker containers
|
||||
Delegate=yes
|
||||
# kill only the docker process, not all processes in the cgroup
|
||||
KillMode=process
|
||||
-# restart the docker process if it exits prematurely
|
||||
-Restart=on-failure
|
||||
-StartLimitBurst=3
|
||||
-StartLimitInterval=60s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
--
|
||||
2.17.1
|
||||
|
||||
199
patch/0076-version-add-EulerVersion.patch
Normal file
199
patch/0076-version-add-EulerVersion.patch
Normal file
@ -0,0 +1,199 @@
|
||||
From 22f9a89d9ddcb03aa5b00dc9ad4372f776c5f73b Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Mon, 21 Jan 2019 23:05:47 +0800
|
||||
Subject: [PATCH 076/111] version: add EulerVersion
|
||||
|
||||
reason: Add EulerVersion and update-version.sh
|
||||
|
||||
Cherry-pick from 17.06 for
|
||||
- 030513895 Add EulerVersion
|
||||
- 102ee9ddc docker-17: add update-version tool for obs build
|
||||
|
||||
Change-Id: I95c9b98bd35e243ce1074fa7dd0d477bdf7dcee9
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/system/version.go | 4 ++++
|
||||
components/cli/cli/version.go | 1 +
|
||||
components/cli/docker.Makefile | 3 ++-
|
||||
components/cli/scripts/build/.variables | 2 ++
|
||||
.../github.com/docker/docker/api/types/types.go | 1 +
|
||||
components/engine/api/types/types.go | 1 +
|
||||
components/engine/daemon/info.go | 3 ++-
|
||||
components/engine/dockerversion/version_lib.go | 1 +
|
||||
components/engine/hack/make.sh | 1 +
|
||||
components/engine/hack/make/.go-autogen | 1 +
|
||||
13 files changed, 34 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/system/version.go b/components/cli/cli/command/system/version.go
|
||||
index 7593b11b81..c13d135ae4 100644
|
||||
--- a/components/cli/cli/command/system/version.go
|
||||
+++ b/components/cli/cli/command/system/version.go
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
var versionTemplate = `{{with .Client -}}
|
||||
Client:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
Version: {{.Version}}
|
||||
+ EulerVersion: {{.EulerVersion}}
|
||||
API version: {{.APIVersion}}{{if ne .APIVersion .DefaultAPIVersion}} (downgraded from {{.DefaultAPIVersion}}){{end}}
|
||||
Go version: {{.GoVersion}}
|
||||
Git commit: {{.GitCommit}}
|
||||
@@ -38,6 +39,7 @@ Server:{{if ne .Platform.Name ""}} {{.Platform.Name}}{{end}}
|
||||
{{$component.Name}}:
|
||||
{{- if eq $component.Name "Engine" }}
|
||||
Version: {{.Version}}
|
||||
+ EulerVersion: {{index .Details "EulerVersion"}}
|
||||
API version: {{index .Details "ApiVersion"}} (minimum version {{index .Details "MinAPIVersion"}})
|
||||
Go version: {{index .Details "GoVersion"}}
|
||||
Git commit: {{index .Details "GitCommit"}}
|
||||
@@ -69,6 +71,7 @@ type clientVersion struct {
|
||||
Platform struct{ Name string } `json:",omitempty"`
|
||||
|
||||
Version string
|
||||
+ EulerVersion string
|
||||
APIVersion string `json:"ApiVersion"`
|
||||
DefaultAPIVersion string `json:"DefaultAPIVersion,omitempty"`
|
||||
GitCommit string
|
||||
@@ -135,6 +138,7 @@ func runVersion(dockerCli command.Cli, opts *versionOptions) error {
|
||||
Client: clientVersion{
|
||||
Platform: struct{ Name string }{cli.PlatformName},
|
||||
Version: cli.Version,
|
||||
+ EulerVersion: cli.EulerVersion,
|
||||
APIVersion: dockerCli.Client().ClientVersion(),
|
||||
DefaultAPIVersion: dockerCli.DefaultVersion(),
|
||||
GoVersion: runtime.Version(),
|
||||
diff --git a/components/cli/cli/version.go b/components/cli/cli/version.go
|
||||
index c4120b9585..eeab90cad2 100644
|
||||
--- a/components/cli/cli/version.go
|
||||
+++ b/components/cli/cli/version.go
|
||||
@@ -5,6 +5,7 @@ package cli
|
||||
var (
|
||||
PlatformName = ""
|
||||
Version = "unknown-version"
|
||||
+ EulerVersion = "unkonwn-version"
|
||||
GitCommit = "unknown-commit"
|
||||
BuildTime = "unknown-buildtime"
|
||||
)
|
||||
diff --git a/components/cli/docker.Makefile b/components/cli/docker.Makefile
|
||||
index 28819997bc..3284d8ce0a 100644
|
||||
--- a/components/cli/docker.Makefile
|
||||
+++ b/components/cli/docker.Makefile
|
||||
@@ -12,7 +12,8 @@ VALIDATE_IMAGE_NAME = docker-cli-shell-validate$(IMAGE_TAG)
|
||||
E2E_IMAGE_NAME = docker-cli-e2e$(IMAGE_TAG)
|
||||
MOUNTS = -v "$(CURDIR)":/go/src/github.com/docker/cli
|
||||
VERSION = $(shell cat VERSION)
|
||||
-ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT -e PLATFORM
|
||||
+GITCOMMIT = $(shell git rev-parse --short HEAD 2> /dev/null || true)
|
||||
+ENVVARS = -e VERSION=$(VERSION) -e GITCOMMIT=$(GITCOMMIT) -e PLATFORM
|
||||
|
||||
# build docker image (dockerfiles/Dockerfile.build)
|
||||
.PHONY: build_docker_image
|
||||
diff --git a/components/cli/scripts/build/.variables b/components/cli/scripts/build/.variables
|
||||
index 208f44c316..d50403266e 100755
|
||||
--- a/components/cli/scripts/build/.variables
|
||||
+++ b/components/cli/scripts/build/.variables
|
||||
@@ -3,6 +3,7 @@ set -eu
|
||||
|
||||
PLATFORM=${PLATFORM:-}
|
||||
VERSION=${VERSION:-"unknown-version"}
|
||||
+EULERVERSION=${EULERVERSION:-$(cat VERSION-EULER)}
|
||||
GITCOMMIT=${GITCOMMIT:-$(git rev-parse --short HEAD 2> /dev/null || true)}
|
||||
BUILDTIME=${BUILDTIME:-$(date --utc --rfc-3339 ns 2> /dev/null | sed -e 's/ /T/')}
|
||||
|
||||
@@ -17,6 +18,7 @@ export LDFLAGS="\
|
||||
-X \"github.com/docker/cli/cli.GitCommit=${GITCOMMIT}\" \
|
||||
-X \"github.com/docker/cli/cli.BuildTime=${BUILDTIME}\" \
|
||||
-X \"github.com/docker/cli/cli.Version=${VERSION}\" \
|
||||
+ -X \"github.com/docker/cli/cli.EulerVersion=${EULERVERSION}\" \
|
||||
${LDFLAGS:-} \
|
||||
"
|
||||
|
||||
diff --git a/components/cli/vendor/github.com/docker/docker/api/types/types.go b/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
index 2fb6c5478b..56f556cad7 100644
|
||||
--- a/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
+++ b/components/cli/vendor/github.com/docker/docker/api/types/types.go
|
||||
@@ -124,6 +124,7 @@ type Version struct {
|
||||
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
|
||||
|
||||
Version string
|
||||
+ EulerVersion string
|
||||
APIVersion string `json:"ApiVersion"`
|
||||
MinAPIVersion string `json:"MinAPIVersion,omitempty"`
|
||||
GitCommit string
|
||||
diff --git a/components/engine/api/types/types.go b/components/engine/api/types/types.go
|
||||
index 820d513cbb..78e97daf98 100644
|
||||
--- a/components/engine/api/types/types.go
|
||||
+++ b/components/engine/api/types/types.go
|
||||
@@ -125,6 +125,7 @@ type Version struct {
|
||||
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
|
||||
|
||||
Version string
|
||||
+ EulerVersion string
|
||||
APIVersion string `json:"ApiVersion"`
|
||||
MinAPIVersion string `json:"MinAPIVersion,omitempty"`
|
||||
GitCommit string
|
||||
diff --git a/components/engine/daemon/info.go b/components/engine/daemon/info.go
|
||||
index 523a396643..4acad11b70 100644
|
||||
--- a/components/engine/daemon/info.go
|
||||
+++ b/components/engine/daemon/info.go
|
||||
@@ -85,13 +85,13 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
||||
// SystemVersion returns version information about the daemon.
|
||||
func (daemon *Daemon) SystemVersion() types.Version {
|
||||
kernelVersion := kernelVersion()
|
||||
-
|
||||
v := types.Version{
|
||||
Components: []types.ComponentVersion{
|
||||
{
|
||||
Name: "Engine",
|
||||
Version: dockerversion.Version,
|
||||
Details: map[string]string{
|
||||
+ "EulerVersion": dockerversion.EulerVersion,
|
||||
"GitCommit": dockerversion.GitCommit,
|
||||
"ApiVersion": api.DefaultVersion,
|
||||
"MinAPIVersion": api.MinVersion,
|
||||
@@ -107,6 +107,7 @@ func (daemon *Daemon) SystemVersion() types.Version {
|
||||
|
||||
// Populate deprecated fields for older clients
|
||||
Version: dockerversion.Version,
|
||||
+ EulerVersion: dockerversion.EulerVersion,
|
||||
GitCommit: dockerversion.GitCommit,
|
||||
APIVersion: api.DefaultVersion,
|
||||
MinAPIVersion: api.MinVersion,
|
||||
diff --git a/components/engine/dockerversion/version_lib.go b/components/engine/dockerversion/version_lib.go
|
||||
index 5d9b3fdd2b..84b1339b5b 100644
|
||||
--- a/components/engine/dockerversion/version_lib.go
|
||||
+++ b/components/engine/dockerversion/version_lib.go
|
||||
@@ -8,6 +8,7 @@ package dockerversion // import "github.com/docker/docker/dockerversion"
|
||||
const (
|
||||
GitCommit = "library-import"
|
||||
Version = "library-import"
|
||||
+ EulerVersion = "library-import"
|
||||
BuildTime = "library-import"
|
||||
IAmStatic = "library-import"
|
||||
InitCommitID = "library-import"
|
||||
diff --git a/components/engine/hack/make.sh b/components/engine/hack/make.sh
|
||||
index 2f4ece3cdb..fa87d9110f 100755
|
||||
--- a/components/engine/hack/make.sh
|
||||
+++ b/components/engine/hack/make.sh
|
||||
@@ -65,6 +65,7 @@ DEFAULT_BUNDLES=(
|
||||
cross
|
||||
)
|
||||
|
||||
+VERSION_EULER=$(< ./VERSION-EULER)
|
||||
VERSION=${VERSION:-dev}
|
||||
! BUILDTIME=$(date -u -d "@${SOURCE_DATE_EPOCH:-$(date +%s)}" --rfc-3339 ns 2> /dev/null | sed -e 's/ /T/')
|
||||
if [ "$DOCKER_GITCOMMIT" ]; then
|
||||
diff --git a/components/engine/hack/make/.go-autogen b/components/engine/hack/make/.go-autogen
|
||||
index ea8a32ff5d..99d45e9cb8 100644
|
||||
--- a/components/engine/hack/make/.go-autogen
|
||||
+++ b/components/engine/hack/make/.go-autogen
|
||||
@@ -17,6 +17,7 @@ package dockerversion
|
||||
const (
|
||||
GitCommit string = "$GITCOMMIT"
|
||||
Version string = "$VERSION"
|
||||
+ EulerVersion string = "$VERSION_EULER"
|
||||
BuildTime string = "$BUILDTIME"
|
||||
IAmStatic string = "${IAMSTATIC:-true}"
|
||||
PlatformName string = "${PLATFORM}"
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From be262686615a41b7377e5e19c9aae2a1d71cb4fb Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Tue, 22 Jan 2019 17:20:38 +0800
|
||||
Subject: [PATCH 077/111] image: fix file not exist for check file
|
||||
size
|
||||
|
||||
reason: check file size should support file not exist.
|
||||
|
||||
Change-Id: Iae3b8d4f477d6cfc51ba71a185a598687f8393a2
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/image/tarexport/load.go | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/components/engine/image/tarexport/load.go b/components/engine/image/tarexport/load.go
|
||||
index b9f8f7e3ac..34574129f1 100644
|
||||
--- a/components/engine/image/tarexport/load.go
|
||||
+++ b/components/engine/image/tarexport/load.go
|
||||
@@ -432,6 +432,10 @@ func checkValidParent(img, parent *image.Image) bool {
|
||||
func checkJsonFileSize(path string) error {
|
||||
fileInfo, err := os.Stat(path)
|
||||
if err != nil {
|
||||
+ // path can not exist.
|
||||
+ if os.IsNotExist(err) {
|
||||
+ return nil
|
||||
+ }
|
||||
return err
|
||||
}
|
||||
fileSize := fileInfo.Size()
|
||||
--
|
||||
2.17.1
|
||||
|
||||
53
patch/0078-spec-add-missing-sysconfigs-to-rpm.patch
Normal file
53
patch/0078-spec-add-missing-sysconfigs-to-rpm.patch
Normal file
@ -0,0 +1,53 @@
|
||||
From bcd276b5b62e1b5ff46eadad71417de076797ec8 Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Tue, 22 Jan 2019 17:26:35 +0800
|
||||
Subject: [PATCH 078/111] spec: add missing sysconfigs to rpm
|
||||
|
||||
reason: add missing sysconfigs to rpm, including
|
||||
- /etc/sysconfig/docker
|
||||
- /etc/sysconfig/docker-network
|
||||
- /etc/sysconfig/docker-storage
|
||||
|
||||
Partly cherry-pick from 17.06 780e079a
|
||||
|
||||
Change-Id: I7a31bc6d99bab6c6a7a60988bc66db2d48f6ca4b
|
||||
Signed-off-by: Lei Jitang <leijitang@huawei.com>
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
.../contrib/init/sysvinit-redhat/docker-network | 2 ++
|
||||
.../contrib/init/sysvinit-redhat/docker-storage | 14 ++++++++++++++
|
||||
5 files changed, 27 insertions(+), 4 deletions(-)
|
||||
create mode 100644 components/engine/contrib/init/sysvinit-redhat/docker-network
|
||||
create mode 100644 components/engine/contrib/init/sysvinit-redhat/docker-storage
|
||||
|
||||
diff --git a/components/engine/contrib/init/sysvinit-redhat/docker-network b/components/engine/contrib/init/sysvinit-redhat/docker-network
|
||||
new file mode 100644
|
||||
index 0000000000..048d1582ec
|
||||
--- /dev/null
|
||||
+++ b/components/engine/contrib/init/sysvinit-redhat/docker-network
|
||||
@@ -0,0 +1,2 @@
|
||||
+# /etc/sysconfig/docker-network
|
||||
+DOCKER_NETWORK_OPTIONS=
|
||||
diff --git a/components/engine/contrib/init/sysvinit-redhat/docker-storage b/components/engine/contrib/init/sysvinit-redhat/docker-storage
|
||||
new file mode 100644
|
||||
index 0000000000..3dc16542ff
|
||||
--- /dev/null
|
||||
+++ b/components/engine/contrib/init/sysvinit-redhat/docker-storage
|
||||
@@ -0,0 +1,14 @@
|
||||
+# This file may be automatically generated by an installation program.
|
||||
+
|
||||
+# By default, Docker uses a loopback-mounted sparse file in
|
||||
+# /var/lib/docker. The loopback makes it slower, and there are some
|
||||
+# restrictive defaults, such as 100GB max storage.
|
||||
+
|
||||
+# If your installation did not set a custom storage for Docker, you
|
||||
+# may do it below.
|
||||
+
|
||||
+# Example: Use a custom pair of raw logical volumes (one for metadata,
|
||||
+# one for data).
|
||||
+# DOCKER_STORAGE_OPTIONS = --storage-opt dm.metadatadev=/dev/mylogvol/my-docker-metadata --storage-opt dm.datadev=/dev/mylogvol/my-docker-data
|
||||
+
|
||||
+DOCKER_STORAGE_OPTIONS=
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 1564b7d772b69da0ba7f6814af2fc094def9d2fd Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 23 Jan 2019 11:07:12 +0800
|
||||
Subject: [PATCH 079/111] rwlayer: fix deadlock for docker
|
||||
commit/export
|
||||
|
||||
reason: this commit avoid deadlock while del reference count.
|
||||
|
||||
Change-Id: I2627752ed38c7bb9d789f4604acd43d130bcb926
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/layer/layer_store.go | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index cbb1ee4a19..553b098dfd 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -680,8 +680,6 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
|
||||
return []Metadata{}, nil
|
||||
}
|
||||
|
||||
- m.Lock()
|
||||
- defer m.Unlock()
|
||||
if err := m.deleteReference(l); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -690,6 +688,8 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
|
||||
return []Metadata{}, nil
|
||||
}
|
||||
|
||||
+ m.Lock()
|
||||
+ defer m.Unlock()
|
||||
if err := ls.driver.Remove(m.mountID); err != nil {
|
||||
logrus.Errorf("Error removing mounted layer %s: %s", m.name, err)
|
||||
m.retakeReference(l)
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
From c1b7332e8f531e53062c740a16f953cd37661d30 Mon Sep 17 00:00:00 2001
|
||||
From: leizhongkai <leizhongkai@huawei.com>
|
||||
Date: Thu, 24 Jan 2019 20:24:08 +0800
|
||||
Subject: [PATCH 081/111] runtime-spec: revert the modify of runtime
|
||||
spec
|
||||
|
||||
reason:revert the modify of runtime spec,make the compatibility in runc
|
||||
|
||||
Change-Id: Ia294a169ff15c860c7db3b7a9ab14cecb605cfef
|
||||
Signed-off-by: leizhongkai <leizhongkai@huawei.com>
|
||||
---
|
||||
.../runtime-spec/specs-go/config.go | 18 +++++++++---------
|
||||
1 file changed, 9 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
index aab7b8a098..46049b3bfa 100644
|
||||
--- a/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
+++ b/components/engine/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
|
||||
@@ -256,20 +256,20 @@ type LinuxThrottleDevice struct {
|
||||
|
||||
// LinuxBlockIO for Linux cgroup 'blkio' resource management
|
||||
type LinuxBlockIO struct {
|
||||
- // Specifies per cgroup weight, range is from 10 to 1000
|
||||
- Weight *uint16 `json:"blkioWeight,omitempty"`
|
||||
- // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, range is from 10 to 1000, CFQ scheduler only
|
||||
- LeafWeight *uint16 `json:"blkioLeafWeight,omitempty"`
|
||||
+ // Specifies per cgroup weight
|
||||
+ Weight *uint16 `json:"weight,omitempty"`
|
||||
+ // Specifies tasks' weight in the given cgroup while competing with the cgroup's child cgroups, CFQ scheduler only
|
||||
+ LeafWeight *uint16 `json:"leafWeight,omitempty"`
|
||||
// Weight per cgroup per device, can override BlkioWeight
|
||||
- WeightDevice []LinuxWeightDevice `json:"blkioWeightDevice,omitempty"`
|
||||
+ WeightDevice []LinuxWeightDevice `json:"weightDevice,omitempty"`
|
||||
// IO read rate limit per cgroup per device, bytes per second
|
||||
- ThrottleReadBpsDevice []LinuxThrottleDevice `json:"blkioThrottleReadBpsDevice,omitempty"`
|
||||
+ ThrottleReadBpsDevice []LinuxThrottleDevice `json:"throttleReadBpsDevice,omitempty"`
|
||||
// IO write rate limit per cgroup per device, bytes per second
|
||||
- ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"blkioThrottleWriteBpsDevice,omitempty"`
|
||||
+ ThrottleWriteBpsDevice []LinuxThrottleDevice `json:"throttleWriteBpsDevice,omitempty"`
|
||||
// IO read rate limit per cgroup per device, IO per second
|
||||
- ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleReadIOPSDevice,omitempty"`
|
||||
+ ThrottleReadIOPSDevice []LinuxThrottleDevice `json:"throttleReadIOPSDevice,omitempty"`
|
||||
// IO write rate limit per cgroup per device, IO per second
|
||||
- ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"blkioThrottleWriteIOPSDevice,omitempty"`
|
||||
+ ThrottleWriteIOPSDevice []LinuxThrottleDevice `json:"throttleWriteIOPSDevice,omitempty"`
|
||||
}
|
||||
|
||||
// LinuxMemory for Linux cgroup 'memory' resource management
|
||||
--
|
||||
2.17.1
|
||||
|
||||
32
patch/0083-test-fix-start-paused-container.patch
Normal file
32
patch/0083-test-fix-start-paused-container.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From 3e2f675c4e55a73e9ac2ae7b6c0dfca8d37dd9d8 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 24 Jan 2019 16:20:24 +0800
|
||||
Subject: [PATCH 083/111] test: fix start paused container
|
||||
|
||||
reason: please unpause before start.
|
||||
|
||||
Change-Id: I435ab7e5cfe4aaed8c6c4e502ca64b0c65fff6a5
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/integration-cli/docker_cli_daemon_test.go | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/integration-cli/docker_cli_daemon_test.go b/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
index d3cd5f1676..02c42c22e2 100644
|
||||
--- a/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
+++ b/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
@@ -1627,9 +1627,8 @@ func (s *DockerDaemonSuite) TestDaemonRestartWithPausedContainer(c *check.C) {
|
||||
case <-time.After(5 * time.Second):
|
||||
c.Fatal("Waiting on start a container timed out")
|
||||
case err := <-errchan:
|
||||
- if err != nil {
|
||||
- c.Fatal(err)
|
||||
- }
|
||||
+ c.Assert(err, check.NotNil, check.Commentf("cannot start a paused container"))
|
||||
+ s.d.Cmd("unpause", "test")
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
47
patch/0084-test-skip-pause-test-with-ctr.patch
Normal file
47
patch/0084-test-skip-pause-test-with-ctr.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From c6edc1d912211c8b35df6c28033fb577a899573e Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Thu, 24 Jan 2019 16:28:45 +0800
|
||||
Subject: [PATCH 084/111] test: skip pause test with ctr
|
||||
|
||||
reason: pause managed by docker only
|
||||
|
||||
Change-Id: I8aae73e4ab1e0bf9ed639495aa112469ac3630d9
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/integration-cli/docker_cli_daemon_test.go | 3 ++-
|
||||
components/engine/integration-cli/requirements_test.go | 5 +++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/integration-cli/docker_cli_daemon_test.go b/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
index 02c42c22e2..467edb04b4 100644
|
||||
--- a/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
+++ b/components/engine/integration-cli/docker_cli_daemon_test.go
|
||||
@@ -2049,7 +2049,8 @@ func (s *DockerDaemonSuite) TestCleanupMountsAfterDaemonCrash(c *check.C) {
|
||||
|
||||
// TestDaemonRestartWithUnpausedRunningContainer requires live restore of running containers.
|
||||
func (s *DockerDaemonSuite) TestDaemonRestartWithUnpausedRunningContainer(t *check.C) {
|
||||
- testRequires(t, DaemonIsLinux)
|
||||
+ testRequires(t, DaemonIsLinux, SupportCtr)
|
||||
+
|
||||
s.d.StartWithBusybox(t, "--live-restore")
|
||||
|
||||
cid, err := s.d.Cmd("run", "-d", "--name", "test", "busybox", "top")
|
||||
diff --git a/components/engine/integration-cli/requirements_test.go b/components/engine/integration-cli/requirements_test.go
|
||||
index 28be59cd2c..4647ce8ccc 100644
|
||||
--- a/components/engine/integration-cli/requirements_test.go
|
||||
+++ b/components/engine/integration-cli/requirements_test.go
|
||||
@@ -38,6 +38,11 @@ func DaemonIsWindowsAtLeastBuild(buildNumber int) func() bool {
|
||||
}
|
||||
}
|
||||
|
||||
+func SupportCtr() bool {
|
||||
+ // not support ctr now.
|
||||
+ return false
|
||||
+}
|
||||
+
|
||||
func DaemonIsLinux() bool {
|
||||
return testEnv.OSType == "linux"
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
129
patch/0085-event-log-detailed-event-with-info-level.patch
Normal file
129
patch/0085-event-log-detailed-event-with-info-level.patch
Normal file
@ -0,0 +1,129 @@
|
||||
From 2a3375c72a5d535864561a0a5fd46dc1fee17013 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Fri, 25 Jan 2019 16:56:08 +0800
|
||||
Subject: [PATCH 085/111] event: log detailed event with info level
|
||||
|
||||
reason: DFX improve event level and record with detailed info.
|
||||
|
||||
Change-Id: Ibb5b1058b84de39f9f7058a46a15c2dbd27bc746
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
.../engine/libcontainerd/client_daemon.go | 51 ++++++++++++++++++-
|
||||
1 file changed, 49 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/libcontainerd/client_daemon.go b/components/engine/libcontainerd/client_daemon.go
|
||||
index cb9cb43a73..491bda281c 100644
|
||||
--- a/components/engine/libcontainerd/client_daemon.go
|
||||
+++ b/components/engine/libcontainerd/client_daemon.go
|
||||
@@ -791,8 +791,6 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
continue
|
||||
}
|
||||
|
||||
- c.logger.WithField("topic", ev.Topic).Debug("event")
|
||||
-
|
||||
switch t := v.(type) {
|
||||
case *apievents.TaskCreate:
|
||||
et = EventCreate
|
||||
@@ -801,6 +799,11 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "Pid": t.Pid,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskStart:
|
||||
et = EventStart
|
||||
ei = EventInfo{
|
||||
@@ -808,6 +811,11 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
ProcessID: t.ContainerID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "Pid": t.Pid,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskExit:
|
||||
et = EventExit
|
||||
ei = EventInfo{
|
||||
@@ -817,6 +825,13 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
ExitCode: t.ExitStatus,
|
||||
ExitedAt: t.ExitedAt,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "Pid": t.Pid,
|
||||
+ "ExitStatus": t.ExitStatus,
|
||||
+ "ExitedAt": t.ExitedAt,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskOOM:
|
||||
et = EventOOM
|
||||
ei = EventInfo{
|
||||
@@ -824,12 +839,22 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
OOMKilled: true,
|
||||
}
|
||||
oomKilled = true
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "OOMKilled": true,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskExecAdded:
|
||||
et = EventExecAdded
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
ProcessID: t.ExecID,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "execID": t.ExecID,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskExecStarted:
|
||||
et = EventExecStarted
|
||||
ei = EventInfo{
|
||||
@@ -837,16 +862,38 @@ func (c *client) processEventStream(ctx context.Context, ns string) {
|
||||
ProcessID: t.ExecID,
|
||||
Pid: t.Pid,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "execID": t.ExecID,
|
||||
+ "Pid": t.Pid,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskPaused:
|
||||
et = EventPaused
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ }).Infof("event")
|
||||
case *apievents.TaskResumed:
|
||||
et = EventResumed
|
||||
ei = EventInfo{
|
||||
ContainerID: t.ContainerID,
|
||||
}
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ }).Infof("event")
|
||||
+ case *apievents.TaskDelete:
|
||||
+ c.logger.WithFields(logrus.Fields{
|
||||
+ "topic": ev.Topic,
|
||||
+ "containerID": t.ContainerID,
|
||||
+ "Pid": t.Pid,
|
||||
+ "ExitStatus": t.ExitStatus,
|
||||
+ "ExitedAt": t.ExitedAt,
|
||||
+ }).Infof("event")
|
||||
default:
|
||||
c.logger.WithFields(logrus.Fields{
|
||||
"topic": ev.Topic,
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
From 99b7f823b7dfe88dc2d4f4073f10cbf3a437bd81 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Fri, 25 Jan 2019 16:59:26 +0800
|
||||
Subject: [PATCH 086/111] restart: fix daemon restart with
|
||||
restart=always container
|
||||
|
||||
reason: fix daemon gracefully restart while container is start with
|
||||
restart=always. restart-manager blocked to start container while
|
||||
restoring, when restoring start container successful, the
|
||||
restart-manager will start container but error with "id already in use".
|
||||
|
||||
related testcase:
|
||||
TestDaemonRestartKillContainers
|
||||
TestDockerNetworkHostModeUngracefulDaemonRestart
|
||||
|
||||
ref:
|
||||
- https://github.com/moby/moby/issues/38249
|
||||
|
||||
Change-Id: I2545286a8371cb656ec6574d23cd15de4ba60283
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon_unix.go | 3 +++
|
||||
components/engine/daemon/start.go | 9 +++++++++
|
||||
2 files changed, 12 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon_unix.go b/components/engine/daemon/daemon_unix.go
|
||||
index b20c66e27b..9abc9a329a 100644
|
||||
--- a/components/engine/daemon/daemon_unix.go
|
||||
+++ b/components/engine/daemon/daemon_unix.go
|
||||
@@ -1291,6 +1291,9 @@ func setupDaemonRootPropagation(cfg *config.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
+ if err := os.MkdirAll(filepath.Dir(cleanupFile), 0700); err != nil {
|
||||
+ return errors.Wrap(err, "error mkdir parent to signal mount cleanup on shutdown")
|
||||
+ }
|
||||
if err := ioutil.WriteFile(cleanupFile, nil, 0600); err != nil {
|
||||
return errors.Wrap(err, "error writing file to signal mount cleanup on shutdown")
|
||||
}
|
||||
diff --git a/components/engine/daemon/start.go b/components/engine/daemon/start.go
|
||||
index c00bd9ceb2..96ae45e11e 100644
|
||||
--- a/components/engine/daemon/start.go
|
||||
+++ b/components/engine/daemon/start.go
|
||||
@@ -108,6 +108,15 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
||||
return nil
|
||||
}
|
||||
|
||||
+ // fix restartManager restarted the container is already started by restore.
|
||||
+ if container.Running {
|
||||
+ _, err := daemon.containerd.Status(context.Background(), container.ID)
|
||||
+ if err == nil {
|
||||
+ logrus.Warnf("skip starting the container is exist and running.")
|
||||
+ return nil
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
if container.RemovalInProgress || container.Dead {
|
||||
return errdefs.Conflict(errors.New("container is marked for removal and cannot be started"))
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
48
patch/0088-attach-add-timeout-return-for-getExitStatus.patch
Normal file
48
patch/0088-attach-add-timeout-return-for-getExitStatus.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 4f99f2ea6fac5d585cee3b7362b109dcf869beda Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Wed, 30 Jan 2019 13:42:34 +0800
|
||||
Subject: [PATCH 088/111] attach: add timeout return for getExitStatus
|
||||
|
||||
reason:In cli/command/container/attach.go, func getExitStatus() will
|
||||
return until container turn to unrunning state. When we excute docker
|
||||
attach and other commands inside container together, for the state of
|
||||
container will not change, docker attach command is stuck.
|
||||
|
||||
Change-Id: Ifda6096643c659341fd6d343eb4a8cbf08e5a71c
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/cli/cli/command/container/attach.go | 4 ++++
|
||||
5 files changed, 10 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/attach.go b/components/cli/cli/command/container/attach.go
|
||||
index de96a3b7d8..ff1014d70c 100644
|
||||
--- a/components/cli/cli/command/container/attach.go
|
||||
+++ b/components/cli/cli/command/container/attach.go
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http/httputil"
|
||||
+ "time"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
@@ -150,6 +151,7 @@ func runAttach(dockerCli command.Cli, opts *attachOptions) error {
|
||||
}
|
||||
|
||||
func getExitStatus(errC <-chan error, resultC <-chan container.ContainerWaitOKBody) error {
|
||||
+ timeout := time.NewTimer(time.Second)
|
||||
select {
|
||||
case result := <-resultC:
|
||||
if result.Error != nil {
|
||||
@@ -160,6 +162,8 @@ func getExitStatus(errC <-chan error, resultC <-chan container.ContainerWaitOKBo
|
||||
}
|
||||
case err := <-errC:
|
||||
return err
|
||||
+ case <-timeout.C:
|
||||
+ return fmt.Errorf("Wait container status timeout.")
|
||||
}
|
||||
|
||||
return nil
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 9a48f9b439a03e7fd5eeec4ff2cebac4cddf669f Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 30 Jan 2019 21:28:16 +0800
|
||||
Subject: [PATCH 089/111] libcontainerd: fix stuck when containerd in
|
||||
T-state
|
||||
|
||||
reason: when containerd is alive but not responding, shall restart
|
||||
containerd avoid cmd stuck.
|
||||
|
||||
Change-Id: Iab220c8988b50b39f4fd84be9454a0b097968751
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/libcontainerd/supervisor/remote_daemon.go | 2 +-
|
||||
5 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/libcontainerd/supervisor/remote_daemon.go b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
index 095300f753..c5da3a56fe 100644
|
||||
--- a/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
+++ b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
@@ -307,7 +307,7 @@ func (r *remote) monitorDaemon(ctx context.Context) {
|
||||
r.logger.WithError(err).WithField("binary", binaryName).Debug("daemon is not responding")
|
||||
|
||||
transientFailureCount++
|
||||
- if transientFailureCount < maxConnectionRetryCount || system.IsProcessAlive(r.daemonPid) {
|
||||
+ if transientFailureCount < maxConnectionRetryCount {
|
||||
delay = time.After(time.Duration(transientFailureCount) * 200 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
73
patch/0090-overlay2-Use-index-off-if-possible.patch
Normal file
73
patch/0090-overlay2-Use-index-off-if-possible.patch
Normal file
@ -0,0 +1,73 @@
|
||||
From b2750c914429b4f981848d0c829ddfc0c8acc37e Mon Sep 17 00:00:00 2001
|
||||
From: xiadanni <xiadanni@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 01:03:12 +0800
|
||||
Subject: [PATCH 090/111] overlay2: Use index=off if possible
|
||||
|
||||
reason: Docker overlay driver can't work with index=on feature of
|
||||
the Linux kernel "overlay" filesystem. In case the global
|
||||
default is set to "yes", Docker will fail with EBUSY when
|
||||
trying to mount.
|
||||
|
||||
Cherry-pick from https://github.com/moby/moby/pull/37993/commits/8422d85087bfa770b62ef4e1daaca95ee6783d86
|
||||
|
||||
Change-Id: Iad1addaca9983ba35c466951e04c7034b0a18fab
|
||||
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index cf8993e9f3..d87f979673 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -111,6 +111,8 @@ var (
|
||||
|
||||
useNaiveDiffLock sync.Once
|
||||
useNaiveDiffOnly bool
|
||||
+
|
||||
+ indexOff string
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -228,7 +230,18 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
return nil, fmt.Errorf("Storage Option overlay2.size only supported for backingFS XFS or ext4. Found %v", backingFs)
|
||||
}
|
||||
|
||||
- logger.Debugf("backingFs=%s, projectQuotaSupported=%v", backingFs, projectQuotaSupported)
|
||||
+ // figure out whether "index=off" option is recognized by the kernel
|
||||
+ _, err = os.Stat("/sys/module/overlay/parameters/index")
|
||||
+ switch {
|
||||
+ case err == nil:
|
||||
+ indexOff = "index=off,"
|
||||
+ case os.IsNotExist(err):
|
||||
+ // old kernel, no index -- do nothing
|
||||
+ default:
|
||||
+ logger.Warnf("Unable to detect whether overlay kernel module supports index parameter: %s", err)
|
||||
+ }
|
||||
+
|
||||
+ logger.Debugf("backingFs=%s, projectQuotaSupported=%v, indexOff=%q", backingFs, projectQuotaSupported, indexOff)
|
||||
|
||||
return d, nil
|
||||
}
|
||||
@@ -632,7 +645,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
||||
for i, s := range splitLowers {
|
||||
absLowers[i] = path.Join(d.home, s)
|
||||
}
|
||||
- opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", strings.Join(absLowers, ":"), path.Join(dir, "diff"), path.Join(dir, "work"))
|
||||
+ opts := indexOff + "lowerdir=" + strings.Join(absLowers, ":") + ",upperdir=" + path.Join(dir, "diff") + ",workdir=" + path.Join(dir, "work")
|
||||
mountData := label.FormatMountLabel(opts, mountLabel)
|
||||
mount := unix.Mount
|
||||
mountTarget := mergedDir
|
||||
@@ -661,7 +674,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
||||
// fit within a page and relative links make the mount data much
|
||||
// smaller at the expense of requiring a fork exec to chroot.
|
||||
if len(mountData) > pageSize {
|
||||
- opts = fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", string(lowers), path.Join(id, "diff"), path.Join(id, "work"))
|
||||
+ opts = indexOff + "lowerdir=" + string(lowers) + ",upperdir=" + path.Join(id, "diff") + ",workdir=" + path.Join(id, "work")
|
||||
mountData = label.FormatMountLabel(opts, mountLabel)
|
||||
if len(mountData) > pageSize {
|
||||
return nil, fmt.Errorf("cannot mount layer, mount label too large %d", len(mountData))
|
||||
--
|
||||
2.17.1
|
||||
|
||||
168
patch/0091-overlay2-use-global-logger-instance.patch
Normal file
168
patch/0091-overlay2-use-global-logger-instance.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From 7bce81e40dbc73b7e778d8676687efc3b04c6d39 Mon Sep 17 00:00:00 2001
|
||||
From: xiadanni <xiadanni@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 01:45:57 +0800
|
||||
Subject: [PATCH 091/111] overlay2: use global logger instance
|
||||
|
||||
reason: This simplifies the code a lot.
|
||||
|
||||
Cherry-pick from https://github.com/moby/moby/pull/37993/commits/a55d32546a8556f9e6cabbc99836b573b9944f0c
|
||||
|
||||
Change-Id: I2c4998d677c8500701e077b2520b96fe49ea4364
|
||||
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
|
||||
Signed-off-by: xiadanni <xiadanni@huawei.com>
|
||||
---
|
||||
.../daemon/graphdriver/overlay2/check.go | 9 ++++-----
|
||||
.../daemon/graphdriver/overlay2/overlay.go | 20 +++++++++----------
|
||||
.../daemon/graphdriver/overlay2/randomid.go | 3 +--
|
||||
3 files changed, 14 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/check.go b/components/engine/daemon/graphdriver/overlay2/check.go
|
||||
index d6ee42f47f..1703b7a00c 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/check.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/check.go
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/pkg/errors"
|
||||
- "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -27,7 +26,7 @@ func doesSupportNativeDiff(d string) error {
|
||||
}
|
||||
defer func() {
|
||||
if err := os.RemoveAll(td); err != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Warnf("Failed to remove check directory %v: %v", td, err)
|
||||
+ logger.Warnf("Failed to remove check directory %v: %v", td, err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -62,7 +61,7 @@ func doesSupportNativeDiff(d string) error {
|
||||
}
|
||||
defer func() {
|
||||
if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
|
||||
+ logger.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -113,7 +112,7 @@ func supportsMultipleLowerDir(d string) error {
|
||||
}
|
||||
defer func() {
|
||||
if err := os.RemoveAll(td); err != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Warnf("Failed to remove check directory %v: %v", td, err)
|
||||
+ logger.Warnf("Failed to remove check directory %v: %v", td, err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -128,7 +127,7 @@ func supportsMultipleLowerDir(d string) error {
|
||||
return errors.Wrap(err, "failed to mount overlay")
|
||||
}
|
||||
if err := unix.Unmount(filepath.Join(td, "merged"), 0); err != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
|
||||
+ logger.Warnf("Failed to unmount check directory %v: %v", filepath.Join(td, "merged"), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index d87f979673..71474f8f36 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -106,6 +106,7 @@ type Driver struct {
|
||||
}
|
||||
|
||||
var (
|
||||
+ logger = logrus.WithField("storage-driver", "overlay2")
|
||||
backingFs = "<unknown>"
|
||||
projectQuotaSupported = false
|
||||
|
||||
@@ -157,8 +158,6 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
backingFs = fsName
|
||||
}
|
||||
|
||||
- logger := logrus.WithField("storage-driver", "overlay2")
|
||||
-
|
||||
switch fsMagic {
|
||||
case graphdriver.FsMagicAufs, graphdriver.FsMagicEcryptfs, graphdriver.FsMagicNfsFs, graphdriver.FsMagicOverlay, graphdriver.FsMagicZfs:
|
||||
logger.Errorf("'overlay2' is not supported over %s", backingFs)
|
||||
@@ -306,14 +305,14 @@ func supportsOverlay() error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
- logrus.WithField("storage-driver", "overlay2").Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.")
|
||||
+ logger.Error("'overlay' not found as a supported filesystem on this host. Please ensure kernel is new enough and has overlay support loaded.")
|
||||
return graphdriver.ErrNotSupported
|
||||
}
|
||||
|
||||
func useNaiveDiff(home string) bool {
|
||||
useNaiveDiffLock.Do(func() {
|
||||
if err := doesSupportNativeDiff(home); err != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Warnf("Not using native diff for overlay2, this may cause degraded performance for building images: %v", err)
|
||||
+ logger.Warnf("Not using native diff for overlay2, this may cause degraded performance for building images: %v", err)
|
||||
useNaiveDiffOnly = true
|
||||
}
|
||||
})
|
||||
@@ -629,11 +628,11 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
|
||||
if retErr != nil {
|
||||
if c := d.ctr.Decrement(mergedDir); c <= 0 {
|
||||
if mntErr := unix.Unmount(mergedDir, 0); mntErr != nil {
|
||||
- logrus.WithField("storage-driver", "overlay2").Errorf("error unmounting %v: %v", mergedDir, mntErr)
|
||||
+ logger.Errorf("error unmounting %v: %v", mergedDir, mntErr)
|
||||
}
|
||||
// Cleanup the created merged directory; see the comment in Put's rmdir
|
||||
if rmErr := unix.Rmdir(mergedDir); rmErr != nil && !os.IsNotExist(rmErr) {
|
||||
- logrus.WithField("storage-driver", "overlay2").Debugf("Failed to remove %s: %v: %v", id, rmErr, err)
|
||||
+ logger.Debugf("Failed to remove %s: %v: %v", id, rmErr, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -716,7 +715,6 @@ func (d *Driver) Put(id string) error {
|
||||
}
|
||||
|
||||
mountpoint := path.Join(dir, "merged")
|
||||
- logger := logrus.WithField("storage-driver", "overlay2")
|
||||
if count := d.ctr.Decrement(mountpoint); count > 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -802,7 +800,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
|
||||
|
||||
applyDir := d.getDiffPath(id)
|
||||
|
||||
- logrus.WithField("storage-driver", "overlay2").Debugf("Applying tar in %s", applyDir)
|
||||
+ logger.Debugf("Applying tar in %s", applyDir)
|
||||
// Overlay doesn't need the parent id to apply the diff
|
||||
if err := untar(diff, applyDir, &archive.TarOptions{
|
||||
UIDMaps: d.uidMaps,
|
||||
@@ -840,7 +838,7 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) {
|
||||
}
|
||||
|
||||
diffPath := d.getDiffPath(id)
|
||||
- logrus.WithField("storage-driver", "overlay2").Debugf("Tar with options on %s", diffPath)
|
||||
+ logger.Debugf("Tar with options on %s", diffPath)
|
||||
return archive.TarWithOptions(diffPath, &archive.TarOptions{
|
||||
Compression: archive.Uncompressed,
|
||||
UIDMaps: d.uidMaps,
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/randomid.go b/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
index 933d9fccb6..6ab50df8e6 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/randomid.go
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
- "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
@@ -48,7 +47,7 @@ func generateID(l int) string {
|
||||
if retryOnError(err) && retries < maxretries {
|
||||
count += n
|
||||
retries++
|
||||
- logrus.Errorf("error generating version 4 uuid, retrying: %v", err)
|
||||
+ logger.Errorf("error generating version 4 uuid, retrying: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
214
patch/0092-Revert-docker-Lock-the-RWLayer-while-committi.patch
Normal file
214
patch/0092-Revert-docker-Lock-the-RWLayer-while-committi.patch
Normal file
@ -0,0 +1,214 @@
|
||||
From 5c472ad67723ba45ee92dce62f9f45292213644e Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 11:02:31 +0800
|
||||
Subject: [PATCH 092/111] Revert "docker: Lock the RWLayer while
|
||||
committing/exporting"
|
||||
|
||||
reason: This reverts commit a3dbaededfff6d20e16740c47ac69de9a91cccff.
|
||||
|
||||
1. rwlayer is already protected by ls.mountL.Lock, no need add lock to
|
||||
mountedLayer.
|
||||
2. rwlayer is protected by reference, no need add lock during commit or
|
||||
export.
|
||||
|
||||
known issues:
|
||||
- commit or export will put reference during hold lock, if put the last
|
||||
reference, dead lock happens on release layer.
|
||||
- delete(docker rm) will set container.RWLayer = nil, it's dangrous
|
||||
after export or commit when calling container.RWLayer.RUnlockRWLayer().
|
||||
|
||||
Change-Id: I72cc72a3398133d693cb813fde1964068544ec03
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/commit.go | 2 --
|
||||
components/engine/daemon/export.go | 2 --
|
||||
components/engine/layer/empty.go | 13 +------------
|
||||
components/engine/layer/layer.go | 7 -------
|
||||
components/engine/layer/layer_store.go | 4 ----
|
||||
components/engine/layer/mounted_layer.go | 10 ----------
|
||||
components/engine/layer/ro_layer.go | 10 ----------
|
||||
11 files changed, 7 insertions(+), 53 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/commit.go b/components/engine/daemon/commit.go
|
||||
index fc7d2782ef..0f6f440514 100644
|
||||
--- a/components/engine/daemon/commit.go
|
||||
+++ b/components/engine/daemon/commit.go
|
||||
@@ -155,8 +155,6 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
|
||||
return "", err
|
||||
}
|
||||
|
||||
- container.RWLayer.RLockRWLayer()
|
||||
- defer container.RWLayer.RUnlockRWLayer()
|
||||
id, err := daemon.imageService.CommitImage(backend.CommitConfig{
|
||||
Author: c.Author,
|
||||
Comment: c.Comment,
|
||||
diff --git a/components/engine/daemon/export.go b/components/engine/daemon/export.go
|
||||
index ebd2d75f40..27bc35967d 100644
|
||||
--- a/components/engine/daemon/export.go
|
||||
+++ b/components/engine/daemon/export.go
|
||||
@@ -34,8 +34,6 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
|
||||
return errdefs.Conflict(err)
|
||||
}
|
||||
|
||||
- container.RWLayer.RLockRWLayer()
|
||||
- defer container.RWLayer.RUnlockRWLayer()
|
||||
data, err := daemon.containerExport(container)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error exporting container %s: %v", name, err)
|
||||
diff --git a/components/engine/layer/empty.go b/components/engine/layer/empty.go
|
||||
index 16a49a7abd..c81c702140 100644
|
||||
--- a/components/engine/layer/empty.go
|
||||
+++ b/components/engine/layer/empty.go
|
||||
@@ -6,16 +6,13 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
- "sync"
|
||||
)
|
||||
|
||||
// DigestSHA256EmptyTar is the canonical sha256 digest of empty tar file -
|
||||
// (1024 NULL bytes)
|
||||
const DigestSHA256EmptyTar = DiffID("sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef")
|
||||
|
||||
-type emptyLayer struct {
|
||||
- sync.RWMutex
|
||||
-}
|
||||
+type emptyLayer struct{}
|
||||
|
||||
// EmptyLayer is a layer that corresponds to empty tar.
|
||||
var EmptyLayer = &emptyLayer{}
|
||||
@@ -58,14 +55,6 @@ func (el *emptyLayer) Metadata() (map[string]string, error) {
|
||||
return make(map[string]string), nil
|
||||
}
|
||||
|
||||
-func (el *emptyLayer) RLockRWLayer() {
|
||||
- el.RLock()
|
||||
-}
|
||||
-
|
||||
-func (el *emptyLayer) RUnlockRWLayer() {
|
||||
- el.RUnlock()
|
||||
-}
|
||||
-
|
||||
// IsEmpty returns true if the layer is an EmptyLayer
|
||||
func IsEmpty(diffID DiffID) bool {
|
||||
return diffID == DigestSHA256EmptyTar
|
||||
diff --git a/components/engine/layer/layer.go b/components/engine/layer/layer.go
|
||||
index e35a13135b..cb13c98d0b 100644
|
||||
--- a/components/engine/layer/layer.go
|
||||
+++ b/components/engine/layer/layer.go
|
||||
@@ -145,13 +145,6 @@ type RWLayer interface {
|
||||
|
||||
// Metadata returns the low level metadata for the mutable layer
|
||||
Metadata() (map[string]string, error)
|
||||
-
|
||||
- // RLockRWLayer locks the RWLayer to block unmounting/removal
|
||||
- // of that layer
|
||||
- RLockRWLayer()
|
||||
-
|
||||
- // RUnlockRWLayer unlocks the RWLayer
|
||||
- RUnlockRWLayer()
|
||||
}
|
||||
|
||||
// Metadata holds information about a
|
||||
diff --git a/components/engine/layer/layer_store.go b/components/engine/layer/layer_store.go
|
||||
index 553b098dfd..b6fc45e655 100644
|
||||
--- a/components/engine/layer/layer_store.go
|
||||
+++ b/components/engine/layer/layer_store.go
|
||||
@@ -598,7 +598,6 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWL
|
||||
// Release parent chain if error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
- m.Lock()
|
||||
if deferErr := ls.driver.Remove(m.mountID); deferErr != nil {
|
||||
logrus.Errorf("Error removing mounted layer during create rw layer %s: %s", m.name, deferErr)
|
||||
}
|
||||
@@ -610,7 +609,6 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWL
|
||||
if deferErr := ls.store.RemoveMount(m.name); deferErr != nil {
|
||||
logrus.Errorf("Error removing mount metadata during create rw layer %s: %s", m.name, deferErr)
|
||||
}
|
||||
- m.Unlock()
|
||||
|
||||
ls.layerL.Lock()
|
||||
ls.releaseLayer(p)
|
||||
@@ -688,8 +686,6 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
|
||||
return []Metadata{}, nil
|
||||
}
|
||||
|
||||
- m.Lock()
|
||||
- defer m.Unlock()
|
||||
if err := ls.driver.Remove(m.mountID); err != nil {
|
||||
logrus.Errorf("Error removing mounted layer %s: %s", m.name, err)
|
||||
m.retakeReference(l)
|
||||
diff --git a/components/engine/layer/mounted_layer.go b/components/engine/layer/mounted_layer.go
|
||||
index 66711d6cf7..d6858c662c 100644
|
||||
--- a/components/engine/layer/mounted_layer.go
|
||||
+++ b/components/engine/layer/mounted_layer.go
|
||||
@@ -2,7 +2,6 @@ package layer // import "github.com/docker/docker/layer"
|
||||
|
||||
import (
|
||||
"io"
|
||||
- "sync"
|
||||
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
@@ -17,7 +16,6 @@ type mountedLayer struct {
|
||||
layerStore *layerStore
|
||||
|
||||
references map[RWLayer]*referencedRWLayer
|
||||
- sync.RWMutex
|
||||
}
|
||||
|
||||
func (ml *mountedLayer) cacheParent() string {
|
||||
@@ -60,14 +58,6 @@ func (ml *mountedLayer) Metadata() (map[string]string, error) {
|
||||
return ml.layerStore.driver.GetMetadata(ml.mountID)
|
||||
}
|
||||
|
||||
-func (ml *mountedLayer) RLockRWLayer() {
|
||||
- ml.RLock()
|
||||
-}
|
||||
-
|
||||
-func (ml *mountedLayer) RUnlockRWLayer() {
|
||||
- ml.RUnlock()
|
||||
-}
|
||||
-
|
||||
func (ml *mountedLayer) getReference() RWLayer {
|
||||
ref := &referencedRWLayer{
|
||||
mountedLayer: ml,
|
||||
diff --git a/components/engine/layer/ro_layer.go b/components/engine/layer/ro_layer.go
|
||||
index 59bcf17d18..3555e8b027 100644
|
||||
--- a/components/engine/layer/ro_layer.go
|
||||
+++ b/components/engine/layer/ro_layer.go
|
||||
@@ -3,7 +3,6 @@ package layer // import "github.com/docker/docker/layer"
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
- "sync"
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/opencontainers/go-digest"
|
||||
@@ -20,7 +19,6 @@ type roLayer struct {
|
||||
|
||||
referenceCount int
|
||||
references map[Layer]struct{}
|
||||
- sync.RWMutex
|
||||
}
|
||||
|
||||
// TarStream for roLayer guarantees that the data that is produced is the exact
|
||||
@@ -94,14 +92,6 @@ func (rl *roLayer) Metadata() (map[string]string, error) {
|
||||
return rl.layerStore.driver.GetMetadata(rl.cacheID)
|
||||
}
|
||||
|
||||
-func (rl *roLayer) RLockRWLayer() {
|
||||
- rl.RLock()
|
||||
-}
|
||||
-
|
||||
-func (rl *roLayer) RUnlockRWLayer() {
|
||||
- rl.RUnlock()
|
||||
-}
|
||||
-
|
||||
type referencedCacheLayer struct {
|
||||
*roLayer
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 03024503528f2355a666cb37a6b6bc3902bc977d Mon Sep 17 00:00:00 2001
|
||||
From: zhangsong34 <zhangsong34@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 17:34:44 +0800
|
||||
Subject: [PATCH 093/111] docker: do not try to connect containerd if
|
||||
containerd daemon is down
|
||||
|
||||
reason:do not try to connect containerd if containerd daemon is down, reduce
|
||||
delay time to restart containerd.
|
||||
|
||||
Change-Id: I7e6ab9e4c154a82b3b2609440cbfc7d3ea14d28d
|
||||
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
|
||||
---
|
||||
components/engine/libcontainerd/supervisor/remote_daemon.go | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/libcontainerd/supervisor/remote_daemon.go b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
index c5da3a56fe..45cc3c3032 100644
|
||||
--- a/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
+++ b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
@@ -289,7 +289,7 @@ func (r *remote) monitorDaemon(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
- if client != nil {
|
||||
+ if client != nil && system.IsProcessAlive(r.daemonPid) {
|
||||
tctx, cancel := context.WithTimeout(ctx, healthCheckTimeout)
|
||||
_, err := client.IsServing(tctx)
|
||||
cancel()
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
From 69edbbf9eca76adf67e2b26ee564b53eaef76aff Mon Sep 17 00:00:00 2001
|
||||
From: zhangsong34 <zhangsong34@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 19:00:14 +0800
|
||||
Subject: [PATCH 094/111] docker: change health check minum param to
|
||||
one second
|
||||
|
||||
reason:change health check minum period to one second, include
|
||||
--health-interval, --health-timeout and --health-start-period.
|
||||
|
||||
Change-Id: I1ebab75c23edf4f9006142f92894114c5d447f75
|
||||
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
|
||||
---
|
||||
components/engine/daemon/container.go | 12 ++++++------
|
||||
.../engine/integration-cli/docker_api_create_test.go | 7 +++----
|
||||
2 files changed, 9 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/container.go b/components/engine/daemon/container.go
|
||||
index 06a19bb4c8..6d357421f3 100644
|
||||
--- a/components/engine/daemon/container.go
|
||||
+++ b/components/engine/daemon/container.go
|
||||
@@ -421,20 +421,20 @@ func (daemon *Daemon) verifyContainerSettings(platform string, hostConfig *conta
|
||||
|
||||
// Validate the healthcheck params of Config
|
||||
if config.Healthcheck != nil {
|
||||
- if config.Healthcheck.Interval != 0 && config.Healthcheck.Interval < containertypes.MinimumDuration {
|
||||
- return nil, errors.Errorf("Interval in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
|
||||
+ if config.Healthcheck.Interval != 0 && config.Healthcheck.Interval < time.Second {
|
||||
+ return nil, errors.Errorf("Interval in Healthcheck cannot be less than one second")
|
||||
}
|
||||
|
||||
- if config.Healthcheck.Timeout != 0 && config.Healthcheck.Timeout < containertypes.MinimumDuration {
|
||||
- return nil, errors.Errorf("Timeout in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
|
||||
+ if config.Healthcheck.Timeout != 0 && config.Healthcheck.Timeout < time.Second {
|
||||
+ return nil, errors.Errorf("Timeout in Healthcheck cannot be less than one second")
|
||||
}
|
||||
|
||||
if config.Healthcheck.Retries < 0 {
|
||||
return nil, errors.Errorf("Retries in Healthcheck cannot be negative")
|
||||
}
|
||||
|
||||
- if config.Healthcheck.StartPeriod != 0 && config.Healthcheck.StartPeriod < containertypes.MinimumDuration {
|
||||
- return nil, errors.Errorf("StartPeriod in Healthcheck cannot be less than %s", containertypes.MinimumDuration)
|
||||
+ if config.Healthcheck.StartPeriod != 0 && config.Healthcheck.StartPeriod < time.Second {
|
||||
+ return nil, errors.Errorf("StartPeriod in Healthcheck cannot be less than one second")
|
||||
}
|
||||
}
|
||||
}
|
||||
diff --git a/components/engine/integration-cli/docker_api_create_test.go b/components/engine/integration-cli/docker_api_create_test.go
|
||||
index 8c7fff477e..1bbc7653b3 100644
|
||||
--- a/components/engine/integration-cli/docker_api_create_test.go
|
||||
+++ b/components/engine/integration-cli/docker_api_create_test.go
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
- "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/integration-cli/checker"
|
||||
"github.com/docker/docker/internal/test/request"
|
||||
@@ -35,7 +34,7 @@ func (s *DockerSuite) TestAPICreateWithInvalidHealthcheckParams(c *check.C) {
|
||||
buf, err := request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
- expected := fmt.Sprintf("Interval in Healthcheck cannot be less than %s", container.MinimumDuration)
|
||||
+ expected := fmt.Sprintf("Interval in Healthcheck cannot be less than one second")
|
||||
c.Assert(getErrorMessage(c, buf), checker.Contains, expected)
|
||||
|
||||
// test invalid Interval in Healthcheck: larger than 0s but less than 1ms
|
||||
@@ -82,7 +81,7 @@ func (s *DockerSuite) TestAPICreateWithInvalidHealthcheckParams(c *check.C) {
|
||||
buf, err = request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
- expected = fmt.Sprintf("Timeout in Healthcheck cannot be less than %s", container.MinimumDuration)
|
||||
+ expected = fmt.Sprintf("Timeout in Healthcheck cannot be less than one second")
|
||||
c.Assert(getErrorMessage(c, buf), checker.Contains, expected)
|
||||
|
||||
// test invalid Retries in Healthcheck: less than 0
|
||||
@@ -131,6 +130,6 @@ func (s *DockerSuite) TestAPICreateWithInvalidHealthcheckParams(c *check.C) {
|
||||
buf, err = request.ReadBody(body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
- expected = fmt.Sprintf("StartPeriod in Healthcheck cannot be less than %s", container.MinimumDuration)
|
||||
+ expected = fmt.Sprintf("StartPeriod in Healthcheck cannot be less than one second")
|
||||
c.Assert(getErrorMessage(c, buf), checker.Contains, expected)
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From 7f1228356891f66979c7f7e35957ab5392ea8758 Mon Sep 17 00:00:00 2001
|
||||
From: zhangsong34 <zhangsong34@huawei.com>
|
||||
Date: Fri, 1 Feb 2019 21:18:34 +0800
|
||||
Subject: [PATCH 095/111] docker: enable container health check after
|
||||
restart docker
|
||||
|
||||
reason:enable container health check after restart docker.
|
||||
|
||||
Change-Id: Ic877fdbea8de5b87d2a101c19dbb8a9e8e49c0bb
|
||||
Signed-off-by: zhangsong34 <zhangsong34@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon.go | 6 +++++-
|
||||
5 files changed, 11 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index b207709f7c..f5d22bb18b 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -379,6 +379,10 @@ func (daemon *Daemon) restore() error {
|
||||
if c.IsRunning() || c.IsPaused() {
|
||||
c.RestartManager().Cancel() // manually start containers because some need to wait for swarm networking
|
||||
|
||||
+ c.Lock()
|
||||
+ daemon.initHealthMonitor(c)
|
||||
+ c.Unlock()
|
||||
+
|
||||
if c.IsPaused() && alive {
|
||||
s, err := daemon.containerd.Status(context.Background(), c.ID)
|
||||
if err != nil {
|
||||
@@ -930,7 +934,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
|
||||
|
||||
for operatingSystem, gd := range d.graphDrivers {
|
||||
layerStores[operatingSystem], err = layer.NewStoreFromOptions(layer.StoreOptions{
|
||||
- Root: config.Root,
|
||||
+ Root: config.Root,
|
||||
MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
|
||||
GraphDriver: gd,
|
||||
GraphDriverOptions: config.GraphOptions,
|
||||
--
|
||||
2.17.1
|
||||
|
||||
52
patch/0096-pause-check-tasks-before-updateCgroups.patch
Normal file
52
patch/0096-pause-check-tasks-before-updateCgroups.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 086cf3ab125d1c423d07ef877846fd8c1e01f3ac Mon Sep 17 00:00:00 2001
|
||||
From: lujingxiao <lujingxiao@huawei.com>
|
||||
Date: Mon, 11 Feb 2019 18:44:50 +0800
|
||||
Subject: [PATCH 096/111] pause: check tasks before updateCgroups
|
||||
|
||||
reason: In the Pause of dockerd, it updateCgroups first, then
|
||||
check tasks file if any tasks in the cgroups. We should check the
|
||||
tasks file before updateCgroups
|
||||
|
||||
Change-Id: I7f30e314b3db9c50459d995bf071e01a47f359f0
|
||||
Signed-off-by: lujingxiao <lujingxiao@huawei.com>
|
||||
---
|
||||
components/engine/daemon/freezer/freezer.go | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/freezer/freezer.go b/components/engine/daemon/freezer/freezer.go
|
||||
index cd8b3513d7..a0ef299852 100644
|
||||
--- a/components/engine/daemon/freezer/freezer.go
|
||||
+++ b/components/engine/daemon/freezer/freezer.go
|
||||
@@ -122,10 +122,6 @@ func (f *freezer) Pause() error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
- if err := f.updateCgroup(string(configs.Frozen)); err != nil {
|
||||
- return err
|
||||
- }
|
||||
-
|
||||
tasks, err := readFile(f.path, "tasks")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to check container cgroup task status: %v", err)
|
||||
@@ -134,7 +130,8 @@ func (f *freezer) Pause() error {
|
||||
if strings.TrimSpace(tasks) == "" {
|
||||
return fmt.Errorf("error: no tasks running in freeze cgroup")
|
||||
}
|
||||
- return nil
|
||||
+
|
||||
+ return f.updateCgroup(string(configs.Frozen))
|
||||
}
|
||||
|
||||
// Resume will set the container to running state by writing freeze cgroup.
|
||||
@@ -186,7 +183,7 @@ func (f *freezer) updateCgroup(state string) error {
|
||||
}
|
||||
newState, err := readFile(f.path, "freezer.state")
|
||||
if err != nil {
|
||||
- return err
|
||||
+ return fmt.Errorf("read freezer.state failed after write: %v", err)
|
||||
}
|
||||
if strings.TrimSpace(newState) == state {
|
||||
return nil
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
From 8bd08475a06b5475fc88b207d578a006ad9a45cd Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 13 Feb 2019 00:31:32 +0800
|
||||
Subject: [PATCH 097/111] restart: fix --restart=unless-stopped not
|
||||
stop for docker stop
|
||||
|
||||
reason: testCE_secure_container_kata_FUN.054.sh
|
||||
|
||||
Change-Id: I536bb6cf1fe698da9fe330b110f122d4e8af17d6
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/monitor.go | 1 +
|
||||
components/engine/daemon/start.go | 4 +++-
|
||||
2 files changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/components/engine/daemon/monitor.go b/components/engine/daemon/monitor.go
|
||||
index 51159eb76d..7ae85f58a9 100644
|
||||
--- a/components/engine/daemon/monitor.go
|
||||
+++ b/components/engine/daemon/monitor.go
|
||||
@@ -106,6 +106,7 @@ func (daemon *Daemon) ProcessEvent(id string, e libcontainerd.EventType, ei libc
|
||||
if err != restartmanager.ErrRestartCanceled {
|
||||
logrus.Errorf("restartmanger wait error: %+v", err)
|
||||
}
|
||||
+ c.CheckpointTo(daemon.containersReplica)
|
||||
}
|
||||
}()
|
||||
}
|
||||
diff --git a/components/engine/daemon/start.go b/components/engine/daemon/start.go
|
||||
index 96ae45e11e..8ff636b5a5 100644
|
||||
--- a/components/engine/daemon/start.go
|
||||
+++ b/components/engine/daemon/start.go
|
||||
@@ -203,7 +203,9 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
|
||||
}
|
||||
|
||||
container.SetRunning(pid, true)
|
||||
- container.HasBeenManuallyStopped = false
|
||||
+ if resetRestartManager {
|
||||
+ container.HasBeenManuallyStopped = false
|
||||
+ }
|
||||
container.HasBeenStartedBefore = true
|
||||
daemon.setStateCounter(container)
|
||||
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
From b7d540ff87543e02f4d6271afe66edb7aa88477a Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Fri, 15 Feb 2019 15:26:01 +0800
|
||||
Subject: [PATCH 099/111] integration-cli: fix
|
||||
TestInspectAPIImageResponse
|
||||
|
||||
reason:For we tag busybox:glibc before, the tag number will change
|
||||
in this testcase. So we cancel the action of checking tag number.
|
||||
|
||||
Change-Id: Ib7bf6274d8ca05cc5cbbe3ddd341676b64bb809e
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/integration-cli/docker_api_inspect_test.go | 1 -
|
||||
5 files changed, 6 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/integration-cli/docker_api_inspect_test.go b/components/engine/integration-cli/docker_api_inspect_test.go
|
||||
index 68055b6c14..82d1b19606 100644
|
||||
--- a/components/engine/integration-cli/docker_api_inspect_test.go
|
||||
+++ b/components/engine/integration-cli/docker_api_inspect_test.go
|
||||
@@ -114,7 +114,6 @@ func (s *DockerSuite) TestInspectAPIImageResponse(c *check.C) {
|
||||
imageJSON, _, err := cli.ImageInspectWithRaw(context.Background(), "busybox")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
- c.Assert(imageJSON.RepoTags, checker.HasLen, 2)
|
||||
assert.Check(c, is.Contains(imageJSON.RepoTags, "busybox:latest"))
|
||||
assert.Check(c, is.Contains(imageJSON.RepoTags, "busybox:mytag"))
|
||||
}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
63
patch/0100-proquota-fix-quota-basesize.patch
Normal file
63
patch/0100-proquota-fix-quota-basesize.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From 582b84ebefcdd71b963dd431fcf9d1d5f9a20552 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Mon, 18 Feb 2019 21:23:17 +0800
|
||||
Subject: [PATCH 100/111] proquota: fix quota basesize
|
||||
|
||||
reason:fix quota basesize
|
||||
|
||||
Change-Id: I268c600b8c63965daf0086796c48ca4e85263e50
|
||||
Signed-off-by: zhangyu235 <zhangyu235@huawei.com>
|
||||
---
|
||||
components/engine/daemon/graphdriver/overlay2/overlay.go | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/graphdriver/overlay2/overlay.go b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
index 71474f8f36..1a3c9c9d67 100644
|
||||
--- a/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
+++ b/components/engine/daemon/graphdriver/overlay2/overlay.go
|
||||
@@ -89,6 +89,7 @@ const (
|
||||
type overlayOptions struct {
|
||||
overrideKernelCheck bool
|
||||
quota quota.Quota
|
||||
+ quotaBaseSize uint64
|
||||
}
|
||||
|
||||
// Driver contains information about the home directory and the list of active
|
||||
@@ -221,6 +222,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
|
||||
// Try to enable project quota support over xfs and extfs.
|
||||
if d.quotaCtl, err = quota.NewControl(home, backingFs); err == nil {
|
||||
projectQuotaSupported = true
|
||||
+ d.options.quotaBaseSize = opts.quotaBaseSize
|
||||
} else if opts.quota.Size > 0 {
|
||||
return nil, fmt.Errorf("Storage option overlay2.size not supported. Filesystem does not support Project Quota: %v", err)
|
||||
}
|
||||
@@ -280,7 +282,7 @@ func parseOptions(options []string) (*overlayOptions, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
- o.quota.Size = uint64(size)
|
||||
+ o.quotaBaseSize = uint64(size)
|
||||
default:
|
||||
return nil, fmt.Errorf("overlay2: unknown option %s", key)
|
||||
}
|
||||
@@ -422,14 +422,14 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
|
||||
}
|
||||
}()
|
||||
|
||||
- if (opts != nil && len(opts.StorageOpt) > 0) || d.options.quota.Size > 0 {
|
||||
+ if opts != nil && (len(opts.StorageOpt) > 0 || d.options.quotaBaseSize > 0) {
|
||||
driver := &Driver{}
|
||||
if err := d.parseStorageOpt(opts.StorageOpt, driver); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
- if driver.options.quota.Size == 0 && d.options.quota.Size > 0 {
|
||||
- driver.options.quota.Size = d.options.quota.Size
|
||||
+ if driver.options.quota.Size == 0 && d.options.quotaBaseSize > 0 {
|
||||
+ driver.options.quota.Size = d.options.quotaBaseSize
|
||||
}
|
||||
|
||||
if driver.options.quota.Size > 0 {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
From 4711c062b0fd8409eef7ed6ed0963b638765cc7f Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Mon, 18 Feb 2019 21:57:38 +0800
|
||||
Subject: [PATCH 101/111] daeamon: add judge for client in case of
|
||||
panic
|
||||
|
||||
reason:Add judge for client in monitorDaemon(), in case of
|
||||
null ptr error return cause panic.
|
||||
|
||||
Change-Id: Ia0dd64ba0341414d2dbe213a53daa94e2c5d1723
|
||||
---
|
||||
components/engine/libcontainerd/supervisor/remote_daemon.go | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/components/engine/libcontainerd/supervisor/remote_daemon.go b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
index 45cc3c3032..62ea58c8b4 100644
|
||||
--- a/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
+++ b/components/engine/libcontainerd/supervisor/remote_daemon.go
|
||||
@@ -318,8 +318,10 @@ func (r *remote) monitorDaemon(ctx context.Context) {
|
||||
r.killDaemon()
|
||||
}
|
||||
|
||||
- client.Close()
|
||||
- client = nil
|
||||
+ if client != nil {
|
||||
+ client.Close()
|
||||
+ client = nil
|
||||
+ }
|
||||
r.daemonPid = -1
|
||||
delay = nil
|
||||
transientFailureCount = 0
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 40c55ba190f46487686d6131b0005737d8bd06af Mon Sep 17 00:00:00 2001
|
||||
From: jiangpengfei9 <jiangpengfei9@huawei.com>
|
||||
Date: Fri, 15 Feb 2019 14:13:47 -0500
|
||||
Subject: [PATCH 102/111] docker-18.09: fix docker stop error if docker
|
||||
has been stopped
|
||||
|
||||
reason: If docker stop send SIGTERM signal to stop container failed, it will wait a short time
|
||||
and send SIGKILL signal to kill container, but if container has exit while docker stop send
|
||||
SIGKILL to container, which will cause an error which is "Container %s is not running".So if
|
||||
docker stop meet this problem, we just let it go and print the warning log.
|
||||
|
||||
Change-Id: Ia832aa93c3a94086849cda70110eb772ac3c0a52
|
||||
Signed-off-by: jiangpengfei9 <jiangpengfei9@huawei.com>
|
||||
---
|
||||
components/engine/daemon/kill.go | 6 ++++--
|
||||
components/engine/daemon/stop.go | 1 +
|
||||
6 files changed, 11 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/kill.go b/components/engine/daemon/kill.go
|
||||
index 5b2e497604..d185065b54 100644
|
||||
--- a/components/engine/daemon/kill.go
|
||||
+++ b/components/engine/daemon/kill.go
|
||||
@@ -72,7 +72,8 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
||||
}
|
||||
|
||||
if !container.Running {
|
||||
- return errNotRunning(container.ID)
|
||||
+ logrus.Warnf("killWithSignal skip send kill signal to container %s due to container has been stopped",container.ID)
|
||||
+ return nil
|
||||
}
|
||||
|
||||
var unpause bool
|
||||
@@ -127,7 +128,8 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
||||
// Kill forcefully terminates a container.
|
||||
func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
||||
if !container.IsRunning() {
|
||||
- return errNotRunning(container.ID)
|
||||
+ logrus.Warnf("Kill skip send kill signal to container %s due to container has been stopped",container.ID)
|
||||
+ return nil
|
||||
}
|
||||
|
||||
// 1. Send SIGKILL
|
||||
diff --git a/components/engine/daemon/stop.go b/components/engine/daemon/stop.go
|
||||
index c3ac09056a..3c4cd766c9 100644
|
||||
--- a/components/engine/daemon/stop.go
|
||||
+++ b/components/engine/daemon/stop.go
|
||||
@@ -45,6 +45,7 @@ func (daemon *Daemon) containerStop(container *containerpkg.Container, seconds i
|
||||
stopSignal := container.StopSignal()
|
||||
// 1. Send a stop signal
|
||||
if err := daemon.killPossiblyDeadProcess(container, stopSignal); err != nil {
|
||||
+ logrus.Infof("docker send %d signal to stop container get error: %v", stopSignal, err)
|
||||
// While normally we might "return err" here we're not going to
|
||||
// because if we can't stop the container by this point then
|
||||
// it's probably because it's already stopped. Meaning, between
|
||||
--
|
||||
2.17.1
|
||||
|
||||
62
patch/0103-docker-fix-parsing-name-with.patch
Normal file
62
patch/0103-docker-fix-parsing-name-with.patch
Normal file
@ -0,0 +1,62 @@
|
||||
From 405d10b7df5fa329a7070cb842a8d5e4e46861d6 Mon Sep 17 00:00:00 2001
|
||||
From: lixiang172 <lixiang172@huawei.com>
|
||||
Date: Mon, 18 Feb 2019 22:13:53 +0800
|
||||
Subject: [PATCH 103/111] docker: fix parsing name with /
|
||||
|
||||
reason: fix parsing name with /
|
||||
Do the error check when using --link option,
|
||||
if the alias name and container name is the same, return error
|
||||
|
||||
Change-Id: I64c39915d34d79ee8abbba2ebe0e66ad3ad08551
|
||||
Signed-off-by: yangshukui <yangshukui@huawei.com>
|
||||
Signed-off-by: lixiang172 <lixiang172@huawei.com>
|
||||
---
|
||||
components/engine/daemon/daemon.go | 13 +++++++++++++
|
||||
.../engine/integration-cli/docker_cli_links_test.go | 8 ++++++++
|
||||
2 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/components/engine/daemon/daemon.go b/components/engine/daemon/daemon.go
|
||||
index f5d22bb18b..e26494ed68 100644
|
||||
--- a/components/engine/daemon/daemon.go
|
||||
+++ b/components/engine/daemon/daemon.go
|
||||
@@ -657,8 +657,21 @@ func (daemon *Daemon) parents(c *container.Container) map[string]*container.Cont
|
||||
return daemon.linkIndex.parents(c)
|
||||
}
|
||||
|
||||
+func validateAlias(alias string, c *container.Container) error {
|
||||
+ if !validContainerNamePattern.MatchString(alias) {
|
||||
+ return fmt.Errorf("Invalid alias name (%s), only %s are allowed", alias, validContainerNameChars)
|
||||
+ }
|
||||
+ if alias == c.Config.Hostname {
|
||||
+ return fmt.Errorf("Invalid alias name (%s), alias is the same to current container's hostname", alias)
|
||||
+ }
|
||||
+ return nil
|
||||
+}
|
||||
+
|
||||
func (daemon *Daemon) registerLink(parent, child *container.Container, alias string) error {
|
||||
fullName := path.Join(parent.Name, alias)
|
||||
+ if err := validateAlias(alias, parent); err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
if err := daemon.containersReplica.ReserveName(fullName, child.ID); err != nil {
|
||||
if err == container.ErrNameReserved {
|
||||
logrus.Warnf("error registering link for %s, to %s, as alias %s, ignoring: %v", parent.ID, child.ID, alias, err)
|
||||
diff --git a/components/engine/integration-cli/docker_cli_links_test.go b/components/engine/integration-cli/docker_cli_links_test.go
|
||||
index 17b25d7994..9efa1cfbf6 100644
|
||||
--- a/components/engine/integration-cli/docker_cli_links_test.go
|
||||
+++ b/components/engine/integration-cli/docker_cli_links_test.go
|
||||
@@ -237,3 +237,11 @@ func (s *DockerSuite) TestLinksMultipleWithSameName(c *check.C) {
|
||||
dockerCmd(c, "run", "-d", "--name=upstream-b", "busybox", "top")
|
||||
dockerCmd(c, "run", "--link", "upstream-a:upstream", "--link", "upstream-b:upstream", "busybox", "sh", "-c", "ping -c 1 upstream")
|
||||
}
|
||||
+func (s *DockerSuite) TestLinksAliasCheck(c *check.C) {
|
||||
+ testRequires(c, DaemonIsLinux, NotUserNamespace)
|
||||
+ dockerCmd(c, "run", "-d", "--name=linkalias", "busybox", "top")
|
||||
+ out, _, _ := dockerCmdWithError("run", "-d", "--link=linkalias:hello/sep", "busybox", "top")
|
||||
+ c.Assert(out, checker.Contains, "Invalid alias name")
|
||||
+ out, _, _ = dockerCmdWithError("run", "-d", "--hostname=linkhostname", "--link=linkalias:linkhostname", "busybox", "top")
|
||||
+ c.Assert(out, checker.Contains, "alias is the same to current container's hostname")
|
||||
+}
|
||||
--
|
||||
2.17.1
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
From f983b1959dae1d5f0dcae1f7480db5ae69906f74 Mon Sep 17 00:00:00 2001
|
||||
From: zhangyu235 <zhangyu235@huawei.com>
|
||||
Date: Wed, 20 Feb 2019 11:45:45 +0800
|
||||
Subject: [PATCH 104/111] docker stats: increase the timeout of docker
|
||||
stats command
|
||||
|
||||
reason:Increase the timeout of docker stats command, in case of data lost.
|
||||
|
||||
Change-Id: Ib698f7cfdc06928838b343821a6bdca875327ff7
|
||||
---
|
||||
components/cli/cli/command/container/stats.go | 2 +-
|
||||
5 files changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/cli/cli/command/container/stats.go b/components/cli/cli/command/container/stats.go
|
||||
index 1f9e1b8556..8387fc988d 100644
|
||||
--- a/components/cli/cli/command/container/stats.go
|
||||
+++ b/components/cli/cli/command/container/stats.go
|
||||
@@ -172,7 +172,7 @@ func runStats(dockerCli command.Cli, opts *statsOptions) error {
|
||||
|
||||
// Do a quick pause to detect any error with the provided list of
|
||||
// container names.
|
||||
- time.Sleep(1500 * time.Millisecond)
|
||||
+ time.Sleep(2500 * time.Millisecond)
|
||||
var errs []string
|
||||
cStats.mu.Lock()
|
||||
for _, c := range cStats.cs {
|
||||
--
|
||||
2.17.1
|
||||
|
||||
55
patch/0105-pause-fix-pause-on-exited-container.patch
Normal file
55
patch/0105-pause-fix-pause-on-exited-container.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From f66b0742f72a0f15c6b805751c00af2c7b0f3193 Mon Sep 17 00:00:00 2001
|
||||
From: jingrui <jingrui@huawei.com>
|
||||
Date: Wed, 20 Feb 2019 23:42:00 +0800
|
||||
Subject: [PATCH 105/111] pause: fix pause on exited container
|
||||
|
||||
reason: fix pause on exited container
|
||||
|
||||
Change-Id: I109a88ab6832c3118f6be48f5924679549607740
|
||||
Signed-off-by: jingrui <jingrui@huawei.com>
|
||||
---
|
||||
components/engine/daemon/freezer/freezer.go | 21 ++++++++++++++++++-
|
||||
5 files changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/components/engine/daemon/freezer/freezer.go b/components/engine/daemon/freezer/freezer.go
|
||||
index a0ef299852..907c7aac2a 100644
|
||||
--- a/components/engine/daemon/freezer/freezer.go
|
||||
+++ b/components/engine/daemon/freezer/freezer.go
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
+ "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Freezer is the interface which could be used to pause/resume container,
|
||||
@@ -131,7 +132,25 @@ func (f *freezer) Pause() error {
|
||||
return fmt.Errorf("error: no tasks running in freeze cgroup")
|
||||
}
|
||||
|
||||
- return f.updateCgroup(string(configs.Frozen))
|
||||
+ err = f.updateCgroup(string(configs.Frozen))
|
||||
+ if err != nil {
|
||||
+ return err
|
||||
+ }
|
||||
+
|
||||
+ tasks, err = readFile(f.path, "tasks")
|
||||
+ if err != nil {
|
||||
+ err := f.updateCgroup(string(configs.Thawed))
|
||||
+ logrus.Warnf("revert pause due to no tasks file. revert-error=%v", err)
|
||||
+ return fmt.Errorf("failed to check container cgroup task status: %v", err)
|
||||
+ }
|
||||
+
|
||||
+ if strings.TrimSpace(tasks) == "" {
|
||||
+ err := f.updateCgroup(string(configs.Thawed))
|
||||
+ logrus.Warnf("revert pause due to no tasks. revert-error=%v", err)
|
||||
+ return fmt.Errorf("error: no tasks running in freeze cgroup")
|
||||
+ }
|
||||
+
|
||||
+ return nil
|
||||
}
|
||||
|
||||
// Resume will set the container to running state by writing freeze cgroup.
|
||||
--
|
||||
2.17.1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user