mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Add functional support for Docker sub commands on Solaris
Signed-off-by: Amit Krishnan <krish.amit@gmail.com> Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
		
							parent
							
								
									c5ceb0f945
								
							
						
					
					
						commit
						934328d8ea
					
				
					 77 changed files with 1572 additions and 571 deletions
				
			
		| 
						 | 
				
			
			@ -137,7 +137,8 @@ ENV DOCKER_CROSSPLATFORMS \
 | 
			
		|||
	linux/386 linux/arm \
 | 
			
		||||
	darwin/amd64 \
 | 
			
		||||
	freebsd/amd64 freebsd/386 freebsd/arm \
 | 
			
		||||
	windows/amd64 windows/386
 | 
			
		||||
	windows/amd64 windows/386 \
 | 
			
		||||
	solaris/amd64
 | 
			
		||||
 | 
			
		||||
# Dependency for golint
 | 
			
		||||
ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										20
									
								
								Dockerfile.solaris
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								Dockerfile.solaris
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
# Defines an image that hosts a native Docker build environment for Solaris
 | 
			
		||||
# TODO: Improve stub
 | 
			
		||||
 | 
			
		||||
FROM solaris:latest
 | 
			
		||||
 | 
			
		||||
# compile and runtime deps
 | 
			
		||||
RUN pkg install --accept \
 | 
			
		||||
		git \
 | 
			
		||||
		gnu-coreutils \
 | 
			
		||||
		gnu-make \
 | 
			
		||||
		gnu-tar \
 | 
			
		||||
		diagnostic/top \
 | 
			
		||||
		golang \
 | 
			
		||||
		library/golang/* \
 | 
			
		||||
		developer/gcc-*
 | 
			
		||||
 | 
			
		||||
ENV GOPATH /go/:/usr/lib/gocode/1.5/
 | 
			
		||||
ENV DOCKER_CROSSPLATFORMS solaris/amd64
 | 
			
		||||
WORKDIR /go/src/github.com/docker/docker
 | 
			
		||||
COPY . /go/src/github.com/docker/docker
 | 
			
		||||
| 
						 | 
				
			
			@ -52,6 +52,11 @@ func notifySystem() {
 | 
			
		|||
 | 
			
		||||
func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
 | 
			
		||||
	opts := []libcontainerd.RemoteOption{}
 | 
			
		||||
	if cli.Config.ContainerdAddr != "" {
 | 
			
		||||
		opts = append(opts, libcontainerd.WithRemoteAddr(cli.Config.ContainerdAddr))
 | 
			
		||||
	} else {
 | 
			
		||||
		opts = append(opts, libcontainerd.WithStartDaemon(true))
 | 
			
		||||
	}
 | 
			
		||||
	return opts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,15 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
// +build !windows,!solaris
 | 
			
		||||
 | 
			
		||||
// TODO: Create new file for Solaris which tests config parameters
 | 
			
		||||
// as described in daemon/config_solaris.go
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/daemon"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/assert"
 | 
			
		||||
	"github.com/docker/docker/pkg/testutil/tempfile"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLoadDaemonCliConfigWithDaemonFlags(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										9
									
								
								container/container_linux.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								container/container_linux.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package container
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func detachMounted(path string) error {
 | 
			
		||||
	return unix.Unmount(path, unix.MNT_DETACH)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								container/container_notlinux.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								container/container_notlinux.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
// +build solaris freebsd
 | 
			
		||||
 | 
			
		||||
package container
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func detachMounted(path string) error {
 | 
			
		||||
	//Solaris and FreeBSD do not support the lazy unmount or MNT_DETACH feature.
 | 
			
		||||
	// Therefore there are separate definitions for this.
 | 
			
		||||
	return unix.Unmount(path, 0)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,100 +0,0 @@
 | 
			
		|||
// +build solaris
 | 
			
		||||
 | 
			
		||||
package container
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/volume"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Container holds fields specific to the Solaris implementation. See
 | 
			
		||||
// CommonContainer for standard fields common to all containers.
 | 
			
		||||
type Container struct {
 | 
			
		||||
	CommonContainer
 | 
			
		||||
 | 
			
		||||
	// fields below here are platform specific.
 | 
			
		||||
	HostnamePath   string
 | 
			
		||||
	HostsPath      string
 | 
			
		||||
	ResolvConfPath string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExitStatus provides exit reasons for a container.
 | 
			
		||||
type ExitStatus struct {
 | 
			
		||||
	// The exit code with which the container exited.
 | 
			
		||||
	ExitCode int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateDaemonEnvironment creates a new environment variable slice for this container.
 | 
			
		||||
func (container *Container) CreateDaemonEnvironment(_ bool, linkedEnv []string) []string {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func appendNetworkMounts(container *Container, volumeMounts []volume.MountPoint) ([]volume.MountPoint, error) {
 | 
			
		||||
	return volumeMounts, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TrySetNetworkMount attempts to set the network mounts given a provided destination and
 | 
			
		||||
// the path to use for it; return true if the given destination was a network mount file
 | 
			
		||||
func (container *Container) TrySetNetworkMount(destination string, path string) bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NetworkMounts returns the list of network mounts.
 | 
			
		||||
func (container *Container) NetworkMounts() []Mount {
 | 
			
		||||
	var mount []Mount
 | 
			
		||||
	return mount
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CopyImagePathContent copies files in destination to the volume.
 | 
			
		||||
func (container *Container) CopyImagePathContent(v volume.Volume, destination string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmountIpcMounts unmount Ipc related mounts.
 | 
			
		||||
func (container *Container) UnmountIpcMounts(unmount func(pth string) error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IpcMounts returns the list of Ipc related mounts.
 | 
			
		||||
func (container *Container) IpcMounts() []Mount {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateContainer updates configuration of a container
 | 
			
		||||
func (container *Container) UpdateContainer(hostConfig *container.HostConfig) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmountVolumes explicitly unmounts volumes from the container.
 | 
			
		||||
func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog func(name, action string, attributes map[string]string)) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TmpfsMounts returns the list of tmpfs mounts
 | 
			
		||||
func (container *Container) TmpfsMounts() []Mount {
 | 
			
		||||
	var mounts []Mount
 | 
			
		||||
	return mounts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// cleanResourcePath cleans a resource path and prepares to combine with mnt path
 | 
			
		||||
func cleanResourcePath(path string) string {
 | 
			
		||||
	return filepath.Join(string(os.PathSeparator), path)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildHostnameFile writes the container's hostname file.
 | 
			
		||||
func (container *Container) BuildHostnameFile() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// canMountFS determines if the file system for the container
 | 
			
		||||
// can be mounted locally. A no-op on non-Windows platforms
 | 
			
		||||
func (container *Container) canMountFS() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableServiceDiscoveryOnDefaultNetwork Enable service discovery on default network
 | 
			
		||||
func (container *Container) EnableServiceDiscoveryOnDefaultNetwork() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build linux freebsd
 | 
			
		||||
// +build linux freebsd solaris
 | 
			
		||||
 | 
			
		||||
package container
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -8,7 +8,6 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +19,7 @@ import (
 | 
			
		|||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/docker/docker/volume"
 | 
			
		||||
	"github.com/opencontainers/runc/libcontainer/label"
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultSHMSize is the default size (64MB) of the SHM which will be mounted in the container
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +200,7 @@ func (container *Container) CopyImagePathContent(v volume.Volume, destination st
 | 
			
		|||
			logrus.Warnf("error while unmounting volume %s: %v", v.Name(), err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	if err := label.Relabel(path, container.MountLabel, true); err != nil && err != syscall.ENOTSUP {
 | 
			
		||||
	if err := label.Relabel(path, container.MountLabel, true); err != nil && err != unix.ENOTSUP {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return copyExistingContents(rootfs, path)
 | 
			
		||||
| 
						 | 
				
			
			@ -320,10 +320,6 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func detachMounted(path string) error {
 | 
			
		||||
	return syscall.Unmount(path, syscall.MNT_DETACH)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmountVolumes unmounts all volumes
 | 
			
		||||
func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog func(name, action string, attributes map[string]string)) error {
 | 
			
		||||
	var (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
package container
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// memoryStore implements a Store in memory.
 | 
			
		||||
type memoryStore struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +27,9 @@ func (c *memoryStore) Add(id string, cont *Container) {
 | 
			
		|||
 | 
			
		||||
// Get returns a container from the store by id.
 | 
			
		||||
func (c *memoryStore) Get(id string) *Container {
 | 
			
		||||
	var res *Container
 | 
			
		||||
	c.RLock()
 | 
			
		||||
	res := c.s[id]
 | 
			
		||||
	res = c.s[id]
 | 
			
		||||
	c.RUnlock()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
// +build !windows,!solaris
 | 
			
		||||
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								contrib/httpserver/Dockerfile.solaris
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								contrib/httpserver/Dockerfile.solaris
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
FROM solaris
 | 
			
		||||
EXPOSE 80/tcp
 | 
			
		||||
COPY httpserver .
 | 
			
		||||
CMD ["./httpserver"]
 | 
			
		||||
| 
						 | 
				
			
			@ -11,11 +11,22 @@ usage() {
 | 
			
		|||
	echo >&2 "       $mkimg -t someuser/centos:5 rinse --distribution centos-5"
 | 
			
		||||
	echo >&2 "       $mkimg -t someuser/mageia:4 mageia-urpmi --version=4"
 | 
			
		||||
	echo >&2 "       $mkimg -t someuser/mageia:4 mageia-urpmi --version=4 --mirror=http://somemirror/"
 | 
			
		||||
	echo >&2 "       $mkimg -t someuser/solaris solaris" 
 | 
			
		||||
	exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
scriptDir="$(dirname "$(readlink -f "$BASH_SOURCE")")/mkimage"
 | 
			
		||||
 | 
			
		||||
os=
 | 
			
		||||
os=$(uname -o)
 | 
			
		||||
 | 
			
		||||
# set up path to gnu tools if solaris
 | 
			
		||||
[[ $os == "Solaris" ]] && export PATH=/usr/gnu/bin:$PATH 
 | 
			
		||||
# TODO check for gnu-tar, gnu-getopt
 | 
			
		||||
 | 
			
		||||
# TODO requires root/sudo due to some pkg operations. sigh.
 | 
			
		||||
[[ $os == "Solaris" && $EUID != "0" ]] && echo >&2 "image create on Solaris requires superuser privilege"
 | 
			
		||||
 | 
			
		||||
optTemp=$(getopt --options '+d:t:c:hC' --longoptions 'dir:,tag:,compression:,no-compression,help' --name "$mkimg" -- "$@")
 | 
			
		||||
eval set -- "$optTemp"
 | 
			
		||||
unset optTemp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								contrib/mkimage/solaris
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										89
									
								
								contrib/mkimage/solaris
									
										
									
									
									
										Executable file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
#!/usr/bin/env bash
 | 
			
		||||
#
 | 
			
		||||
# Solaris 12 base image build script. 
 | 
			
		||||
#
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
# TODO add optional package publisher origin
 | 
			
		||||
 | 
			
		||||
rootfsDir="$1"
 | 
			
		||||
shift
 | 
			
		||||
 | 
			
		||||
# base install
 | 
			
		||||
(
 | 
			
		||||
	set -x
 | 
			
		||||
 | 
			
		||||
	pkg image-create --full --zone \
 | 
			
		||||
		--facet facet.locale.*=false \
 | 
			
		||||
		--facet facet.locale.POSIX=true \
 | 
			
		||||
		--facet facet.doc=false \
 | 
			
		||||
		--facet facet.doc.*=false \
 | 
			
		||||
		"$rootfsDir"
 | 
			
		||||
 | 
			
		||||
	pkg -R "$rootfsDir" set-property use-system-repo true
 | 
			
		||||
 | 
			
		||||
	pkg -R "$rootfsDir" set-property flush-content-cache-on-success true
 | 
			
		||||
 | 
			
		||||
	pkg -R "$rootfsDir" install core-os
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Lay in stock configuration, set up milestone
 | 
			
		||||
# XXX This all may become optional in a base image
 | 
			
		||||
(
 | 
			
		||||
	# faster to build repository database on tmpfs
 | 
			
		||||
	REPO_DB=/system/volatile/repository.$$
 | 
			
		||||
	export SVCCFG_REPOSITORY=${REPO_DB}
 | 
			
		||||
	export SVCCFG_DOOR_PATH=$rootfsDir/system/volatile/tmp_repo_door
 | 
			
		||||
 | 
			
		||||
	# Import base manifests. NOTE These are a combination of basic requirement
 | 
			
		||||
	# and gleaned from container milestone manifest. They may change.
 | 
			
		||||
	for m in $rootfsDir/lib/svc/manifest/system/environment.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/system/svc/global.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/system/svc/restarter.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/network/dns/client.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/system/name-service/switch.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/system/name-service/cache.xml \
 | 
			
		||||
		$rootfsDir/lib/svc/manifest/milestone/container.xml ; do
 | 
			
		||||
		svccfg import $m
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# Apply system layer profile, deleting unnecessary dependencies
 | 
			
		||||
	svccfg apply $rootfsDir/etc/svc/profile/generic_container.xml 
 | 
			
		||||
 | 
			
		||||
	# XXX Even if we keep a repo in the base image, this is definitely optional
 | 
			
		||||
	svccfg apply $rootfsDir/etc/svc/profile/sysconfig/container_sc.xml
 | 
			
		||||
 | 
			
		||||
	for s in svc:/system/svc/restarter \
 | 
			
		||||
		svc:/system/environment \
 | 
			
		||||
		svc:/network/dns/client \
 | 
			
		||||
		svc:/system/name-service/switch \
 | 
			
		||||
		svc:/system/name-service/cache \
 | 
			
		||||
		svc:/system/svc/global \
 | 
			
		||||
		svc:/milestone/container ;do
 | 
			
		||||
		svccfg -s $s refresh
 | 
			
		||||
	done
 | 
			
		||||
 | 
			
		||||
	# now copy the built up repository into the base rootfs
 | 
			
		||||
	mv $REPO_DB $rootfsDir/etc/svc/repository.db
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# pkg(1) needs the zoneproxy-client running in the container.
 | 
			
		||||
# use a simple wrapper to run it as needed.
 | 
			
		||||
# XXX maybe we go back to running this in SMF?
 | 
			
		||||
mv "$rootfsDir/usr/bin/pkg" "$rootfsDir/usr/bin/wrapped_pkg"
 | 
			
		||||
cat > "$rootfsDir/usr/bin/pkg" <<-'EOF'
 | 
			
		||||
#!/bin/sh
 | 
			
		||||
#
 | 
			
		||||
# THIS FILE CREATED DURING DOCKER BASE IMAGE CREATION
 | 
			
		||||
# 
 | 
			
		||||
# The Solaris base image uses the sysrepo proxy mechanism. The
 | 
			
		||||
# IPS client pkg(1) requires the zoneproxy-client to reach the
 | 
			
		||||
# remote publisher origins through the host. This wrapper script
 | 
			
		||||
# enables and disables the proxy client as needed. This is a
 | 
			
		||||
# temporary solution.
 | 
			
		||||
 | 
			
		||||
/usr/lib/zones/zoneproxy-client -s localhost:1008
 | 
			
		||||
PKG_SYSREPO_URL=http://localhost:1008 /usr/bin/wrapped_pkg "$@"
 | 
			
		||||
pkill -9 zoneproxy-client
 | 
			
		||||
EOF
 | 
			
		||||
chmod +x "$rootfsDir/usr/bin/pkg"
 | 
			
		||||
							
								
								
									
										5
									
								
								daemon/bindmount_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								daemon/bindmount_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
// +build solaris
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
const bindMountType = "lofs"
 | 
			
		||||
							
								
								
									
										5
									
								
								daemon/bindmount_unix.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								daemon/bindmount_unix.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
// +build linux freebsd
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
const bindMountType = "bind"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build !linux
 | 
			
		||||
// +build !linux,!solaris
 | 
			
		||||
 | 
			
		||||
package cluster
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										57
									
								
								daemon/cluster/listen_addr_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								daemon/cluster/listen_addr_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
package cluster
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (c *Cluster) resolveSystemAddr() (net.IP, error) {
 | 
			
		||||
	defRouteCmd := "/usr/sbin/ipadm show-addr -p -o addr " +
 | 
			
		||||
		"`/usr/sbin/route get default | /usr/bin/grep interface | " +
 | 
			
		||||
		"/usr/bin/awk '{print $2}'`"
 | 
			
		||||
	out, err := exec.Command("/usr/bin/bash", "-c", defRouteCmd).Output()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("cannot get default route: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defInterface := strings.SplitN(string(out), "/", 2)
 | 
			
		||||
	defInterfaceIP := net.ParseIP(defInterface[0])
 | 
			
		||||
 | 
			
		||||
	return defInterfaceIP, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listSystemIPs() []net.IP {
 | 
			
		||||
	var systemAddrs []net.IP
 | 
			
		||||
	cmd := exec.Command("/usr/sbin/ipadm", "show-addr", "-p", "-o", "addr")
 | 
			
		||||
	cmdReader, err := cmd.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := cmd.Start(); err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	scanner := bufio.NewScanner(cmdReader)
 | 
			
		||||
	go func() {
 | 
			
		||||
		for scanner.Scan() {
 | 
			
		||||
			text := scanner.Text()
 | 
			
		||||
			nameAddrPair := strings.SplitN(text, "/", 2)
 | 
			
		||||
			// Let go of loopback interfaces and docker interfaces
 | 
			
		||||
			systemAddrs = append(systemAddrs, net.ParseIP(nameAddrPair[0]))
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if err := scanner.Err(); err != nil {
 | 
			
		||||
		fmt.Printf("scan underwent err: %+v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := cmd.Wait(); err != nil {
 | 
			
		||||
		fmt.Printf("run command wait: %+v\n", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return systemAddrs
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -126,9 +126,9 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
 | 
			
		|||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// It is not possible to commit a running container on Windows
 | 
			
		||||
	if runtime.GOOS == "windows" && container.IsRunning() {
 | 
			
		||||
		return "", fmt.Errorf("Windows does not support commit of a running container")
 | 
			
		||||
	// It is not possible to commit a running container on Windows and on Solaris.
 | 
			
		||||
	if (runtime.GOOS == "windows" || runtime.GOOS == "solaris") && container.IsRunning() {
 | 
			
		||||
		return "", fmt.Errorf("%+v does not support commit of a running container", runtime.GOOS)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if c.Pause && !container.IsPaused() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
| 
						 | 
				
			
			@ -221,6 +222,9 @@ func NewConfig() *Config {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) {
 | 
			
		||||
	if runtime.GOOS == "solaris" && (clusterAdvertise != "" || clusterStore != "") {
 | 
			
		||||
		return "", errors.New("Cluster Advertise Settings not supported on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	if clusterAdvertise == "" {
 | 
			
		||||
		return "", errDiscoveryDisabled
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										80
									
								
								daemon/config_common_unix.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								daemon/config_common_unix.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
// +build solaris linux freebsd
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/opts"
 | 
			
		||||
	runconfigopts "github.com/docker/docker/runconfig/opts"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CommonUnixConfig defines configuration of a docker daemon that is
 | 
			
		||||
// common across Unix platforms.
 | 
			
		||||
type CommonUnixConfig struct {
 | 
			
		||||
	ExecRoot       string                   `json:"exec-root,omitempty"`
 | 
			
		||||
	ContainerdAddr string                   `json:"containerd,omitempty"`
 | 
			
		||||
	Runtimes       map[string]types.Runtime `json:"runtimes,omitempty"`
 | 
			
		||||
	DefaultRuntime string                   `json:"default-runtime,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type commonUnixBridgeConfig struct {
 | 
			
		||||
	DefaultIP                   net.IP `json:"ip,omitempty"`
 | 
			
		||||
	IP                          string `json:"bip,omitempty"`
 | 
			
		||||
	DefaultGatewayIPv4          net.IP `json:"default-gateway,omitempty"`
 | 
			
		||||
	DefaultGatewayIPv6          net.IP `json:"default-gateway-v6,omitempty"`
 | 
			
		||||
	InterContainerCommunication bool   `json:"icc,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstallCommonUnixFlags adds command-line options to the top-level flag parser for
 | 
			
		||||
// the current process that are common across Unix platforms.
 | 
			
		||||
func (config *Config) InstallCommonUnixFlags(flags *pflag.FlagSet) {
 | 
			
		||||
	config.Runtimes = make(map[string]types.Runtime)
 | 
			
		||||
 | 
			
		||||
	flags.StringVarP(&config.SocketGroup, "group", "G", "docker", "Group for the unix socket")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.IP, "bip", "", "Specify network bridge IP")
 | 
			
		||||
	flags.StringVarP(&config.bridgeConfig.Iface, "bridge", "b", "", "Attach containers to a network bridge")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), "default-gateway", "Container default gateway IPv4 address")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), "default-gateway-v6", "Container default gateway IPv6 address")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), "ip", "Default IP when binding container ports")
 | 
			
		||||
	flags.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
 | 
			
		||||
	flags.StringVar(&config.DefaultRuntime, "default-runtime", stockRuntimeName, "Default OCI runtime for containers")
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRuntime returns the runtime path and arguments for a given
 | 
			
		||||
// runtime name
 | 
			
		||||
func (config *Config) GetRuntime(name string) *types.Runtime {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	defer config.reloadLock.Unlock()
 | 
			
		||||
	if rt, ok := config.Runtimes[name]; ok {
 | 
			
		||||
		return &rt
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDefaultRuntimeName returns the current default runtime
 | 
			
		||||
func (config *Config) GetDefaultRuntimeName() string {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	rt := config.DefaultRuntime
 | 
			
		||||
	config.reloadLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	return rt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllRuntimes returns a copy of the runtimes map
 | 
			
		||||
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	rts := config.Runtimes
 | 
			
		||||
	config.reloadLock.Unlock()
 | 
			
		||||
	return rts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExecRoot returns the user configured Exec-root
 | 
			
		||||
func (config *Config) GetExecRoot() string {
 | 
			
		||||
	return config.ExecRoot
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5,7 +5,7 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	defaultPidFile = "/var/run/docker.pid"
 | 
			
		||||
	defaultPidFile = "/system/volatile/docker/docker.pid"
 | 
			
		||||
	defaultGraph   = "/var/lib/docker"
 | 
			
		||||
	defaultExec    = "zones"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -16,14 +16,17 @@ var (
 | 
			
		|||
type Config struct {
 | 
			
		||||
	CommonConfig
 | 
			
		||||
 | 
			
		||||
	// Fields below here are platform specific.
 | 
			
		||||
	ExecRoot string `json:"exec-root,omitempty"`
 | 
			
		||||
	// These fields are common to all unix platforms.
 | 
			
		||||
	CommonUnixConfig
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bridgeConfig stores all the bridge driver specific
 | 
			
		||||
// configuration.
 | 
			
		||||
type bridgeConfig struct {
 | 
			
		||||
	commonBridgeConfig
 | 
			
		||||
 | 
			
		||||
	// Fields below here are platform specific.
 | 
			
		||||
	commonUnixBridgeConfig
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstallFlags adds command-line options to the top-level flag parser for
 | 
			
		||||
| 
						 | 
				
			
			@ -32,14 +35,13 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
 | 
			
		|||
	// First handle install flags which are consistent cross-platform
 | 
			
		||||
	config.InstallCommonFlags(flags)
 | 
			
		||||
 | 
			
		||||
	// Then install flags common to unix platforms
 | 
			
		||||
	config.InstallCommonUnixFlags(flags)
 | 
			
		||||
 | 
			
		||||
	// Then platform-specific install flags
 | 
			
		||||
	config.attachExperimentalFlags(flags)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExecRoot returns the user configured Exec-root
 | 
			
		||||
func (config *Config) GetExecRoot() string {
 | 
			
		||||
	return config.ExecRoot
 | 
			
		||||
}
 | 
			
		||||
func (config *Config) isSwarmCompatible() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,6 +36,9 @@ func TestDaemonBrokenConfiguration(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestParseClusterAdvertiseSettings(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("ClusterSettings not supported on Solaris\n")
 | 
			
		||||
	}
 | 
			
		||||
	_, err := parseClusterAdvertiseSettings("something", "")
 | 
			
		||||
	if err != errDiscoveryDisabled {
 | 
			
		||||
		t.Fatalf("expected discovery disabled error, got %v\n", err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,10 +4,7 @@ package daemon
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/opts"
 | 
			
		||||
	runconfigopts "github.com/docker/docker/runconfig/opts"
 | 
			
		||||
	units "github.com/docker/go-units"
 | 
			
		||||
	"github.com/spf13/pflag"
 | 
			
		||||
| 
						 | 
				
			
			@ -25,15 +22,14 @@ var (
 | 
			
		|||
type Config struct {
 | 
			
		||||
	CommonConfig
 | 
			
		||||
 | 
			
		||||
	// These fields are common to all unix platforms.
 | 
			
		||||
	CommonUnixConfig
 | 
			
		||||
 | 
			
		||||
	// Fields below here are platform specific.
 | 
			
		||||
	CgroupParent         string                   `json:"cgroup-parent,omitempty"`
 | 
			
		||||
	ContainerdAddr       string                   `json:"containerd,omitempty"`
 | 
			
		||||
	EnableSelinuxSupport bool                     `json:"selinux-enabled,omitempty"`
 | 
			
		||||
	ExecRoot             string                   `json:"exec-root,omitempty"`
 | 
			
		||||
	RemappedRoot         string                   `json:"userns-remap,omitempty"`
 | 
			
		||||
	Ulimits              map[string]*units.Ulimit `json:"default-ulimits,omitempty"`
 | 
			
		||||
	Runtimes             map[string]types.Runtime `json:"runtimes,omitempty"`
 | 
			
		||||
	DefaultRuntime       string                   `json:"default-runtime,omitempty"`
 | 
			
		||||
	CPURealtimePeriod    int64                    `json:"cpu-rt-period,omitempty"`
 | 
			
		||||
	CPURealtimeRuntime   int64                    `json:"cpu-rt-runtime,omitempty"`
 | 
			
		||||
	OOMScoreAdjust       int                      `json:"oom-score-adjust,omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +43,9 @@ type Config struct {
 | 
			
		|||
type bridgeConfig struct {
 | 
			
		||||
	commonBridgeConfig
 | 
			
		||||
 | 
			
		||||
	// These fields are common to all unix platforms.
 | 
			
		||||
	commonUnixBridgeConfig
 | 
			
		||||
 | 
			
		||||
	// Fields below here are platform specific.
 | 
			
		||||
	EnableIPv6          bool   `json:"ipv6,omitempty"`
 | 
			
		||||
	EnableIPTables      bool   `json:"iptables,omitempty"`
 | 
			
		||||
| 
						 | 
				
			
			@ -54,12 +53,7 @@ type bridgeConfig struct {
 | 
			
		|||
	EnableIPMasq        bool   `json:"ip-masq,omitempty"`
 | 
			
		||||
	EnableUserlandProxy bool   `json:"userland-proxy,omitempty"`
 | 
			
		||||
	UserlandProxyPath   string `json:"userland-proxy-path,omitempty"`
 | 
			
		||||
	DefaultIP                   net.IP `json:"ip,omitempty"`
 | 
			
		||||
	IP                          string `json:"bip,omitempty"`
 | 
			
		||||
	FixedCIDRv6         string `json:"fixed-cidr-v6,omitempty"`
 | 
			
		||||
	DefaultGatewayIPv4          net.IP `json:"default-gateway,omitempty"`
 | 
			
		||||
	DefaultGatewayIPv6          net.IP `json:"default-gateway-v6,omitempty"`
 | 
			
		||||
	InterContainerCommunication bool   `json:"icc,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InstallFlags adds flags to the pflag.FlagSet to configure the daemon
 | 
			
		||||
| 
						 | 
				
			
			@ -67,26 +61,20 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
 | 
			
		|||
	// First handle install flags which are consistent cross-platform
 | 
			
		||||
	config.InstallCommonFlags(flags)
 | 
			
		||||
 | 
			
		||||
	// Then install flags common to unix platforms
 | 
			
		||||
	config.InstallCommonUnixFlags(flags)
 | 
			
		||||
 | 
			
		||||
	config.Ulimits = make(map[string]*units.Ulimit)
 | 
			
		||||
	config.Runtimes = make(map[string]types.Runtime)
 | 
			
		||||
 | 
			
		||||
	// Then platform-specific install flags
 | 
			
		||||
	flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support")
 | 
			
		||||
	flags.StringVarP(&config.SocketGroup, "group", "G", "docker", "Group for the unix socket")
 | 
			
		||||
	flags.Var(runconfigopts.NewUlimitOpt(&config.Ulimits), "default-ulimit", "Default ulimits for containers")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.EnableIPTables, "iptables", true, "Enable addition of iptables rules")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.EnableIPForward, "ip-forward", true, "Enable net.ipv4.ip_forward")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.EnableIPv6, "ipv6", false, "Enable IPv6 networking")
 | 
			
		||||
	flags.StringVar(&config.ExecRoot, "exec-root", defaultExecRoot, "Root directory for execution state files")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.IP, "bip", "", "Specify network bridge IP")
 | 
			
		||||
	flags.StringVarP(&config.bridgeConfig.Iface, "bridge", "b", "", "Attach containers to a network bridge")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.FixedCIDR, "fixed-cidr", "", "IPv4 subnet for fixed IPs")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.FixedCIDRv6, "fixed-cidr-v6", "", "IPv6 subnet for fixed IPs")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv4, ""), "default-gateway", "Container default gateway IPv4 address")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultGatewayIPv6, ""), "default-gateway-v6", "Container default gateway IPv6 address")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.InterContainerCommunication, "icc", true, "Enable inter-container communication")
 | 
			
		||||
	flags.Var(opts.NewIPOpt(&config.bridgeConfig.DefaultIP, "0.0.0.0"), "ip", "Default IP when binding container ports")
 | 
			
		||||
	flags.BoolVar(&config.bridgeConfig.EnableUserlandProxy, "userland-proxy", true, "Use userland proxy for loopback traffic")
 | 
			
		||||
	flags.StringVar(&config.bridgeConfig.UserlandProxyPath, "userland-proxy-path", "", "Path to the userland proxy binary")
 | 
			
		||||
	flags.BoolVar(&config.EnableCors, "api-enable-cors", false, "Enable CORS headers in the remote API, this is deprecated by --api-cors-header")
 | 
			
		||||
| 
						 | 
				
			
			@ -95,8 +83,6 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
 | 
			
		|||
	flags.StringVar(&config.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces")
 | 
			
		||||
	flags.StringVar(&config.ContainerdAddr, "containerd", "", "Path to containerd socket")
 | 
			
		||||
	flags.BoolVar(&config.LiveRestoreEnabled, "live-restore", false, "Enable live restore of docker when containers are still running")
 | 
			
		||||
	flags.Var(runconfigopts.NewNamedRuntimeOpt("runtimes", &config.Runtimes, stockRuntimeName), "add-runtime", "Register an additional OCI compatible runtime")
 | 
			
		||||
	flags.StringVar(&config.DefaultRuntime, "default-runtime", stockRuntimeName, "Default OCI runtime for containers")
 | 
			
		||||
	flags.IntVar(&config.OOMScoreAdjust, "oom-score-adjust", -500, "Set the oom_score_adj for the daemon")
 | 
			
		||||
	flags.BoolVar(&config.Init, "init", false, "Run an init in the container to forward signals and reap processes")
 | 
			
		||||
	flags.StringVar(&config.InitPath, "init-path", "", "Path to the docker-init binary")
 | 
			
		||||
| 
						 | 
				
			
			@ -107,39 +93,6 @@ func (config *Config) InstallFlags(flags *pflag.FlagSet) {
 | 
			
		|||
	config.attachExperimentalFlags(flags)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRuntime returns the runtime path and arguments for a given
 | 
			
		||||
// runtime name
 | 
			
		||||
func (config *Config) GetRuntime(name string) *types.Runtime {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	defer config.reloadLock.Unlock()
 | 
			
		||||
	if rt, ok := config.Runtimes[name]; ok {
 | 
			
		||||
		return &rt
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDefaultRuntimeName returns the current default runtime
 | 
			
		||||
func (config *Config) GetDefaultRuntimeName() string {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	rt := config.DefaultRuntime
 | 
			
		||||
	config.reloadLock.Unlock()
 | 
			
		||||
 | 
			
		||||
	return rt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllRuntimes returns a copy of the runtimes map
 | 
			
		||||
func (config *Config) GetAllRuntimes() map[string]types.Runtime {
 | 
			
		||||
	config.reloadLock.Lock()
 | 
			
		||||
	rts := config.Runtimes
 | 
			
		||||
	config.reloadLock.Unlock()
 | 
			
		||||
	return rts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetExecRoot returns the user configured Exec-root
 | 
			
		||||
func (config *Config) GetExecRoot() string {
 | 
			
		||||
	return config.ExecRoot
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (config *Config) isSwarmCompatible() error {
 | 
			
		||||
	if config.ClusterStore != "" || config.ClusterAdvertise != "" {
 | 
			
		||||
		return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,25 +2,20 @@
 | 
			
		|||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import "github.com/docker/docker/container"
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/libnetwork"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSize returns real size & virtual size
 | 
			
		||||
func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
 | 
			
		||||
	return 0, 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) setupIpcDirs(container *container.Container) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) mountVolumes(container *container.Container) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func killProcessDirectly(container *container.Container) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -30,9 +25,22 @@ func detachMounted(path string) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func isLinkable(child *container.Container) bool {
 | 
			
		||||
	// A container is linkable only if it belongs to the default network
 | 
			
		||||
	_, ok := child.NetworkSettings.Networks[runconfig.DefaultDaemonNetworkMode().NetworkName()]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func enableIPOnPredefinedNetwork() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) isNetworkHotPluggable() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupPathsAndSandboxOptions(container *container.Container, sboxOptions *[]libnetwork.SandboxOption) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initializeNetworkingPaths(container *container.Container, nc *container.Container) {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,9 +15,7 @@ import (
 | 
			
		|||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
	"github.com/docker/docker/daemon/links"
 | 
			
		||||
	"github.com/docker/docker/pkg/fileutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/idtools"
 | 
			
		||||
	"github.com/docker/docker/pkg/mount"
 | 
			
		||||
	"github.com/docker/docker/pkg/stringid"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/libnetwork"
 | 
			
		||||
| 
						 | 
				
			
			@ -63,39 +61,6 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
 | 
			
		|||
	return env, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getSize returns the real size & virtual size of the container.
 | 
			
		||||
func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
 | 
			
		||||
	var (
 | 
			
		||||
		sizeRw, sizeRootfs int64
 | 
			
		||||
		err                error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err := daemon.Mount(container); err != nil {
 | 
			
		||||
		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
 | 
			
		||||
		return sizeRw, sizeRootfs
 | 
			
		||||
	}
 | 
			
		||||
	defer daemon.Unmount(container)
 | 
			
		||||
 | 
			
		||||
	sizeRw, err = container.RWLayer.Size()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s",
 | 
			
		||||
			daemon.GraphDriverName(), container.ID, err)
 | 
			
		||||
		// FIXME: GetSize should return an error. Not changing it now in case
 | 
			
		||||
		// there is a side-effect.
 | 
			
		||||
		sizeRw = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if parent := container.RWLayer.Parent(); parent != nil {
 | 
			
		||||
		sizeRootfs, err = parent.Size()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			sizeRootfs = -1
 | 
			
		||||
		} else if sizeRw != -1 {
 | 
			
		||||
			sizeRootfs += sizeRw
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sizeRw, sizeRootfs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) getIpcContainer(container *container.Container) (*container.Container, error) {
 | 
			
		||||
	containerID := container.HostConfig.IpcMode.Container()
 | 
			
		||||
	c, err := daemon.GetContainer(containerID)
 | 
			
		||||
| 
						 | 
				
			
			@ -174,54 +139,6 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
 | 
			
		|||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) mountVolumes(container *container.Container) error {
 | 
			
		||||
	mounts, err := daemon.setupMounts(container)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, m := range mounts {
 | 
			
		||||
		dest, err := container.GetResourcePath(m.Destination)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var stat os.FileInfo
 | 
			
		||||
		stat, err = os.Stat(m.Source)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		opts := "rbind,ro"
 | 
			
		||||
		if m.Writable {
 | 
			
		||||
			opts = "rbind,rw"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := mount.Mount(m.Source, dest, "bind", opts); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// mountVolumes() seems to be called for temporary mounts
 | 
			
		||||
		// outside the container. Soon these will be unmounted with
 | 
			
		||||
		// lazy unmount option and given we have mounted the rbind,
 | 
			
		||||
		// all the submounts will propagate if these are shared. If
 | 
			
		||||
		// daemon is running in host namespace and has / as shared
 | 
			
		||||
		// then these unmounts will propagate and unmount original
 | 
			
		||||
		// mount as well. So make all these mounts rprivate.
 | 
			
		||||
		// Do not use propagation property of volume as that should
 | 
			
		||||
		// apply only when mounting happen inside the container.
 | 
			
		||||
		if err := mount.MakeRPrivate(dest); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func killProcessDirectly(container *container.Container) error {
 | 
			
		||||
	if _, err := container.WaitStop(10 * time.Second); err != nil {
 | 
			
		||||
		// Ensure that we don't kill ourselves
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,14 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/api/errors"
 | 
			
		||||
	apierrors "github.com/docker/docker/api/errors"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
	networktypes "github.com/docker/docker/api/types/network"
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +81,10 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
 | 
			
		|||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if runtime.GOOS == "solaris" && img.OS != "solaris " {
 | 
			
		||||
			return nil, errors.New("Platform on which parent image was created is not Solaris")
 | 
			
		||||
		}
 | 
			
		||||
		imgID = img.ID()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -260,14 +267,14 @@ func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingCo
 | 
			
		|||
		for _, v := range nwConfig.EndpointsConfig {
 | 
			
		||||
			if v != nil && v.IPAMConfig != nil {
 | 
			
		||||
				if v.IPAMConfig.IPv4Address != "" && net.ParseIP(v.IPAMConfig.IPv4Address).To4() == nil {
 | 
			
		||||
					return errors.NewBadRequestError(fmt.Errorf("invalid IPv4 address: %s", v.IPAMConfig.IPv4Address))
 | 
			
		||||
					return apierrors.NewBadRequestError(fmt.Errorf("invalid IPv4 address: %s", v.IPAMConfig.IPv4Address))
 | 
			
		||||
				}
 | 
			
		||||
				if v.IPAMConfig.IPv6Address != "" {
 | 
			
		||||
					n := net.ParseIP(v.IPAMConfig.IPv6Address)
 | 
			
		||||
					// if the address is an invalid network address (ParseIP == nil) or if it is
 | 
			
		||||
					// an IPv4 address (To4() != nil), then it is an invalid IPv6 address
 | 
			
		||||
					if n == nil || n.To4() != nil {
 | 
			
		||||
						return errors.NewBadRequestError(fmt.Errorf("invalid IPv6 address: %s", v.IPAMConfig.IPv6Address))
 | 
			
		||||
						return apierrors.NewBadRequestError(fmt.Errorf("invalid IPv6 address: %s", v.IPAMConfig.IPv6Address))
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -279,5 +286,5 @@ func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingCo
 | 
			
		|||
		l = append(l, k)
 | 
			
		||||
	}
 | 
			
		||||
	err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
 | 
			
		||||
	return errors.NewBadRequestError(err)
 | 
			
		||||
	return apierrors.NewBadRequestError(err)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,7 +4,10 @@ package daemon
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
| 
						 | 
				
			
			@ -12,9 +15,17 @@ import (
 | 
			
		|||
	"github.com/docker/docker/layer"
 | 
			
		||||
	"github.com/docker/docker/pkg/idtools"
 | 
			
		||||
	"github.com/docker/docker/pkg/parsers/kernel"
 | 
			
		||||
	"github.com/docker/docker/pkg/sysinfo"
 | 
			
		||||
	"github.com/docker/docker/reference"
 | 
			
		||||
	"github.com/docker/libnetwork"
 | 
			
		||||
	nwconfig "github.com/docker/libnetwork/config"
 | 
			
		||||
	"github.com/docker/libnetwork/drivers/solaris/bridge"
 | 
			
		||||
	"github.com/docker/libnetwork/netlabel"
 | 
			
		||||
	"github.com/docker/libnetwork/netutils"
 | 
			
		||||
	lntypes "github.com/docker/libnetwork/types"
 | 
			
		||||
	"github.com/opencontainers/runc/libcontainer/label"
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//#include <zone.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -27,12 +38,50 @@ const (
 | 
			
		|||
	solarisMaxCPUShares  = 65535
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getMemoryResources(config containertypes.Resources) specs.CappedMemory {
 | 
			
		||||
	memory := specs.CappedMemory{}
 | 
			
		||||
 | 
			
		||||
	if config.Memory > 0 {
 | 
			
		||||
		memory.Physical = strconv.FormatInt(config.Memory, 10)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.MemorySwap != 0 {
 | 
			
		||||
		memory.Swap = strconv.FormatInt(config.MemorySwap, 10)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return memory
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCPUResources(config containertypes.Resources) specs.CappedCPU {
 | 
			
		||||
	cpu := specs.CappedCPU{}
 | 
			
		||||
 | 
			
		||||
	if config.CpusetCpus != "" {
 | 
			
		||||
		cpu.Ncpus = config.CpusetCpus
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cpu
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) cleanupMountsByID(id string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error {
 | 
			
		||||
	return nil
 | 
			
		||||
	//Since config.SecurityOpt is specifically defined as a "List of string values to
 | 
			
		||||
	//customize labels for MLs systems, such as SELinux"
 | 
			
		||||
	//until we figure out how to map to Trusted Extensions
 | 
			
		||||
	//this is being disabled for now on Solaris
 | 
			
		||||
	var (
 | 
			
		||||
		labelOpts []string
 | 
			
		||||
		err       error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if len(config.SecurityOpt) > 0 {
 | 
			
		||||
		return errors.New("Security options are not supported on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	container.ProcessLabel, container.MountLabel, err = label.InitLabels(labelOpts)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
 | 
			
		||||
| 
						 | 
				
			
			@ -67,13 +116,198 @@ func (daemon *Daemon) getCgroupDriver() string {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConfig, adjustCPUShares bool) error {
 | 
			
		||||
	if hostConfig.CPUShares < 0 {
 | 
			
		||||
		logrus.Warnf("Changing requested CPUShares of %d to minimum allowed of %d", hostConfig.CPUShares, solarisMinCPUShares)
 | 
			
		||||
		hostConfig.CPUShares = solarisMinCPUShares
 | 
			
		||||
	} else if hostConfig.CPUShares > solarisMaxCPUShares {
 | 
			
		||||
		logrus.Warnf("Changing requested CPUShares of %d to maximum allowed of %d", hostConfig.CPUShares, solarisMaxCPUShares)
 | 
			
		||||
		hostConfig.CPUShares = solarisMaxCPUShares
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.Memory > 0 && hostConfig.MemorySwap == 0 {
 | 
			
		||||
		// By default, MemorySwap is set to twice the size of Memory.
 | 
			
		||||
		hostConfig.MemorySwap = hostConfig.Memory * 2
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.ShmSize != 0 {
 | 
			
		||||
		hostConfig.ShmSize = container.DefaultSHMSize
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.OomKillDisable == nil {
 | 
			
		||||
		defaultOomKillDisable := false
 | 
			
		||||
		hostConfig.OomKillDisable = &defaultOomKillDisable
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UsingSystemd returns true if cli option includes native.cgroupdriver=systemd
 | 
			
		||||
func UsingSystemd(config *Config) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// verifyPlatformContainerSettings performs platform-specific validation of the
 | 
			
		||||
// hostconfig and config structures.
 | 
			
		||||
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
 | 
			
		||||
	warnings := []string{}
 | 
			
		||||
	sysInfo := sysinfo.New(true)
 | 
			
		||||
	// NOTE: We do not enforce a minimum value for swap limits for zones on Solaris and
 | 
			
		||||
	// therefore we will not do that for Docker container either.
 | 
			
		||||
	if hostConfig.Memory > 0 && !sysInfo.MemoryLimit {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support memory limit capabilities. Limitation discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support memory limit capabilities. Limitation discarded.")
 | 
			
		||||
		hostConfig.Memory = 0
 | 
			
		||||
		hostConfig.MemorySwap = -1
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.Memory > 0 && hostConfig.MemorySwap != -1 && !sysInfo.SwapLimit {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support swap limit capabilities, memory limited without swap.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support swap limit capabilities, memory limited without swap.")
 | 
			
		||||
		hostConfig.MemorySwap = -1
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.Memory > 0 && hostConfig.MemorySwap > 0 && hostConfig.MemorySwap < hostConfig.Memory {
 | 
			
		||||
		return warnings, fmt.Errorf("Minimum memoryswap limit should be larger than memory limit, see usage.")
 | 
			
		||||
	}
 | 
			
		||||
	// Solaris NOTE: We allow and encourage setting the swap without setting the memory limit.
 | 
			
		||||
 | 
			
		||||
	if hostConfig.MemorySwappiness != nil && *hostConfig.MemorySwappiness != -1 && !sysInfo.MemorySwappiness {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support memory swappiness capabilities, memory swappiness discarded.")
 | 
			
		||||
		hostConfig.MemorySwappiness = nil
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.MemoryReservation > 0 && !sysInfo.MemoryReservation {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support memory soft limit capabilities. Limitation discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support memory soft limit capabilities. Limitation discarded.")
 | 
			
		||||
		hostConfig.MemoryReservation = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.Memory > 0 && hostConfig.MemoryReservation > 0 && hostConfig.Memory < hostConfig.MemoryReservation {
 | 
			
		||||
		return warnings, fmt.Errorf("Minimum memory limit should be larger than memory reservation limit, see usage.")
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.KernelMemory > 0 && !sysInfo.KernelMemory {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support kernel memory limit capabilities. Limitation discarded.")
 | 
			
		||||
		hostConfig.KernelMemory = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.CPUShares != 0 && !sysInfo.CPUShares {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support CPU shares. Shares discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support CPU shares. Shares discarded.")
 | 
			
		||||
		hostConfig.CPUShares = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.CPUShares < 0 {
 | 
			
		||||
		warnings = append(warnings, "Invalid CPUShares value. Must be positive. Discarding.")
 | 
			
		||||
		logrus.Warnf("Invalid CPUShares value. Must be positive. Discarding.")
 | 
			
		||||
		hostConfig.CPUQuota = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.CPUShares > 0 && !sysinfo.IsCPUSharesAvailable() {
 | 
			
		||||
		warnings = append(warnings, "Global zone default scheduling class not FSS. Discarding shares.")
 | 
			
		||||
		logrus.Warnf("Global zone default scheduling class not FSS. Discarding shares.")
 | 
			
		||||
		hostConfig.CPUShares = 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Solaris NOTE: Linux does not do negative checking for CPUShares and Quota here. But it makes sense to.
 | 
			
		||||
	if hostConfig.CPUPeriod > 0 && !sysInfo.CPUCfsPeriod {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support CPU cfs period. Period discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support CPU cfs period. Period discarded.")
 | 
			
		||||
		if hostConfig.CPUQuota > 0 {
 | 
			
		||||
			warnings = append(warnings, "Quota will be applied on default period, not period specified.")
 | 
			
		||||
			logrus.Warnf("Quota will be applied on default period, not period specified.")
 | 
			
		||||
		}
 | 
			
		||||
		hostConfig.CPUPeriod = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.CPUQuota != 0 && !sysInfo.CPUCfsQuota {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support CPU cfs quota. Quota discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support CPU cfs quota. Quota discarded.")
 | 
			
		||||
		hostConfig.CPUQuota = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.CPUQuota < 0 {
 | 
			
		||||
		warnings = append(warnings, "Invalid CPUQuota value. Must be positive. Discarding.")
 | 
			
		||||
		logrus.Warnf("Invalid CPUQuota value. Must be positive. Discarding.")
 | 
			
		||||
		hostConfig.CPUQuota = 0
 | 
			
		||||
	}
 | 
			
		||||
	if (hostConfig.CpusetCpus != "" || hostConfig.CpusetMems != "") && !sysInfo.Cpuset {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support cpuset. Cpuset discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support cpuset. Cpuset discarded.")
 | 
			
		||||
		hostConfig.CpusetCpus = ""
 | 
			
		||||
		hostConfig.CpusetMems = ""
 | 
			
		||||
	}
 | 
			
		||||
	cpusAvailable, err := sysInfo.IsCpusetCpusAvailable(hostConfig.CpusetCpus)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return warnings, fmt.Errorf("Invalid value %s for cpuset cpus.", hostConfig.CpusetCpus)
 | 
			
		||||
	}
 | 
			
		||||
	if !cpusAvailable {
 | 
			
		||||
		return warnings, fmt.Errorf("Requested CPUs are not available - requested %s, available: %s.", hostConfig.CpusetCpus, sysInfo.Cpus)
 | 
			
		||||
	}
 | 
			
		||||
	memsAvailable, err := sysInfo.IsCpusetMemsAvailable(hostConfig.CpusetMems)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return warnings, fmt.Errorf("Invalid value %s for cpuset mems.", hostConfig.CpusetMems)
 | 
			
		||||
	}
 | 
			
		||||
	if !memsAvailable {
 | 
			
		||||
		return warnings, fmt.Errorf("Requested memory nodes are not available - requested %s, available: %s.", hostConfig.CpusetMems, sysInfo.Mems)
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.BlkioWeight > 0 && !sysInfo.BlkioWeight {
 | 
			
		||||
		warnings = append(warnings, "Your kernel does not support Block I/O weight. Weight discarded.")
 | 
			
		||||
		logrus.Warnf("Your kernel does not support Block I/O weight. Weight discarded.")
 | 
			
		||||
		hostConfig.BlkioWeight = 0
 | 
			
		||||
	}
 | 
			
		||||
	if hostConfig.OomKillDisable != nil && !sysInfo.OomKillDisable {
 | 
			
		||||
		*hostConfig.OomKillDisable = false
 | 
			
		||||
		// Don't warn; this is the default setting but only applicable to Linux
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if sysInfo.IPv4ForwardingDisabled {
 | 
			
		||||
		warnings = append(warnings, "IPv4 forwarding is disabled. Networking will not work.")
 | 
			
		||||
		logrus.Warnf("IPv4 forwarding is disabled. Networking will not work")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Solaris NOTE: We do not allow setting Linux specific options, so check and warn for all of them.
 | 
			
		||||
 | 
			
		||||
	if hostConfig.CapAdd != nil || hostConfig.CapDrop != nil {
 | 
			
		||||
		warnings = append(warnings, "Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.")
 | 
			
		||||
		logrus.Warnf("Adding or dropping kernel capabilities unsupported on Solaris.Discarding capabilities lists.")
 | 
			
		||||
		hostConfig.CapAdd = nil
 | 
			
		||||
		hostConfig.CapDrop = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.GroupAdd != nil {
 | 
			
		||||
		warnings = append(warnings, "Additional groups unsupported on Solaris.Discarding groups lists.")
 | 
			
		||||
		logrus.Warnf("Additional groups unsupported on Solaris.Discarding groups lists.")
 | 
			
		||||
		hostConfig.GroupAdd = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.IpcMode != "" {
 | 
			
		||||
		warnings = append(warnings, "IPC namespace assignment unsupported on Solaris.Discarding IPC setting.")
 | 
			
		||||
		logrus.Warnf("IPC namespace assignment unsupported on Solaris.Discarding IPC setting.")
 | 
			
		||||
		hostConfig.IpcMode = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.PidMode != "" {
 | 
			
		||||
		warnings = append(warnings, "PID namespace setting  unsupported on Solaris. Running container in host PID namespace.")
 | 
			
		||||
		logrus.Warnf("PID namespace setting  unsupported on Solaris. Running container in host PID namespace.")
 | 
			
		||||
		hostConfig.PidMode = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.Privileged {
 | 
			
		||||
		warnings = append(warnings, "Privileged mode unsupported on Solaris. Discarding privileged mode setting.")
 | 
			
		||||
		logrus.Warnf("Privileged mode unsupported on Solaris. Discarding privileged mode setting.")
 | 
			
		||||
		hostConfig.Privileged = false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.UTSMode != "" {
 | 
			
		||||
		warnings = append(warnings, "UTS namespace assignment unsupported on Solaris.Discarding UTS setting.")
 | 
			
		||||
		logrus.Warnf("UTS namespace assignment unsupported on Solaris.Discarding UTS setting.")
 | 
			
		||||
		hostConfig.UTSMode = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.CgroupParent != "" {
 | 
			
		||||
		warnings = append(warnings, "Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.")
 | 
			
		||||
		logrus.Warnf("Specifying Cgroup parent unsupported on Solaris. Discarding cgroup parent setting.")
 | 
			
		||||
		hostConfig.CgroupParent = ""
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hostConfig.Ulimits != nil {
 | 
			
		||||
		warnings = append(warnings, "Specifying ulimits unsupported on Solaris. Discarding ulimits setting.")
 | 
			
		||||
		logrus.Warnf("Specifying ulimits unsupported on Solaris. Discarding ulimits setting.")
 | 
			
		||||
		hostConfig.Ulimits = nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return warnings, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,6 +318,16 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string {
 | 
			
		|||
 | 
			
		||||
// verifyDaemonSettings performs validation of daemon config struct
 | 
			
		||||
func verifyDaemonSettings(config *Config) error {
 | 
			
		||||
 | 
			
		||||
	if config.DefaultRuntime == "" {
 | 
			
		||||
		config.DefaultRuntime = stockRuntimeName
 | 
			
		||||
	}
 | 
			
		||||
	if config.Runtimes == nil {
 | 
			
		||||
		config.Runtimes = make(map[string]types.Runtime)
 | 
			
		||||
	}
 | 
			
		||||
	stockRuntimeOpts := []string{}
 | 
			
		||||
	config.Runtimes[stockRuntimeName] = types.Runtime{Path: DefaultRuntimeBinary, Args: stockRuntimeOpts}
 | 
			
		||||
 | 
			
		||||
	// checkSystem validates platform-specific requirements
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +363,120 @@ func configureKernelSecuritySupport(config *Config, driverName string) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) initNetworkController(config *Config, activeSandboxes map[string]interface{}) (libnetwork.NetworkController, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
	netOptions, err := daemon.networkOptions(config, daemon.PluginStore, activeSandboxes)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	controller, err := libnetwork.New(netOptions...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("error obtaining controller instance: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Initialize default network on "null"
 | 
			
		||||
	if _, err := controller.NewNetwork("null", "none", "", libnetwork.NetworkOptionPersist(false)); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("Error creating default 'null' network: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !config.DisableBridge {
 | 
			
		||||
		// Initialize default driver "bridge"
 | 
			
		||||
		if err := initBridgeDriver(controller, config); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return controller, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initBridgeDriver(controller libnetwork.NetworkController, config *Config) error {
 | 
			
		||||
	if n, err := controller.NetworkByName("bridge"); err == nil {
 | 
			
		||||
		if err = n.Delete(); err != nil {
 | 
			
		||||
			return fmt.Errorf("could not delete the default bridge network: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bridgeName := bridge.DefaultBridgeName
 | 
			
		||||
	if config.bridgeConfig.Iface != "" {
 | 
			
		||||
		bridgeName = config.bridgeConfig.Iface
 | 
			
		||||
	}
 | 
			
		||||
	netOption := map[string]string{
 | 
			
		||||
		bridge.BridgeName:    bridgeName,
 | 
			
		||||
		bridge.DefaultBridge: strconv.FormatBool(true),
 | 
			
		||||
		netlabel.DriverMTU:   strconv.Itoa(config.Mtu),
 | 
			
		||||
		bridge.EnableICC:     strconv.FormatBool(config.bridgeConfig.InterContainerCommunication),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// --ip processing
 | 
			
		||||
	if config.bridgeConfig.DefaultIP != nil {
 | 
			
		||||
		netOption[bridge.DefaultBindingIP] = config.bridgeConfig.DefaultIP.String()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var ipamV4Conf *libnetwork.IpamConf
 | 
			
		||||
 | 
			
		||||
	ipamV4Conf = &libnetwork.IpamConf{AuxAddresses: make(map[string]string)}
 | 
			
		||||
 | 
			
		||||
	nwList, _, err := netutils.ElectInterfaceAddresses(bridgeName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.Wrap(err, "list bridge addresses failed")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nw := nwList[0]
 | 
			
		||||
	if len(nwList) > 1 && config.bridgeConfig.FixedCIDR != "" {
 | 
			
		||||
		_, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return errors.Wrap(err, "parse CIDR failed")
 | 
			
		||||
		}
 | 
			
		||||
		// Iterate through in case there are multiple addresses for the bridge
 | 
			
		||||
		for _, entry := range nwList {
 | 
			
		||||
			if fCIDR.Contains(entry.IP) {
 | 
			
		||||
				nw = entry
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ipamV4Conf.PreferredPool = lntypes.GetIPNetCanonical(nw).String()
 | 
			
		||||
	hip, _ := lntypes.GetHostPartIP(nw.IP, nw.Mask)
 | 
			
		||||
	if hip.IsGlobalUnicast() {
 | 
			
		||||
		ipamV4Conf.Gateway = nw.IP.String()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.bridgeConfig.IP != "" {
 | 
			
		||||
		ipamV4Conf.PreferredPool = config.bridgeConfig.IP
 | 
			
		||||
		ip, _, err := net.ParseCIDR(config.bridgeConfig.IP)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		ipamV4Conf.Gateway = ip.String()
 | 
			
		||||
	} else if bridgeName == bridge.DefaultBridgeName && ipamV4Conf.PreferredPool != "" {
 | 
			
		||||
		logrus.Infof("Default bridge (%s) is assigned with an IP address %s. Daemon option --bip can be used to set a preferred IP address", bridgeName, ipamV4Conf.PreferredPool)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.bridgeConfig.FixedCIDR != "" {
 | 
			
		||||
		_, fCIDR, err := net.ParseCIDR(config.bridgeConfig.FixedCIDR)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ipamV4Conf.SubPool = fCIDR.String()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if config.bridgeConfig.DefaultGatewayIPv4 != nil {
 | 
			
		||||
		ipamV4Conf.AuxAddresses["DefaultGatewayIPv4"] = config.bridgeConfig.DefaultGatewayIPv4.String()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v4Conf := []*libnetwork.IpamConf{ipamV4Conf}
 | 
			
		||||
	v6Conf := []*libnetwork.IpamConf{}
 | 
			
		||||
 | 
			
		||||
	// Initialize default network on "bridge" with the same name
 | 
			
		||||
	_, err = controller.NewNetwork("bridge", "bridge", "",
 | 
			
		||||
		libnetwork.NetworkOptionDriverOpts(netOption),
 | 
			
		||||
		libnetwork.NetworkOptionIpam("default", "", v4Conf, v6Conf, nil),
 | 
			
		||||
		libnetwork.NetworkOptionDeferIPv6Alloc(false))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error creating default 'bridge' network: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// registerLinks sets up links between containers and writes the
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +492,7 @@ func (daemon *Daemon) cleanupMounts() error {
 | 
			
		|||
// conditionalMountOnStart is a platform specific helper function during the
 | 
			
		||||
// container start to call mount.
 | 
			
		||||
func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
 | 
			
		||||
	return nil
 | 
			
		||||
	return daemon.Mount(container)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// conditionalUnmountOnCleanup is a platform specific helper function called
 | 
			
		||||
| 
						 | 
				
			
			@ -171,13 +528,6 @@ func setupDaemonProcess(config *Config) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// verifyVolumesInfo is a no-op on solaris.
 | 
			
		||||
// This is called during daemon initialization to migrate volumes from pre-1.7.
 | 
			
		||||
// Solaris was not supported on pre-1.7 daemons.
 | 
			
		||||
func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) setupSeccompProfile() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build !solaris
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
// +build !windows,!solaris
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										41
									
								
								daemon/getsize_unix.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								daemon/getsize_unix.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
// +build linux freebsd solaris
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// getSize returns the real size & virtual size of the container.
 | 
			
		||||
func (daemon *Daemon) getSize(container *container.Container) (int64, int64) {
 | 
			
		||||
	var (
 | 
			
		||||
		sizeRw, sizeRootfs int64
 | 
			
		||||
		err                error
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	if err := daemon.Mount(container); err != nil {
 | 
			
		||||
		logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err)
 | 
			
		||||
		return sizeRw, sizeRootfs
 | 
			
		||||
	}
 | 
			
		||||
	defer daemon.Unmount(container)
 | 
			
		||||
 | 
			
		||||
	sizeRw, err = container.RWLayer.Size()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logrus.Errorf("Driver %s couldn't return diff size of container %s: %s",
 | 
			
		||||
			daemon.GraphDriverName(), container.ID, err)
 | 
			
		||||
		// FIXME: GetSize should return an error. Not changing it now in case
 | 
			
		||||
		// there is a side-effect.
 | 
			
		||||
		sizeRw = -1
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if parent := container.RWLayer.Parent(); parent != nil {
 | 
			
		||||
		sizeRootfs, err = parent.Size()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			sizeRootfs = -1
 | 
			
		||||
		} else if sizeRw != -1 {
 | 
			
		||||
			sizeRootfs += sizeRw
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return sizeRw, sizeRootfs
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ import (
 | 
			
		|||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/pkg/mount"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +45,37 @@ func GetFSMagic(rootpath string) (FsMagic, error) {
 | 
			
		|||
	return 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fsChecker struct {
 | 
			
		||||
	t FsMagic
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *fsChecker) IsMounted(path string) bool {
 | 
			
		||||
	m, _ := Mounted(c.t, path)
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewFsChecker returns a checker configured for the provied FsMagic
 | 
			
		||||
func NewFsChecker(t FsMagic) Checker {
 | 
			
		||||
	return &fsChecker{
 | 
			
		||||
		t: t,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDefaultChecker returns a check that parses /proc/mountinfo to check
 | 
			
		||||
// if the specified path is mounted.
 | 
			
		||||
// No-op on Solaris.
 | 
			
		||||
func NewDefaultChecker() Checker {
 | 
			
		||||
	return &defaultChecker{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type defaultChecker struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *defaultChecker) IsMounted(path string) bool {
 | 
			
		||||
	m, _ := mount.Mounted(path)
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mounted checks if the given path is mounted as the fs type
 | 
			
		||||
//Solaris supports only ZFS for now
 | 
			
		||||
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build linux freebsd
 | 
			
		||||
// +build linux freebsd solaris
 | 
			
		||||
 | 
			
		||||
package graphtest
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/backend"
 | 
			
		||||
	"github.com/docker/docker/api/types/versions/v1p19"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
	"github.com/docker/docker/daemon/exec"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -13,8 +14,8 @@ func setPlatformSpecificContainerFields(container *container.Container, contJSON
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// containerInspectPre120 get containers for pre 1.20 APIs.
 | 
			
		||||
func (daemon *Daemon) containerInspectPre120(name string) (*types.ContainerJSON, error) {
 | 
			
		||||
	return daemon.containerInspectCurrent(name, false)
 | 
			
		||||
func (daemon *Daemon) containerInspectPre120(name string) (*v1p19.ContainerJSON, error) {
 | 
			
		||||
	return &v1p19.ContainerJSON{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addMountPoints(container *container.Container) []types.MountPoint {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,17 +3,19 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/api/errors"
 | 
			
		||||
	apierrors "github.com/docker/docker/api/errors"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	"github.com/docker/docker/api/types/network"
 | 
			
		||||
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
 | 
			
		||||
	"github.com/docker/docker/runconfig"
 | 
			
		||||
	"github.com/docker/libnetwork"
 | 
			
		||||
	networktypes "github.com/docker/libnetwork/types"
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +238,7 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string
 | 
			
		|||
 | 
			
		||||
	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
 | 
			
		||||
		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
 | 
			
		||||
		return nil, errors.NewRequestForbiddenError(err)
 | 
			
		||||
		return nil, apierrors.NewRequestForbiddenError(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var warning string
 | 
			
		||||
| 
						 | 
				
			
			@ -336,6 +338,9 @@ func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, service
 | 
			
		|||
// network. If either cannot be found, an err is returned. If the
 | 
			
		||||
// network cannot be set up, an err is returned.
 | 
			
		||||
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		return errors.New("docker network connect is unsupported on Solaris platform")
 | 
			
		||||
	}
 | 
			
		||||
	container, err := daemon.GetContainer(containerName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -346,6 +351,9 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin
 | 
			
		|||
// DisconnectContainerFromNetwork disconnects the given container from
 | 
			
		||||
// the given network. If either cannot be found, an err is returned.
 | 
			
		||||
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		return errors.New("docker network disconnect is unsupported on Solaris platform")
 | 
			
		||||
	}
 | 
			
		||||
	container, err := daemon.GetContainer(containerName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if force {
 | 
			
		||||
| 
						 | 
				
			
			@ -401,7 +409,7 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
 | 
			
		|||
 | 
			
		||||
	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
 | 
			
		||||
		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
 | 
			
		||||
		return errors.NewRequestForbiddenError(err)
 | 
			
		||||
		return apierrors.NewRequestForbiddenError(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := nw.Delete(); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,183 @@
 | 
			
		|||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
	"github.com/docker/docker/oci"
 | 
			
		||||
	"github.com/docker/libnetwork"
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func setResources(s *specs.Spec, r containertypes.Resources) error {
 | 
			
		||||
	mem := getMemoryResources(r)
 | 
			
		||||
	s.Solaris.CappedMemory = &mem
 | 
			
		||||
 | 
			
		||||
	capCPU := getCPUResources(r)
 | 
			
		||||
	s.Solaris.CappedCPU = &capCPU
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setUser(s *specs.Spec, c *container.Container) error {
 | 
			
		||||
	uid, gid, additionalGids, err := getUser(c, c.Config.User)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	s.Process.User.UID = uid
 | 
			
		||||
	s.Process.User.GID = gid
 | 
			
		||||
	s.Process.User.AdditionalGids = additionalGids
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getUser(c *container.Container, username string) (uint32, uint32, []uint32, error) {
 | 
			
		||||
	return 0, 0, nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) getRunzAnet(ep libnetwork.Endpoint) (specs.Anet, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		linkName  string
 | 
			
		||||
		lowerLink string
 | 
			
		||||
		defRouter string
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	epInfo := ep.Info()
 | 
			
		||||
	if epInfo == nil {
 | 
			
		||||
		return specs.Anet{}, fmt.Errorf("invalid endpoint")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	nw, err := daemon.GetNetworkByName(ep.Network())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return specs.Anet{}, fmt.Errorf("Failed to get network %s: %v", ep.Network(), err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Evaluate default router, linkname and lowerlink for interface endpoint
 | 
			
		||||
	switch nw.Type() {
 | 
			
		||||
	case "bridge":
 | 
			
		||||
		defRouter = epInfo.Gateway().String()
 | 
			
		||||
		linkName = "net0" // Should always be net0 for a container
 | 
			
		||||
 | 
			
		||||
		// TODO We construct lowerlink here exactly as done for solaris bridge
 | 
			
		||||
		// initialization. Need modular code to reuse.
 | 
			
		||||
		options := nw.Info().DriverOptions()
 | 
			
		||||
		nwName := options["com.docker.network.bridge.name"]
 | 
			
		||||
		lastChar := nwName[len(nwName)-1:]
 | 
			
		||||
		if _, err = strconv.Atoi(lastChar); err != nil {
 | 
			
		||||
			lowerLink = nwName + "_0"
 | 
			
		||||
		} else {
 | 
			
		||||
			lowerLink = nwName
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	case "overlay":
 | 
			
		||||
		defRouter = ""
 | 
			
		||||
		linkName = "net1"
 | 
			
		||||
 | 
			
		||||
		// TODO Follows generateVxlanName() in solaris overlay.
 | 
			
		||||
		id := nw.ID()
 | 
			
		||||
		if len(nw.ID()) > 12 {
 | 
			
		||||
			id = nw.ID()[:12]
 | 
			
		||||
		}
 | 
			
		||||
		lowerLink = "vx_" + id + "_0"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	runzanet := specs.Anet{
 | 
			
		||||
		Linkname:          linkName,
 | 
			
		||||
		Lowerlink:         lowerLink,
 | 
			
		||||
		Allowedaddr:       epInfo.Iface().Address().String(),
 | 
			
		||||
		Configallowedaddr: "true",
 | 
			
		||||
		Defrouter:         defRouter,
 | 
			
		||||
		Linkprotection:    "mac-nospoof, ip-nospoof",
 | 
			
		||||
		Macaddress:        epInfo.Iface().MacAddress().String(),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return runzanet, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) setNetworkInterface(s *specs.Spec, c *container.Container) error {
 | 
			
		||||
	var anets []specs.Anet
 | 
			
		||||
 | 
			
		||||
	sb, err := daemon.netController.SandboxByID(c.NetworkSettings.SandboxID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Could not obtain sandbox for container")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Populate interfaces required for each endpoint
 | 
			
		||||
	for _, ep := range sb.Endpoints() {
 | 
			
		||||
		runzanet, err := daemon.getRunzAnet(ep)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("Failed to get interface information for endpoint %d: %v", ep.ID(), err)
 | 
			
		||||
		}
 | 
			
		||||
		anets = append(anets, runzanet)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.Solaris.Anet = anets
 | 
			
		||||
	if anets != nil {
 | 
			
		||||
		s.Solaris.Milestone = "svc:/milestone/container:default"
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container) error {
 | 
			
		||||
	linkedEnv, err := daemon.setupLinkedContainers(c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	s.Root = specs.Root{
 | 
			
		||||
		Path:     filepath.Dir(c.BaseFS),
 | 
			
		||||
		Readonly: c.HostConfig.ReadonlyRootfs,
 | 
			
		||||
	}
 | 
			
		||||
	rootUID, rootGID := daemon.GetRemappedUIDGID()
 | 
			
		||||
	if err := c.SetupWorkingDirectory(rootUID, rootGID); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	cwd := c.Config.WorkingDir
 | 
			
		||||
	s.Process.Args = append([]string{c.Path}, c.Args...)
 | 
			
		||||
	s.Process.Cwd = cwd
 | 
			
		||||
	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
 | 
			
		||||
	s.Process.Terminal = c.Config.Tty
 | 
			
		||||
	s.Hostname = c.FullHostname()
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
 | 
			
		||||
	s := oci.DefaultSpec()
 | 
			
		||||
	if err := daemon.populateCommonSpec(&s, c); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := setResources(&s, c.HostConfig.Resources); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("runtime spec resources: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := setUser(&s, c); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("spec user: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := daemon.setNetworkInterface(&s, c); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := daemon.setupIpcDirs(c); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ms, err := daemon.setupMounts(c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ms = append(ms, c.IpcMounts()...)
 | 
			
		||||
	tmpfsMounts, err := c.TmpfsMounts()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	ms = append(ms, tmpfsMounts...)
 | 
			
		||||
	sort.Sort(mounts(ms))
 | 
			
		||||
 | 
			
		||||
	return (*specs.Spec)(&s), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,7 @@ import (
 | 
			
		|||
	"google.golang.org/grpc"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/docker/api/errors"
 | 
			
		||||
	apierrors "github.com/docker/docker/api/errors"
 | 
			
		||||
	"github.com/docker/docker/api/types"
 | 
			
		||||
	containertypes "github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ import (
 | 
			
		|||
// ContainerStart starts a container.
 | 
			
		||||
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error {
 | 
			
		||||
	if checkpoint != "" && !daemon.HasExperimental() {
 | 
			
		||||
		return errors.NewBadRequestError(fmt.Errorf("checkpoint is only supported in experimental mode"))
 | 
			
		||||
		return apierrors.NewBadRequestError(fmt.Errorf("checkpoint is only supported in experimental mode"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	container, err := daemon.GetContainer(name)
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
 | 
			
		|||
 | 
			
		||||
	if container.IsRunning() {
 | 
			
		||||
		err := fmt.Errorf("Container already started")
 | 
			
		||||
		return errors.NewErrorWithStatusCode(err, http.StatusNotModified)
 | 
			
		||||
		return apierrors.NewErrorWithStatusCode(err, http.StatusNotModified)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Windows does not have the backwards compatibility issue here.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package daemon
 | 
			
		|||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +20,9 @@ import (
 | 
			
		|||
// ContainerStats writes information about the container to the stream
 | 
			
		||||
// given in the config object.
 | 
			
		||||
func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, config *backend.ContainerStatsConfig) error {
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		return fmt.Errorf("%+v does not support stats", runtime.GOOS)
 | 
			
		||||
	}
 | 
			
		||||
	// Remote API version (used for backwards compatibility)
 | 
			
		||||
	apiVersion := config.Version
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
// TODO(amitkris): We need to split this file for solaris.
 | 
			
		||||
 | 
			
		||||
package daemon
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +13,8 @@ import (
 | 
			
		|||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/container"
 | 
			
		||||
	"github.com/docker/docker/pkg/fileutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/mount"
 | 
			
		||||
	"github.com/docker/docker/volume"
 | 
			
		||||
	"github.com/docker/docker/volume/drivers"
 | 
			
		||||
	"github.com/docker/docker/volume/local"
 | 
			
		||||
| 
						 | 
				
			
			@ -165,3 +169,50 @@ func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
 | 
			
		|||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (daemon *Daemon) mountVolumes(container *container.Container) error {
 | 
			
		||||
	mounts, err := daemon.setupMounts(container)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, m := range mounts {
 | 
			
		||||
		dest, err := container.GetResourcePath(m.Destination)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var stat os.FileInfo
 | 
			
		||||
		stat, err = os.Stat(m.Source)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if err = fileutils.CreateIfNotExists(dest, stat.IsDir()); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		opts := "rbind,ro"
 | 
			
		||||
		if m.Writable {
 | 
			
		||||
			opts = "rbind,rw"
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err := mount.Mount(m.Source, dest, bindMountType, opts); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// mountVolumes() seems to be called for temporary mounts
 | 
			
		||||
		// outside the container. Soon these will be unmounted with
 | 
			
		||||
		// lazy unmount option and given we have mounted the rbind,
 | 
			
		||||
		// all the submounts will propagate if these are shared. If
 | 
			
		||||
		// daemon is running in host namespace and has / as shared
 | 
			
		||||
		// then these unmounts will propagate and unmount original
 | 
			
		||||
		// mount as well. So make all these mounts rprivate.
 | 
			
		||||
		// Do not use propagation property of volume as that should
 | 
			
		||||
		// apply only when mounting happen inside the container.
 | 
			
		||||
		if err := mount.MakeRPrivate(dest); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,6 +56,9 @@ case "$PACKAGE_ARCH" in
 | 
			
		|||
			windows)
 | 
			
		||||
				DOCKERFILE='Dockerfile.windows'
 | 
			
		||||
				;;
 | 
			
		||||
			solaris)
 | 
			
		||||
				DOCKERFILE='Dockerfile.solaris'
 | 
			
		||||
				;;
 | 
			
		||||
		esac
 | 
			
		||||
		;;
 | 
			
		||||
	*)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,8 @@ for platform in $DOCKER_CROSSPLATFORMS; do
 | 
			
		|||
		export GOOS=${platform%/*}
 | 
			
		||||
		export GOARCH=${platform##*/}
 | 
			
		||||
 | 
			
		||||
		if [ "$GOOS" != "solaris" ]; then
 | 
			
		||||
			# TODO. Solaris cannot be cross build because of CGO calls.
 | 
			
		||||
			if [ -z "${daemonSupporting[$platform]}" ]; then
 | 
			
		||||
				# we just need a simple client for these platforms
 | 
			
		||||
				export LDFLAGS_STATIC_DOCKER=""
 | 
			
		||||
| 
						 | 
				
			
			@ -39,5 +41,6 @@ for platform in $DOCKER_CROSSPLATFORMS; do
 | 
			
		|||
				source "${MAKEDIR}/binary-client"
 | 
			
		||||
				source "${MAKEDIR}/binary-daemon"
 | 
			
		||||
			fi
 | 
			
		||||
		fi
 | 
			
		||||
	)
 | 
			
		||||
done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,19 @@ bundle_test_unit() {
 | 
			
		|||
	else
 | 
			
		||||
		TEST_PATH=./${TESTDIRS}
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	if [ "$(go env GOHOSTOS)" = 'solaris' ]; then
 | 
			
		||||
		pkg_list=$(go list -e \
 | 
			
		||||
			-f '{{if ne .Name "github.com/docker/docker"}}
 | 
			
		||||
				{{.ImportPath}}
 | 
			
		||||
			    {{end}}' \
 | 
			
		||||
			"${BUILDFLAGS[@]}" $TEST_PATH \
 | 
			
		||||
			| grep github.com/docker/docker \
 | 
			
		||||
			| grep -v github.com/docker/docker/vendor \
 | 
			
		||||
			| grep -v github.com/docker/docker/daemon/graphdriver \
 | 
			
		||||
			| grep -v github.com/docker/docker/man \
 | 
			
		||||
			| grep -v github.com/docker/docker/integration-cli)
 | 
			
		||||
	else
 | 
			
		||||
		pkg_list=$(go list -e \
 | 
			
		||||
			-f '{{if ne .Name "github.com/docker/docker"}}
 | 
			
		||||
				{{.ImportPath}}
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +47,8 @@ bundle_test_unit() {
 | 
			
		|||
			| grep -v github.com/docker/docker/vendor \
 | 
			
		||||
			| grep -v github.com/docker/docker/man \
 | 
			
		||||
			| grep -v github.com/docker/docker/integration-cli)
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
	go test -cover -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS $pkg_list
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,9 @@ for d in "$CROSS/"*/*; do
 | 
			
		|||
		# if windows use a zip, not tgz
 | 
			
		||||
		BUNDLE_EXTENSION=".zip"
 | 
			
		||||
		IS_TAR="false"
 | 
			
		||||
	elif [ "$GOOS" == "solaris" ]; then
 | 
			
		||||
		# Solaris bypasses cross due to CGO issues.
 | 
			
		||||
		continue
 | 
			
		||||
	else
 | 
			
		||||
		BUNDLE_EXTENSION=".tgz"
 | 
			
		||||
		IS_TAR="true"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,8 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"syscall"
 | 
			
		||||
| 
						 | 
				
			
			@ -12,7 +10,6 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/docker/docker/pkg/idtools"
 | 
			
		||||
	"github.com/docker/docker/pkg/ioutils"
 | 
			
		||||
	"github.com/docker/docker/pkg/mount"
 | 
			
		||||
	"github.com/golang/protobuf/ptypes"
 | 
			
		||||
| 
						 | 
				
			
			@ -124,87 +121,6 @@ func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendly
 | 
			
		|||
	return int(resp.SystemPid), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) prepareBundleDir(uid, gid int) (string, error) {
 | 
			
		||||
	root, err := filepath.Abs(clnt.remote.stateDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if uid == 0 && gid == 0 {
 | 
			
		||||
		return root, nil
 | 
			
		||||
	}
 | 
			
		||||
	p := string(filepath.Separator)
 | 
			
		||||
	for _, d := range strings.Split(root, string(filepath.Separator))[1:] {
 | 
			
		||||
		p = filepath.Join(p, d)
 | 
			
		||||
		fi, err := os.Stat(p)
 | 
			
		||||
		if err != nil && !os.IsNotExist(err) {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		if os.IsNotExist(err) || fi.Mode()&1 == 0 {
 | 
			
		||||
			p = fmt.Sprintf("%s.%d.%d", p, uid, gid)
 | 
			
		||||
			if err := idtools.MkdirAs(p, 0700, uid, gid); err != nil && !os.IsExist(err) {
 | 
			
		||||
				return "", err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return p, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Create(containerID string, checkpoint string, checkpointDir string, spec specs.Spec, attachStdio StdioCallback, options ...CreateOption) (err error) {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
 | 
			
		||||
	if _, err := clnt.getContainer(containerID); err == nil {
 | 
			
		||||
		return fmt.Errorf("Container %s is already active", containerID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uid, gid, err := getRootIDs(specs.Spec(spec))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	dir, err := clnt.prepareBundleDir(uid, gid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	container := clnt.newContainer(filepath.Join(dir, containerID), options...)
 | 
			
		||||
	if err := container.clean(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			container.clean()
 | 
			
		||||
			clnt.deleteContainer(containerID)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if err := idtools.MkdirAllAs(container.dir, 0700, uid, gid); err != nil && !os.IsExist(err) {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := os.Create(filepath.Join(container.dir, configFilename))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	if err := json.NewEncoder(f).Encode(spec); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return container.start(checkpoint, checkpointDir, attachStdio)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Signal(containerID string, sig int) error {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
	_, err := clnt.remote.apiClient.Signal(context.Background(), &containerd.SignalRequest{
 | 
			
		||||
		Id:     containerID,
 | 
			
		||||
		Pid:    InitFriendlyName,
 | 
			
		||||
		Signal: uint32(sig),
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) SignalProcess(containerID string, pid string, sig int) error {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
| 
						 | 
				
			
			@ -340,28 +256,6 @@ func (clnt *client) getContainerdContainer(containerID string) (*containerd.Cont
 | 
			
		|||
	return nil, fmt.Errorf("invalid state response")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) newContainer(dir string, options ...CreateOption) *container {
 | 
			
		||||
	container := &container{
 | 
			
		||||
		containerCommon: containerCommon{
 | 
			
		||||
			process: process{
 | 
			
		||||
				dir: dir,
 | 
			
		||||
				processCommon: processCommon{
 | 
			
		||||
					containerID:  filepath.Base(dir),
 | 
			
		||||
					client:       clnt,
 | 
			
		||||
					friendlyName: InitFriendlyName,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			processes: make(map[string]*process),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, option := range options {
 | 
			
		||||
		if err := option.Apply(container); err != nil {
 | 
			
		||||
			logrus.Errorf("libcontainerd: newContainer(): %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return container
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) UpdateResources(containerID string, resources Resources) error {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
| 
						 | 
				
			
			@ -627,27 +521,6 @@ func (clnt *client) Restore(containerID string, attachStdio StdioCallback, optio
 | 
			
		|||
	return clnt.setExited(containerID, uint32(255))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type exitNotifier struct {
 | 
			
		||||
	id     string
 | 
			
		||||
	client *client
 | 
			
		||||
	c      chan struct{}
 | 
			
		||||
	once   sync.Once
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (en *exitNotifier) close() {
 | 
			
		||||
	en.once.Do(func() {
 | 
			
		||||
		close(en.c)
 | 
			
		||||
		en.client.mapMutex.Lock()
 | 
			
		||||
		if en == en.client.exitNotifiers[en.id] {
 | 
			
		||||
			delete(en.client.exitNotifiers, en.id)
 | 
			
		||||
		}
 | 
			
		||||
		en.client.mapMutex.Unlock()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
func (en *exitNotifier) wait() <-chan struct{} {
 | 
			
		||||
	return en.c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) CreateCheckpoint(containerID string, checkpointID string, checkpointDir string, exit bool) error {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,17 +6,17 @@ type client struct {
 | 
			
		|||
	clientCommon
 | 
			
		||||
 | 
			
		||||
	// Platform specific properties below here.
 | 
			
		||||
	remote        *remote
 | 
			
		||||
	q             queue
 | 
			
		||||
	exitNotifiers map[string]*exitNotifier
 | 
			
		||||
	liveRestore   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendlyName string, specp Process) error {
 | 
			
		||||
	return nil
 | 
			
		||||
func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendlyName string, specp Process, attachStdio StdioCallback) (int, error) {
 | 
			
		||||
	return -1, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Create(containerID string, checkpoint string, checkpointDir string, spec Spec, options ...CreateOption) (err error) {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Signal(containerID string, sig int) error {
 | 
			
		||||
func (clnt *client) SignalProcess(containerID string, pid string, sig int) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +36,25 @@ func (clnt *client) Stats(containerID string) (*Stats, error) {
 | 
			
		|||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) getExitNotifier(containerID string) *exitNotifier {
 | 
			
		||||
	clnt.mapMutex.RLock()
 | 
			
		||||
	defer clnt.mapMutex.RUnlock()
 | 
			
		||||
	return clnt.exitNotifiers[containerID]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) getOrCreateExitNotifier(containerID string) *exitNotifier {
 | 
			
		||||
	clnt.mapMutex.Lock()
 | 
			
		||||
	defer clnt.mapMutex.Unlock()
 | 
			
		||||
	w, ok := clnt.exitNotifiers[containerID]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		w = &exitNotifier{c: make(chan struct{}), client: clnt}
 | 
			
		||||
		clnt.exitNotifiers[containerID] = w
 | 
			
		||||
	}
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore is the handler for restoring a container
 | 
			
		||||
func (clnt *client) Restore(containerID string, unusedOnWindows ...CreateOption) error {
 | 
			
		||||
func (clnt *client) Restore(containerID string, attachStdio StdioCallback, options ...CreateOption) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -56,3 +73,15 @@ func (clnt *client) UpdateResources(containerID string, resources Resources) err
 | 
			
		|||
	// but we should return nil for enabling updating container
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) CreateCheckpoint(containerID string, checkpointID string, checkpointDir string, exit bool) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) DeleteCheckpoint(containerID string, checkpointID string, checkpointDir string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) ListCheckpoints(containerID string, checkpointDir string) (*Checkpoints, error) {
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										142
									
								
								libcontainerd/client_unix.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								libcontainerd/client_unix.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,142 @@
 | 
			
		|||
// +build linux solaris
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/docker/docker/pkg/idtools"
 | 
			
		||||
	specs "github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (clnt *client) prepareBundleDir(uid, gid int) (string, error) {
 | 
			
		||||
	root, err := filepath.Abs(clnt.remote.stateDir)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if uid == 0 && gid == 0 {
 | 
			
		||||
		return root, nil
 | 
			
		||||
	}
 | 
			
		||||
	p := string(filepath.Separator)
 | 
			
		||||
	for _, d := range strings.Split(root, string(filepath.Separator))[1:] {
 | 
			
		||||
		p = filepath.Join(p, d)
 | 
			
		||||
		fi, err := os.Stat(p)
 | 
			
		||||
		if err != nil && !os.IsNotExist(err) {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		if os.IsNotExist(err) || fi.Mode()&1 == 0 {
 | 
			
		||||
			p = fmt.Sprintf("%s.%d.%d", p, uid, gid)
 | 
			
		||||
			if err := idtools.MkdirAs(p, 0700, uid, gid); err != nil && !os.IsExist(err) {
 | 
			
		||||
				return "", err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return p, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Create(containerID string, checkpoint string, checkpointDir string, spec specs.Spec, attachStdio StdioCallback, options ...CreateOption) (err error) {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
 | 
			
		||||
	if _, err := clnt.getContainer(containerID); err == nil {
 | 
			
		||||
		return fmt.Errorf("Container %s is already active", containerID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uid, gid, err := getRootIDs(specs.Spec(spec))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	dir, err := clnt.prepareBundleDir(uid, gid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	container := clnt.newContainer(filepath.Join(dir, containerID), options...)
 | 
			
		||||
	if err := container.clean(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			container.clean()
 | 
			
		||||
			clnt.deleteContainer(containerID)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if err := idtools.MkdirAllAs(container.dir, 0700, uid, gid); err != nil && !os.IsExist(err) {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := os.Create(filepath.Join(container.dir, configFilename))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
	if err := json.NewEncoder(f).Encode(spec); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return container.start(checkpoint, checkpointDir, attachStdio)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) Signal(containerID string, sig int) error {
 | 
			
		||||
	clnt.lock(containerID)
 | 
			
		||||
	defer clnt.unlock(containerID)
 | 
			
		||||
	_, err := clnt.remote.apiClient.Signal(context.Background(), &containerd.SignalRequest{
 | 
			
		||||
		Id:     containerID,
 | 
			
		||||
		Pid:    InitFriendlyName,
 | 
			
		||||
		Signal: uint32(sig),
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (clnt *client) newContainer(dir string, options ...CreateOption) *container {
 | 
			
		||||
	container := &container{
 | 
			
		||||
		containerCommon: containerCommon{
 | 
			
		||||
			process: process{
 | 
			
		||||
				dir: dir,
 | 
			
		||||
				processCommon: processCommon{
 | 
			
		||||
					containerID:  filepath.Base(dir),
 | 
			
		||||
					client:       clnt,
 | 
			
		||||
					friendlyName: InitFriendlyName,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			processes: make(map[string]*process),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, option := range options {
 | 
			
		||||
		if err := option.Apply(container); err != nil {
 | 
			
		||||
			logrus.Errorf("libcontainerd: newContainer(): %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return container
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type exitNotifier struct {
 | 
			
		||||
	id     string
 | 
			
		||||
	client *client
 | 
			
		||||
	c      chan struct{}
 | 
			
		||||
	once   sync.Once
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (en *exitNotifier) close() {
 | 
			
		||||
	en.once.Do(func() {
 | 
			
		||||
		close(en.c)
 | 
			
		||||
		en.client.mapMutex.Lock()
 | 
			
		||||
		if en == en.client.exitNotifiers[en.id] {
 | 
			
		||||
			delete(en.client.exitNotifiers, en.id)
 | 
			
		||||
		}
 | 
			
		||||
		en.client.mapMutex.Unlock()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
func (en *exitNotifier) wait() <-chan struct{} {
 | 
			
		||||
	return en.c
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,5 +0,0 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
type container struct {
 | 
			
		||||
	containerCommon
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build linux solaris
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
							
								
								
									
										31
									
								
								libcontainerd/oom_linux.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								libcontainerd/oom_linux.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/opencontainers/runc/libcontainer/system"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func setOOMScore(pid, score int) error {
 | 
			
		||||
	oomScoreAdjPath := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
 | 
			
		||||
	f, err := os.OpenFile(oomScoreAdjPath, os.O_WRONLY, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	stringScore := strconv.Itoa(score)
 | 
			
		||||
	_, err = f.WriteString(stringScore)
 | 
			
		||||
	f.Close()
 | 
			
		||||
	if os.IsPermission(err) {
 | 
			
		||||
		// Setting oom_score_adj does not work in an
 | 
			
		||||
		// unprivileged container. Ignore the error, but log
 | 
			
		||||
		// it if we appear not to be in that situation.
 | 
			
		||||
		if !system.RunningInUserNS() {
 | 
			
		||||
			logrus.Debugf("Permission denied writing %q to %s", stringScore, oomScoreAdjPath)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								libcontainerd/oom_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								libcontainerd/oom_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
func setOOMScore(pid, score int) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -1,6 +0,0 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
// process keeps the state for both main container process and exec process.
 | 
			
		||||
type process struct {
 | 
			
		||||
	processCommon
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build linux solaris
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -5,18 +7,19 @@ import (
 | 
			
		|||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	goruntime "runtime"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/tonistiigi/fifo"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var fdNames = map[int]string{
 | 
			
		||||
	syscall.Stdin:  "stdin",
 | 
			
		||||
	syscall.Stdout: "stdout",
 | 
			
		||||
	syscall.Stderr: "stderr",
 | 
			
		||||
	unix.Stdin:  "stdin",
 | 
			
		||||
	unix.Stdout: "stdout",
 | 
			
		||||
	unix.Stderr: "stderr",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// process keeps the state for both main container process and exec process.
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +39,7 @@ func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
 | 
			
		|||
 | 
			
		||||
	io := &IOPipe{}
 | 
			
		||||
 | 
			
		||||
	io.Stdin, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stdin), syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
 | 
			
		||||
	io.Stdin, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdin), unix.O_WRONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +50,7 @@ func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
 | 
			
		|||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stdout), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
 | 
			
		||||
	io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdout), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -58,8 +61,10 @@ func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
 | 
			
		|||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if !terminal {
 | 
			
		||||
		io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stderr), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
 | 
			
		||||
	if goruntime.GOOS == "solaris" || !terminal {
 | 
			
		||||
		// For Solaris terminal handling is done exclusively by the runtime therefore we make no distinction
 | 
			
		||||
		// in the processing for terminal and !terminal cases.
 | 
			
		||||
		io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(unix.Stderr), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build linux solaris
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
| 
						 | 
				
			
			@ -1,34 +0,0 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import "github.com/docker/docker/pkg/locker"
 | 
			
		||||
 | 
			
		||||
type remote struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *remote) Client(b Backend) (Client, error) {
 | 
			
		||||
	c := &client{
 | 
			
		||||
		clientCommon: clientCommon{
 | 
			
		||||
			backend:    b,
 | 
			
		||||
			containers: make(map[string]*container),
 | 
			
		||||
			locker:     locker.New(),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *remote) Cleanup() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *remote) UpdateOptions(opts ...RemoteOption) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// New creates a fresh instance of libcontainerd remote.
 | 
			
		||||
func New(_ string, _ ...RemoteOption) (Remote, error) {
 | 
			
		||||
	return &remote{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithLiveRestore is a noop on solaris.
 | 
			
		||||
func WithLiveRestore(v bool) RemoteOption {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build linux solaris
 | 
			
		||||
 | 
			
		||||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +11,7 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	goruntime "runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
| 
						 | 
				
			
			@ -22,7 +25,6 @@ import (
 | 
			
		|||
	"github.com/docker/docker/utils"
 | 
			
		||||
	"github.com/golang/protobuf/ptypes"
 | 
			
		||||
	"github.com/golang/protobuf/ptypes/timestamp"
 | 
			
		||||
	rsystem "github.com/opencontainers/runc/libcontainer/system"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
	"google.golang.org/grpc"
 | 
			
		||||
	"google.golang.org/grpc/grpclog"
 | 
			
		||||
| 
						 | 
				
			
			@ -374,15 +376,19 @@ func (r *remote) runContainerdDaemon() error {
 | 
			
		|||
	// Start a new instance
 | 
			
		||||
	args := []string{
 | 
			
		||||
		"-l", fmt.Sprintf("unix://%s", r.rpcAddr),
 | 
			
		||||
		"--shim", "docker-containerd-shim",
 | 
			
		||||
		"--metrics-interval=0",
 | 
			
		||||
		"--start-timeout", "2m",
 | 
			
		||||
		"--state-dir", filepath.Join(r.stateDir, containerdStateDir),
 | 
			
		||||
	}
 | 
			
		||||
	if goruntime.GOOS == "solaris" {
 | 
			
		||||
		args = append(args, "--shim", "containerd-shim", "--runtime", "runc")
 | 
			
		||||
	} else {
 | 
			
		||||
		args = append(args, "--shim", "docker-containerd-shim")
 | 
			
		||||
		if r.runtime != "" {
 | 
			
		||||
			args = append(args, "--runtime")
 | 
			
		||||
			args = append(args, r.runtime)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if r.debugLog {
 | 
			
		||||
		args = append(args, "--debug")
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -398,7 +404,7 @@ func (r *remote) runContainerdDaemon() error {
 | 
			
		|||
	// redirect containerd logs to docker logs
 | 
			
		||||
	cmd.Stdout = os.Stdout
 | 
			
		||||
	cmd.Stderr = os.Stderr
 | 
			
		||||
	cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true, Pdeathsig: syscall.SIGKILL}
 | 
			
		||||
	cmd.SysProcAttr = setSysProcAttr(true)
 | 
			
		||||
	cmd.Env = nil
 | 
			
		||||
	// clear the NOTIFY_SOCKET from the env when starting containerd
 | 
			
		||||
	for _, e := range os.Environ() {
 | 
			
		||||
| 
						 | 
				
			
			@ -428,27 +434,6 @@ func (r *remote) runContainerdDaemon() error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func setOOMScore(pid, score int) error {
 | 
			
		||||
	oomScoreAdjPath := fmt.Sprintf("/proc/%d/oom_score_adj", pid)
 | 
			
		||||
	f, err := os.OpenFile(oomScoreAdjPath, os.O_WRONLY, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	stringScore := strconv.Itoa(score)
 | 
			
		||||
	_, err = f.WriteString(stringScore)
 | 
			
		||||
	f.Close()
 | 
			
		||||
	if os.IsPermission(err) {
 | 
			
		||||
		// Setting oom_score_adj does not work in an
 | 
			
		||||
		// unprivileged container. Ignore the error, but log
 | 
			
		||||
		// it if we appear not to be in that situation.
 | 
			
		||||
		if !rsystem.RunningInUserNS() {
 | 
			
		||||
			logrus.Debugf("Permission denied writing %q to %s", stringScore, oomScoreAdjPath)
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WithRemoteAddr sets the external containerd socket to connect to.
 | 
			
		||||
func WithRemoteAddr(addr string) RemoteOption {
 | 
			
		||||
	return rpcAddr(addr)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,25 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Process contains information to start a specific application inside the container.
 | 
			
		||||
type Process struct {
 | 
			
		||||
	// Terminal creates an interactive terminal for the container.
 | 
			
		||||
	Terminal bool `json:"terminal"`
 | 
			
		||||
	// User specifies user information for the process.
 | 
			
		||||
	User *specs.User `json:"user"`
 | 
			
		||||
	// Args specifies the binary and arguments for the application to execute.
 | 
			
		||||
	Args []string `json:"args"`
 | 
			
		||||
	// Env populates the process environment for the process.
 | 
			
		||||
	Env []string `json:"env,omitempty"`
 | 
			
		||||
	// Cwd is the current working directory for the process and must be
 | 
			
		||||
	// relative to the container's root.
 | 
			
		||||
	Cwd *string `json:"cwd"`
 | 
			
		||||
	// Capabilities are linux capabilities that are kept for the container.
 | 
			
		||||
	Capabilities []string `json:"capabilities,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stats contains a stats properties from containerd.
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +33,11 @@ type StateInfo struct {
 | 
			
		|||
	CommonStateInfo
 | 
			
		||||
 | 
			
		||||
	// Platform specific StateInfo
 | 
			
		||||
	OOMKilled bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Resources defines updatable container resource values.
 | 
			
		||||
type Resources struct{}
 | 
			
		||||
 | 
			
		||||
// Checkpoints contains the details of a checkpoint
 | 
			
		||||
type Checkpoints containerd.ListCheckpointResponse
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,8 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -50,3 +52,11 @@ func convertRlimits(sr []specs.Rlimit) (cr []*containerd.Rlimit) {
 | 
			
		|||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPDeathSig sets the parent death signal to SIGKILL
 | 
			
		||||
func setSysProcAttr(sid bool) *syscall.SysProcAttr {
 | 
			
		||||
	return &syscall.SysProcAttr{
 | 
			
		||||
		Setsid:    sid,
 | 
			
		||||
		Pdeathsig: syscall.SIGKILL,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								libcontainerd/utils_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								libcontainerd/utils_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
package libcontainerd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
 | 
			
		||||
	containerd "github.com/docker/containerd/api/grpc/types"
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func getRootIDs(s specs.Spec) (int, int, error) {
 | 
			
		||||
	return 0, 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func systemPid(ctr *containerd.Container) uint32 {
 | 
			
		||||
	var pid uint32
 | 
			
		||||
	for _, p := range ctr.Processes {
 | 
			
		||||
		if p.Pid == InitFriendlyName {
 | 
			
		||||
			pid = p.SystemPid
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return pid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// setPDeathSig sets the parent death signal to SIGKILL
 | 
			
		||||
func setSysProcAttr(sid bool) *syscall.SysProcAttr {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,20 @@
 | 
			
		|||
package oci
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"runtime"
 | 
			
		||||
 | 
			
		||||
	"github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DefaultSpec returns default oci spec used by docker.
 | 
			
		||||
func DefaultSpec() specs.Spec {
 | 
			
		||||
	s := specs.Spec{}
 | 
			
		||||
	s := specs.Spec{
 | 
			
		||||
		Version: "0.6.0",
 | 
			
		||||
		Platform: specs.Platform{
 | 
			
		||||
			OS:   "SunOS",
 | 
			
		||||
			Arch: runtime.GOARCH,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	s.Solaris = &specs.Solaris{}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ func TestIsArchivePathDir(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestIsArchivePathInvalidFile(t *testing.T) {
 | 
			
		||||
	cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1K count=1 of=/tmp/archive && gzip --stdout /tmp/archive > /tmp/archive.gz")
 | 
			
		||||
	cmd := exec.Command("sh", "-c", "dd if=/dev/zero bs=1024 count=1 of=/tmp/archive && gzip --stdout /tmp/archive > /tmp/archive.gz")
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Fail to create an archive file for test : %s.", output)
 | 
			
		||||
| 
						 | 
				
			
			@ -81,7 +81,14 @@ func TestIsArchivePathInvalidFile(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestIsArchivePathTar(t *testing.T) {
 | 
			
		||||
	cmd := exec.Command("sh", "-c", "touch /tmp/archivedata && tar -cf /tmp/archive /tmp/archivedata && gzip --stdout /tmp/archive > /tmp/archive.gz")
 | 
			
		||||
	var whichTar string
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		whichTar = "gtar"
 | 
			
		||||
	} else {
 | 
			
		||||
		whichTar = "tar"
 | 
			
		||||
	}
 | 
			
		||||
	cmdStr := fmt.Sprintf("touch /tmp/archivedata && %s -cf /tmp/archive /tmp/archivedata && gzip --stdout /tmp/archive > /tmp/archive.gz", whichTar)
 | 
			
		||||
	cmd := exec.Command("sh", "-c", cmdStr)
 | 
			
		||||
	output, err := cmd.CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Fail to create an archive file for test : %s.", output)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ import (
 | 
			
		|||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -203,6 +204,9 @@ func TestTarWithBlockCharFifo(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
// TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows
 | 
			
		||||
func TestTarUntarWithXattr(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
	}
 | 
			
		||||
	origin, err := ioutil.TempDir("", "docker-test-untar-origin")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,11 +7,16 @@ import (
 | 
			
		|||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestHardLinkOrder(t *testing.T) {
 | 
			
		||||
	//TODO Should run for Solaris
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("gcp failures on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	names := []string{"file1.txt", "file2.txt", "file3.txt"}
 | 
			
		||||
	msg := []byte("Hey y'all")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,10 @@ func max(x, y int) int {
 | 
			
		|||
 | 
			
		||||
func copyDir(src, dst string) error {
 | 
			
		||||
	cmd := exec.Command("cp", "-a", src, dst)
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		cmd = exec.Command("gcp", "-a", src, dst)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := cmd.Run(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -256,8 +260,9 @@ func TestChangesWithChangesGH13590(t *testing.T) {
 | 
			
		|||
func TestChangesDirsEmpty(t *testing.T) {
 | 
			
		||||
	// TODO Windows. There may be a way of running this, but turning off for now
 | 
			
		||||
	// as createSampleDir uses symlinks.
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		t.Skip("symlinks on Windows")
 | 
			
		||||
	// TODO Should work for Solaris
 | 
			
		||||
	if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("symlinks on Windows; gcp failure on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	src, err := ioutil.TempDir("", "docker-changes-test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -364,8 +369,9 @@ func mutateSampleDir(t *testing.T, root string) {
 | 
			
		|||
func TestChangesDirsMutated(t *testing.T) {
 | 
			
		||||
	// TODO Windows. There may be a way of running this, but turning off for now
 | 
			
		||||
	// as createSampleDir uses symlinks.
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		t.Skip("symlinks on Windows")
 | 
			
		||||
	// TODO Should work for Solaris
 | 
			
		||||
	if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("symlinks on Windows; gcp failures on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	src, err := ioutil.TempDir("", "docker-changes-test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -425,8 +431,9 @@ func TestChangesDirsMutated(t *testing.T) {
 | 
			
		|||
func TestApplyLayer(t *testing.T) {
 | 
			
		||||
	// TODO Windows. There may be a way of running this, but turning off for now
 | 
			
		||||
	// as createSampleDir uses symlinks.
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		t.Skip("symlinks on Windows")
 | 
			
		||||
	// TODO Should work for Solaris
 | 
			
		||||
	if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("symlinks on Windows; gcp failures on Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	src, err := ioutil.TempDir("", "docker-changes-test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,7 +165,7 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
 | 
			
		|||
	if err := system.MkdirAll(src, 0700); err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	if _, err := prepareSourceDirectory(10, src, true); err != nil {
 | 
			
		||||
	if _, err := prepareSourceDirectory(10, src, false); err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	dest := filepath.Join(tmpdir, "dest")
 | 
			
		||||
| 
						 | 
				
			
			@ -179,8 +179,8 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
func TestChrootCopyWithTar(t *testing.T) {
 | 
			
		||||
	// TODO Windows: Figure out why this is failing
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
		t.Skip("Failing on Windows")
 | 
			
		||||
	if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip("Failing on Windows and Solaris")
 | 
			
		||||
	}
 | 
			
		||||
	tmpdir, err := ioutil.TempDir("", "docker-TestChrootCopyWithTar")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -284,7 +284,7 @@ func TestChrootUntarPath(t *testing.T) {
 | 
			
		|||
	if err := system.MkdirAll(src, 0700); err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	if _, err := prepareSourceDirectory(10, src, true); err != nil {
 | 
			
		||||
	if _, err := prepareSourceDirectory(10, src, false); err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	dest := filepath.Join(tmpdir, "dest")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,14 +15,20 @@ func TestRunCommand(t *testing.T) {
 | 
			
		|||
		t.Skip("Needs porting to Windows")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := RunCommand("ls")
 | 
			
		||||
	var cmd string
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		cmd = "gls"
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "ls"
 | 
			
		||||
	}
 | 
			
		||||
	result := RunCommand(cmd)
 | 
			
		||||
	result.Assert(t, Expected{})
 | 
			
		||||
 | 
			
		||||
	result = RunCommand("doesnotexists")
 | 
			
		||||
	expectedError := `exec: "doesnotexists": executable file not found`
 | 
			
		||||
	result.Assert(t, Expected{ExitCode: 127, Error: expectedError})
 | 
			
		||||
 | 
			
		||||
	result = RunCommand("ls", "-z")
 | 
			
		||||
	result = RunCommand(cmd, "-z")
 | 
			
		||||
	result.Assert(t, Expected{
 | 
			
		||||
		ExitCode: 2,
 | 
			
		||||
		Error:    "exit status 2",
 | 
			
		||||
| 
						 | 
				
			
			@ -90,11 +96,19 @@ func TestRunCommandWithStdoutStderrError(t *testing.T) {
 | 
			
		|||
	switch runtime.GOOS {
 | 
			
		||||
	case "windows":
 | 
			
		||||
		expected = "ls: unknown option"
 | 
			
		||||
	case "solaris":
 | 
			
		||||
		expected = "gls: invalid option"
 | 
			
		||||
	default:
 | 
			
		||||
		expected = "ls: invalid option"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result = RunCommand("ls", "-z")
 | 
			
		||||
	var cmd string
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		cmd = "gls"
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "ls"
 | 
			
		||||
	}
 | 
			
		||||
	result = RunCommand(cmd, "-z")
 | 
			
		||||
	result.Assert(t, Expected{
 | 
			
		||||
		Out:      None,
 | 
			
		||||
		Err:      expected,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,6 +83,10 @@ func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestRunCommandPipelineWithOutput(t *testing.T) {
 | 
			
		||||
	//TODO: Should run on Solaris
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
	}
 | 
			
		||||
	cmds := []*exec.Cmd{
 | 
			
		||||
		// Print 2 characters
 | 
			
		||||
		exec.Command("echo", "-n", "11"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
// +build !windows,!solaris
 | 
			
		||||
 | 
			
		||||
package mount
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										58
									
								
								pkg/mount/sharedsubtree_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								pkg/mount/sharedsubtree_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
// +build solaris
 | 
			
		||||
 | 
			
		||||
package mount
 | 
			
		||||
 | 
			
		||||
// MakeShared ensures a mounted filesystem has the SHARED mount option enabled.
 | 
			
		||||
// See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeShared(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "shared")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRShared ensures a mounted filesystem has the RSHARED mount option enabled.
 | 
			
		||||
// See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeRShared(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "rshared")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakePrivate ensures a mounted filesystem has the PRIVATE mount option enabled.
 | 
			
		||||
// See the supported options in flags.go for further reference.
 | 
			
		||||
func MakePrivate(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "private")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRPrivate ensures a mounted filesystem has the RPRIVATE mount option
 | 
			
		||||
// enabled. See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeRPrivate(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "rprivate")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeSlave ensures a mounted filesystem has the SLAVE mount option enabled.
 | 
			
		||||
// See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeSlave(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "slave")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRSlave ensures a mounted filesystem has the RSLAVE mount option enabled.
 | 
			
		||||
// See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeRSlave(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "rslave")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeUnbindable ensures a mounted filesystem has the UNBINDABLE mount option
 | 
			
		||||
// enabled. See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeUnbindable(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "unbindable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MakeRUnbindable ensures a mounted filesystem has the RUNBINDABLE mount
 | 
			
		||||
// option enabled. See the supported options in flags.go for further reference.
 | 
			
		||||
func MakeRUnbindable(mountPoint string) error {
 | 
			
		||||
	return ensureMountedAs(mountPoint, "runbindable")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ensureMountedAs(mountPoint, options string) error {
 | 
			
		||||
	// TODO: Solaris does not support bind mounts.
 | 
			
		||||
	// Evaluate lofs and also look at the relevant
 | 
			
		||||
	// mount flags to be supported.
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								plugin/manager_solaris.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								plugin/manager_solaris.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
package plugin
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/plugin/v2"
 | 
			
		||||
	specs "github.com/opencontainers/runtime-spec/specs-go"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (pm *Manager) enable(p *v2.Plugin, force bool) error {
 | 
			
		||||
	return fmt.Errorf("Not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *Manager) initSpec(p *v2.Plugin) (*specs.Spec, error) {
 | 
			
		||||
	return nil, fmt.Errorf("Not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *Manager) disable(p *v2.Plugin) error {
 | 
			
		||||
	return fmt.Errorf("Not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pm *Manager) restore(p *v2.Plugin) error {
 | 
			
		||||
	return fmt.Errorf("Not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Shutdown plugins
 | 
			
		||||
func (pm *Manager) Shutdown() {
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,7 @@
 | 
			
		|||
// +build !solaris
 | 
			
		||||
 | 
			
		||||
// TODO: Support Solaris
 | 
			
		||||
 | 
			
		||||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build !solaris
 | 
			
		||||
 | 
			
		||||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,5 @@
 | 
			
		|||
// +build !solaris
 | 
			
		||||
 | 
			
		||||
package registry
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,11 @@ func TestDecodeContainerConfig(t *testing.T) {
 | 
			
		|||
		image    string
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	//TODO: Should run for Solaris
 | 
			
		||||
	if runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if runtime.GOOS != "windows" {
 | 
			
		||||
		image = "ubuntu"
 | 
			
		||||
		fixtures = []f{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,6 @@
 | 
			
		|||
package runconfig
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/docker/api/types/container"
 | 
			
		||||
	"github.com/docker/docker/pkg/sysinfo"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -11,7 +8,7 @@ import (
 | 
			
		|||
// DefaultDaemonNetworkMode returns the default network stack the daemon should
 | 
			
		||||
// use.
 | 
			
		||||
func DefaultDaemonNetworkMode() container.NetworkMode {
 | 
			
		||||
	return container.NetworkMode("default")
 | 
			
		||||
	return container.NetworkMode("bridge")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsPreDefinedNetwork indicates if a network is predefined by the daemon
 | 
			
		||||
| 
						 | 
				
			
			@ -23,15 +20,6 @@ func IsPreDefinedNetwork(network string) bool {
 | 
			
		|||
// network settings are valid.
 | 
			
		||||
func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
 | 
			
		||||
	// We may not be passed a host config, such as in the case of docker commit
 | 
			
		||||
	if hc == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	parts := strings.Split(string(hc.NetworkMode), ":")
 | 
			
		||||
	switch mode := parts[0]; mode {
 | 
			
		||||
	case "default", "none":
 | 
			
		||||
	default:
 | 
			
		||||
		return fmt.Errorf("invalid --net: %s", hc.NetworkMode)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
// +build linux freebsd
 | 
			
		||||
// +build linux freebsd solaris
 | 
			
		||||
 | 
			
		||||
package utils
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -164,10 +164,9 @@ func TestValidateName(t *testing.T) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func TestCreateWithOpts(t *testing.T) {
 | 
			
		||||
	if runtime.GOOS == "windows" {
 | 
			
		||||
	if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rootDir, err := ioutil.TempDir("", "local-volume-test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue