The LXC driver was deprecated in Docker 1.8.
Following the deprecation rules, we can remove a deprecated feature
after two major releases. LXC won't be supported anymore starting on Docker 1.10.
Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -72,16 +72,6 @@ RUN cd /usr/local/lvm2 \ |
| 72 | 72 |
&& make install_device-mapper |
| 73 | 73 |
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL |
| 74 | 74 |
|
| 75 |
-# Install lxc |
|
| 76 |
-ENV LXC_VERSION 1.1.2 |
|
| 77 |
-RUN mkdir -p /usr/src/lxc \ |
|
| 78 |
- && curl -sSL https://linuxcontainers.org/downloads/lxc/lxc-${LXC_VERSION}.tar.gz | tar -v -C /usr/src/lxc/ -xz --strip-components=1
|
|
| 79 |
-RUN cd /usr/src/lxc \ |
|
| 80 |
- && ./configure \ |
|
| 81 |
- && make \ |
|
| 82 |
- && make install \ |
|
| 83 |
- && ldconfig |
|
| 84 |
- |
|
| 85 | 75 |
# Install Go |
| 86 | 76 |
ENV GO_VERSION 1.5.1 |
| 87 | 77 |
RUN curl -sSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd64.tar.gz" | tar -v -C /usr/local -xz
|
| ... | ... |
@@ -39,16 +39,6 @@ RUN cd /usr/local/lvm2 \ |
| 39 | 39 |
&& make install_device-mapper |
| 40 | 40 |
# see https://git.fedorahosted.org/cgit/lvm2.git/tree/INSTALL |
| 41 | 41 |
|
| 42 |
-# Install lxc |
|
| 43 |
-ENV LXC_VERSION 1.1.2 |
|
| 44 |
-RUN mkdir -p /usr/src/lxc \ |
|
| 45 |
- && curl -sSL https://linuxcontainers.org/downloads/lxc/lxc-${LXC_VERSION}.tar.gz | tar -v -C /usr/src/lxc/ -xz --strip-components=1
|
|
| 46 |
-RUN cd /usr/src/lxc \ |
|
| 47 |
- && ./configure \ |
|
| 48 |
- && make \ |
|
| 49 |
- && make install \ |
|
| 50 |
- && ldconfig |
|
| 51 |
- |
|
| 52 | 42 |
ENV GOPATH /go:/go/src/github.com/docker/docker/vendor |
| 53 | 43 |
|
| 54 | 44 |
# Get the "docker-py" source so we can run their integration tests |
| ... | ... |
@@ -1,6 +1,6 @@ |
| 1 | 1 |
(from "ubuntu:14.04") |
| 2 | 2 |
(maintainer "Tianon Gravi <admwiggin@gmail.com> (@tianon)") |
| 3 |
-(run "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq \tapt-utils \taufs-tools \tautomake \tbtrfs-tools \tbuild-essential \tcurl \tdpkg-sig \tgit \tiptables \tlibapparmor-dev \tlibcap-dev \tlibsqlite3-dev \tlxc=1.0* \tmercurial \tpandoc \tparallel \treprepro \truby1.9.1 \truby1.9.1-dev \ts3cmd=1.1.0* \t--no-install-recommends") |
|
| 3 |
+(run "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -yq \tapt-utils \taufs-tools \tautomake \tbtrfs-tools \tbuild-essential \tcurl \tdpkg-sig \tgit \tiptables \tlibapparmor-dev \tlibcap-dev \tlibsqlite3-dev \tmercurial \tpandoc \tparallel \treprepro \truby1.9.1 \truby1.9.1-dev \ts3cmd=1.1.0* \t--no-install-recommends") |
|
| 4 | 4 |
(run "git clone --no-checkout https://git.fedorahosted.org/git/lvm2.git /usr/local/lvm2 && cd /usr/local/lvm2 && git checkout -q v2_02_103") |
| 5 | 5 |
(run "cd /usr/local/lvm2 && ./configure --enable-static_link && make device-mapper && make install_device-mapper") |
| 6 | 6 |
(run "curl -sSL https://golang.org/dl/go1.3.src.tar.gz | tar -v -C /usr/local -xz") |
| ... | ... |
@@ -135,7 +135,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l help -d 'Pri |
| 135 | 135 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s i -l interactive -d 'Keep STDIN open even if not attached' |
| 136 | 136 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container' |
| 137 | 137 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l link -d 'Add link to another container in the form of <name|id>:alias' |
| 138 |
-complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"' |
|
| 139 | 138 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -s m -l memory -d 'Memory limit (format: <number>[<unit>], where unit = b, k, m or g)' |
| 140 | 139 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' |
| 141 | 140 |
complete -c docker -A -f -n '__fish_seen_subcommand_from create' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number>[<unit>], where unit = b, k, m or g)" |
| ... | ... |
@@ -324,7 +323,6 @@ complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l help -d 'Print |
| 324 | 324 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s i -l interactive -d 'Keep STDIN open even if not attached' |
| 325 | 325 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l ipc -d 'Default is to create a private IPC namespace (POSIX SysV IPC) for the container' |
| 326 | 326 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l link -d 'Add link to another container in the form of <name|id>:alias' |
| 327 |
-complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l lxc-conf -d '(lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1"' |
|
| 328 | 327 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -s m -l memory -d 'Memory limit (format: <number>[<unit>], where unit = b, k, m or g)' |
| 329 | 328 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l mac-address -d 'Container MAC address (e.g. 92:d0:c6:0a:29:33)' |
| 330 | 329 |
complete -c docker -A -f -n '__fish_seen_subcommand_from run' -l memory-swap -d "Total memory usage (memory + swap), set '-1' to disable swap (format: <number>[<unit>], where unit = b, k, m or g)" |
| ... | ... |
@@ -438,7 +438,6 @@ __docker_subcommand() {
|
| 438 | 438 |
"($help)*"{-l=,--label=}"[Set meta data on a container]:label: "
|
| 439 | 439 |
"($help)--log-driver=[Default driver for container logs]:Logging driver:(json-file syslog journald gelf fluentd awslogs splunk none)" |
| 440 | 440 |
"($help)*--log-opt=[Log driver specific options]:log driver options: " |
| 441 |
- "($help)*--lxc-conf=[Add custom lxc options]:lxc options: " |
|
| 442 | 441 |
"($help)--mac-address=[Container MAC address]:MAC address: " |
| 443 | 442 |
"($help)--name=[Container name]:name: " |
| 444 | 443 |
"($help)--net=[Connect a container to a network]:network mode:(bridge none container host)" |
| ... | ... |
@@ -541,7 +540,7 @@ __docker_subcommand() {
|
| 541 | 541 |
"($help)*--dns-opt=[DNS options to use]:DNS option: " \ |
| 542 | 542 |
"($help)*--default-ulimit=[Set default ulimit settings for containers]:ulimit: " \ |
| 543 | 543 |
"($help)--disable-legacy-registry[Do not contact legacy registries]" \ |
| 544 |
- "($help -e --exec-driver)"{-e=,--exec-driver=}"[Exec driver to use]:driver:(native lxc windows)" \
|
|
| 544 |
+ "($help -e --exec-driver)"{-e=,--exec-driver=}"[Exec driver to use]:driver:(native windows)" \
|
|
| 545 | 545 |
"($help)*--exec-opt=[Set exec driver options]:exec driver options: " \ |
| 546 | 546 |
"($help)--exec-root=[Root of the Docker execdriver]:path:_directories" \ |
| 547 | 547 |
"($help)--fixed-cidr=[IPv4 subnet for fixed IPs]:IPv4 subnet: " \ |
| ... | ... |
@@ -14,10 +14,6 @@ |
| 14 | 14 |
/var/run/docker\.sock -s gen_context(system_u:object_r:docker_var_run_t,s0) |
| 15 | 15 |
/var/run/docker-client(/.*)? gen_context(system_u:object_r:docker_var_run_t,s0) |
| 16 | 16 |
|
| 17 |
-/var/lock/lxc(/.*)? gen_context(system_u:object_r:docker_lock_t,s0) |
|
| 18 |
- |
|
| 19 |
-/var/log/lxc(/.*)? gen_context(system_u:object_r:docker_log_t,s0) |
|
| 20 |
- |
|
| 21 | 17 |
/var/lib/docker/init(/.*)? gen_context(system_u:object_r:docker_share_t,s0) |
| 22 | 18 |
/var/lib/docker/containers/.*/hosts gen_context(system_u:object_r:docker_share_t,s0) |
| 23 | 19 |
/var/lib/docker/containers/.*/hostname gen_context(system_u:object_r:docker_share_t,s0) |
| ... | ... |
@@ -292,7 +292,6 @@ interface(`docker_filetrans_named_content',` |
| 292 | 292 |
files_pid_filetrans($1, docker_var_run_t, file, "docker.pid") |
| 293 | 293 |
files_pid_filetrans($1, docker_var_run_t, sock_file, "docker.sock") |
| 294 | 294 |
files_pid_filetrans($1, docker_var_run_t, dir, "docker-client") |
| 295 |
- logging_log_filetrans($1, docker_log_t, dir, "lxc") |
|
| 296 | 295 |
files_var_lib_filetrans($1, docker_var_lib_t, dir, "docker") |
| 297 | 296 |
filetrans_pattern($1, docker_var_lib_t, docker_share_t, file, "config.env") |
| 298 | 297 |
filetrans_pattern($1, docker_var_lib_t, docker_share_t, file, "hosts") |
| ... | ... |
@@ -406,11 +405,6 @@ interface(`staff_stub',` |
| 406 | 406 |
type staff_t; |
| 407 | 407 |
') |
| 408 | 408 |
') |
| 409 |
-interface(`virt_stub_lxc',` |
|
| 410 |
- gen_require(` |
|
| 411 |
- type virtd_lxc_t; |
|
| 412 |
- ') |
|
| 413 |
-') |
|
| 414 | 409 |
interface(`virt_stub_svirt_sandbox_domain',` |
| 415 | 410 |
gen_require(` |
| 416 | 411 |
attribute svirt_sandbox_domain; |
| ... | ... |
@@ -90,7 +90,6 @@ files_etc_filetrans(docker_t, docker_config_t, dir, "docker") |
| 90 | 90 |
|
| 91 | 91 |
manage_dirs_pattern(docker_t, docker_lock_t, docker_lock_t) |
| 92 | 92 |
manage_files_pattern(docker_t, docker_lock_t, docker_lock_t) |
| 93 |
-files_lock_filetrans(docker_t, docker_lock_t, { dir file }, "lxc")
|
|
| 94 | 93 |
|
| 95 | 94 |
manage_dirs_pattern(docker_t, docker_log_t, docker_log_t) |
| 96 | 95 |
manage_files_pattern(docker_t, docker_log_t, docker_log_t) |
| ... | ... |
@@ -213,10 +212,6 @@ optional_policy(` |
| 213 | 213 |
openvswitch_stream_connect(docker_t) |
| 214 | 214 |
') |
| 215 | 215 |
|
| 216 |
-# |
|
| 217 |
-# lxc rules |
|
| 218 |
-# |
|
| 219 |
- |
|
| 220 | 216 |
allow docker_t self:capability { dac_override setgid setpcap setuid sys_admin sys_boot sys_chroot sys_ptrace };
|
| 221 | 217 |
|
| 222 | 218 |
allow docker_t self:process { getcap setcap setexec setpgid setsched signal_perms };
|
| ... | ... |
@@ -317,7 +312,6 @@ optional_policy(` |
| 317 | 317 |
virt_exec_sandbox_files(docker_t) |
| 318 | 318 |
virt_manage_sandbox_files(docker_t) |
| 319 | 319 |
virt_relabel_sandbox_filesystem(docker_t) |
| 320 |
- # for lxc |
|
| 321 | 320 |
virt_transition_svirt_sandbox(docker_t, system_r) |
| 322 | 321 |
virt_mounton_sandbox_file(docker_t) |
| 323 | 322 |
# virt_attach_sandbox_tun_iface(docker_t) |
| ... | ... |
@@ -388,11 +382,6 @@ optional_policy(` |
| 388 | 388 |
') |
| 389 | 389 |
|
| 390 | 390 |
optional_policy(` |
| 391 |
- virt_stub_lxc() |
|
| 392 |
- docker_exec_lib(virtd_lxc_t) |
|
| 393 |
-') |
|
| 394 |
- |
|
| 395 |
-optional_policy(` |
|
| 396 | 391 |
virt_stub_svirt_sandbox_domain() |
| 397 | 392 |
virt_stub_svirt_sandbox_file() |
| 398 | 393 |
allow svirt_sandbox_domain self:netlink_kobject_uevent_socket create_socket_perms; |
| 399 | 394 |
deleted file mode 100755 |
| ... | ... |
@@ -1,77 +0,0 @@ |
| 1 |
-#!/usr/bin/perl |
|
| 2 |
-# |
|
| 3 |
-# A simple helper script to help people build seccomp profiles for |
|
| 4 |
-# Docker/LXC. The goal is mostly to reduce the attack surface to the |
|
| 5 |
-# kernel, by restricting access to rarely used, recently added or not used |
|
| 6 |
-# syscalls. |
|
| 7 |
-# |
|
| 8 |
-# This script processes one or more files which contain the list of system |
|
| 9 |
-# calls to be allowed. See mkseccomp.sample for more information how you |
|
| 10 |
-# can configure the list of syscalls. When run, this script produces output |
|
| 11 |
-# which, when stored in a file, can be passed to docker as follows: |
|
| 12 |
-# |
|
| 13 |
-# docker run --lxc-conf="lxc.seccomp=$file" <rest of arguments> |
|
| 14 |
-# |
|
| 15 |
-# The included sample file shows how to cut about a quarter of all syscalls, |
|
| 16 |
-# which affecting most applications. |
|
| 17 |
-# |
|
| 18 |
-# For specific situations it is possible to reduce the list further. By |
|
| 19 |
-# reducing the list to just those syscalls required by a certain application |
|
| 20 |
-# you can make it difficult for unknown/unexpected code to run. |
|
| 21 |
-# |
|
| 22 |
-# Run this script as follows: |
|
| 23 |
-# |
|
| 24 |
-# ./mkseccomp.pl < mkseccomp.sample >syscalls.list |
|
| 25 |
-# or |
|
| 26 |
-# ./mkseccomp.pl mkseccomp.sample >syscalls.list |
|
| 27 |
-# |
|
| 28 |
-# Multiple files can be specified, in which case the lists of syscalls are |
|
| 29 |
-# combined. |
|
| 30 |
-# |
|
| 31 |
-# By Martijn van Oosterhout <kleptog@svana.org> Nov 2013 |
|
| 32 |
- |
|
| 33 |
-# How it works: |
|
| 34 |
-# |
|
| 35 |
-# This program basically spawns two processes to form a chain like: |
|
| 36 |
-# |
|
| 37 |
-# <process data section to prefix __NR_> | cpp | <add header and filter unknown syscalls> |
|
| 38 |
- |
|
| 39 |
-use strict; |
|
| 40 |
-use warnings; |
|
| 41 |
- |
|
| 42 |
-if( -t ) {
|
|
| 43 |
- print STDERR "Helper script to make seccomp filters for Docker/LXC.\n"; |
|
| 44 |
- print STDERR "Usage: mkseccomp.pl < [files...]\n"; |
|
| 45 |
- exit 1; |
|
| 46 |
-} |
|
| 47 |
- |
|
| 48 |
-my $pid = open(my $in, "-|") // die "Couldn't fork1 ($!)\n"; |
|
| 49 |
- |
|
| 50 |
-if($pid == 0) { # Child
|
|
| 51 |
- $pid = open(my $out, "|-") // die "Couldn't fork2 ($!)\n"; |
|
| 52 |
- |
|
| 53 |
- if($pid == 0) { # Child, which execs cpp
|
|
| 54 |
- exec "cpp" or die "Couldn't exec cpp ($!)\n"; |
|
| 55 |
- exit 1; |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- # Process the DATA section and output to cpp |
|
| 59 |
- print $out "#include <sys/syscall.h>\n"; |
|
| 60 |
- while(<>) {
|
|
| 61 |
- if(/^\w/) {
|
|
| 62 |
- print $out "__NR_$_"; |
|
| 63 |
- } |
|
| 64 |
- } |
|
| 65 |
- close $out; |
|
| 66 |
- exit 0; |
|
| 67 |
- |
|
| 68 |
-} |
|
| 69 |
- |
|
| 70 |
-# Print header and then process output from cpp. |
|
| 71 |
-print "1\n"; |
|
| 72 |
-print "whitelist\n"; |
|
| 73 |
- |
|
| 74 |
-while(<$in>) {
|
|
| 75 |
- print if( /^[0-9]/ ); |
|
| 76 |
-} |
|
| 77 |
- |
| 78 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,444 +0,0 @@ |
| 1 |
-/* This sample file is an example for mkseccomp.pl to produce a seccomp file |
|
| 2 |
- * which restricts syscalls that are only useful for an admin but allows the |
|
| 3 |
- * vast majority of normal userspace programs to run normally. |
|
| 4 |
- * |
|
| 5 |
- * The format of this file is one line per syscall. This is then processed |
|
| 6 |
- * and passed to 'cpp' to convert the names to numbers using whatever is |
|
| 7 |
- * correct for your platform. As such C-style comments are permitted. Note |
|
| 8 |
- * this also means that C preprocessor macros are also allowed. So it is |
|
| 9 |
- * possible to create groups surrounded by #ifdef/#endif and control their |
|
| 10 |
- * inclusion via #define (not #include). |
|
| 11 |
- * |
|
| 12 |
- * Syscalls that don't exist on your architecture are silently filtered out. |
|
| 13 |
- * Syscalls marked with (*) are required for a container to spawn a bash |
|
| 14 |
- * shell successfully (not necessarily full featured). Listing the same |
|
| 15 |
- * syscall multiple times is no problem. |
|
| 16 |
- * |
|
| 17 |
- * If you want to make a list specifically for one application the easiest |
|
| 18 |
- * way is to run the application under strace, like so: |
|
| 19 |
- * |
|
| 20 |
- * $ strace -f -q -c -o strace.out application args... |
|
| 21 |
- * |
|
| 22 |
- * Once you have a reasonable sample of the execution of the program, exit |
|
| 23 |
- * it. The file strace.out will have a summary of the syscalls used. Copy |
|
| 24 |
- * that list into this file, comment out everything else except the starred |
|
| 25 |
- * syscalls (which you need for the container to start) and you're done. |
|
| 26 |
- * |
|
| 27 |
- * To get the list of syscalls from the strace output this works well for |
|
| 28 |
- * me |
|
| 29 |
- * |
|
| 30 |
- * $ cut -c52 < strace.out |
|
| 31 |
- * |
|
| 32 |
- * This sample list was compiled as a combination of all the syscalls |
|
| 33 |
- * available on i386 and amd64 on Ubuntu Precise, as such it may not contain |
|
| 34 |
- * everything and not everything may be relevant for your system. This |
|
| 35 |
- * shouldn't be a problem. |
|
| 36 |
- */ |
|
| 37 |
- |
|
| 38 |
-// Filesystem/File descriptor related |
|
| 39 |
-access // (*) |
|
| 40 |
-chdir // (*) |
|
| 41 |
-chmod |
|
| 42 |
-chown |
|
| 43 |
-chown32 |
|
| 44 |
-close // (*) |
|
| 45 |
-creat |
|
| 46 |
-dup // (*) |
|
| 47 |
-dup2 // (*) |
|
| 48 |
-dup3 |
|
| 49 |
-epoll_create |
|
| 50 |
-epoll_create1 |
|
| 51 |
-epoll_ctl |
|
| 52 |
-epoll_ctl_old |
|
| 53 |
-epoll_pwait |
|
| 54 |
-epoll_wait |
|
| 55 |
-epoll_wait_old |
|
| 56 |
-eventfd |
|
| 57 |
-eventfd2 |
|
| 58 |
-faccessat // (*) |
|
| 59 |
-fadvise64 |
|
| 60 |
-fadvise64_64 |
|
| 61 |
-fallocate |
|
| 62 |
-fanotify_init |
|
| 63 |
-fanotify_mark |
|
| 64 |
-ioctl // (*) |
|
| 65 |
-fchdir |
|
| 66 |
-fchmod |
|
| 67 |
-fchmodat |
|
| 68 |
-fchown |
|
| 69 |
-fchown32 |
|
| 70 |
-fchownat |
|
| 71 |
-fcntl // (*) |
|
| 72 |
-fcntl64 |
|
| 73 |
-fdatasync |
|
| 74 |
-fgetxattr |
|
| 75 |
-flistxattr |
|
| 76 |
-flock |
|
| 77 |
-fremovexattr |
|
| 78 |
-fsetxattr |
|
| 79 |
-fstat // (*) |
|
| 80 |
-fstat64 |
|
| 81 |
-fstatat64 |
|
| 82 |
-fstatfs |
|
| 83 |
-fstatfs64 |
|
| 84 |
-fsync |
|
| 85 |
-ftruncate |
|
| 86 |
-ftruncate64 |
|
| 87 |
-getcwd // (*) |
|
| 88 |
-getdents // (*) |
|
| 89 |
-getdents64 |
|
| 90 |
-getxattr |
|
| 91 |
-inotify_add_watch |
|
| 92 |
-inotify_init |
|
| 93 |
-inotify_init1 |
|
| 94 |
-inotify_rm_watch |
|
| 95 |
-io_cancel |
|
| 96 |
-io_destroy |
|
| 97 |
-io_getevents |
|
| 98 |
-io_setup |
|
| 99 |
-io_submit |
|
| 100 |
-lchown |
|
| 101 |
-lchown32 |
|
| 102 |
-lgetxattr |
|
| 103 |
-link |
|
| 104 |
-linkat |
|
| 105 |
-listxattr |
|
| 106 |
-llistxattr |
|
| 107 |
-llseek |
|
| 108 |
-_llseek |
|
| 109 |
-lremovexattr |
|
| 110 |
-lseek // (*) |
|
| 111 |
-lsetxattr |
|
| 112 |
-lstat |
|
| 113 |
-lstat64 |
|
| 114 |
-mkdir |
|
| 115 |
-mkdirat |
|
| 116 |
-mknod |
|
| 117 |
-mknodat |
|
| 118 |
-newfstatat |
|
| 119 |
-_newselect |
|
| 120 |
-oldfstat |
|
| 121 |
-oldlstat |
|
| 122 |
-oldolduname |
|
| 123 |
-oldstat |
|
| 124 |
-olduname |
|
| 125 |
-oldwait4 |
|
| 126 |
-open // (*) |
|
| 127 |
-openat // (*) |
|
| 128 |
-pipe // (*) |
|
| 129 |
-pipe2 |
|
| 130 |
-poll |
|
| 131 |
-ppoll |
|
| 132 |
-pread64 |
|
| 133 |
-preadv |
|
| 134 |
-futimesat |
|
| 135 |
-pselect6 |
|
| 136 |
-pwrite64 |
|
| 137 |
-pwritev |
|
| 138 |
-read // (*) |
|
| 139 |
-readahead |
|
| 140 |
-readdir |
|
| 141 |
-readlink |
|
| 142 |
-readlinkat |
|
| 143 |
-readv |
|
| 144 |
-removexattr |
|
| 145 |
-rename |
|
| 146 |
-renameat |
|
| 147 |
-rmdir |
|
| 148 |
-select |
|
| 149 |
-sendfile |
|
| 150 |
-sendfile64 |
|
| 151 |
-setxattr |
|
| 152 |
-splice |
|
| 153 |
-stat // (*) |
|
| 154 |
-stat64 |
|
| 155 |
-statfs // (*) |
|
| 156 |
-statfs64 |
|
| 157 |
-symlink |
|
| 158 |
-symlinkat |
|
| 159 |
-sync |
|
| 160 |
-sync_file_range |
|
| 161 |
-sync_file_range2 |
|
| 162 |
-syncfs |
|
| 163 |
-tee |
|
| 164 |
-truncate |
|
| 165 |
-truncate64 |
|
| 166 |
-umask |
|
| 167 |
-unlink |
|
| 168 |
-unlinkat |
|
| 169 |
-ustat |
|
| 170 |
-utime |
|
| 171 |
-utimensat |
|
| 172 |
-utimes |
|
| 173 |
-write // (*) |
|
| 174 |
-writev |
|
| 175 |
- |
|
| 176 |
-// Network related |
|
| 177 |
-accept |
|
| 178 |
-accept4 |
|
| 179 |
-bind // (*) |
|
| 180 |
-connect // (*) |
|
| 181 |
-getpeername |
|
| 182 |
-getsockname // (*) |
|
| 183 |
-getsockopt |
|
| 184 |
-listen |
|
| 185 |
-recv |
|
| 186 |
-recvfrom // (*) |
|
| 187 |
-recvmmsg |
|
| 188 |
-recvmsg |
|
| 189 |
-send |
|
| 190 |
-sendmmsg |
|
| 191 |
-sendmsg |
|
| 192 |
-sendto // (*) |
|
| 193 |
-setsockopt |
|
| 194 |
-shutdown |
|
| 195 |
-socket // (*) |
|
| 196 |
-socketcall |
|
| 197 |
-socketpair |
|
| 198 |
-sethostname // (*) |
|
| 199 |
- |
|
| 200 |
-// Signal related |
|
| 201 |
-pause |
|
| 202 |
-rt_sigaction // (*) |
|
| 203 |
-rt_sigpending |
|
| 204 |
-rt_sigprocmask // (*) |
|
| 205 |
-rt_sigqueueinfo |
|
| 206 |
-rt_sigreturn // (*) |
|
| 207 |
-rt_sigsuspend |
|
| 208 |
-rt_sigtimedwait |
|
| 209 |
-rt_tgsigqueueinfo |
|
| 210 |
-sigaction |
|
| 211 |
-sigaltstack // (*) |
|
| 212 |
-signal |
|
| 213 |
-signalfd |
|
| 214 |
-signalfd4 |
|
| 215 |
-sigpending |
|
| 216 |
-sigprocmask |
|
| 217 |
-sigreturn |
|
| 218 |
-sigsuspend |
|
| 219 |
- |
|
| 220 |
-// Other needed POSIX |
|
| 221 |
-alarm |
|
| 222 |
-brk // (*) |
|
| 223 |
-clock_adjtime |
|
| 224 |
-clock_getres |
|
| 225 |
-clock_gettime |
|
| 226 |
-clock_nanosleep |
|
| 227 |
-//clock_settime |
|
| 228 |
-gettimeofday |
|
| 229 |
-nanosleep |
|
| 230 |
-nice |
|
| 231 |
-sysinfo |
|
| 232 |
-syslog |
|
| 233 |
-time |
|
| 234 |
-timer_create |
|
| 235 |
-timer_delete |
|
| 236 |
-timerfd_create |
|
| 237 |
-timerfd_gettime |
|
| 238 |
-timerfd_settime |
|
| 239 |
-timer_getoverrun |
|
| 240 |
-timer_gettime |
|
| 241 |
-timer_settime |
|
| 242 |
-times |
|
| 243 |
-uname // (*) |
|
| 244 |
- |
|
| 245 |
-// Memory control |
|
| 246 |
-madvise |
|
| 247 |
-mbind |
|
| 248 |
-mincore |
|
| 249 |
-mlock |
|
| 250 |
-mlockall |
|
| 251 |
-mmap // (*) |
|
| 252 |
-mmap2 |
|
| 253 |
-mprotect // (*) |
|
| 254 |
-mremap |
|
| 255 |
-msync |
|
| 256 |
-munlock |
|
| 257 |
-munlockall |
|
| 258 |
-munmap // (*) |
|
| 259 |
-remap_file_pages |
|
| 260 |
-set_mempolicy |
|
| 261 |
-vmsplice |
|
| 262 |
- |
|
| 263 |
-// Process control |
|
| 264 |
-capget |
|
| 265 |
-capset // (*) |
|
| 266 |
-clone // (*) |
|
| 267 |
-execve // (*) |
|
| 268 |
-exit // (*) |
|
| 269 |
-exit_group // (*) |
|
| 270 |
-fork |
|
| 271 |
-getcpu |
|
| 272 |
-getpgid |
|
| 273 |
-getpgrp // (*) |
|
| 274 |
-getpid // (*) |
|
| 275 |
-getppid // (*) |
|
| 276 |
-getpriority |
|
| 277 |
-getresgid |
|
| 278 |
-getresgid32 |
|
| 279 |
-getresuid |
|
| 280 |
-getresuid32 |
|
| 281 |
-getrlimit // (*) |
|
| 282 |
-getrusage |
|
| 283 |
-getsid |
|
| 284 |
-getuid // (*) |
|
| 285 |
-getuid32 |
|
| 286 |
-getegid // (*) |
|
| 287 |
-getegid32 |
|
| 288 |
-geteuid // (*) |
|
| 289 |
-geteuid32 |
|
| 290 |
-getgid // (*) |
|
| 291 |
-getgid32 |
|
| 292 |
-getgroups |
|
| 293 |
-getgroups32 |
|
| 294 |
-getitimer |
|
| 295 |
-get_mempolicy |
|
| 296 |
-kill |
|
| 297 |
-//personality |
|
| 298 |
-prctl |
|
| 299 |
-prlimit64 |
|
| 300 |
-sched_getaffinity |
|
| 301 |
-sched_getparam |
|
| 302 |
-sched_get_priority_max |
|
| 303 |
-sched_get_priority_min |
|
| 304 |
-sched_getscheduler |
|
| 305 |
-sched_rr_get_interval |
|
| 306 |
-//sched_setaffinity |
|
| 307 |
-//sched_setparam |
|
| 308 |
-//sched_setscheduler |
|
| 309 |
-sched_yield |
|
| 310 |
-setfsgid |
|
| 311 |
-setfsgid32 |
|
| 312 |
-setfsuid |
|
| 313 |
-setfsuid32 |
|
| 314 |
-setgid |
|
| 315 |
-setgid32 |
|
| 316 |
-setgroups |
|
| 317 |
-setgroups32 |
|
| 318 |
-setitimer |
|
| 319 |
-setpgid // (*) |
|
| 320 |
-setpriority |
|
| 321 |
-setregid |
|
| 322 |
-setregid32 |
|
| 323 |
-setresgid |
|
| 324 |
-setresgid32 |
|
| 325 |
-setresuid |
|
| 326 |
-setresuid32 |
|
| 327 |
-setreuid |
|
| 328 |
-setreuid32 |
|
| 329 |
-setrlimit |
|
| 330 |
-setsid |
|
| 331 |
-setuid |
|
| 332 |
-setuid32 |
|
| 333 |
-ugetrlimit |
|
| 334 |
-vfork |
|
| 335 |
-wait4 // (*) |
|
| 336 |
-waitid |
|
| 337 |
-waitpid |
|
| 338 |
- |
|
| 339 |
-// IPC |
|
| 340 |
-ipc |
|
| 341 |
-mq_getsetattr |
|
| 342 |
-mq_notify |
|
| 343 |
-mq_open |
|
| 344 |
-mq_timedreceive |
|
| 345 |
-mq_timedsend |
|
| 346 |
-mq_unlink |
|
| 347 |
-msgctl |
|
| 348 |
-msgget |
|
| 349 |
-msgrcv |
|
| 350 |
-msgsnd |
|
| 351 |
-semctl |
|
| 352 |
-semget |
|
| 353 |
-semop |
|
| 354 |
-semtimedop |
|
| 355 |
-shmat |
|
| 356 |
-shmctl |
|
| 357 |
-shmdt |
|
| 358 |
-shmget |
|
| 359 |
- |
|
| 360 |
-// Linux specific, mostly needed for thread-related stuff |
|
| 361 |
-arch_prctl // (*) |
|
| 362 |
-get_robust_list |
|
| 363 |
-get_thread_area |
|
| 364 |
-gettid |
|
| 365 |
-futex // (*) |
|
| 366 |
-restart_syscall // (*) |
|
| 367 |
-set_robust_list // (*) |
|
| 368 |
-set_thread_area |
|
| 369 |
-set_tid_address // (*) |
|
| 370 |
-tgkill |
|
| 371 |
-tkill |
|
| 372 |
- |
|
| 373 |
-// Admin syscalls, these are blocked |
|
| 374 |
-//acct |
|
| 375 |
-//adjtimex |
|
| 376 |
-//bdflush |
|
| 377 |
-//chroot |
|
| 378 |
-//create_module |
|
| 379 |
-//delete_module |
|
| 380 |
-//get_kernel_syms // Obsolete |
|
| 381 |
-//idle // Obsolete |
|
| 382 |
-//init_module |
|
| 383 |
-//ioperm |
|
| 384 |
-//iopl |
|
| 385 |
-//ioprio_get |
|
| 386 |
-//ioprio_set |
|
| 387 |
-//kexec_load |
|
| 388 |
-//lookup_dcookie // oprofile only? |
|
| 389 |
-//migrate_pages // NUMA |
|
| 390 |
-//modify_ldt |
|
| 391 |
-//mount |
|
| 392 |
-//move_pages // NUMA |
|
| 393 |
-//name_to_handle_at // NFS server |
|
| 394 |
-//nfsservctl // NFS server |
|
| 395 |
-//open_by_handle_at // NFS server |
|
| 396 |
-//perf_event_open |
|
| 397 |
-//pivot_root |
|
| 398 |
-//process_vm_readv // For debugger |
|
| 399 |
-//process_vm_writev // For debugger |
|
| 400 |
-//ptrace // For debugger |
|
| 401 |
-//query_module |
|
| 402 |
-//quotactl |
|
| 403 |
-//reboot |
|
| 404 |
-//setdomainname |
|
| 405 |
-//setns |
|
| 406 |
-//settimeofday |
|
| 407 |
-//sgetmask // Obsolete |
|
| 408 |
-//ssetmask // Obsolete |
|
| 409 |
-//stime |
|
| 410 |
-//swapoff |
|
| 411 |
-//swapon |
|
| 412 |
-//_sysctl |
|
| 413 |
-//sysfs |
|
| 414 |
-//sys_setaltroot |
|
| 415 |
-//umount |
|
| 416 |
-//umount2 |
|
| 417 |
-//unshare |
|
| 418 |
-//uselib |
|
| 419 |
-//vhangup |
|
| 420 |
-//vm86 |
|
| 421 |
-//vm86old |
|
| 422 |
- |
|
| 423 |
-// Kernel key management |
|
| 424 |
-//add_key |
|
| 425 |
-//keyctl |
|
| 426 |
-//request_key |
|
| 427 |
- |
|
| 428 |
-// Unimplemented |
|
| 429 |
-//afs_syscall |
|
| 430 |
-//break |
|
| 431 |
-//ftime |
|
| 432 |
-//getpmsg |
|
| 433 |
-//gtty |
|
| 434 |
-//lock |
|
| 435 |
-//madvise1 |
|
| 436 |
-//mpx |
|
| 437 |
-//prof |
|
| 438 |
-//profil |
|
| 439 |
-//putpmsg |
|
| 440 |
-//security |
|
| 441 |
-//stty |
|
| 442 |
-//tuxcall |
|
| 443 |
-//ulimit |
|
| 444 |
-//vserver |
| ... | ... |
@@ -261,7 +261,6 @@ func (container *Container) jsonPath() (string, error) {
|
| 261 | 261 |
return container.getRootResourcePath("config.json")
|
| 262 | 262 |
} |
| 263 | 263 |
|
| 264 |
-// This method must be exported to be used from the lxc template |
|
| 265 | 264 |
// This directory is only usable when the container is running |
| 266 | 265 |
func (container *Container) rootfsPath() string {
|
| 267 | 266 |
return container.basefs |
| ... | ... |
@@ -255,12 +255,6 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error {
|
| 255 | 255 |
|
| 256 | 256 |
autoCreatedDevices := mergeDevices(configs.DefaultAutoCreatedDevices, userSpecifiedDevices) |
| 257 | 257 |
|
| 258 |
- // TODO: this can be removed after lxc-conf is fully deprecated |
|
| 259 |
- lxcConfig, err := mergeLxcConfIntoOptions(c.hostConfig) |
|
| 260 |
- if err != nil {
|
|
| 261 |
- return err |
|
| 262 |
- } |
|
| 263 |
- |
|
| 264 | 258 |
var rlimits []*ulimit.Rlimit |
| 265 | 259 |
ulimits := c.hostConfig.Ulimits |
| 266 | 260 |
|
| ... | ... |
@@ -345,7 +339,6 @@ func (daemon *Daemon) populateCommand(c *Container, env []string) error {
|
| 345 | 345 |
GIDMapping: gidMap, |
| 346 | 346 |
GroupAdd: c.hostConfig.GroupAdd, |
| 347 | 347 |
Ipc: ipc, |
| 348 |
- LxcConfig: lxcConfig, |
|
| 349 | 348 |
Pid: pid, |
| 350 | 349 |
ReadonlyRootfs: c.hostConfig.ReadonlyRootfs, |
| 351 | 350 |
RemappedRoot: remappedRoot, |
| ... | ... |
@@ -451,7 +451,6 @@ func (daemon *Daemon) generateNewName(id string) (string, error) {
|
| 451 | 451 |
|
| 452 | 452 |
func (daemon *Daemon) generateHostname(id string, config *runconfig.Config) {
|
| 453 | 453 |
// Generate default hostname |
| 454 |
- // FIXME: the lxc template no longer needs to set a default hostname |
|
| 455 | 454 |
if config.Hostname == "" {
|
| 456 | 455 |
config.Hostname = id[:12] |
| 457 | 456 |
} |
| ... | ... |
@@ -786,13 +785,6 @@ func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemo |
| 786 | 786 |
d.containerGraphDB = graph |
| 787 | 787 |
|
| 788 | 788 |
var sysInitPath string |
| 789 |
- if config.ExecDriver == "lxc" {
|
|
| 790 |
- initPath, err := configureSysInit(config, rootUID, rootGID) |
|
| 791 |
- if err != nil {
|
|
| 792 |
- return nil, err |
|
| 793 |
- } |
|
| 794 |
- sysInitPath = initPath |
|
| 795 |
- } |
|
| 796 | 789 |
|
| 797 | 790 |
sysInfo := sysinfo.New(false) |
| 798 | 791 |
// Check if Devices cgroup is mounted, it is hard requirement for container security, |
| ... | ... |
@@ -128,10 +128,6 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *runconfig.HostC |
| 128 | 128 |
return warnings, err |
| 129 | 129 |
} |
| 130 | 130 |
|
| 131 |
- if hostConfig.LxcConf.Len() > 0 && !strings.Contains(daemon.ExecutionDriver().Name(), "lxc") {
|
|
| 132 |
- return warnings, fmt.Errorf("Cannot use --lxc-conf with execdriver: %s", daemon.ExecutionDriver().Name())
|
|
| 133 |
- } |
|
| 134 |
- |
|
| 135 | 131 |
// memory subsystem checks and adjustments |
| 136 | 132 |
if hostConfig.Memory != 0 && hostConfig.Memory < 4194304 {
|
| 137 | 133 |
return warnings, fmt.Errorf("Minimum memory limit allowed is 4MB")
|
| ... | ... |
@@ -148,11 +148,6 @@ func (d *Daemon) getActiveContainer(name string) (*Container, error) {
|
| 148 | 148 |
|
| 149 | 149 |
// ContainerExecCreate sets up an exec in a running container. |
| 150 | 150 |
func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) {
|
| 151 |
- // Not all drivers support Exec (LXC for example) |
|
| 152 |
- if err := checkExecSupport(d.execDriver.Name()); err != nil {
|
|
| 153 |
- return "", err |
|
| 154 |
- } |
|
| 155 |
- |
|
| 156 | 151 |
container, err := d.getActiveContainer(config.Container) |
| 157 | 152 |
if err != nil {
|
| 158 | 153 |
return "", err |
| 10 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,18 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "strings" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/docker/daemon/execdriver/lxc" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-// checkExecSupport returns an error if the exec driver does not support exec, |
|
| 12 |
-// or nil if it is supported. |
|
| 13 |
-func checkExecSupport(drivername string) error {
|
|
| 14 |
- if strings.HasPrefix(drivername, lxc.DriverName) {
|
|
| 15 |
- return lxc.ErrExec |
|
| 16 |
- } |
|
| 17 |
- return nil |
|
| 18 |
-} |
| ... | ... |
@@ -100,7 +100,6 @@ type Command struct {
|
| 100 | 100 |
GIDMapping []idtools.IDMap `json:"gidmapping"` |
| 101 | 101 |
GroupAdd []string `json:"group_add"` |
| 102 | 102 |
Ipc *Ipc `json:"ipc"` |
| 103 |
- LxcConfig []string `json:"lxc_config"` |
|
| 104 | 103 |
Pid *Pid `json:"pid"` |
| 105 | 104 |
ReadonlyRootfs bool `json:"readonly_rootfs"` |
| 106 | 105 |
RemappedRoot *User `json:"remap_root"` |
| ... | ... |
@@ -6,24 +6,15 @@ import ( |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"path" |
| 8 | 8 |
|
| 9 |
- "github.com/Sirupsen/logrus" |
|
| 10 | 9 |
"github.com/docker/docker/daemon/execdriver" |
| 11 |
- "github.com/docker/docker/daemon/execdriver/lxc" |
|
| 12 | 10 |
"github.com/docker/docker/daemon/execdriver/native" |
| 13 | 11 |
"github.com/docker/docker/pkg/sysinfo" |
| 14 | 12 |
) |
| 15 | 13 |
|
| 16 | 14 |
// NewDriver returns a new execdriver.Driver from the given name configured with the provided options. |
| 17 | 15 |
func NewDriver(name string, options []string, root, libPath, initPath string, sysInfo *sysinfo.SysInfo) (execdriver.Driver, error) {
|
| 18 |
- switch name {
|
|
| 19 |
- case "lxc": |
|
| 20 |
- // we want to give the lxc driver the full docker root because it needs |
|
| 21 |
- // to access and write config and template files in /var/lib/docker/containers/* |
|
| 22 |
- // to be backwards compatible |
|
| 23 |
- logrus.Warn("LXC built-in support is deprecated.")
|
|
| 24 |
- return lxc.NewDriver(root, libPath, initPath, sysInfo.AppArmor) |
|
| 25 |
- case "native": |
|
| 26 |
- return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options) |
|
| 16 |
+ if name != "native" {
|
|
| 17 |
+ return nil, fmt.Errorf("unknown exec driver %s", name)
|
|
| 27 | 18 |
} |
| 28 |
- return nil, fmt.Errorf("unknown exec driver %s", name)
|
|
| 19 |
+ return native.NewDriver(path.Join(root, "execdriver", "native"), initPath, options) |
|
| 29 | 20 |
} |
| 30 | 21 |
deleted file mode 100644 |
| ... | ... |
@@ -1,906 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "encoding/json" |
|
| 7 |
- "errors" |
|
| 8 |
- "fmt" |
|
| 9 |
- "io" |
|
| 10 |
- "io/ioutil" |
|
| 11 |
- "os" |
|
| 12 |
- "os/exec" |
|
| 13 |
- "path" |
|
| 14 |
- "path/filepath" |
|
| 15 |
- "runtime" |
|
| 16 |
- "strconv" |
|
| 17 |
- "strings" |
|
| 18 |
- "sync" |
|
| 19 |
- "syscall" |
|
| 20 |
- "time" |
|
| 21 |
- |
|
| 22 |
- "github.com/Sirupsen/logrus" |
|
| 23 |
- "github.com/docker/docker/daemon/execdriver" |
|
| 24 |
- "github.com/docker/docker/pkg/stringutils" |
|
| 25 |
- sysinfo "github.com/docker/docker/pkg/system" |
|
| 26 |
- "github.com/docker/docker/pkg/term" |
|
| 27 |
- "github.com/docker/docker/pkg/version" |
|
| 28 |
- "github.com/kr/pty" |
|
| 29 |
- "github.com/opencontainers/runc/libcontainer" |
|
| 30 |
- "github.com/opencontainers/runc/libcontainer/cgroups" |
|
| 31 |
- "github.com/opencontainers/runc/libcontainer/configs" |
|
| 32 |
- "github.com/opencontainers/runc/libcontainer/system" |
|
| 33 |
- "github.com/opencontainers/runc/libcontainer/user" |
|
| 34 |
- "github.com/vishvananda/netns" |
|
| 35 |
-) |
|
| 36 |
- |
|
| 37 |
-// DriverName for lxc driver |
|
| 38 |
-const DriverName = "lxc" |
|
| 39 |
- |
|
| 40 |
-// ErrExec defines unsupported error message |
|
| 41 |
-var ErrExec = errors.New("Unsupported: Exec is not supported by the lxc driver")
|
|
| 42 |
- |
|
| 43 |
-// Driver contains all information for lxc driver, |
|
| 44 |
-// it implements execdriver.Driver |
|
| 45 |
-type Driver struct {
|
|
| 46 |
- root string // root path for the driver to use |
|
| 47 |
- libPath string |
|
| 48 |
- initPath string |
|
| 49 |
- apparmor bool |
|
| 50 |
- sharedRoot bool |
|
| 51 |
- activeContainers map[string]*activeContainer |
|
| 52 |
- machineMemory int64 |
|
| 53 |
- sync.Mutex |
|
| 54 |
-} |
|
| 55 |
- |
|
| 56 |
-type activeContainer struct {
|
|
| 57 |
- container *configs.Config |
|
| 58 |
- cmd *exec.Cmd |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-// NewDriver returns a new lxc driver, called from NewDriver of execdriver |
|
| 62 |
-func NewDriver(root, libPath, initPath string, apparmor bool) (*Driver, error) {
|
|
| 63 |
- if err := os.MkdirAll(root, 0700); err != nil {
|
|
| 64 |
- return nil, err |
|
| 65 |
- } |
|
| 66 |
- // setup unconfined symlink |
|
| 67 |
- if err := linkLxcStart(root); err != nil {
|
|
| 68 |
- return nil, err |
|
| 69 |
- } |
|
| 70 |
- meminfo, err := sysinfo.ReadMemInfo() |
|
| 71 |
- if err != nil {
|
|
| 72 |
- return nil, err |
|
| 73 |
- } |
|
| 74 |
- return &Driver{
|
|
| 75 |
- apparmor: apparmor, |
|
| 76 |
- root: root, |
|
| 77 |
- libPath: libPath, |
|
| 78 |
- initPath: initPath, |
|
| 79 |
- sharedRoot: rootIsShared(), |
|
| 80 |
- activeContainers: make(map[string]*activeContainer), |
|
| 81 |
- machineMemory: meminfo.MemTotal, |
|
| 82 |
- }, nil |
|
| 83 |
-} |
|
| 84 |
- |
|
| 85 |
-// Name implements the exec driver Driver interface. |
|
| 86 |
-func (d *Driver) Name() string {
|
|
| 87 |
- version := d.version() |
|
| 88 |
- return fmt.Sprintf("%s-%s", DriverName, version)
|
|
| 89 |
-} |
|
| 90 |
- |
|
| 91 |
-func setupNetNs(nsPath string) (*os.Process, error) {
|
|
| 92 |
- runtime.LockOSThread() |
|
| 93 |
- defer runtime.UnlockOSThread() |
|
| 94 |
- |
|
| 95 |
- origns, err := netns.Get() |
|
| 96 |
- if err != nil {
|
|
| 97 |
- return nil, err |
|
| 98 |
- } |
|
| 99 |
- defer origns.Close() |
|
| 100 |
- |
|
| 101 |
- f, err := os.OpenFile(nsPath, os.O_RDONLY, 0) |
|
| 102 |
- if err != nil {
|
|
| 103 |
- return nil, fmt.Errorf("failed to get network namespace %q: %v", nsPath, err)
|
|
| 104 |
- } |
|
| 105 |
- defer f.Close() |
|
| 106 |
- |
|
| 107 |
- nsFD := f.Fd() |
|
| 108 |
- if err := netns.Set(netns.NsHandle(nsFD)); err != nil {
|
|
| 109 |
- return nil, fmt.Errorf("failed to set network namespace %q: %v", nsPath, err)
|
|
| 110 |
- } |
|
| 111 |
- defer netns.Set(origns) |
|
| 112 |
- |
|
| 113 |
- cmd := exec.Command("/bin/sh", "-c", "while true; do sleep 1; done")
|
|
| 114 |
- if err := cmd.Start(); err != nil {
|
|
| 115 |
- return nil, fmt.Errorf("failed to start netns process: %v", err)
|
|
| 116 |
- } |
|
| 117 |
- |
|
| 118 |
- return cmd.Process, nil |
|
| 119 |
-} |
|
| 120 |
- |
|
| 121 |
-func killNetNsProc(proc *os.Process) {
|
|
| 122 |
- proc.Kill() |
|
| 123 |
- proc.Wait() |
|
| 124 |
-} |
|
| 125 |
- |
|
| 126 |
-// Run implements the exec driver Driver interface, |
|
| 127 |
-// it calls 'exec.Cmd' to launch lxc commands to run a container. |
|
| 128 |
-func (d *Driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, hooks execdriver.Hooks) (execdriver.ExitStatus, error) {
|
|
| 129 |
- var ( |
|
| 130 |
- term execdriver.Terminal |
|
| 131 |
- err error |
|
| 132 |
- dataPath = d.containerDir(c.ID) |
|
| 133 |
- ) |
|
| 134 |
- |
|
| 135 |
- if c.Network == nil || (c.Network.NamespacePath == "" && c.Network.ContainerID == "") {
|
|
| 136 |
- return execdriver.ExitStatus{ExitCode: -1}, fmt.Errorf("empty namespace path for non-container network")
|
|
| 137 |
- } |
|
| 138 |
- |
|
| 139 |
- container, err := d.createContainer(c) |
|
| 140 |
- if err != nil {
|
|
| 141 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 142 |
- } |
|
| 143 |
- |
|
| 144 |
- if c.ProcessConfig.Tty {
|
|
| 145 |
- term, err = NewTtyConsole(&c.ProcessConfig, pipes) |
|
| 146 |
- } else {
|
|
| 147 |
- term, err = execdriver.NewStdConsole(&c.ProcessConfig, pipes) |
|
| 148 |
- } |
|
| 149 |
- if err != nil {
|
|
| 150 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 151 |
- } |
|
| 152 |
- c.ProcessConfig.Terminal = term |
|
| 153 |
- |
|
| 154 |
- d.Lock() |
|
| 155 |
- d.activeContainers[c.ID] = &activeContainer{
|
|
| 156 |
- container: container, |
|
| 157 |
- cmd: &c.ProcessConfig.Cmd, |
|
| 158 |
- } |
|
| 159 |
- d.Unlock() |
|
| 160 |
- |
|
| 161 |
- c.Mounts = append(c.Mounts, execdriver.Mount{
|
|
| 162 |
- Source: d.initPath, |
|
| 163 |
- Destination: c.InitPath, |
|
| 164 |
- Writable: false, |
|
| 165 |
- Private: true, |
|
| 166 |
- }) |
|
| 167 |
- |
|
| 168 |
- if err := d.generateEnvConfig(c); err != nil {
|
|
| 169 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 170 |
- } |
|
| 171 |
- configPath, err := d.generateLXCConfig(c) |
|
| 172 |
- if err != nil {
|
|
| 173 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 174 |
- } |
|
| 175 |
- params := []string{
|
|
| 176 |
- "lxc-start", |
|
| 177 |
- "-n", c.ID, |
|
| 178 |
- "-f", configPath, |
|
| 179 |
- "-q", |
|
| 180 |
- } |
|
| 181 |
- |
|
| 182 |
- // From lxc>=1.1 the default behavior is to daemonize containers after start |
|
| 183 |
- lxcVersion := version.Version(d.version()) |
|
| 184 |
- if lxcVersion.GreaterThanOrEqualTo(version.Version("1.1")) {
|
|
| 185 |
- params = append(params, "-F") |
|
| 186 |
- } |
|
| 187 |
- |
|
| 188 |
- proc := &os.Process{}
|
|
| 189 |
- if c.Network.ContainerID != "" {
|
|
| 190 |
- params = append(params, |
|
| 191 |
- "--share-net", c.Network.ContainerID, |
|
| 192 |
- ) |
|
| 193 |
- } else {
|
|
| 194 |
- proc, err = setupNetNs(c.Network.NamespacePath) |
|
| 195 |
- if err != nil {
|
|
| 196 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- pidStr := fmt.Sprintf("%d", proc.Pid)
|
|
| 200 |
- params = append(params, |
|
| 201 |
- "--share-net", pidStr) |
|
| 202 |
- } |
|
| 203 |
- if c.Ipc != nil {
|
|
| 204 |
- if c.Ipc.ContainerID != "" {
|
|
| 205 |
- params = append(params, |
|
| 206 |
- "--share-ipc", c.Ipc.ContainerID, |
|
| 207 |
- ) |
|
| 208 |
- } else if c.Ipc.HostIpc {
|
|
| 209 |
- params = append(params, |
|
| 210 |
- "--share-ipc", "1", |
|
| 211 |
- ) |
|
| 212 |
- } |
|
| 213 |
- } |
|
| 214 |
- |
|
| 215 |
- params = append(params, |
|
| 216 |
- "--", |
|
| 217 |
- c.InitPath, |
|
| 218 |
- ) |
|
| 219 |
- |
|
| 220 |
- if c.ProcessConfig.User != "" {
|
|
| 221 |
- params = append(params, "-u", c.ProcessConfig.User) |
|
| 222 |
- } |
|
| 223 |
- |
|
| 224 |
- if c.ProcessConfig.Privileged {
|
|
| 225 |
- if d.apparmor {
|
|
| 226 |
- params[0] = path.Join(d.root, "lxc-start-unconfined") |
|
| 227 |
- |
|
| 228 |
- } |
|
| 229 |
- params = append(params, "-privileged") |
|
| 230 |
- } |
|
| 231 |
- |
|
| 232 |
- if c.WorkingDir != "" {
|
|
| 233 |
- params = append(params, "-w", c.WorkingDir) |
|
| 234 |
- } |
|
| 235 |
- |
|
| 236 |
- params = append(params, "--", c.ProcessConfig.Entrypoint) |
|
| 237 |
- params = append(params, c.ProcessConfig.Arguments...) |
|
| 238 |
- |
|
| 239 |
- if d.sharedRoot {
|
|
| 240 |
- // lxc-start really needs / to be non-shared, or all kinds of stuff break |
|
| 241 |
- // when lxc-start unmount things and those unmounts propagate to the main |
|
| 242 |
- // mount namespace. |
|
| 243 |
- // What we really want is to clone into a new namespace and then |
|
| 244 |
- // mount / MS_REC|MS_SLAVE, but since we can't really clone or fork |
|
| 245 |
- // without exec in go we have to do this horrible shell hack... |
|
| 246 |
- shellString := |
|
| 247 |
- "mount --make-rslave /; exec " + |
|
| 248 |
- stringutils.ShellQuoteArguments(params) |
|
| 249 |
- |
|
| 250 |
- params = []string{
|
|
| 251 |
- "unshare", "-m", "--", "/bin/sh", "-c", shellString, |
|
| 252 |
- } |
|
| 253 |
- } |
|
| 254 |
- logrus.Debugf("lxc params %s", params)
|
|
| 255 |
- var ( |
|
| 256 |
- name = params[0] |
|
| 257 |
- arg = params[1:] |
|
| 258 |
- ) |
|
| 259 |
- aname, err := exec.LookPath(name) |
|
| 260 |
- if err != nil {
|
|
| 261 |
- aname = name |
|
| 262 |
- } |
|
| 263 |
- c.ProcessConfig.Path = aname |
|
| 264 |
- c.ProcessConfig.Args = append([]string{name}, arg...)
|
|
| 265 |
- |
|
| 266 |
- if err := createDeviceNodes(c.Rootfs, c.AutoCreatedDevices); err != nil {
|
|
| 267 |
- killNetNsProc(proc) |
|
| 268 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 269 |
- } |
|
| 270 |
- |
|
| 271 |
- if err := c.ProcessConfig.Start(); err != nil {
|
|
| 272 |
- killNetNsProc(proc) |
|
| 273 |
- return execdriver.ExitStatus{ExitCode: -1}, err
|
|
| 274 |
- } |
|
| 275 |
- |
|
| 276 |
- var ( |
|
| 277 |
- waitErr error |
|
| 278 |
- waitLock = make(chan struct{})
|
|
| 279 |
- ) |
|
| 280 |
- |
|
| 281 |
- go func() {
|
|
| 282 |
- if err := c.ProcessConfig.Wait(); err != nil {
|
|
| 283 |
- if _, ok := err.(*exec.ExitError); !ok { // Do not propagate the error if it's simply a status code != 0
|
|
| 284 |
- waitErr = err |
|
| 285 |
- } |
|
| 286 |
- } |
|
| 287 |
- close(waitLock) |
|
| 288 |
- }() |
|
| 289 |
- |
|
| 290 |
- terminate := func(terr error) (execdriver.ExitStatus, error) {
|
|
| 291 |
- if c.ProcessConfig.Process != nil {
|
|
| 292 |
- c.ProcessConfig.Process.Kill() |
|
| 293 |
- c.ProcessConfig.Wait() |
|
| 294 |
- } |
|
| 295 |
- return execdriver.ExitStatus{ExitCode: -1}, terr
|
|
| 296 |
- } |
|
| 297 |
- // Poll lxc for RUNNING status |
|
| 298 |
- pid, err := d.waitForStart(c, waitLock) |
|
| 299 |
- if err != nil {
|
|
| 300 |
- killNetNsProc(proc) |
|
| 301 |
- return terminate(err) |
|
| 302 |
- } |
|
| 303 |
- killNetNsProc(proc) |
|
| 304 |
- |
|
| 305 |
- cgroupPaths, err := cgroupPaths(c.ID) |
|
| 306 |
- if err != nil {
|
|
| 307 |
- return terminate(err) |
|
| 308 |
- } |
|
| 309 |
- |
|
| 310 |
- state := &libcontainer.State{
|
|
| 311 |
- InitProcessPid: pid, |
|
| 312 |
- CgroupPaths: cgroupPaths, |
|
| 313 |
- } |
|
| 314 |
- |
|
| 315 |
- f, err := os.Create(filepath.Join(dataPath, "state.json")) |
|
| 316 |
- if err != nil {
|
|
| 317 |
- return terminate(err) |
|
| 318 |
- } |
|
| 319 |
- defer f.Close() |
|
| 320 |
- |
|
| 321 |
- if err := json.NewEncoder(f).Encode(state); err != nil {
|
|
| 322 |
- return terminate(err) |
|
| 323 |
- } |
|
| 324 |
- |
|
| 325 |
- c.ContainerPid = pid |
|
| 326 |
- |
|
| 327 |
- if hooks.Start != nil {
|
|
| 328 |
- logrus.Debugf("Invoking startCallback")
|
|
| 329 |
- chOOM := make(chan struct{})
|
|
| 330 |
- close(chOOM) |
|
| 331 |
- hooks.Start(&c.ProcessConfig, pid, chOOM) |
|
| 332 |
- } |
|
| 333 |
- |
|
| 334 |
- oomKillNotification := notifyChannelOOM(cgroupPaths) |
|
| 335 |
- |
|
| 336 |
- <-waitLock |
|
| 337 |
- exitCode := getExitCode(c) |
|
| 338 |
- |
|
| 339 |
- _, oomKill := <-oomKillNotification |
|
| 340 |
- logrus.Debugf("oomKill error: %v, waitErr: %v", oomKill, waitErr)
|
|
| 341 |
- |
|
| 342 |
- // check oom error |
|
| 343 |
- if oomKill {
|
|
| 344 |
- exitCode = 137 |
|
| 345 |
- } |
|
| 346 |
- |
|
| 347 |
- return execdriver.ExitStatus{ExitCode: exitCode, OOMKilled: oomKill}, waitErr
|
|
| 348 |
-} |
|
| 349 |
- |
|
| 350 |
-func notifyChannelOOM(paths map[string]string) <-chan struct{} {
|
|
| 351 |
- oom, err := notifyOnOOM(paths) |
|
| 352 |
- if err != nil {
|
|
| 353 |
- logrus.Warnf("Your kernel does not support OOM notifications: %s", err)
|
|
| 354 |
- c := make(chan struct{})
|
|
| 355 |
- close(c) |
|
| 356 |
- return c |
|
| 357 |
- } |
|
| 358 |
- return oom |
|
| 359 |
-} |
|
| 360 |
- |
|
| 361 |
-// copy from libcontainer |
|
| 362 |
-func notifyOnOOM(paths map[string]string) (<-chan struct{}, error) {
|
|
| 363 |
- dir := paths["memory"] |
|
| 364 |
- if dir == "" {
|
|
| 365 |
- return nil, fmt.Errorf("There is no path for %q in state", "memory")
|
|
| 366 |
- } |
|
| 367 |
- oomControl, err := os.Open(filepath.Join(dir, "memory.oom_control")) |
|
| 368 |
- if err != nil {
|
|
| 369 |
- return nil, err |
|
| 370 |
- } |
|
| 371 |
- fd, _, syserr := syscall.RawSyscall(syscall.SYS_EVENTFD2, 0, syscall.FD_CLOEXEC, 0) |
|
| 372 |
- if syserr != 0 {
|
|
| 373 |
- oomControl.Close() |
|
| 374 |
- return nil, syserr |
|
| 375 |
- } |
|
| 376 |
- |
|
| 377 |
- eventfd := os.NewFile(fd, "eventfd") |
|
| 378 |
- |
|
| 379 |
- eventControlPath := filepath.Join(dir, "cgroup.event_control") |
|
| 380 |
- data := fmt.Sprintf("%d %d", eventfd.Fd(), oomControl.Fd())
|
|
| 381 |
- if err := ioutil.WriteFile(eventControlPath, []byte(data), 0700); err != nil {
|
|
| 382 |
- eventfd.Close() |
|
| 383 |
- oomControl.Close() |
|
| 384 |
- return nil, err |
|
| 385 |
- } |
|
| 386 |
- ch := make(chan struct{})
|
|
| 387 |
- go func() {
|
|
| 388 |
- defer func() {
|
|
| 389 |
- close(ch) |
|
| 390 |
- eventfd.Close() |
|
| 391 |
- oomControl.Close() |
|
| 392 |
- }() |
|
| 393 |
- buf := make([]byte, 8) |
|
| 394 |
- for {
|
|
| 395 |
- if _, err := eventfd.Read(buf); err != nil {
|
|
| 396 |
- logrus.Warn(err) |
|
| 397 |
- return |
|
| 398 |
- } |
|
| 399 |
- // When a cgroup is destroyed, an event is sent to eventfd. |
|
| 400 |
- // So if the control path is gone, return instead of notifying. |
|
| 401 |
- if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
|
|
| 402 |
- logrus.Warn(err) |
|
| 403 |
- return |
|
| 404 |
- } |
|
| 405 |
- ch <- struct{}{}
|
|
| 406 |
- } |
|
| 407 |
- }() |
|
| 408 |
- return ch, nil |
|
| 409 |
-} |
|
| 410 |
- |
|
| 411 |
-// createContainer populates and configures the container type with the |
|
| 412 |
-// data provided by the execdriver.Command |
|
| 413 |
-func (d *Driver) createContainer(c *execdriver.Command) (*configs.Config, error) {
|
|
| 414 |
- container := execdriver.InitContainer(c) |
|
| 415 |
- if err := execdriver.SetupCgroups(container, c); err != nil {
|
|
| 416 |
- return nil, err |
|
| 417 |
- } |
|
| 418 |
- return container, nil |
|
| 419 |
-} |
|
| 420 |
- |
|
| 421 |
-// Return an map of susbystem -> absolute container cgroup path |
|
| 422 |
-func cgroupPaths(containerID string) (map[string]string, error) {
|
|
| 423 |
- subsystems, err := cgroups.GetAllSubsystems() |
|
| 424 |
- if err != nil {
|
|
| 425 |
- return nil, err |
|
| 426 |
- } |
|
| 427 |
- logrus.Debugf("subsystems: %s", subsystems)
|
|
| 428 |
- paths := make(map[string]string) |
|
| 429 |
- for _, subsystem := range subsystems {
|
|
| 430 |
- cgroupRoot, cgroupDir, err := findCgroupRootAndDir(subsystem) |
|
| 431 |
- logrus.Debugf("cgroup path %s %s", cgroupRoot, cgroupDir)
|
|
| 432 |
- if err != nil {
|
|
| 433 |
- //unsupported subystem |
|
| 434 |
- continue |
|
| 435 |
- } |
|
| 436 |
- // if we are running dind |
|
| 437 |
- dockerPathIdx := strings.LastIndex(cgroupDir, "docker") |
|
| 438 |
- if dockerPathIdx != -1 {
|
|
| 439 |
- cgroupDir = cgroupDir[:dockerPathIdx-1] |
|
| 440 |
- } |
|
| 441 |
- path := filepath.Join(cgroupRoot, cgroupDir, "lxc", containerID) |
|
| 442 |
- paths[subsystem] = path |
|
| 443 |
- } |
|
| 444 |
- |
|
| 445 |
- return paths, nil |
|
| 446 |
-} |
|
| 447 |
- |
|
| 448 |
-// this is copy from old libcontainer nodes.go |
|
| 449 |
-func createDeviceNodes(rootfs string, nodesToCreate []*configs.Device) error {
|
|
| 450 |
- oldMask := syscall.Umask(0000) |
|
| 451 |
- defer syscall.Umask(oldMask) |
|
| 452 |
- |
|
| 453 |
- for _, node := range nodesToCreate {
|
|
| 454 |
- if err := createDeviceNode(rootfs, node); err != nil {
|
|
| 455 |
- return err |
|
| 456 |
- } |
|
| 457 |
- } |
|
| 458 |
- return nil |
|
| 459 |
-} |
|
| 460 |
- |
|
| 461 |
-// Creates the device node in the rootfs of the container. |
|
| 462 |
-func createDeviceNode(rootfs string, node *configs.Device) error {
|
|
| 463 |
- var ( |
|
| 464 |
- dest = filepath.Join(rootfs, node.Path) |
|
| 465 |
- parent = filepath.Dir(dest) |
|
| 466 |
- ) |
|
| 467 |
- |
|
| 468 |
- if err := os.MkdirAll(parent, 0755); err != nil {
|
|
| 469 |
- return err |
|
| 470 |
- } |
|
| 471 |
- |
|
| 472 |
- fileMode := node.FileMode |
|
| 473 |
- switch node.Type {
|
|
| 474 |
- case 'c': |
|
| 475 |
- fileMode |= syscall.S_IFCHR |
|
| 476 |
- case 'b': |
|
| 477 |
- fileMode |= syscall.S_IFBLK |
|
| 478 |
- default: |
|
| 479 |
- return fmt.Errorf("%c is not a valid device type for device %s", node.Type, node.Path)
|
|
| 480 |
- } |
|
| 481 |
- |
|
| 482 |
- if err := syscall.Mknod(dest, uint32(fileMode), node.Mkdev()); err != nil && !os.IsExist(err) {
|
|
| 483 |
- return fmt.Errorf("mknod %s %s", node.Path, err)
|
|
| 484 |
- } |
|
| 485 |
- |
|
| 486 |
- if err := syscall.Chown(dest, int(node.Uid), int(node.Gid)); err != nil {
|
|
| 487 |
- return fmt.Errorf("chown %s to %d:%d", node.Path, node.Uid, node.Gid)
|
|
| 488 |
- } |
|
| 489 |
- |
|
| 490 |
- return nil |
|
| 491 |
-} |
|
| 492 |
- |
|
| 493 |
-// setupUser changes the groups, gid, and uid for the user inside the container |
|
| 494 |
-// copy from libcontainer, cause not it's private |
|
| 495 |
-func setupUser(userSpec string) error {
|
|
| 496 |
- // Set up defaults. |
|
| 497 |
- defaultExecUser := user.ExecUser{
|
|
| 498 |
- Uid: syscall.Getuid(), |
|
| 499 |
- Gid: syscall.Getgid(), |
|
| 500 |
- Home: "/", |
|
| 501 |
- } |
|
| 502 |
- passwdPath, err := user.GetPasswdPath() |
|
| 503 |
- if err != nil {
|
|
| 504 |
- return err |
|
| 505 |
- } |
|
| 506 |
- groupPath, err := user.GetGroupPath() |
|
| 507 |
- if err != nil {
|
|
| 508 |
- return err |
|
| 509 |
- } |
|
| 510 |
- execUser, err := user.GetExecUserPath(userSpec, &defaultExecUser, passwdPath, groupPath) |
|
| 511 |
- if err != nil {
|
|
| 512 |
- return err |
|
| 513 |
- } |
|
| 514 |
- if err := syscall.Setgroups(execUser.Sgids); err != nil {
|
|
| 515 |
- return err |
|
| 516 |
- } |
|
| 517 |
- if err := system.Setgid(execUser.Gid); err != nil {
|
|
| 518 |
- return err |
|
| 519 |
- } |
|
| 520 |
- if err := system.Setuid(execUser.Uid); err != nil {
|
|
| 521 |
- return err |
|
| 522 |
- } |
|
| 523 |
- // if we didn't get HOME already, set it based on the user's HOME |
|
| 524 |
- if envHome := os.Getenv("HOME"); envHome == "" {
|
|
| 525 |
- if err := os.Setenv("HOME", execUser.Home); err != nil {
|
|
| 526 |
- return err |
|
| 527 |
- } |
|
| 528 |
- } |
|
| 529 |
- return nil |
|
| 530 |
-} |
|
| 531 |
- |
|
| 532 |
-// getExitCode returns the exit code of the process. |
|
| 533 |
-// If the process has not exited -1 will be returned. |
|
| 534 |
-func getExitCode(c *execdriver.Command) int {
|
|
| 535 |
- if c.ProcessConfig.ProcessState == nil {
|
|
| 536 |
- return -1 |
|
| 537 |
- } |
|
| 538 |
- return c.ProcessConfig.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() |
|
| 539 |
-} |
|
| 540 |
- |
|
| 541 |
-// Kill implements the exec driver Driver interface. |
|
| 542 |
-func (d *Driver) Kill(c *execdriver.Command, sig int) error {
|
|
| 543 |
- if sig == 9 || c.ProcessConfig.Process == nil {
|
|
| 544 |
- return killLxc(c.ID, sig) |
|
| 545 |
- } |
|
| 546 |
- |
|
| 547 |
- return c.ProcessConfig.Process.Signal(syscall.Signal(sig)) |
|
| 548 |
-} |
|
| 549 |
- |
|
| 550 |
-// Pause implements the exec driver Driver interface, |
|
| 551 |
-// it executes lxc-freeze to pause a container. |
|
| 552 |
-func (d *Driver) Pause(c *execdriver.Command) error {
|
|
| 553 |
- _, err := exec.LookPath("lxc-freeze")
|
|
| 554 |
- if err == nil {
|
|
| 555 |
- output, errExec := exec.Command("lxc-freeze", "-n", c.ID).CombinedOutput()
|
|
| 556 |
- if errExec != nil {
|
|
| 557 |
- return fmt.Errorf("Err: %s Output: %s", errExec, output)
|
|
| 558 |
- } |
|
| 559 |
- } |
|
| 560 |
- |
|
| 561 |
- return err |
|
| 562 |
-} |
|
| 563 |
- |
|
| 564 |
-// Unpause implements the exec driver Driver interface, |
|
| 565 |
-// it executes lxc-unfreeze to unpause a container. |
|
| 566 |
-func (d *Driver) Unpause(c *execdriver.Command) error {
|
|
| 567 |
- _, err := exec.LookPath("lxc-unfreeze")
|
|
| 568 |
- if err == nil {
|
|
| 569 |
- output, errExec := exec.Command("lxc-unfreeze", "-n", c.ID).CombinedOutput()
|
|
| 570 |
- if errExec != nil {
|
|
| 571 |
- return fmt.Errorf("Err: %s Output: %s", errExec, output)
|
|
| 572 |
- } |
|
| 573 |
- } |
|
| 574 |
- |
|
| 575 |
- return err |
|
| 576 |
-} |
|
| 577 |
- |
|
| 578 |
-// Terminate implements the exec driver Driver interface. |
|
| 579 |
-func (d *Driver) Terminate(c *execdriver.Command) error {
|
|
| 580 |
- return killLxc(c.ID, 9) |
|
| 581 |
-} |
|
| 582 |
- |
|
| 583 |
-func (d *Driver) version() string {
|
|
| 584 |
- var ( |
|
| 585 |
- version string |
|
| 586 |
- output []byte |
|
| 587 |
- err error |
|
| 588 |
- ) |
|
| 589 |
- if _, errPath := exec.LookPath("lxc-version"); errPath == nil {
|
|
| 590 |
- output, err = exec.Command("lxc-version").CombinedOutput()
|
|
| 591 |
- } else {
|
|
| 592 |
- output, err = exec.Command("lxc-start", "--version").CombinedOutput()
|
|
| 593 |
- } |
|
| 594 |
- if err == nil {
|
|
| 595 |
- version = strings.TrimSpace(string(output)) |
|
| 596 |
- if parts := strings.SplitN(version, ":", 2); len(parts) == 2 {
|
|
| 597 |
- version = strings.TrimSpace(parts[1]) |
|
| 598 |
- } |
|
| 599 |
- } |
|
| 600 |
- return version |
|
| 601 |
-} |
|
| 602 |
- |
|
| 603 |
-func killLxc(id string, sig int) error {
|
|
| 604 |
- var ( |
|
| 605 |
- err error |
|
| 606 |
- output []byte |
|
| 607 |
- ) |
|
| 608 |
- _, err = exec.LookPath("lxc-kill")
|
|
| 609 |
- if err == nil {
|
|
| 610 |
- output, err = exec.Command("lxc-kill", "-n", id, strconv.Itoa(sig)).CombinedOutput()
|
|
| 611 |
- } else {
|
|
| 612 |
- // lxc-stop does not take arbitrary signals like lxc-kill does |
|
| 613 |
- output, err = exec.Command("lxc-stop", "-k", "-n", id).CombinedOutput()
|
|
| 614 |
- } |
|
| 615 |
- if err != nil {
|
|
| 616 |
- return fmt.Errorf("Err: %s Output: %s", err, output)
|
|
| 617 |
- } |
|
| 618 |
- return nil |
|
| 619 |
-} |
|
| 620 |
- |
|
| 621 |
-// wait for the process to start and return the pid for the process |
|
| 622 |
-func (d *Driver) waitForStart(c *execdriver.Command, waitLock chan struct{}) (int, error) {
|
|
| 623 |
- var ( |
|
| 624 |
- err error |
|
| 625 |
- output []byte |
|
| 626 |
- ) |
|
| 627 |
- // We wait for the container to be fully running. |
|
| 628 |
- // Timeout after 5 seconds. In case of broken pipe, just retry. |
|
| 629 |
- // Note: The container can run and finish correctly before |
|
| 630 |
- // the end of this loop |
|
| 631 |
- for now := time.Now(); time.Since(now) < 5*time.Second; {
|
|
| 632 |
- select {
|
|
| 633 |
- case <-waitLock: |
|
| 634 |
- // If the process dies while waiting for it, just return |
|
| 635 |
- return -1, nil |
|
| 636 |
- default: |
|
| 637 |
- } |
|
| 638 |
- |
|
| 639 |
- output, err = d.getInfo(c.ID) |
|
| 640 |
- if err == nil {
|
|
| 641 |
- info, err := parseLxcInfo(string(output)) |
|
| 642 |
- if err != nil {
|
|
| 643 |
- return -1, err |
|
| 644 |
- } |
|
| 645 |
- if info.Running {
|
|
| 646 |
- return info.Pid, nil |
|
| 647 |
- } |
|
| 648 |
- } |
|
| 649 |
- time.Sleep(50 * time.Millisecond) |
|
| 650 |
- } |
|
| 651 |
- return -1, execdriver.ErrNotRunning |
|
| 652 |
-} |
|
| 653 |
- |
|
| 654 |
-func (d *Driver) getInfo(id string) ([]byte, error) {
|
|
| 655 |
- return exec.Command("lxc-info", "-n", id).CombinedOutput()
|
|
| 656 |
-} |
|
| 657 |
- |
|
| 658 |
-type info struct {
|
|
| 659 |
- ID string |
|
| 660 |
- driver *Driver |
|
| 661 |
-} |
|
| 662 |
- |
|
| 663 |
-func (i *info) IsRunning() bool {
|
|
| 664 |
- var running bool |
|
| 665 |
- |
|
| 666 |
- output, err := i.driver.getInfo(i.ID) |
|
| 667 |
- if err != nil {
|
|
| 668 |
- logrus.Errorf("Error getting info for lxc container %s: %s (%s)", i.ID, err, output)
|
|
| 669 |
- return false |
|
| 670 |
- } |
|
| 671 |
- if strings.Contains(string(output), "RUNNING") {
|
|
| 672 |
- running = true |
|
| 673 |
- } |
|
| 674 |
- return running |
|
| 675 |
-} |
|
| 676 |
- |
|
| 677 |
-// Info implements the exec driver Driver interface. |
|
| 678 |
-func (d *Driver) Info(id string) execdriver.Info {
|
|
| 679 |
- return &info{
|
|
| 680 |
- ID: id, |
|
| 681 |
- driver: d, |
|
| 682 |
- } |
|
| 683 |
-} |
|
| 684 |
- |
|
| 685 |
-func findCgroupRootAndDir(subsystem string) (string, string, error) {
|
|
| 686 |
- cgroupRoot, err := cgroups.FindCgroupMountpoint(subsystem) |
|
| 687 |
- if err != nil {
|
|
| 688 |
- return "", "", err |
|
| 689 |
- } |
|
| 690 |
- |
|
| 691 |
- cgroupDir, err := cgroups.GetThisCgroupDir(subsystem) |
|
| 692 |
- if err != nil {
|
|
| 693 |
- return "", "", err |
|
| 694 |
- } |
|
| 695 |
- return cgroupRoot, cgroupDir, nil |
|
| 696 |
-} |
|
| 697 |
- |
|
| 698 |
-// GetPidsForContainer implements the exec driver Driver interface. |
|
| 699 |
-func (d *Driver) GetPidsForContainer(id string) ([]int, error) {
|
|
| 700 |
- pids := []int{}
|
|
| 701 |
- |
|
| 702 |
- // cpu is chosen because it is the only non optional subsystem in cgroups |
|
| 703 |
- subsystem := "cpu" |
|
| 704 |
- cgroupRoot, cgroupDir, err := findCgroupRootAndDir(subsystem) |
|
| 705 |
- if err != nil {
|
|
| 706 |
- return pids, err |
|
| 707 |
- } |
|
| 708 |
- |
|
| 709 |
- filename := filepath.Join(cgroupRoot, cgroupDir, id, "tasks") |
|
| 710 |
- if _, err := os.Stat(filename); os.IsNotExist(err) {
|
|
| 711 |
- // With more recent lxc versions use, cgroup will be in lxc/ |
|
| 712 |
- filename = filepath.Join(cgroupRoot, cgroupDir, "lxc", id, "tasks") |
|
| 713 |
- } |
|
| 714 |
- |
|
| 715 |
- output, err := ioutil.ReadFile(filename) |
|
| 716 |
- if err != nil {
|
|
| 717 |
- return pids, err |
|
| 718 |
- } |
|
| 719 |
- for _, p := range strings.Split(string(output), "\n") {
|
|
| 720 |
- if len(p) == 0 {
|
|
| 721 |
- continue |
|
| 722 |
- } |
|
| 723 |
- pid, err := strconv.Atoi(p) |
|
| 724 |
- if err != nil {
|
|
| 725 |
- return pids, fmt.Errorf("Invalid pid '%s': %s", p, err)
|
|
| 726 |
- } |
|
| 727 |
- pids = append(pids, pid) |
|
| 728 |
- } |
|
| 729 |
- return pids, nil |
|
| 730 |
-} |
|
| 731 |
- |
|
| 732 |
-func linkLxcStart(root string) error {
|
|
| 733 |
- sourcePath, err := exec.LookPath("lxc-start")
|
|
| 734 |
- if err != nil {
|
|
| 735 |
- return err |
|
| 736 |
- } |
|
| 737 |
- targetPath := path.Join(root, "lxc-start-unconfined") |
|
| 738 |
- |
|
| 739 |
- if _, err := os.Lstat(targetPath); err != nil && !os.IsNotExist(err) {
|
|
| 740 |
- return err |
|
| 741 |
- } else if err == nil {
|
|
| 742 |
- if err := os.Remove(targetPath); err != nil {
|
|
| 743 |
- return err |
|
| 744 |
- } |
|
| 745 |
- } |
|
| 746 |
- return os.Symlink(sourcePath, targetPath) |
|
| 747 |
-} |
|
| 748 |
- |
|
| 749 |
-// TODO: This can be moved to the mountinfo reader in the mount pkg |
|
| 750 |
-func rootIsShared() bool {
|
|
| 751 |
- if data, err := ioutil.ReadFile("/proc/self/mountinfo"); err == nil {
|
|
| 752 |
- for _, line := range strings.Split(string(data), "\n") {
|
|
| 753 |
- cols := strings.Split(line, " ") |
|
| 754 |
- if len(cols) >= 6 && cols[4] == "/" {
|
|
| 755 |
- return strings.HasPrefix(cols[6], "shared") |
|
| 756 |
- } |
|
| 757 |
- } |
|
| 758 |
- } |
|
| 759 |
- |
|
| 760 |
- // No idea, probably safe to assume so |
|
| 761 |
- return true |
|
| 762 |
-} |
|
| 763 |
- |
|
| 764 |
-func (d *Driver) containerDir(containerID string) string {
|
|
| 765 |
- return path.Join(d.libPath, "containers", containerID) |
|
| 766 |
-} |
|
| 767 |
- |
|
| 768 |
-func (d *Driver) generateLXCConfig(c *execdriver.Command) (string, error) {
|
|
| 769 |
- root := path.Join(d.containerDir(c.ID), "config.lxc") |
|
| 770 |
- |
|
| 771 |
- fo, err := os.Create(root) |
|
| 772 |
- if err != nil {
|
|
| 773 |
- return "", err |
|
| 774 |
- } |
|
| 775 |
- defer fo.Close() |
|
| 776 |
- |
|
| 777 |
- if err := lxcTemplateCompiled.Execute(fo, struct {
|
|
| 778 |
- *execdriver.Command |
|
| 779 |
- AppArmor bool |
|
| 780 |
- }{
|
|
| 781 |
- Command: c, |
|
| 782 |
- AppArmor: d.apparmor, |
|
| 783 |
- }); err != nil {
|
|
| 784 |
- return "", err |
|
| 785 |
- } |
|
| 786 |
- |
|
| 787 |
- return root, nil |
|
| 788 |
-} |
|
| 789 |
- |
|
| 790 |
-func (d *Driver) generateEnvConfig(c *execdriver.Command) error {
|
|
| 791 |
- data, err := json.Marshal(c.ProcessConfig.Env) |
|
| 792 |
- if err != nil {
|
|
| 793 |
- return err |
|
| 794 |
- } |
|
| 795 |
- p := path.Join(d.libPath, "containers", c.ID, "config.env") |
|
| 796 |
- c.Mounts = append(c.Mounts, execdriver.Mount{
|
|
| 797 |
- Source: p, |
|
| 798 |
- Destination: "/.dockerenv", |
|
| 799 |
- Writable: false, |
|
| 800 |
- Private: true, |
|
| 801 |
- }) |
|
| 802 |
- |
|
| 803 |
- return ioutil.WriteFile(p, data, 0600) |
|
| 804 |
-} |
|
| 805 |
- |
|
| 806 |
-// Clean implements the exec driver Driver interface, |
|
| 807 |
-// it's not implemented by lxc. |
|
| 808 |
-func (d *Driver) Clean(id string) error {
|
|
| 809 |
- return nil |
|
| 810 |
-} |
|
| 811 |
- |
|
| 812 |
-// TtyConsole implements the exec driver Terminal interface, |
|
| 813 |
-// it stores the master and slave ends of the container's pty. |
|
| 814 |
-type TtyConsole struct {
|
|
| 815 |
- MasterPty *os.File |
|
| 816 |
- SlavePty *os.File |
|
| 817 |
-} |
|
| 818 |
- |
|
| 819 |
-// NewTtyConsole returns a new TtyConsole struct. |
|
| 820 |
-// Wired up to the provided process config and stdin/stdout/stderr pipes. |
|
| 821 |
-func NewTtyConsole(processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes) (*TtyConsole, error) {
|
|
| 822 |
- // lxc is special in that we cannot create the master outside of the container without |
|
| 823 |
- // opening the slave because we have nothing to provide to the cmd. We have to open both then do |
|
| 824 |
- // the crazy setup on command right now instead of passing the console path to lxc and telling it |
|
| 825 |
- // to open up that console. we save a couple of openfiles in the native driver because we can do |
|
| 826 |
- // this. |
|
| 827 |
- ptyMaster, ptySlave, err := pty.Open() |
|
| 828 |
- if err != nil {
|
|
| 829 |
- return nil, err |
|
| 830 |
- } |
|
| 831 |
- |
|
| 832 |
- tty := &TtyConsole{
|
|
| 833 |
- MasterPty: ptyMaster, |
|
| 834 |
- SlavePty: ptySlave, |
|
| 835 |
- } |
|
| 836 |
- |
|
| 837 |
- if err := tty.AttachPipes(&processConfig.Cmd, pipes); err != nil {
|
|
| 838 |
- tty.Close() |
|
| 839 |
- return nil, err |
|
| 840 |
- } |
|
| 841 |
- |
|
| 842 |
- processConfig.Console = tty.SlavePty.Name() |
|
| 843 |
- |
|
| 844 |
- return tty, nil |
|
| 845 |
-} |
|
| 846 |
- |
|
| 847 |
-// Resize implements Resize method of Terminal interface |
|
| 848 |
-func (t *TtyConsole) Resize(h, w int) error {
|
|
| 849 |
- return term.SetWinsize(t.MasterPty.Fd(), &term.Winsize{Height: uint16(h), Width: uint16(w)})
|
|
| 850 |
-} |
|
| 851 |
- |
|
| 852 |
-// AttachPipes attaches given pipes to exec.Cmd |
|
| 853 |
-func (t *TtyConsole) AttachPipes(command *exec.Cmd, pipes *execdriver.Pipes) error {
|
|
| 854 |
- command.Stdout = t.SlavePty |
|
| 855 |
- command.Stderr = t.SlavePty |
|
| 856 |
- |
|
| 857 |
- go func() {
|
|
| 858 |
- if wb, ok := pipes.Stdout.(interface {
|
|
| 859 |
- CloseWriters() error |
|
| 860 |
- }); ok {
|
|
| 861 |
- defer wb.CloseWriters() |
|
| 862 |
- } |
|
| 863 |
- |
|
| 864 |
- io.Copy(pipes.Stdout, t.MasterPty) |
|
| 865 |
- }() |
|
| 866 |
- |
|
| 867 |
- if pipes.Stdin != nil {
|
|
| 868 |
- command.Stdin = t.SlavePty |
|
| 869 |
- command.SysProcAttr.Setctty = true |
|
| 870 |
- |
|
| 871 |
- go func() {
|
|
| 872 |
- io.Copy(t.MasterPty, pipes.Stdin) |
|
| 873 |
- |
|
| 874 |
- pipes.Stdin.Close() |
|
| 875 |
- }() |
|
| 876 |
- } |
|
| 877 |
- return nil |
|
| 878 |
-} |
|
| 879 |
- |
|
| 880 |
-// Close implements Close method of Terminal interface |
|
| 881 |
-func (t *TtyConsole) Close() error {
|
|
| 882 |
- t.SlavePty.Close() |
|
| 883 |
- return t.MasterPty.Close() |
|
| 884 |
-} |
|
| 885 |
- |
|
| 886 |
-// Exec implements the exec driver Driver interface, |
|
| 887 |
-// it is not implemented by lxc. |
|
| 888 |
-func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
|
|
| 889 |
- return -1, ErrExec |
|
| 890 |
-} |
|
| 891 |
- |
|
| 892 |
-// Stats implements the exec driver Driver interface. |
|
| 893 |
-// Lxc doesn't implement it's own Stats, it does some trick by implementing |
|
| 894 |
-// execdriver.Stats to get stats info by libcontainer APIs. |
|
| 895 |
-func (d *Driver) Stats(id string) (*execdriver.ResourceStats, error) {
|
|
| 896 |
- if _, ok := d.activeContainers[id]; !ok {
|
|
| 897 |
- return nil, fmt.Errorf("%s is not a key in active containers", id)
|
|
| 898 |
- } |
|
| 899 |
- return execdriver.Stats(d.containerDir(id), d.activeContainers[id].container.Cgroups.Memory, d.machineMemory) |
|
| 900 |
-} |
|
| 901 |
- |
|
| 902 |
-// SupportsHooks implements the execdriver Driver interface. |
|
| 903 |
-// The LXC execdriver does not support the hook mechanism, which is currently unique to runC/libcontainer. |
|
| 904 |
-func (d *Driver) SupportsHooks() bool {
|
|
| 905 |
- return false |
|
| 906 |
-} |
| 907 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,53 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "bufio" |
|
| 7 |
- "errors" |
|
| 8 |
- "strconv" |
|
| 9 |
- "strings" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-// Define error messages |
|
| 13 |
-var ( |
|
| 14 |
- ErrCannotParse = errors.New("cannot parse raw input")
|
|
| 15 |
-) |
|
| 16 |
- |
|
| 17 |
-type lxcInfo struct {
|
|
| 18 |
- Running bool |
|
| 19 |
- Pid int |
|
| 20 |
-} |
|
| 21 |
- |
|
| 22 |
-func parseLxcInfo(raw string) (*lxcInfo, error) {
|
|
| 23 |
- if raw == "" {
|
|
| 24 |
- return nil, ErrCannotParse |
|
| 25 |
- } |
|
| 26 |
- var ( |
|
| 27 |
- err error |
|
| 28 |
- s = bufio.NewScanner(strings.NewReader(raw)) |
|
| 29 |
- info = &lxcInfo{}
|
|
| 30 |
- ) |
|
| 31 |
- for s.Scan() {
|
|
| 32 |
- text := s.Text() |
|
| 33 |
- |
|
| 34 |
- if s.Err() != nil {
|
|
| 35 |
- return nil, s.Err() |
|
| 36 |
- } |
|
| 37 |
- |
|
| 38 |
- parts := strings.Split(text, ":") |
|
| 39 |
- if len(parts) < 2 {
|
|
| 40 |
- continue |
|
| 41 |
- } |
|
| 42 |
- switch strings.ToLower(strings.TrimSpace(parts[0])) {
|
|
| 43 |
- case "state": |
|
| 44 |
- info.Running = strings.TrimSpace(parts[1]) == "RUNNING" |
|
| 45 |
- case "pid": |
|
| 46 |
- info.Pid, err = strconv.Atoi(strings.TrimSpace(parts[1])) |
|
| 47 |
- if err != nil {
|
|
| 48 |
- return nil, err |
|
| 49 |
- } |
|
| 50 |
- } |
|
| 51 |
- } |
|
| 52 |
- return info, nil |
|
| 53 |
-} |
| 54 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,38 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "testing" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-func TestParseRunningInfo(t *testing.T) {
|
|
| 10 |
- raw := ` |
|
| 11 |
- state: RUNNING |
|
| 12 |
- pid: 50` |
|
| 13 |
- |
|
| 14 |
- info, err := parseLxcInfo(raw) |
|
| 15 |
- if err != nil {
|
|
| 16 |
- t.Fatal(err) |
|
| 17 |
- } |
|
| 18 |
- if !info.Running {
|
|
| 19 |
- t.Fatal("info should return a running state")
|
|
| 20 |
- } |
|
| 21 |
- if info.Pid != 50 {
|
|
| 22 |
- t.Fatalf("info should have pid 50 got %d", info.Pid)
|
|
| 23 |
- } |
|
| 24 |
-} |
|
| 25 |
- |
|
| 26 |
-func TestEmptyInfo(t *testing.T) {
|
|
| 27 |
- _, err := parseLxcInfo("")
|
|
| 28 |
- if err == nil {
|
|
| 29 |
- t.Fatal("error should not be nil")
|
|
| 30 |
- } |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-func TestBadInfo(t *testing.T) {
|
|
| 34 |
- _, err := parseLxcInfo("state")
|
|
| 35 |
- if err != nil {
|
|
| 36 |
- t.Fatal(err) |
|
| 37 |
- } |
|
| 38 |
-} |
| 39 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,145 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "encoding/json" |
|
| 7 |
- "flag" |
|
| 8 |
- "fmt" |
|
| 9 |
- "os" |
|
| 10 |
- "os/exec" |
|
| 11 |
- "runtime" |
|
| 12 |
- "strings" |
|
| 13 |
- "syscall" |
|
| 14 |
- |
|
| 15 |
- "github.com/Sirupsen/logrus" |
|
| 16 |
- "github.com/docker/docker/pkg/reexec" |
|
| 17 |
-) |
|
| 18 |
- |
|
| 19 |
-// InitArgs contains args provided to the init function for a driver |
|
| 20 |
-type InitArgs struct {
|
|
| 21 |
- User string |
|
| 22 |
- Gateway string |
|
| 23 |
- IP string |
|
| 24 |
- WorkDir string |
|
| 25 |
- Privileged bool |
|
| 26 |
- Env []string |
|
| 27 |
- Args []string |
|
| 28 |
- Mtu int |
|
| 29 |
- Console string |
|
| 30 |
- Pipe int |
|
| 31 |
- Root string |
|
| 32 |
- CapAdd string |
|
| 33 |
- CapDrop string |
|
| 34 |
-} |
|
| 35 |
- |
|
| 36 |
-func init() {
|
|
| 37 |
- // like always lxc requires a hack to get this to work |
|
| 38 |
- reexec.Register("/.dockerinit", dockerInititalizer)
|
|
| 39 |
-} |
|
| 40 |
- |
|
| 41 |
-func dockerInititalizer() {
|
|
| 42 |
- initializer() |
|
| 43 |
-} |
|
| 44 |
- |
|
| 45 |
-// initializer is the lxc driver's init function that is run inside the namespace to setup |
|
| 46 |
-// additional configurations |
|
| 47 |
-func initializer() {
|
|
| 48 |
- runtime.LockOSThread() |
|
| 49 |
- |
|
| 50 |
- args := getArgs() |
|
| 51 |
- |
|
| 52 |
- if err := setupNamespace(args); err != nil {
|
|
| 53 |
- logrus.Fatal(err) |
|
| 54 |
- } |
|
| 55 |
-} |
|
| 56 |
- |
|
| 57 |
-func setupNamespace(args *InitArgs) error {
|
|
| 58 |
- if err := setupEnv(args); err != nil {
|
|
| 59 |
- return err |
|
| 60 |
- } |
|
| 61 |
- |
|
| 62 |
- if err := finalizeNamespace(args); err != nil {
|
|
| 63 |
- return err |
|
| 64 |
- } |
|
| 65 |
- |
|
| 66 |
- path, err := exec.LookPath(args.Args[0]) |
|
| 67 |
- if err != nil {
|
|
| 68 |
- logrus.Infof("Unable to locate %v", args.Args[0])
|
|
| 69 |
- os.Exit(127) |
|
| 70 |
- } |
|
| 71 |
- |
|
| 72 |
- if err := syscall.Exec(path, args.Args, os.Environ()); err != nil {
|
|
| 73 |
- return fmt.Errorf("dockerinit unable to execute %s - %s", path, err)
|
|
| 74 |
- } |
|
| 75 |
- |
|
| 76 |
- return nil |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 |
-func getArgs() *InitArgs {
|
|
| 80 |
- var ( |
|
| 81 |
- // Get cmdline arguments |
|
| 82 |
- user = flag.String("u", "", "username or uid")
|
|
| 83 |
- gateway = flag.String("g", "", "gateway address")
|
|
| 84 |
- ip = flag.String("i", "", "ip address")
|
|
| 85 |
- workDir = flag.String("w", "", "workdir")
|
|
| 86 |
- privileged = flag.Bool("privileged", false, "privileged mode")
|
|
| 87 |
- mtu = flag.Int("mtu", 1500, "interface mtu")
|
|
| 88 |
- capAdd = flag.String("cap-add", "", "capabilities to add")
|
|
| 89 |
- capDrop = flag.String("cap-drop", "", "capabilities to drop")
|
|
| 90 |
- ) |
|
| 91 |
- |
|
| 92 |
- flag.Parse() |
|
| 93 |
- |
|
| 94 |
- return &InitArgs{
|
|
| 95 |
- User: *user, |
|
| 96 |
- Gateway: *gateway, |
|
| 97 |
- IP: *ip, |
|
| 98 |
- WorkDir: *workDir, |
|
| 99 |
- Privileged: *privileged, |
|
| 100 |
- Args: flag.Args(), |
|
| 101 |
- Mtu: *mtu, |
|
| 102 |
- CapAdd: *capAdd, |
|
| 103 |
- CapDrop: *capDrop, |
|
| 104 |
- } |
|
| 105 |
-} |
|
| 106 |
- |
|
| 107 |
-// Clear environment pollution introduced by lxc-start |
|
| 108 |
-func setupEnv(args *InitArgs) error {
|
|
| 109 |
- // Get env |
|
| 110 |
- var env []string |
|
| 111 |
- dockerenv, err := os.Open(".dockerenv")
|
|
| 112 |
- if err != nil {
|
|
| 113 |
- return fmt.Errorf("Unable to load environment variables: %v", err)
|
|
| 114 |
- } |
|
| 115 |
- defer dockerenv.Close() |
|
| 116 |
- if err := json.NewDecoder(dockerenv).Decode(&env); err != nil {
|
|
| 117 |
- return fmt.Errorf("Unable to decode environment variables: %v", err)
|
|
| 118 |
- } |
|
| 119 |
- // Propagate the plugin-specific container env variable |
|
| 120 |
- env = append(env, "container="+os.Getenv("container"))
|
|
| 121 |
- |
|
| 122 |
- args.Env = env |
|
| 123 |
- |
|
| 124 |
- os.Clearenv() |
|
| 125 |
- for _, kv := range args.Env {
|
|
| 126 |
- parts := strings.SplitN(kv, "=", 2) |
|
| 127 |
- if len(parts) == 1 {
|
|
| 128 |
- parts = append(parts, "") |
|
| 129 |
- } |
|
| 130 |
- os.Setenv(parts[0], parts[1]) |
|
| 131 |
- } |
|
| 132 |
- |
|
| 133 |
- return nil |
|
| 134 |
-} |
|
| 135 |
- |
|
| 136 |
-// Setup working directory |
|
| 137 |
-func setupWorkingDirectory(args *InitArgs) error {
|
|
| 138 |
- if args.WorkDir == "" {
|
|
| 139 |
- return nil |
|
| 140 |
- } |
|
| 141 |
- if err := syscall.Chdir(args.WorkDir); err != nil {
|
|
| 142 |
- return fmt.Errorf("Unable to change dir to %v: %v", args.WorkDir, err)
|
|
| 143 |
- } |
|
| 144 |
- return nil |
|
| 145 |
-} |
| 146 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,22 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- |
|
| 8 |
- "github.com/opencontainers/runc/libcontainer/utils" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-func finalizeNamespace(args *InitArgs) error {
|
|
| 12 |
- if err := utils.CloseExecFrom(3); err != nil {
|
|
| 13 |
- return err |
|
| 14 |
- } |
|
| 15 |
- if err := setupUser(args.User); err != nil {
|
|
| 16 |
- return fmt.Errorf("setup user %s", err)
|
|
| 17 |
- } |
|
| 18 |
- if err := setupWorkingDirectory(args); err != nil {
|
|
| 19 |
- return err |
|
| 20 |
- } |
|
| 21 |
- return nil |
|
| 22 |
-} |
| 23 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,11 +0,0 @@ |
| 1 |
-// +build !linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-// InitArgs contains args provided to the init function for a driver |
|
| 6 |
-type InitArgs struct {
|
|
| 7 |
-} |
|
| 8 |
- |
|
| 9 |
-func finalizeNamespace(args *InitArgs) error {
|
|
| 10 |
- panic("Not supported on this platform")
|
|
| 11 |
-} |
| 12 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,247 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "fmt" |
|
| 7 |
- "os" |
|
| 8 |
- "strings" |
|
| 9 |
- "text/template" |
|
| 10 |
- |
|
| 11 |
- "github.com/Sirupsen/logrus" |
|
| 12 |
- "github.com/docker/docker/daemon/execdriver" |
|
| 13 |
- nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" |
|
| 14 |
- "github.com/docker/docker/pkg/stringutils" |
|
| 15 |
- "github.com/opencontainers/runc/libcontainer/label" |
|
| 16 |
-) |
|
| 17 |
- |
|
| 18 |
-// LxcTemplate is the template for lxc driver, it's used |
|
| 19 |
-// to configure LXC. |
|
| 20 |
-const LxcTemplate = ` |
|
| 21 |
-lxc.network.type = none |
|
| 22 |
-# root filesystem |
|
| 23 |
-{{$ROOTFS := .Rootfs}}
|
|
| 24 |
-lxc.rootfs = {{$ROOTFS}}
|
|
| 25 |
- |
|
| 26 |
-# use a dedicated pts for the container (and limit the number of pseudo terminal |
|
| 27 |
-# available) |
|
| 28 |
-lxc.pts = 1024 |
|
| 29 |
- |
|
| 30 |
-# disable the main console |
|
| 31 |
-lxc.console = none |
|
| 32 |
- |
|
| 33 |
-# no controlling tty at all |
|
| 34 |
-lxc.tty = 1 |
|
| 35 |
- |
|
| 36 |
-{{if .ProcessConfig.Privileged}}
|
|
| 37 |
-lxc.cgroup.devices.allow = a |
|
| 38 |
-{{else}}
|
|
| 39 |
-# no implicit access to devices |
|
| 40 |
-lxc.cgroup.devices.deny = a |
|
| 41 |
-#Allow the devices passed to us in the AllowedDevices list. |
|
| 42 |
-{{range $allowedDevice := .AllowedDevices}}
|
|
| 43 |
-lxc.cgroup.devices.allow = {{$allowedDevice.CgroupString}}
|
|
| 44 |
-{{end}}
|
|
| 45 |
-{{end}}
|
|
| 46 |
- |
|
| 47 |
-# standard mount point |
|
| 48 |
-# Use mnt.putold as per https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/986385 |
|
| 49 |
-lxc.pivotdir = lxc_putold |
|
| 50 |
- |
|
| 51 |
-# lxc.autodev is not compatible with lxc --device switch |
|
| 52 |
-lxc.autodev = 0 |
|
| 53 |
- |
|
| 54 |
-# NOTICE: These mounts must be applied within the namespace |
|
| 55 |
-{{if .ProcessConfig.Privileged}}
|
|
| 56 |
-# WARNING: mounting procfs and/or sysfs read-write is a known attack vector. |
|
| 57 |
-# See e.g. http://blog.zx2c4.com/749 and https://bit.ly/T9CkqJ |
|
| 58 |
-# We mount them read-write here, but later, dockerinit will call the Restrict() function to remount them read-only. |
|
| 59 |
-# We cannot mount them directly read-only, because that would prevent loading AppArmor profiles. |
|
| 60 |
-lxc.mount.entry = proc {{escapeFstabSpaces $ROOTFS}}/proc proc nosuid,nodev,noexec 0 0
|
|
| 61 |
-lxc.mount.entry = sysfs {{escapeFstabSpaces $ROOTFS}}/sys sysfs nosuid,nodev,noexec 0 0
|
|
| 62 |
- {{if .AppArmor}}
|
|
| 63 |
-lxc.aa_profile = unconfined |
|
| 64 |
- {{end}}
|
|
| 65 |
-{{else}}
|
|
| 66 |
-# In non-privileged mode, lxc will automatically mount /proc and /sys in readonly mode |
|
| 67 |
-# for security. See: http://man7.org/linux/man-pages/man5/lxc.container.conf.5.html |
|
| 68 |
-lxc.mount.auto = proc sys |
|
| 69 |
- {{if .AppArmorProfile}}
|
|
| 70 |
-lxc.aa_profile = {{.AppArmorProfile}}
|
|
| 71 |
- {{end}}
|
|
| 72 |
-{{end}}
|
|
| 73 |
- |
|
| 74 |
-{{if .ProcessConfig.Tty}}
|
|
| 75 |
-lxc.mount.entry = {{.ProcessConfig.Console}} {{escapeFstabSpaces $ROOTFS}}/dev/console none bind,rw,create=file 0 0
|
|
| 76 |
-{{end}}
|
|
| 77 |
- |
|
| 78 |
-lxc.mount.entry = devpts {{escapeFstabSpaces $ROOTFS}}/dev/pts devpts {{formatMountLabel "newinstance,ptmxmode=0666,nosuid,noexec,create=dir" ""}} 0 0
|
|
| 79 |
-lxc.mount.entry = shm {{escapeFstabSpaces $ROOTFS}}/dev/shm tmpfs {{formatMountLabel "size=65536k,nosuid,nodev,noexec,create=dir" ""}} 0 0
|
|
| 80 |
- |
|
| 81 |
-{{range $value := .Mounts}}
|
|
| 82 |
-{{$createVal := isDirectory $value.Source}}
|
|
| 83 |
-{{if $value.Writable}}
|
|
| 84 |
-lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,rw,create={{$createVal}} 0 0
|
|
| 85 |
-{{else}}
|
|
| 86 |
-lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabSpaces $value.Destination}} none rbind,ro,create={{$createVal}} 0 0
|
|
| 87 |
-{{end}}
|
|
| 88 |
-{{end}}
|
|
| 89 |
- |
|
| 90 |
-# limits |
|
| 91 |
-{{if .Resources}}
|
|
| 92 |
-{{if .Resources.Memory}}
|
|
| 93 |
-lxc.cgroup.memory.limit_in_bytes = {{.Resources.Memory}}
|
|
| 94 |
-{{end}}
|
|
| 95 |
-{{if gt .Resources.MemorySwap 0}}
|
|
| 96 |
-lxc.cgroup.memory.memsw.limit_in_bytes = {{.Resources.MemorySwap}}
|
|
| 97 |
-{{end}}
|
|
| 98 |
-{{if gt .Resources.MemoryReservation 0}}
|
|
| 99 |
-lxc.cgroup.memory.soft_limit_in_bytes = {{.Resources.MemoryReservation}}
|
|
| 100 |
-{{end}}
|
|
| 101 |
-{{if gt .Resources.KernelMemory 0}}
|
|
| 102 |
-lxc.cgroup.memory.kmem.limit_in_bytes = {{.Resources.KernelMemory}}
|
|
| 103 |
-{{end}}
|
|
| 104 |
-{{if .Resources.CPUShares}}
|
|
| 105 |
-lxc.cgroup.cpu.shares = {{.Resources.CPUShares}}
|
|
| 106 |
-{{end}}
|
|
| 107 |
-{{if .Resources.CPUPeriod}}
|
|
| 108 |
-lxc.cgroup.cpu.cfs_period_us = {{.Resources.CPUPeriod}}
|
|
| 109 |
-{{end}}
|
|
| 110 |
-{{if .Resources.CpusetCpus}}
|
|
| 111 |
-lxc.cgroup.cpuset.cpus = {{.Resources.CpusetCpus}}
|
|
| 112 |
-{{end}}
|
|
| 113 |
-{{if .Resources.CpusetMems}}
|
|
| 114 |
-lxc.cgroup.cpuset.mems = {{.Resources.CpusetMems}}
|
|
| 115 |
-{{end}}
|
|
| 116 |
-{{if .Resources.CPUQuota}}
|
|
| 117 |
-lxc.cgroup.cpu.cfs_quota_us = {{.Resources.CPUQuota}}
|
|
| 118 |
-{{end}}
|
|
| 119 |
-{{if .Resources.BlkioWeight}}
|
|
| 120 |
-lxc.cgroup.blkio.weight = {{.Resources.BlkioWeight}}
|
|
| 121 |
-{{end}}
|
|
| 122 |
-{{if .Resources.OomKillDisable}}
|
|
| 123 |
-lxc.cgroup.memory.oom_control = {{.Resources.OomKillDisable}}
|
|
| 124 |
-{{end}}
|
|
| 125 |
-{{if gt .Resources.MemorySwappiness 0}}
|
|
| 126 |
-lxc.cgroup.memory.swappiness = {{.Resources.MemorySwappiness}}
|
|
| 127 |
-{{end}}
|
|
| 128 |
-{{end}}
|
|
| 129 |
- |
|
| 130 |
-{{if .LxcConfig}}
|
|
| 131 |
-{{range $value := .LxcConfig}}
|
|
| 132 |
-lxc.{{$value}}
|
|
| 133 |
-{{end}}
|
|
| 134 |
-{{end}}
|
|
| 135 |
- |
|
| 136 |
-{{if .ProcessConfig.Env}}
|
|
| 137 |
-lxc.utsname = {{getHostname .ProcessConfig.Env}}
|
|
| 138 |
-{{end}}
|
|
| 139 |
- |
|
| 140 |
-{{if .ProcessConfig.Privileged}}
|
|
| 141 |
-# No cap values are needed, as lxc is starting in privileged mode |
|
| 142 |
-{{else}}
|
|
| 143 |
- {{ with keepCapabilities .CapAdd .CapDrop }}
|
|
| 144 |
- {{range .}}
|
|
| 145 |
-lxc.cap.keep = {{.}}
|
|
| 146 |
- {{end}}
|
|
| 147 |
- {{else}}
|
|
| 148 |
- {{ with dropList .CapDrop }}
|
|
| 149 |
- {{range .}}
|
|
| 150 |
-lxc.cap.drop = {{.}}
|
|
| 151 |
- {{end}}
|
|
| 152 |
- {{end}}
|
|
| 153 |
- {{end}}
|
|
| 154 |
-{{end}}
|
|
| 155 |
-` |
|
| 156 |
- |
|
| 157 |
-var lxcTemplateCompiled *template.Template |
|
| 158 |
- |
|
| 159 |
-// Escape spaces in strings according to the fstab documentation, which is the |
|
| 160 |
-// format for "lxc.mount.entry" lines in lxc.conf. See also "man 5 fstab". |
|
| 161 |
-func escapeFstabSpaces(field string) string {
|
|
| 162 |
- return strings.Replace(field, " ", "\\040", -1) |
|
| 163 |
-} |
|
| 164 |
- |
|
| 165 |
-func keepCapabilities(adds []string, drops []string) ([]string, error) {
|
|
| 166 |
- container := nativeTemplate.New() |
|
| 167 |
- logrus.Debugf("adds %s drops %s\n", adds, drops)
|
|
| 168 |
- caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) |
|
| 169 |
- if err != nil {
|
|
| 170 |
- return nil, err |
|
| 171 |
- } |
|
| 172 |
- var newCaps []string |
|
| 173 |
- for _, cap := range caps {
|
|
| 174 |
- logrus.Debugf("cap %s\n", cap)
|
|
| 175 |
- realCap := execdriver.GetCapability(cap) |
|
| 176 |
- numCap := fmt.Sprintf("%d", realCap.Value)
|
|
| 177 |
- newCaps = append(newCaps, numCap) |
|
| 178 |
- } |
|
| 179 |
- |
|
| 180 |
- return newCaps, nil |
|
| 181 |
-} |
|
| 182 |
- |
|
| 183 |
-func dropList(drops []string) ([]string, error) {
|
|
| 184 |
- if stringutils.InSlice(drops, "all") {
|
|
| 185 |
- var newCaps []string |
|
| 186 |
- for _, capName := range execdriver.GetAllCapabilities() {
|
|
| 187 |
- cap := execdriver.GetCapability(capName) |
|
| 188 |
- logrus.Debugf("drop cap %s\n", cap.Key)
|
|
| 189 |
- numCap := fmt.Sprintf("%d", cap.Value)
|
|
| 190 |
- newCaps = append(newCaps, numCap) |
|
| 191 |
- } |
|
| 192 |
- return newCaps, nil |
|
| 193 |
- } |
|
| 194 |
- return []string{}, nil
|
|
| 195 |
-} |
|
| 196 |
- |
|
| 197 |
-func isDirectory(source string) string {
|
|
| 198 |
- f, err := os.Stat(source) |
|
| 199 |
- logrus.Debugf("dir: %s\n", source)
|
|
| 200 |
- if err != nil {
|
|
| 201 |
- if os.IsNotExist(err) {
|
|
| 202 |
- return "dir" |
|
| 203 |
- } |
|
| 204 |
- return "" |
|
| 205 |
- } |
|
| 206 |
- if f.IsDir() {
|
|
| 207 |
- return "dir" |
|
| 208 |
- } |
|
| 209 |
- return "file" |
|
| 210 |
-} |
|
| 211 |
- |
|
| 212 |
-func getLabel(c map[string][]string, name string) string {
|
|
| 213 |
- label := c["label"] |
|
| 214 |
- for _, l := range label {
|
|
| 215 |
- parts := strings.SplitN(l, "=", 2) |
|
| 216 |
- if strings.TrimSpace(parts[0]) == name {
|
|
| 217 |
- return strings.TrimSpace(parts[1]) |
|
| 218 |
- } |
|
| 219 |
- } |
|
| 220 |
- return "" |
|
| 221 |
-} |
|
| 222 |
- |
|
| 223 |
-func getHostname(env []string) string {
|
|
| 224 |
- for _, kv := range env {
|
|
| 225 |
- parts := strings.SplitN(kv, "=", 2) |
|
| 226 |
- if parts[0] == "HOSTNAME" && len(parts) == 2 {
|
|
| 227 |
- return parts[1] |
|
| 228 |
- } |
|
| 229 |
- } |
|
| 230 |
- return "" |
|
| 231 |
-} |
|
| 232 |
- |
|
| 233 |
-func init() {
|
|
| 234 |
- var err error |
|
| 235 |
- funcMap := template.FuncMap{
|
|
| 236 |
- "escapeFstabSpaces": escapeFstabSpaces, |
|
| 237 |
- "formatMountLabel": label.FormatMountLabel, |
|
| 238 |
- "isDirectory": isDirectory, |
|
| 239 |
- "keepCapabilities": keepCapabilities, |
|
| 240 |
- "dropList": dropList, |
|
| 241 |
- "getHostname": getHostname, |
|
| 242 |
- } |
|
| 243 |
- lxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
|
| 244 |
- if err != nil {
|
|
| 245 |
- panic(err) |
|
| 246 |
- } |
|
| 247 |
-} |
| 248 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,355 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package lxc |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "bufio" |
|
| 7 |
- "fmt" |
|
| 8 |
- "io/ioutil" |
|
| 9 |
- "math/rand" |
|
| 10 |
- "os" |
|
| 11 |
- "path" |
|
| 12 |
- "strings" |
|
| 13 |
- "testing" |
|
| 14 |
- "time" |
|
| 15 |
- |
|
| 16 |
- "github.com/docker/docker/daemon/execdriver" |
|
| 17 |
- nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template" |
|
| 18 |
- "github.com/opencontainers/runc/libcontainer/configs" |
|
| 19 |
- "github.com/syndtr/gocapability/capability" |
|
| 20 |
-) |
|
| 21 |
- |
|
| 22 |
-func TestLXCConfig(t *testing.T) {
|
|
| 23 |
- root, err := ioutil.TempDir("", "TestLXCConfig")
|
|
| 24 |
- if err != nil {
|
|
| 25 |
- t.Fatal(err) |
|
| 26 |
- } |
|
| 27 |
- defer os.RemoveAll(root) |
|
| 28 |
- |
|
| 29 |
- os.MkdirAll(path.Join(root, "containers", "1"), 0777) |
|
| 30 |
- |
|
| 31 |
- // Memory is allocated randomly for testing |
|
| 32 |
- r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) |
|
| 33 |
- var ( |
|
| 34 |
- memMin = 33554432 |
|
| 35 |
- memMax = 536870912 |
|
| 36 |
- mem = memMin + r.Intn(memMax-memMin) |
|
| 37 |
- swap = memMax |
|
| 38 |
- cpuMin = 100 |
|
| 39 |
- cpuMax = 10000 |
|
| 40 |
- cpu = cpuMin + r.Intn(cpuMax-cpuMin) |
|
| 41 |
- ) |
|
| 42 |
- |
|
| 43 |
- driver, err := NewDriver(root, root, "", false) |
|
| 44 |
- if err != nil {
|
|
| 45 |
- t.Fatal(err) |
|
| 46 |
- } |
|
| 47 |
- command := &execdriver.Command{
|
|
| 48 |
- CommonCommand: execdriver.CommonCommand{
|
|
| 49 |
- ID: "1", |
|
| 50 |
- Network: &execdriver.Network{
|
|
| 51 |
- Mtu: 1500, |
|
| 52 |
- }, |
|
| 53 |
- ProcessConfig: execdriver.ProcessConfig{},
|
|
| 54 |
- Resources: &execdriver.Resources{
|
|
| 55 |
- MemorySwap: int64(swap), |
|
| 56 |
- CommonResources: execdriver.CommonResources{
|
|
| 57 |
- Memory: int64(mem), |
|
| 58 |
- CPUShares: int64(cpu), |
|
| 59 |
- }, |
|
| 60 |
- }, |
|
| 61 |
- }, |
|
| 62 |
- AllowedDevices: make([]*configs.Device, 0), |
|
| 63 |
- } |
|
| 64 |
- p, err := driver.generateLXCConfig(command) |
|
| 65 |
- if err != nil {
|
|
| 66 |
- t.Fatal(err) |
|
| 67 |
- } |
|
| 68 |
- grepFile(t, p, |
|
| 69 |
- fmt.Sprintf("lxc.cgroup.memory.limit_in_bytes = %d", mem))
|
|
| 70 |
- |
|
| 71 |
- grepFile(t, p, |
|
| 72 |
- fmt.Sprintf("lxc.cgroup.memory.memsw.limit_in_bytes = %d", swap))
|
|
| 73 |
-} |
|
| 74 |
- |
|
| 75 |
-func TestCustomLxcConfig(t *testing.T) {
|
|
| 76 |
- root, err := ioutil.TempDir("", "TestCustomLxcConfig")
|
|
| 77 |
- if err != nil {
|
|
| 78 |
- t.Fatal(err) |
|
| 79 |
- } |
|
| 80 |
- defer os.RemoveAll(root) |
|
| 81 |
- |
|
| 82 |
- os.MkdirAll(path.Join(root, "containers", "1"), 0777) |
|
| 83 |
- |
|
| 84 |
- driver, err := NewDriver(root, root, "", false) |
|
| 85 |
- if err != nil {
|
|
| 86 |
- t.Fatal(err) |
|
| 87 |
- } |
|
| 88 |
- processConfig := execdriver.ProcessConfig{
|
|
| 89 |
- Privileged: false, |
|
| 90 |
- } |
|
| 91 |
- command := &execdriver.Command{
|
|
| 92 |
- CommonCommand: execdriver.CommonCommand{
|
|
| 93 |
- ID: "1", |
|
| 94 |
- Network: &execdriver.Network{
|
|
| 95 |
- Mtu: 1500, |
|
| 96 |
- }, |
|
| 97 |
- ProcessConfig: processConfig, |
|
| 98 |
- }, |
|
| 99 |
- LxcConfig: []string{
|
|
| 100 |
- "lxc.utsname = docker", |
|
| 101 |
- "lxc.cgroup.cpuset.cpus = 0,1", |
|
| 102 |
- }, |
|
| 103 |
- } |
|
| 104 |
- |
|
| 105 |
- p, err := driver.generateLXCConfig(command) |
|
| 106 |
- if err != nil {
|
|
| 107 |
- t.Fatal(err) |
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- grepFile(t, p, "lxc.utsname = docker") |
|
| 111 |
- grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") |
|
| 112 |
-} |
|
| 113 |
- |
|
| 114 |
-func grepFile(t *testing.T, path string, pattern string) {
|
|
| 115 |
- grepFileWithReverse(t, path, pattern, false) |
|
| 116 |
-} |
|
| 117 |
- |
|
| 118 |
-func grepFileWithReverse(t *testing.T, path string, pattern string, inverseGrep bool) {
|
|
| 119 |
- f, err := os.Open(path) |
|
| 120 |
- if err != nil {
|
|
| 121 |
- t.Fatal(err) |
|
| 122 |
- } |
|
| 123 |
- defer f.Close() |
|
| 124 |
- r := bufio.NewReader(f) |
|
| 125 |
- var ( |
|
| 126 |
- line string |
|
| 127 |
- ) |
|
| 128 |
- err = nil |
|
| 129 |
- for err == nil {
|
|
| 130 |
- line, err = r.ReadString('\n')
|
|
| 131 |
- if strings.Contains(line, pattern) == true {
|
|
| 132 |
- if inverseGrep {
|
|
| 133 |
- t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path)
|
|
| 134 |
- } |
|
| 135 |
- return |
|
| 136 |
- } |
|
| 137 |
- } |
|
| 138 |
- if inverseGrep {
|
|
| 139 |
- return |
|
| 140 |
- } |
|
| 141 |
- t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
|
|
| 142 |
-} |
|
| 143 |
- |
|
| 144 |
-func TestEscapeFstabSpaces(t *testing.T) {
|
|
| 145 |
- var testInputs = map[string]string{
|
|
| 146 |
- " ": "\\040", |
|
| 147 |
- "": "", |
|
| 148 |
- "/double space": "/double\\040\\040space", |
|
| 149 |
- "/some long test string": "/some\\040long\\040test\\040string", |
|
| 150 |
- "/var/lib/docker": "/var/lib/docker", |
|
| 151 |
- " leading": "\\040leading", |
|
| 152 |
- "trailing ": "trailing\\040", |
|
| 153 |
- } |
|
| 154 |
- for in, exp := range testInputs {
|
|
| 155 |
- if out := escapeFstabSpaces(in); exp != out {
|
|
| 156 |
- t.Logf("Expected %s got %s", exp, out)
|
|
| 157 |
- t.Fail() |
|
| 158 |
- } |
|
| 159 |
- } |
|
| 160 |
-} |
|
| 161 |
- |
|
| 162 |
-func TestIsDirectory(t *testing.T) {
|
|
| 163 |
- tempDir, err := ioutil.TempDir("", "TestIsDir")
|
|
| 164 |
- if err != nil {
|
|
| 165 |
- t.Fatal(err) |
|
| 166 |
- } |
|
| 167 |
- defer os.RemoveAll(tempDir) |
|
| 168 |
- |
|
| 169 |
- tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") |
|
| 170 |
- if err != nil {
|
|
| 171 |
- t.Fatal(err) |
|
| 172 |
- } |
|
| 173 |
- |
|
| 174 |
- if isDirectory(tempDir) != "dir" {
|
|
| 175 |
- t.Logf("Could not identify %s as a directory", tempDir)
|
|
| 176 |
- t.Fail() |
|
| 177 |
- } |
|
| 178 |
- |
|
| 179 |
- if isDirectory(tempFile.Name()) != "file" {
|
|
| 180 |
- t.Logf("Could not identify %s as a file", tempFile.Name())
|
|
| 181 |
- t.Fail() |
|
| 182 |
- } |
|
| 183 |
-} |
|
| 184 |
- |
|
| 185 |
-func TestCustomLxcConfigMounts(t *testing.T) {
|
|
| 186 |
- root, err := ioutil.TempDir("", "TestCustomLxcConfig")
|
|
| 187 |
- if err != nil {
|
|
| 188 |
- t.Fatal(err) |
|
| 189 |
- } |
|
| 190 |
- defer os.RemoveAll(root) |
|
| 191 |
- tempDir, err := ioutil.TempDir("", "TestIsDir")
|
|
| 192 |
- if err != nil {
|
|
| 193 |
- t.Fatal(err) |
|
| 194 |
- } |
|
| 195 |
- defer os.RemoveAll(tempDir) |
|
| 196 |
- |
|
| 197 |
- tempFile, err := ioutil.TempFile(tempDir, "TestIsDirFile") |
|
| 198 |
- if err != nil {
|
|
| 199 |
- t.Fatal(err) |
|
| 200 |
- } |
|
| 201 |
- os.MkdirAll(path.Join(root, "containers", "1"), 0777) |
|
| 202 |
- |
|
| 203 |
- driver, err := NewDriver(root, root, "", false) |
|
| 204 |
- if err != nil {
|
|
| 205 |
- t.Fatal(err) |
|
| 206 |
- } |
|
| 207 |
- processConfig := execdriver.ProcessConfig{
|
|
| 208 |
- Privileged: false, |
|
| 209 |
- } |
|
| 210 |
- mounts := []execdriver.Mount{
|
|
| 211 |
- {
|
|
| 212 |
- Source: tempDir, |
|
| 213 |
- Destination: tempDir, |
|
| 214 |
- Writable: false, |
|
| 215 |
- Private: true, |
|
| 216 |
- }, |
|
| 217 |
- {
|
|
| 218 |
- Source: tempFile.Name(), |
|
| 219 |
- Destination: tempFile.Name(), |
|
| 220 |
- Writable: true, |
|
| 221 |
- Private: true, |
|
| 222 |
- }, |
|
| 223 |
- } |
|
| 224 |
- command := &execdriver.Command{
|
|
| 225 |
- CommonCommand: execdriver.CommonCommand{
|
|
| 226 |
- ID: "1", |
|
| 227 |
- Network: &execdriver.Network{
|
|
| 228 |
- Mtu: 1500, |
|
| 229 |
- }, |
|
| 230 |
- Mounts: mounts, |
|
| 231 |
- ProcessConfig: processConfig, |
|
| 232 |
- }, |
|
| 233 |
- LxcConfig: []string{
|
|
| 234 |
- "lxc.utsname = docker", |
|
| 235 |
- "lxc.cgroup.cpuset.cpus = 0,1", |
|
| 236 |
- }, |
|
| 237 |
- } |
|
| 238 |
- |
|
| 239 |
- p, err := driver.generateLXCConfig(command) |
|
| 240 |
- if err != nil {
|
|
| 241 |
- t.Fatal(err) |
|
| 242 |
- } |
|
| 243 |
- |
|
| 244 |
- grepFile(t, p, "lxc.utsname = docker") |
|
| 245 |
- grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") |
|
| 246 |
- |
|
| 247 |
- grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir"))
|
|
| 248 |
- grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file"))
|
|
| 249 |
-} |
|
| 250 |
- |
|
| 251 |
-func TestCustomLxcConfigMisc(t *testing.T) {
|
|
| 252 |
- root, err := ioutil.TempDir("", "TestCustomLxcConfig")
|
|
| 253 |
- if err != nil {
|
|
| 254 |
- t.Fatal(err) |
|
| 255 |
- } |
|
| 256 |
- defer os.RemoveAll(root) |
|
| 257 |
- os.MkdirAll(path.Join(root, "containers", "1"), 0777) |
|
| 258 |
- driver, err := NewDriver(root, root, "", true) |
|
| 259 |
- |
|
| 260 |
- if err != nil {
|
|
| 261 |
- t.Fatal(err) |
|
| 262 |
- } |
|
| 263 |
- processConfig := execdriver.ProcessConfig{
|
|
| 264 |
- Privileged: false, |
|
| 265 |
- } |
|
| 266 |
- |
|
| 267 |
- processConfig.Env = []string{"HOSTNAME=testhost"}
|
|
| 268 |
- command := &execdriver.Command{
|
|
| 269 |
- CommonCommand: execdriver.CommonCommand{
|
|
| 270 |
- ID: "1", |
|
| 271 |
- Network: &execdriver.Network{
|
|
| 272 |
- Mtu: 1500, |
|
| 273 |
- }, |
|
| 274 |
- ProcessConfig: processConfig, |
|
| 275 |
- }, |
|
| 276 |
- LxcConfig: []string{
|
|
| 277 |
- "lxc.cgroup.cpuset.cpus = 0,1", |
|
| 278 |
- }, |
|
| 279 |
- CapAdd: []string{"net_admin", "syslog"},
|
|
| 280 |
- CapDrop: []string{"kill", "mknod"},
|
|
| 281 |
- AppArmorProfile: "lxc-container-default-with-nesting", |
|
| 282 |
- } |
|
| 283 |
- |
|
| 284 |
- p, err := driver.generateLXCConfig(command) |
|
| 285 |
- if err != nil {
|
|
| 286 |
- t.Fatal(err) |
|
| 287 |
- } |
|
| 288 |
- grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting") |
|
| 289 |
- // hostname |
|
| 290 |
- grepFile(t, p, "lxc.utsname = testhost") |
|
| 291 |
- grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") |
|
| 292 |
- container := nativeTemplate.New() |
|
| 293 |
- for _, cap := range container.Capabilities {
|
|
| 294 |
- realCap := execdriver.GetCapability(cap) |
|
| 295 |
- numCap := fmt.Sprintf("%d", realCap.Value)
|
|
| 296 |
- if cap != "MKNOD" && cap != "KILL" {
|
|
| 297 |
- grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
|
|
| 298 |
- } |
|
| 299 |
- } |
|
| 300 |
- |
|
| 301 |
- grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
|
|
| 302 |
- grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
|
|
| 303 |
-} |
|
| 304 |
- |
|
| 305 |
-func TestCustomLxcConfigMiscOverride(t *testing.T) {
|
|
| 306 |
- root, err := ioutil.TempDir("", "TestCustomLxcConfig")
|
|
| 307 |
- if err != nil {
|
|
| 308 |
- t.Fatal(err) |
|
| 309 |
- } |
|
| 310 |
- defer os.RemoveAll(root) |
|
| 311 |
- os.MkdirAll(path.Join(root, "containers", "1"), 0777) |
|
| 312 |
- driver, err := NewDriver(root, root, "", false) |
|
| 313 |
- if err != nil {
|
|
| 314 |
- t.Fatal(err) |
|
| 315 |
- } |
|
| 316 |
- processConfig := execdriver.ProcessConfig{
|
|
| 317 |
- Privileged: false, |
|
| 318 |
- } |
|
| 319 |
- |
|
| 320 |
- processConfig.Env = []string{"HOSTNAME=testhost"}
|
|
| 321 |
- command := &execdriver.Command{
|
|
| 322 |
- CommonCommand: execdriver.CommonCommand{
|
|
| 323 |
- ID: "1", |
|
| 324 |
- Network: &execdriver.Network{
|
|
| 325 |
- Mtu: 1500, |
|
| 326 |
- }, |
|
| 327 |
- ProcessConfig: processConfig, |
|
| 328 |
- }, |
|
| 329 |
- LxcConfig: []string{
|
|
| 330 |
- "lxc.cgroup.cpuset.cpus = 0,1", |
|
| 331 |
- "lxc.network.ipv4 = 172.0.0.1", |
|
| 332 |
- }, |
|
| 333 |
- CapAdd: []string{"NET_ADMIN", "SYSLOG"},
|
|
| 334 |
- CapDrop: []string{"KILL", "MKNOD"},
|
|
| 335 |
- } |
|
| 336 |
- |
|
| 337 |
- p, err := driver.generateLXCConfig(command) |
|
| 338 |
- if err != nil {
|
|
| 339 |
- t.Fatal(err) |
|
| 340 |
- } |
|
| 341 |
- |
|
| 342 |
- // hostname |
|
| 343 |
- grepFile(t, p, "lxc.utsname = testhost") |
|
| 344 |
- grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") |
|
| 345 |
- container := nativeTemplate.New() |
|
| 346 |
- for _, cap := range container.Capabilities {
|
|
| 347 |
- realCap := execdriver.GetCapability(cap) |
|
| 348 |
- numCap := fmt.Sprintf("%d", realCap.Value)
|
|
| 349 |
- if cap != "MKNOD" && cap != "KILL" {
|
|
| 350 |
- grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap))
|
|
| 351 |
- } |
|
| 352 |
- } |
|
| 353 |
- grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true)
|
|
| 354 |
- grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true)
|
|
| 355 |
-} |
| ... | ... |
@@ -1504,7 +1504,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
| 1504 | 1504 |
} |
| 1505 | 1505 |
|
| 1506 | 1506 |
// It seems libdevmapper opens this without O_CLOEXEC, and go exec will not close files |
| 1507 |
- // that are not Close-on-exec, and lxc-start will die if it inherits any unexpected files, |
|
| 1507 |
+ // that are not Close-on-exec, |
|
| 1508 | 1508 |
// so we add this badhack to make sure it closes itself |
| 1509 | 1509 |
setCloseOnExec("/dev/mapper/control")
|
| 1510 | 1510 |
|
| ... | ... |
@@ -2,14 +2,7 @@ |
| 2 | 2 |
|
| 3 | 3 |
package daemon |
| 4 | 4 |
|
| 5 |
-import ( |
|
| 6 |
- "errors" |
|
| 7 |
- "fmt" |
|
| 8 |
- "strings" |
|
| 9 |
- |
|
| 10 |
- "github.com/docker/docker/runconfig" |
|
| 11 |
- "github.com/opencontainers/runc/libcontainer/selinux" |
|
| 12 |
-) |
|
| 5 |
+import "github.com/opencontainers/runc/libcontainer/selinux" |
|
| 13 | 6 |
|
| 14 | 7 |
func selinuxSetDisabled() {
|
| 15 | 8 |
selinux.SetDisabled() |
| ... | ... |
@@ -22,27 +15,3 @@ func selinuxFreeLxcContexts(label string) {
|
| 22 | 22 |
func selinuxEnabled() bool {
|
| 23 | 23 |
return selinux.SelinuxEnabled() |
| 24 | 24 |
} |
| 25 |
- |
|
| 26 |
-func mergeLxcConfIntoOptions(hostConfig *runconfig.HostConfig) ([]string, error) {
|
|
| 27 |
- if hostConfig == nil {
|
|
| 28 |
- return nil, nil |
|
| 29 |
- } |
|
| 30 |
- |
|
| 31 |
- out := []string{}
|
|
| 32 |
- |
|
| 33 |
- // merge in the lxc conf options into the generic config map |
|
| 34 |
- if lxcConf := hostConfig.LxcConf; lxcConf != nil {
|
|
| 35 |
- lxSlice := lxcConf.Slice() |
|
| 36 |
- for _, pair := range lxSlice {
|
|
| 37 |
- // because lxc conf gets the driver name lxc.XXXX we need to trim it off |
|
| 38 |
- // and let the lxc driver add it back later if needed |
|
| 39 |
- if !strings.Contains(pair.Key, ".") {
|
|
| 40 |
- return nil, errors.New("Illegal Key passed into LXC Configurations")
|
|
| 41 |
- } |
|
| 42 |
- parts := strings.SplitN(pair.Key, ".", 2) |
|
| 43 |
- out = append(out, fmt.Sprintf("%s=%s", parts[1], pair.Value))
|
|
| 44 |
- } |
|
| 45 |
- } |
|
| 46 |
- |
|
| 47 |
- return out, nil |
|
| 48 |
-} |
| 49 | 25 |
deleted file mode 100644 |
| ... | ... |
@@ -1,28 +0,0 @@ |
| 1 |
-// +build linux |
|
| 2 |
- |
|
| 3 |
-package daemon |
|
| 4 |
- |
|
| 5 |
-import ( |
|
| 6 |
- "testing" |
|
| 7 |
- |
|
| 8 |
- "github.com/docker/docker/runconfig" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-func TestMergeLxcConfig(t *testing.T) {
|
|
| 12 |
- kv := []runconfig.KeyValuePair{
|
|
| 13 |
- {"lxc.cgroups.cpuset", "1,2"},
|
|
| 14 |
- } |
|
| 15 |
- hostConfig := &runconfig.HostConfig{
|
|
| 16 |
- LxcConf: runconfig.NewLxcConfig(kv), |
|
| 17 |
- } |
|
| 18 |
- |
|
| 19 |
- out, err := mergeLxcConfIntoOptions(hostConfig) |
|
| 20 |
- if err != nil {
|
|
| 21 |
- t.Fatalf("Failed to merge Lxc Config: %s", err)
|
|
| 22 |
- } |
|
| 23 |
- |
|
| 24 |
- cpuset := out[0] |
|
| 25 |
- if expected := "cgroups.cpuset=1,2"; cpuset != expected {
|
|
| 26 |
- t.Fatalf("expected %s got %s", expected, cpuset)
|
|
| 27 |
- } |
|
| 28 |
-} |
| ... | ... |
@@ -50,7 +50,6 @@ IRC channel on the Freenode network. |
| 50 | 50 |
| contrib | Yes |Install additional contributed scripts and components.| |
| 51 | 51 |
| device-mapper | Yes |Enables dependencies for the "devicemapper" graph driver, including necessary kernel flags.| |
| 52 | 52 |
| doc | |Add extra documentation (API, Javadoc, etc). It is recommended to enable per package instead of globally.| |
| 53 |
-| lxc | |Enables dependencies for the "lxc" execution driver.| |
|
| 54 | 53 |
| vim-syntax | |Pulls in related vim syntax scripts.| |
| 55 | 54 |
| zsh-completion| |Enable zsh completion support.| |
| 56 | 55 |
|
| ... | ... |
@@ -174,7 +174,6 @@ Create a container |
| 174 | 174 |
"HostConfig": {
|
| 175 | 175 |
"Binds": ["/tmp:/tmp"], |
| 176 | 176 |
"Links": ["redis3:redis"], |
| 177 |
- "LxcConf": {"lxc.utsname":"docker"},
|
|
| 178 | 177 |
"Memory": 0, |
| 179 | 178 |
"MemorySwap": 0, |
| 180 | 179 |
"MemoryReservation": 0, |
| ... | ... |
@@ -270,8 +269,6 @@ Json Parameters: |
| 270 | 270 |
+ `volume_name:container_path:ro` to make the bind mount read-only inside the container. |
| 271 | 271 |
- **Links** - A list of links for the container. Each link entry should be |
| 272 | 272 |
in the form of `container_name:alias`. |
| 273 |
- - **LxcConf** - LXC specific configurations. These configurations only |
|
| 274 |
- work when using the `lxc` execution driver. |
|
| 275 | 273 |
- **PortBindings** - A map of exposed container ports and the host port they |
| 276 | 274 |
should map to. A JSON object in the form |
| 277 | 275 |
`{ <port>/<protocol>: [{ "HostPort": "<port>" }] }`
|
| ... | ... |
@@ -48,7 +48,6 @@ Creates a new container. |
| 48 | 48 |
--link=[] Add link to another container |
| 49 | 49 |
--log-driver="" Logging driver for container |
| 50 | 50 |
--log-opt=[] Log driver specific options |
| 51 |
- --lxc-conf=[] Add custom lxc options |
|
| 52 | 51 |
-m, --memory="" Memory limit |
| 53 | 52 |
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) |
| 54 | 53 |
--memory-reservation="" Memory soft limit |
| ... | ... |
@@ -439,11 +439,6 @@ Currently supported options of `zfs`: |
| 439 | 439 |
The Docker daemon uses a specifically built `libcontainer` execution driver as |
| 440 | 440 |
its interface to the Linux kernel `namespaces`, `cgroups`, and `SELinux`. |
| 441 | 441 |
|
| 442 |
-There is still legacy support for the original [LXC userspace tools]( |
|
| 443 |
-https://linuxcontainers.org/) via the `lxc` execution driver, however, this is |
|
| 444 |
-not where the primary development of new functionality is taking place. |
|
| 445 |
-Add `-e lxc` to the daemon flags to use the `lxc` execution driver. |
|
| 446 |
- |
|
| 447 | 442 |
## Options for the native execdriver |
| 448 | 443 |
|
| 449 | 444 |
You can configure the `native` (libcontainer) execdriver using options specified |
| ... | ... |
@@ -47,7 +47,6 @@ parent = "smn_cli" |
| 47 | 47 |
--link=[] Add link to another container |
| 48 | 48 |
--log-driver="" Logging driver for container |
| 49 | 49 |
--log-opt=[] Log driver specific options |
| 50 |
- --lxc-conf=[] Add custom lxc options |
|
| 51 | 50 |
-m, --memory="" Memory limit |
| 52 | 51 |
--mac-address="" Container MAC address (e.g. 92:d0:c6:0a:29:33) |
| 53 | 52 |
--memory-reservation="" Memory soft limit |
| ... | ... |
@@ -39,7 +39,6 @@ defaults related to: |
| 39 | 39 |
* container identification |
| 40 | 40 |
* network settings |
| 41 | 41 |
* runtime constraints on CPU and memory |
| 42 |
- * privileges and LXC configuration |
|
| 43 | 42 |
|
| 44 | 43 |
With the `docker run [OPTIONS]` an operator can add to or override the |
| 45 | 44 |
image defaults set by a developer. And, additionally, operators can |
| ... | ... |
@@ -75,7 +74,7 @@ following options. |
| 75 | 75 |
- [Restart policies (--restart)](#restart-policies-restart) |
| 76 | 76 |
- [Clean up (--rm)](#clean-up-rm) |
| 77 | 77 |
- [Runtime constraints on resources](#runtime-constraints-on-resources) |
| 78 |
- - [Runtime privilege, Linux capabilities, and LXC configuration](#runtime-privilege-linux-capabilities-and-lxc-configuration) |
|
| 78 |
+ - [Runtime privilege and Linux capabilities](#runtime-privilege-and-linux-capabilities) |
|
| 79 | 79 |
|
| 80 | 80 |
## Detached vs foreground |
| 81 | 81 |
|
| ... | ... |
@@ -933,21 +932,18 @@ one can use this flag: |
| 933 | 933 |
$ docker run -ti --rm --group-add audio --group-add dbus --group-add 777 busybox id |
| 934 | 934 |
uid=0(root) gid=0(root) groups=10(wheel),29(audio),81(dbus),777 |
| 935 | 935 |
|
| 936 |
-## Runtime privilege, Linux capabilities, and LXC configuration |
|
| 936 |
+## Runtime privilege and Linux capabilities |
|
| 937 | 937 |
|
| 938 | 938 |
--cap-add: Add Linux capabilities |
| 939 | 939 |
--cap-drop: Drop Linux capabilities |
| 940 | 940 |
--privileged=false: Give extended privileges to this container |
| 941 | 941 |
--device=[]: Allows you to run devices inside the container without the --privileged flag. |
| 942 |
- --lxc-conf=[]: Add custom lxc options |
|
| 943 | 942 |
|
| 944 | 943 |
By default, Docker containers are "unprivileged" and cannot, for |
| 945 | 944 |
example, run a Docker daemon inside a Docker container. This is because |
| 946 | 945 |
by default a container is not allowed to access any devices, but a |
| 947 |
-"privileged" container is given access to all devices (see [lxc-template.go]( |
|
| 948 |
-https://github.com/docker/docker/blob/master/daemon/execdriver/lxc/lxc_template.go) |
|
| 949 |
-and documentation on [cgroups devices]( |
|
| 950 |
-https://www.kernel.org/doc/Documentation/cgroups/devices.txt)). |
|
| 946 |
+"privileged" container is given access to all devices (see |
|
| 947 |
+the documentation on [cgroups devices](https://www.kernel.org/doc/Documentation/cgroups/devices.txt)). |
|
| 951 | 948 |
|
| 952 | 949 |
When the operator executes `docker run --privileged`, Docker will enable |
| 953 | 950 |
to access to all devices on the host as well as set some configuration |
| ... | ... |
@@ -1061,22 +1057,6 @@ To mount a FUSE based filesystem, you need to combine both `--cap-add` and |
| 1061 | 1061 |
.... |
| 1062 | 1062 |
|
| 1063 | 1063 |
|
| 1064 |
-If the Docker daemon was started using the `lxc` exec-driver |
|
| 1065 |
-(`docker daemon --exec-driver=lxc`) then the operator can also specify LXC options |
|
| 1066 |
-using one or more `--lxc-conf` parameters. These can be new parameters or |
|
| 1067 |
-override existing parameters from the [lxc-template.go]( |
|
| 1068 |
-https://github.com/docker/docker/blob/master/daemon/execdriver/lxc/lxc_template.go). |
|
| 1069 |
-Note that in the future, a given host's docker daemon may not use LXC, so this |
|
| 1070 |
-is an implementation-specific configuration meant for operators already |
|
| 1071 |
-familiar with using LXC directly. |
|
| 1072 |
- |
|
| 1073 |
-> **Note:** |
|
| 1074 |
-> If you use `--lxc-conf` to modify a container's configuration which is also |
|
| 1075 |
-> managed by the Docker daemon, then the Docker daemon will not know about this |
|
| 1076 |
-> modification, and you will need to manage any conflicts yourself. For example, |
|
| 1077 |
-> you can use `--lxc-conf` to set a container's IP address, but this will not be |
|
| 1078 |
-> reflected in the `/etc/hosts` file. |
|
| 1079 |
- |
|
| 1080 | 1064 |
## Logging drivers (--log-driver) |
| 1081 | 1065 |
|
| 1082 | 1066 |
The container can have a different logging driver than the Docker daemon. Use |
| ... | ... |
@@ -1258,7 +1238,6 @@ above, or already defined by the developer with a Dockerfile `ENV`: |
| 1258 | 1258 |
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" |
| 1259 | 1259 |
declare -x PWD="/" |
| 1260 | 1260 |
declare -x SHLVL="1" |
| 1261 |
- declare -x container="lxc" |
|
| 1262 | 1261 |
declare -x deep="purple" |
| 1263 | 1262 |
|
| 1264 | 1263 |
Similarly the operator can set the **hostname** with `-h`. |
| ... | ... |
@@ -109,7 +109,6 @@ running a Docker daemon with experimental user namespaces enabled: |
| 109 | 109 |
- A `--readonly` container filesystem (a Linux kernel restriction on remount with new flags of a currently mounted filesystem when inside a user namespace) |
| 110 | 110 |
- external (volume/graph) drivers which are unaware/incapable of using daemon user mappings |
| 111 | 111 |
- Using `--privileged` mode containers |
| 112 |
- - Using the lxc execdriver (only the `native` execdriver is enabled to use user namespaces) |
|
| 113 | 112 |
- volume use without pre-arranging proper file ownership in mounted volumes |
| 114 | 113 |
|
| 115 | 114 |
Additionally, while the `root` user inside a user namespaced container |
| ... | ... |
@@ -31,13 +31,6 @@ if ! mountpoint -q /sys/fs/cgroup; then |
| 31 | 31 |
# Mount the cgroup hierarchies exactly as they are in the parent system. |
| 32 | 32 |
for HIER in $(cut -d: -f2 /proc/1/cgroup); do |
| 33 | 33 |
|
| 34 |
- # The following sections address a bug which manifests itself |
|
| 35 |
- # by a cryptic "lxc-start: no ns_cgroup option specified" when |
|
| 36 |
- # trying to start containers within a container. |
|
| 37 |
- # The bug seems to appear when the cgroup hierarchies are not |
|
| 38 |
- # mounted on the exact same directories in the host, and in the |
|
| 39 |
- # container. |
|
| 40 |
- |
|
| 41 | 34 |
SUBSYSTEMS="${HIER%name=*}"
|
| 42 | 35 |
|
| 43 | 36 |
# If cgroup hierarchy is named(mounted with "-o name=foo") we |
| ... | ... |
@@ -109,10 +109,6 @@ if [ -z "$DOCKER_CLIENTONLY" ]; then |
| 109 | 109 |
fi |
| 110 | 110 |
fi |
| 111 | 111 |
|
| 112 |
-if [ "$DOCKER_EXECDRIVER" = 'lxc' ]; then |
|
| 113 |
- DOCKER_BUILDTAGS+=' test_no_exec' |
|
| 114 |
-fi |
|
| 115 |
- |
|
| 116 | 112 |
# test whether "btrfs/version.h" exists and apply btrfs_noversion appropriately |
| 117 | 113 |
if \ |
| 118 | 114 |
command -v gcc &> /dev/null \ |
| ... | ... |
@@ -58,8 +58,8 @@ func (s *DockerSuite) TestDiffEnsureOnlyKmsgAndPtmx(c *check.C) {
|
| 58 | 58 |
"C /dev": true, |
| 59 | 59 |
"A /dev/full": true, // busybox |
| 60 | 60 |
"C /dev/ptmx": true, // libcontainer |
| 61 |
- "A /dev/mqueue": true, // lxc |
|
| 62 |
- "A /dev/kmsg": true, // lxc |
|
| 61 |
+ "A /dev/mqueue": true, |
|
| 62 |
+ "A /dev/kmsg": true, |
|
| 63 | 63 |
"A /dev/fd": true, |
| 64 | 64 |
"A /dev/fuse": true, |
| 65 | 65 |
"A /dev/ptmx": true, |
| ... | ... |
@@ -66,13 +66,11 @@ func (s *DockerSuite) TestRunLookupGoogleDns(c *check.C) {
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
// the exit code should be 0 |
| 69 |
-// some versions of lxc might make this test fail |
|
| 70 | 69 |
func (s *DockerSuite) TestRunExitCodeZero(c *check.C) {
|
| 71 | 70 |
dockerCmd(c, "run", "busybox", "true") |
| 72 | 71 |
} |
| 73 | 72 |
|
| 74 | 73 |
// the exit code should be 1 |
| 75 |
-// some versions of lxc might make this test fail |
|
| 76 | 74 |
func (s *DockerSuite) TestRunExitCodeOne(c *check.C) {
|
| 77 | 75 |
_, exitCode, err := dockerCmdWithError("run", "busybox", "false")
|
| 78 | 76 |
if err != nil && !strings.Contains("exit status 1", fmt.Sprintf("%s", err)) {
|
| ... | ... |
@@ -84,7 +82,6 @@ func (s *DockerSuite) TestRunExitCodeOne(c *check.C) {
|
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 | 86 |
// it should be possible to pipe in data via stdin to a process running in a container |
| 87 |
-// some versions of lxc might make this test fail |
|
| 88 | 87 |
func (s *DockerSuite) TestRunStdinPipe(c *check.C) {
|
| 89 | 88 |
// TODO Windows: This needs some work to make compatible. |
| 90 | 89 |
testRequires(c, DaemonIsLinux) |
| ... | ... |
@@ -664,7 +661,7 @@ func (s *DockerSuite) TestRunTwoConcurrentContainers(c *check.C) {
|
| 664 | 664 |
|
| 665 | 665 |
func (s *DockerSuite) TestRunEnvironment(c *check.C) {
|
| 666 | 666 |
// TODO Windows: Environment handling is different between Linux and |
| 667 |
- // Windows and this test relies currently on lxc and unix functionality. |
|
| 667 |
+ // Windows and this test relies currently on unix functionality. |
|
| 668 | 668 |
testRequires(c, DaemonIsLinux) |
| 669 | 669 |
cmd := exec.Command(dockerBinary, "run", "-h", "testing", "-e=FALSE=true", "-e=TRUE", "-e=TRICKY", "-e=HOME=", "busybox", "env") |
| 670 | 670 |
cmd.Env = append(os.Environ(), |
| ... | ... |
@@ -677,13 +674,7 @@ func (s *DockerSuite) TestRunEnvironment(c *check.C) {
|
| 677 | 677 |
c.Fatal(err, out) |
| 678 | 678 |
} |
| 679 | 679 |
|
| 680 |
- actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") |
|
| 681 |
- actualEnv := []string{}
|
|
| 682 |
- for i := range actualEnvLxc {
|
|
| 683 |
- if actualEnvLxc[i] != "container=lxc" {
|
|
| 684 |
- actualEnv = append(actualEnv, actualEnvLxc[i]) |
|
| 685 |
- } |
|
| 686 |
- } |
|
| 680 |
+ actualEnv := strings.Split(strings.TrimSpace(out), "\n") |
|
| 687 | 681 |
sort.Strings(actualEnv) |
| 688 | 682 |
|
| 689 | 683 |
goodEnv := []string{
|
| ... | ... |
@@ -709,7 +700,7 @@ func (s *DockerSuite) TestRunEnvironment(c *check.C) {
|
| 709 | 709 |
|
| 710 | 710 |
func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) {
|
| 711 | 711 |
// TODO Windows: Environment handling is different between Linux and |
| 712 |
- // Windows and this test relies currently on lxc and unix functionality. |
|
| 712 |
+ // Windows and this test relies currently on unix functionality. |
|
| 713 | 713 |
testRequires(c, DaemonIsLinux) |
| 714 | 714 |
|
| 715 | 715 |
// Test to make sure that when we use -e on env vars that are |
| ... | ... |
@@ -724,13 +715,7 @@ func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) {
|
| 724 | 724 |
c.Fatal(err, out) |
| 725 | 725 |
} |
| 726 | 726 |
|
| 727 |
- actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") |
|
| 728 |
- actualEnv := []string{}
|
|
| 729 |
- for i := range actualEnvLxc {
|
|
| 730 |
- if actualEnvLxc[i] != "container=lxc" {
|
|
| 731 |
- actualEnv = append(actualEnv, actualEnvLxc[i]) |
|
| 732 |
- } |
|
| 733 |
- } |
|
| 727 |
+ actualEnv := strings.Split(strings.TrimSpace(out), "\n") |
|
| 734 | 728 |
sort.Strings(actualEnv) |
| 735 | 729 |
|
| 736 | 730 |
goodEnv := []string{
|
| ... | ... |
@@ -750,7 +735,7 @@ func (s *DockerSuite) TestRunEnvironmentErase(c *check.C) {
|
| 750 | 750 |
|
| 751 | 751 |
func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) {
|
| 752 | 752 |
// TODO Windows: Environment handling is different between Linux and |
| 753 |
- // Windows and this test relies currently on lxc and unix functionality. |
|
| 753 |
+ // Windows and this test relies currently on unix functionality. |
|
| 754 | 754 |
testRequires(c, DaemonIsLinux) |
| 755 | 755 |
|
| 756 | 756 |
// Test to make sure that when we use -e on env vars that are |
| ... | ... |
@@ -764,13 +749,7 @@ func (s *DockerSuite) TestRunEnvironmentOverride(c *check.C) {
|
| 764 | 764 |
c.Fatal(err, out) |
| 765 | 765 |
} |
| 766 | 766 |
|
| 767 |
- actualEnvLxc := strings.Split(strings.TrimSpace(out), "\n") |
|
| 768 |
- actualEnv := []string{}
|
|
| 769 |
- for i := range actualEnvLxc {
|
|
| 770 |
- if actualEnvLxc[i] != "container=lxc" {
|
|
| 771 |
- actualEnv = append(actualEnv, actualEnvLxc[i]) |
|
| 772 |
- } |
|
| 773 |
- } |
|
| 767 |
+ actualEnv := strings.Split(strings.TrimSpace(out), "\n") |
|
| 774 | 768 |
sort.Strings(actualEnv) |
| 775 | 769 |
|
| 776 | 770 |
goodEnv := []string{
|
| ... | ... |
@@ -17,7 +17,6 @@ import ( |
| 17 | 17 |
"github.com/docker/docker/pkg/mount" |
| 18 | 18 |
"github.com/docker/docker/pkg/parsers" |
| 19 | 19 |
"github.com/docker/docker/pkg/sysinfo" |
| 20 |
- "github.com/docker/docker/pkg/units" |
|
| 21 | 20 |
"github.com/go-check/check" |
| 22 | 21 |
"github.com/kr/pty" |
| 23 | 22 |
) |
| ... | ... |
@@ -437,22 +436,3 @@ func (s *DockerSuite) TestRunInvalidCPUShares(c *check.C) {
|
| 437 | 437 |
expected = "The maximum allowed cpu-shares is" |
| 438 | 438 |
c.Assert(out, checker.Contains, expected) |
| 439 | 439 |
} |
| 440 |
- |
|
| 441 |
-func (s *DockerSuite) TestRunWithCorrectMemorySwapOnLXC(c *check.C) {
|
|
| 442 |
- testRequires(c, memoryLimitSupport) |
|
| 443 |
- testRequires(c, swapMemorySupport) |
|
| 444 |
- testRequires(c, SameHostDaemon) |
|
| 445 |
- |
|
| 446 |
- out, _ := dockerCmd(c, "run", "-d", "-m", "32m", "--memory-swap", "64m", "busybox", "top") |
|
| 447 |
- if _, err := os.Stat("/sys/fs/cgroup/memory/lxc"); err != nil {
|
|
| 448 |
- c.Skip("Excecution driver must be LXC for this test")
|
|
| 449 |
- } |
|
| 450 |
- id := strings.TrimSpace(out) |
|
| 451 |
- memorySwap, err := ioutil.ReadFile(fmt.Sprintf("/sys/fs/cgroup/memory/lxc/%s/memory.memsw.limit_in_bytes", id))
|
|
| 452 |
- c.Assert(err, check.IsNil) |
|
| 453 |
- cgSwap, err := strconv.ParseInt(strings.TrimSpace(string(memorySwap)), 10, 64) |
|
| 454 |
- c.Assert(err, check.IsNil) |
|
| 455 |
- swap, err := units.RAMInBytes("64m")
|
|
| 456 |
- c.Assert(err, check.IsNil) |
|
| 457 |
- c.Assert(cgSwap, check.Equals, swap) |
|
| 458 |
-} |
| ... | ... |
@@ -37,7 +37,6 @@ docker-create - Create a new container |
| 37 | 37 |
[**--link**[=*[]*]] |
| 38 | 38 |
[**--log-driver**[=*[]*]] |
| 39 | 39 |
[**--log-opt**[=*[]*]] |
| 40 |
-[**--lxc-conf**[=*[]*]] |
|
| 41 | 40 |
[**-m**|**--memory**[=*MEMORY*]] |
| 42 | 41 |
[**--mac-address**[=*MAC-ADDRESS*]] |
| 43 | 42 |
[**--memory-reservation**[=*MEMORY-RESERVATION*]] |
| ... | ... |
@@ -182,9 +181,6 @@ millions of trillions. |
| 182 | 182 |
**--log-opt**=[] |
| 183 | 183 |
Logging driver specific options. |
| 184 | 184 |
|
| 185 |
-**--lxc-conf**=[] |
|
| 186 |
- (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" |
|
| 187 |
- |
|
| 188 | 185 |
**-m**, **--memory**="" |
| 189 | 186 |
Memory limit (format: <number>[<unit>], where unit = b, k, m or g) |
| 190 | 187 |
|
| ... | ... |
@@ -38,7 +38,6 @@ docker-run - Run a command in a new container |
| 38 | 38 |
[**--link**[=*[]*]] |
| 39 | 39 |
[**--log-driver**[=*[]*]] |
| 40 | 40 |
[**--log-opt**[=*[]*]] |
| 41 |
-[**--lxc-conf**[=*[]*]] |
|
| 42 | 41 |
[**-m**|**--memory**[=*MEMORY*]] |
| 43 | 42 |
[**--mac-address**[=*MAC-ADDRESS*]] |
| 44 | 43 |
[**--memory-reservation**[=*MEMORY-RESERVATION*]] |
| ... | ... |
@@ -274,9 +273,6 @@ container can access the exposed port via a private networking interface. Docker |
| 274 | 274 |
will set some environment variables in the client container to help indicate |
| 275 | 275 |
which interface and port to use. |
| 276 | 276 |
|
| 277 |
-**--lxc-conf**=[] |
|
| 278 |
- (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" |
|
| 279 |
- |
|
| 280 | 277 |
**--log-driver**="|*json-file*|*syslog*|*journald*|*gelf*|*fluentd*|*awslogs*|*splunk*|*none*" |
| 281 | 278 |
Logging driver for container. Default is defined by daemon `--log-driver` flag. |
| 282 | 279 |
**Warning**: the `docker logs` command works only for the `json-file` and |
| ... | ... |
@@ -298,7 +298,6 @@ the client will even run on alternative platforms such as Mac OS X / Darwin. |
| 298 | 298 |
Some of Docker's features are activated by using optional command-line flags or |
| 299 | 299 |
by having support for them in the kernel or userspace. A few examples include: |
| 300 | 300 |
|
| 301 |
-* LXC execution driver (requires version 1.0.7 or later of lxc and the lxc-libs) |
|
| 302 | 301 |
* AUFS graph driver (requires AUFS patches/support enabled in the kernel, and at |
| 303 | 302 |
least the "auplink" utility from aufs-tools) |
| 304 | 303 |
* BTRFS graph driver (requires BTRFS support enabled in the kernel) |
| ... | ... |
@@ -24,7 +24,7 @@ type NetworkMode string |
| 24 | 24 |
type IsolationLevel string |
| 25 | 25 |
|
| 26 | 26 |
// IsDefault indicates the default isolation level of a container. On Linux this |
| 27 |
-// is LXC. On Windows, this is a Windows Server Container. |
|
| 27 |
+// is the native driver. On Windows, this is a Windows Server Container. |
|
| 28 | 28 |
func (i IsolationLevel) IsDefault() bool {
|
| 29 | 29 |
return strings.ToLower(string(i)) == "default" || string(i) == "" |
| 30 | 30 |
} |
| ... | ... |
@@ -164,69 +164,12 @@ type LogConfig struct {
|
| 164 | 164 |
Config map[string]string |
| 165 | 165 |
} |
| 166 | 166 |
|
| 167 |
-// LxcConfig represents the specific LXC configuration of the container. |
|
| 168 |
-type LxcConfig struct {
|
|
| 169 |
- values []KeyValuePair |
|
| 170 |
-} |
|
| 171 |
- |
|
| 172 |
-// MarshalJSON marshals (or serializes) the LxcConfig into JSON. |
|
| 173 |
-func (c *LxcConfig) MarshalJSON() ([]byte, error) {
|
|
| 174 |
- if c == nil {
|
|
| 175 |
- return []byte{}, nil
|
|
| 176 |
- } |
|
| 177 |
- return json.Marshal(c.Slice()) |
|
| 178 |
-} |
|
| 179 |
- |
|
| 180 |
-// UnmarshalJSON unmarshals (or deserializes) the specified byte slices from JSON to |
|
| 181 |
-// a LxcConfig. |
|
| 182 |
-func (c *LxcConfig) UnmarshalJSON(b []byte) error {
|
|
| 183 |
- if len(b) == 0 {
|
|
| 184 |
- return nil |
|
| 185 |
- } |
|
| 186 |
- |
|
| 187 |
- var kv []KeyValuePair |
|
| 188 |
- if err := json.Unmarshal(b, &kv); err != nil {
|
|
| 189 |
- var h map[string]string |
|
| 190 |
- if err := json.Unmarshal(b, &h); err != nil {
|
|
| 191 |
- return err |
|
| 192 |
- } |
|
| 193 |
- for k, v := range h {
|
|
| 194 |
- kv = append(kv, KeyValuePair{k, v})
|
|
| 195 |
- } |
|
| 196 |
- } |
|
| 197 |
- c.values = kv |
|
| 198 |
- |
|
| 199 |
- return nil |
|
| 200 |
-} |
|
| 201 |
- |
|
| 202 |
-// Len returns the number of specific lxc configuration. |
|
| 203 |
-func (c *LxcConfig) Len() int {
|
|
| 204 |
- if c == nil {
|
|
| 205 |
- return 0 |
|
| 206 |
- } |
|
| 207 |
- return len(c.values) |
|
| 208 |
-} |
|
| 209 |
- |
|
| 210 |
-// Slice returns the specific lxc configuration into a slice of KeyValuePair. |
|
| 211 |
-func (c *LxcConfig) Slice() []KeyValuePair {
|
|
| 212 |
- if c == nil {
|
|
| 213 |
- return nil |
|
| 214 |
- } |
|
| 215 |
- return c.values |
|
| 216 |
-} |
|
| 217 |
- |
|
| 218 |
-// NewLxcConfig creates a LxcConfig from the specified slice of KeyValuePair. |
|
| 219 |
-func NewLxcConfig(values []KeyValuePair) *LxcConfig {
|
|
| 220 |
- return &LxcConfig{values}
|
|
| 221 |
-} |
|
| 222 |
- |
|
| 223 | 167 |
// HostConfig the non-portable Config structure of a container. |
| 224 | 168 |
// Here, "non-portable" means "dependent of the host we are running on". |
| 225 | 169 |
// Portable information *should* appear in Config. |
| 226 | 170 |
type HostConfig struct {
|
| 227 | 171 |
Binds []string // List of volume bindings for this container |
| 228 | 172 |
ContainerIDFile string // File (path) where the containerId is written |
| 229 |
- LxcConf *LxcConfig // Additional lxc configuration |
|
| 230 | 173 |
Memory int64 // Memory limit (in bytes) |
| 231 | 174 |
MemoryReservation int64 // Memory soft limit (in bytes) |
| 232 | 175 |
MemorySwap int64 // Total memory usage (memory + swap); set `-1` to disable swap |
| ... | ... |
@@ -162,53 +162,6 @@ func TestRestartPolicy(t *testing.T) {
|
| 162 | 162 |
} |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 |
-func TestLxcConfigMarshalJSON(t *testing.T) {
|
|
| 166 |
- lxcConfigs := map[*LxcConfig]string{
|
|
| 167 |
- nil: "", |
|
| 168 |
- &LxcConfig{}: "null",
|
|
| 169 |
- &LxcConfig{
|
|
| 170 |
- []KeyValuePair{{"key1", "value1"}},
|
|
| 171 |
- }: `[{"Key":"key1","Value":"value1"}]`,
|
|
| 172 |
- } |
|
| 173 |
- |
|
| 174 |
- for lxcconfig, expected := range lxcConfigs {
|
|
| 175 |
- data, err := lxcconfig.MarshalJSON() |
|
| 176 |
- if err != nil {
|
|
| 177 |
- t.Fatal(err) |
|
| 178 |
- } |
|
| 179 |
- if string(data) != expected {
|
|
| 180 |
- t.Fatalf("Expected %v, got %v", expected, string(data))
|
|
| 181 |
- } |
|
| 182 |
- } |
|
| 183 |
-} |
|
| 184 |
- |
|
| 185 |
-func TestLxcConfigUnmarshalJSON(t *testing.T) {
|
|
| 186 |
- keyvaluePairs := map[string][]KeyValuePair{
|
|
| 187 |
- "": {{"key1", "value1"}},
|
|
| 188 |
- "[]": {},
|
|
| 189 |
- `[{"Key":"key2","Value":"value2"}]`: {{"key2", "value2"}},
|
|
| 190 |
- } |
|
| 191 |
- for json, expectedParts := range keyvaluePairs {
|
|
| 192 |
- lxcConfig := &LxcConfig{
|
|
| 193 |
- []KeyValuePair{{"key1", "value1"}},
|
|
| 194 |
- } |
|
| 195 |
- if err := lxcConfig.UnmarshalJSON([]byte(json)); err != nil {
|
|
| 196 |
- t.Fatal(err) |
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- actualParts := lxcConfig.Slice() |
|
| 200 |
- if len(actualParts) != len(expectedParts) {
|
|
| 201 |
- t.Fatalf("Expected %v keyvaluePairs, got %v (%v)", len(expectedParts), len(actualParts), expectedParts)
|
|
| 202 |
- } |
|
| 203 |
- for index, part := range actualParts {
|
|
| 204 |
- if part != expectedParts[index] {
|
|
| 205 |
- t.Fatalf("Expected %v, got %v", expectedParts, actualParts)
|
|
| 206 |
- break |
|
| 207 |
- } |
|
| 208 |
- } |
|
| 209 |
- } |
|
| 210 |
-} |
|
| 211 |
- |
|
| 212 | 165 |
func TestMergeConfigs(t *testing.T) {
|
| 213 | 166 |
expectedHostname := "hostname" |
| 214 | 167 |
expectedContainerIDFile := "containerIdFile" |
| ... | ... |
@@ -62,7 +62,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 62 | 62 |
flDNSOptions = opts.NewListOpts(nil) |
| 63 | 63 |
flExtraHosts = opts.NewListOpts(opts.ValidateExtraHost) |
| 64 | 64 |
flVolumesFrom = opts.NewListOpts(nil) |
| 65 |
- flLxcOpts = opts.NewListOpts(nil) |
|
| 66 | 65 |
flEnvFile = opts.NewListOpts(nil) |
| 67 | 66 |
flCapAdd = opts.NewListOpts(nil) |
| 68 | 67 |
flCapDrop = opts.NewListOpts(nil) |
| ... | ... |
@@ -121,7 +120,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 121 | 121 |
cmd.Var(&flDNSOptions, []string{"-dns-opt"}, "Set DNS options")
|
| 122 | 122 |
cmd.Var(&flExtraHosts, []string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
|
| 123 | 123 |
cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
| 124 |
- cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options")
|
|
| 125 | 124 |
cmd.Var(&flCapAdd, []string{"-cap-add"}, "Add Linux capabilities")
|
| 126 | 125 |
cmd.Var(&flCapDrop, []string{"-cap-drop"}, "Drop Linux capabilities")
|
| 127 | 126 |
cmd.Var(&flGroupAdd, []string{"-group-add"}, "Add additional groups to join")
|
| ... | ... |
@@ -223,12 +221,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 223 | 223 |
entrypoint = stringutils.NewStrSlice(*flEntrypoint) |
| 224 | 224 |
} |
| 225 | 225 |
|
| 226 |
- lc, err := parseKeyValueOpts(flLxcOpts) |
|
| 227 |
- if err != nil {
|
|
| 228 |
- return nil, nil, cmd, err |
|
| 229 |
- } |
|
| 230 |
- lxcConf := NewLxcConfig(lc) |
|
| 231 |
- |
|
| 232 | 226 |
var ( |
| 233 | 227 |
domainname string |
| 234 | 228 |
hostname = *flHostname |
| ... | ... |
@@ -340,7 +332,6 @@ func Parse(cmd *flag.FlagSet, args []string) (*Config, *HostConfig, *flag.FlagSe |
| 340 | 340 |
hostConfig := &HostConfig{
|
| 341 | 341 |
Binds: binds, |
| 342 | 342 |
ContainerIDFile: *flContainerIDFile, |
| 343 |
- LxcConf: lxcConf, |
|
| 344 | 343 |
Memory: flMemory, |
| 345 | 344 |
MemoryReservation: MemoryReservation, |
| 346 | 345 |
MemorySwap: memorySwap, |
| ... | ... |
@@ -12,7 +12,6 @@ import ( |
| 12 | 12 |
|
| 13 | 13 |
flag "github.com/docker/docker/pkg/mflag" |
| 14 | 14 |
"github.com/docker/docker/pkg/nat" |
| 15 |
- "github.com/docker/docker/pkg/parsers" |
|
| 16 | 15 |
) |
| 17 | 16 |
|
| 18 | 17 |
func parseRun(args []string) (*Config, *HostConfig, *flag.FlagSet, error) {
|
| ... | ... |
@@ -344,35 +343,6 @@ func setupPlatformVolume(u []string, w []string) ([]string, string) {
|
| 344 | 344 |
return a, s |
| 345 | 345 |
} |
| 346 | 346 |
|
| 347 |
-func TestParseLxcConfOpt(t *testing.T) {
|
|
| 348 |
- opts := []string{"lxc.utsname=docker", "lxc.utsname = docker "}
|
|
| 349 |
- |
|
| 350 |
- for _, o := range opts {
|
|
| 351 |
- k, v, err := parsers.ParseKeyValueOpt(o) |
|
| 352 |
- if err != nil {
|
|
| 353 |
- t.FailNow() |
|
| 354 |
- } |
|
| 355 |
- if k != "lxc.utsname" {
|
|
| 356 |
- t.Fail() |
|
| 357 |
- } |
|
| 358 |
- if v != "docker" {
|
|
| 359 |
- t.Fail() |
|
| 360 |
- } |
|
| 361 |
- } |
|
| 362 |
- |
|
| 363 |
- // With parseRun too |
|
| 364 |
- _, hostconfig, _, err := parseRun([]string{"lxc.utsname=docker", "lxc.utsname = docker ", "img", "cmd"})
|
|
| 365 |
- if err != nil {
|
|
| 366 |
- t.Fatal(err) |
|
| 367 |
- } |
|
| 368 |
- for _, lxcConf := range hostconfig.LxcConf.Slice() {
|
|
| 369 |
- if lxcConf.Key != "lxc.utsname" || lxcConf.Value != "docker" {
|
|
| 370 |
- t.Fail() |
|
| 371 |
- } |
|
| 372 |
- } |
|
| 373 |
- |
|
| 374 |
-} |
|
| 375 |
- |
|
| 376 | 347 |
// Simple parse with MacAddress validatation |
| 377 | 348 |
func TestParseWithMacAddress(t *testing.T) {
|
| 378 | 349 |
invalidMacAddress := "--mac-address=invalidMacAddress" |
| ... | ... |
@@ -61,8 +61,7 @@ func ValidateNetMode(c *Config, hc *HostConfig) error {
|
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
// ValidateIsolationLevel performs platform specific validation of the |
| 64 |
-// isolation level in the hostconfig structure. Linux only supports "default" |
|
| 65 |
-// which is LXC container isolation |
|
| 64 |
+// isolation level in the hostconfig structure. Linux only supports "default". |
|
| 66 | 65 |
func ValidateIsolationLevel(hc *HostConfig) error {
|
| 67 | 66 |
// We may not be passed a host config, such as in the case of docker commit |
| 68 | 67 |
if hc == nil {
|