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 \
|
linux/386 linux/arm \
|
||||||
darwin/amd64 \
|
darwin/amd64 \
|
||||||
freebsd/amd64 freebsd/386 freebsd/arm \
|
freebsd/amd64 freebsd/386 freebsd/arm \
|
||||||
windows/amd64 windows/386
|
windows/amd64 windows/386 \
|
||||||
|
solaris/amd64
|
||||||
|
|
||||||
# Dependency for golint
|
# Dependency for golint
|
||||||
ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
|
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 {
|
func (cli *DaemonCli) getPlatformRemoteOptions() []libcontainerd.RemoteOption {
|
||||||
opts := []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
|
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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/docker/docker/daemon"
|
"github.com/docker/docker/daemon"
|
||||||
"github.com/docker/docker/pkg/testutil/assert"
|
"github.com/docker/docker/pkg/testutil/assert"
|
||||||
"github.com/docker/docker/pkg/testutil/tempfile"
|
"github.com/docker/docker/pkg/testutil/tempfile"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadDaemonCliConfigWithDaemonFlags(t *testing.T) {
|
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
|
package container
|
||||||
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
|
|
@ -20,6 +19,7 @@ import (
|
||||||
"github.com/docker/docker/utils"
|
"github.com/docker/docker/utils"
|
||||||
"github.com/docker/docker/volume"
|
"github.com/docker/docker/volume"
|
||||||
"github.com/opencontainers/runc/libcontainer/label"
|
"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
|
// 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)
|
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 err
|
||||||
}
|
}
|
||||||
return copyExistingContents(rootfs, path)
|
return copyExistingContents(rootfs, path)
|
||||||
|
|
@ -320,10 +320,6 @@ func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfi
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func detachMounted(path string) error {
|
|
||||||
return syscall.Unmount(path, syscall.MNT_DETACH)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmountVolumes unmounts all volumes
|
// UnmountVolumes unmounts all volumes
|
||||||
func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog func(name, action string, attributes map[string]string)) error {
|
func (container *Container) UnmountVolumes(forceSyscall bool, volumeEventLog func(name, action string, attributes map[string]string)) error {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
// memoryStore implements a Store in memory.
|
// memoryStore implements a Store in memory.
|
||||||
type memoryStore struct {
|
type memoryStore struct {
|
||||||
|
|
@ -25,8 +27,9 @@ func (c *memoryStore) Add(id string, cont *Container) {
|
||||||
|
|
||||||
// Get returns a container from the store by id.
|
// Get returns a container from the store by id.
|
||||||
func (c *memoryStore) Get(id string) *Container {
|
func (c *memoryStore) Get(id string) *Container {
|
||||||
|
var res *Container
|
||||||
c.RLock()
|
c.RLock()
|
||||||
res := c.s[id]
|
res = c.s[id]
|
||||||
c.RUnlock()
|
c.RUnlock()
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,!solaris
|
||||||
|
|
||||||
package main
|
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/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"
|
||||||
echo >&2 " $mkimg -t someuser/mageia:4 mageia-urpmi --version=4 --mirror=http://somemirror/"
|
echo >&2 " $mkimg -t someuser/mageia:4 mageia-urpmi --version=4 --mirror=http://somemirror/"
|
||||||
|
echo >&2 " $mkimg -t someuser/solaris solaris"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptDir="$(dirname "$(readlink -f "$BASH_SOURCE")")/mkimage"
|
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" -- "$@")
|
optTemp=$(getopt --options '+d:t:c:hC' --longoptions 'dir:,tag:,compression:,no-compression,help' --name "$mkimg" -- "$@")
|
||||||
eval set -- "$optTemp"
|
eval set -- "$optTemp"
|
||||||
unset 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
|
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
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is not possible to commit a running container on Windows
|
// It is not possible to commit a running container on Windows and on Solaris.
|
||||||
if runtime.GOOS == "windows" && container.IsRunning() {
|
if (runtime.GOOS == "windows" || runtime.GOOS == "solaris") && container.IsRunning() {
|
||||||
return "", fmt.Errorf("Windows does not support commit of a running container")
|
return "", fmt.Errorf("%+v does not support commit of a running container", runtime.GOOS)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Pause && !container.IsPaused() {
|
if c.Pause && !container.IsPaused() {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -221,6 +222,9 @@ func NewConfig() *Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseClusterAdvertiseSettings(clusterStore, clusterAdvertise string) (string, error) {
|
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 == "" {
|
if clusterAdvertise == "" {
|
||||||
return "", errDiscoveryDisabled
|
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 (
|
var (
|
||||||
defaultPidFile = "/var/run/docker.pid"
|
defaultPidFile = "/system/volatile/docker/docker.pid"
|
||||||
defaultGraph = "/var/lib/docker"
|
defaultGraph = "/var/lib/docker"
|
||||||
defaultExec = "zones"
|
defaultExec = "zones"
|
||||||
)
|
)
|
||||||
|
|
@ -16,14 +16,17 @@ var (
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CommonConfig
|
CommonConfig
|
||||||
|
|
||||||
// Fields below here are platform specific.
|
// These fields are common to all unix platforms.
|
||||||
ExecRoot string `json:"exec-root,omitempty"`
|
CommonUnixConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// bridgeConfig stores all the bridge driver specific
|
// bridgeConfig stores all the bridge driver specific
|
||||||
// configuration.
|
// configuration.
|
||||||
type bridgeConfig struct {
|
type bridgeConfig struct {
|
||||||
commonBridgeConfig
|
commonBridgeConfig
|
||||||
|
|
||||||
|
// Fields below here are platform specific.
|
||||||
|
commonUnixBridgeConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// InstallFlags adds command-line options to the top-level flag parser for
|
// 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
|
// First handle install flags which are consistent cross-platform
|
||||||
config.InstallCommonFlags(flags)
|
config.InstallCommonFlags(flags)
|
||||||
|
|
||||||
|
// Then install flags common to unix platforms
|
||||||
|
config.InstallCommonUnixFlags(flags)
|
||||||
|
|
||||||
// Then platform-specific install flags
|
// Then platform-specific install flags
|
||||||
config.attachExperimentalFlags(flags)
|
config.attachExperimentalFlags(flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExecRoot returns the user configured Exec-root
|
|
||||||
func (config *Config) GetExecRoot() string {
|
|
||||||
return config.ExecRoot
|
|
||||||
}
|
|
||||||
func (config *Config) isSwarmCompatible() error {
|
func (config *Config) isSwarmCompatible() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -35,6 +36,9 @@ func TestDaemonBrokenConfiguration(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseClusterAdvertiseSettings(t *testing.T) {
|
func TestParseClusterAdvertiseSettings(t *testing.T) {
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
t.Skip("ClusterSettings not supported on Solaris\n")
|
||||||
|
}
|
||||||
_, err := parseClusterAdvertiseSettings("something", "")
|
_, err := parseClusterAdvertiseSettings("something", "")
|
||||||
if err != errDiscoveryDisabled {
|
if err != errDiscoveryDisabled {
|
||||||
t.Fatalf("expected discovery disabled error, got %v\n", err)
|
t.Fatalf("expected discovery disabled error, got %v\n", err)
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
|
||||||
"github.com/docker/docker/opts"
|
|
||||||
runconfigopts "github.com/docker/docker/runconfig/opts"
|
runconfigopts "github.com/docker/docker/runconfig/opts"
|
||||||
units "github.com/docker/go-units"
|
units "github.com/docker/go-units"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
@ -25,15 +22,14 @@ var (
|
||||||
type Config struct {
|
type Config struct {
|
||||||
CommonConfig
|
CommonConfig
|
||||||
|
|
||||||
|
// These fields are common to all unix platforms.
|
||||||
|
CommonUnixConfig
|
||||||
|
|
||||||
// Fields below here are platform specific.
|
// Fields below here are platform specific.
|
||||||
CgroupParent string `json:"cgroup-parent,omitempty"`
|
CgroupParent string `json:"cgroup-parent,omitempty"`
|
||||||
ContainerdAddr string `json:"containerd,omitempty"`
|
|
||||||
EnableSelinuxSupport bool `json:"selinux-enabled,omitempty"`
|
EnableSelinuxSupport bool `json:"selinux-enabled,omitempty"`
|
||||||
ExecRoot string `json:"exec-root,omitempty"`
|
|
||||||
RemappedRoot string `json:"userns-remap,omitempty"`
|
RemappedRoot string `json:"userns-remap,omitempty"`
|
||||||
Ulimits map[string]*units.Ulimit `json:"default-ulimits,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"`
|
CPURealtimePeriod int64 `json:"cpu-rt-period,omitempty"`
|
||||||
CPURealtimeRuntime int64 `json:"cpu-rt-runtime,omitempty"`
|
CPURealtimeRuntime int64 `json:"cpu-rt-runtime,omitempty"`
|
||||||
OOMScoreAdjust int `json:"oom-score-adjust,omitempty"`
|
OOMScoreAdjust int `json:"oom-score-adjust,omitempty"`
|
||||||
|
|
@ -47,6 +43,9 @@ type Config struct {
|
||||||
type bridgeConfig struct {
|
type bridgeConfig struct {
|
||||||
commonBridgeConfig
|
commonBridgeConfig
|
||||||
|
|
||||||
|
// These fields are common to all unix platforms.
|
||||||
|
commonUnixBridgeConfig
|
||||||
|
|
||||||
// Fields below here are platform specific.
|
// Fields below here are platform specific.
|
||||||
EnableIPv6 bool `json:"ipv6,omitempty"`
|
EnableIPv6 bool `json:"ipv6,omitempty"`
|
||||||
EnableIPTables bool `json:"iptables,omitempty"`
|
EnableIPTables bool `json:"iptables,omitempty"`
|
||||||
|
|
@ -54,12 +53,7 @@ type bridgeConfig struct {
|
||||||
EnableIPMasq bool `json:"ip-masq,omitempty"`
|
EnableIPMasq bool `json:"ip-masq,omitempty"`
|
||||||
EnableUserlandProxy bool `json:"userland-proxy,omitempty"`
|
EnableUserlandProxy bool `json:"userland-proxy,omitempty"`
|
||||||
UserlandProxyPath string `json:"userland-proxy-path,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"`
|
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
|
// 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
|
// First handle install flags which are consistent cross-platform
|
||||||
config.InstallCommonFlags(flags)
|
config.InstallCommonFlags(flags)
|
||||||
|
|
||||||
|
// Then install flags common to unix platforms
|
||||||
|
config.InstallCommonUnixFlags(flags)
|
||||||
|
|
||||||
config.Ulimits = make(map[string]*units.Ulimit)
|
config.Ulimits = make(map[string]*units.Ulimit)
|
||||||
config.Runtimes = make(map[string]types.Runtime)
|
|
||||||
|
|
||||||
// Then platform-specific install flags
|
// Then platform-specific install flags
|
||||||
flags.BoolVar(&config.EnableSelinuxSupport, "selinux-enabled", false, "Enable selinux support")
|
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.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.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.EnableIPForward, "ip-forward", true, "Enable net.ipv4.ip_forward")
|
||||||
flags.BoolVar(&config.bridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading")
|
flags.BoolVar(&config.bridgeConfig.EnableIPMasq, "ip-masq", true, "Enable IP masquerading")
|
||||||
flags.BoolVar(&config.bridgeConfig.EnableIPv6, "ipv6", false, "Enable IPv6 networking")
|
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.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.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.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.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")
|
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.RemappedRoot, "userns-remap", "", "User/Group setting for user namespaces")
|
||||||
flags.StringVar(&config.ContainerdAddr, "containerd", "", "Path to containerd socket")
|
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.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.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.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")
|
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)
|
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 {
|
func (config *Config) isSwarmCompatible() error {
|
||||||
if config.ClusterStore != "" || config.ClusterAdvertise != "" {
|
if config.ClusterStore != "" || config.ClusterAdvertise != "" {
|
||||||
return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
return fmt.Errorf("--cluster-store and --cluster-advertise daemon configurations are incompatible with swarm mode")
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,20 @@
|
||||||
|
|
||||||
package daemon
|
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) {
|
func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]string, error) {
|
||||||
return nil, nil
|
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 {
|
func (daemon *Daemon) setupIpcDirs(container *container.Container) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) mountVolumes(container *container.Container) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func killProcessDirectly(container *container.Container) error {
|
func killProcessDirectly(container *container.Container) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -30,9 +25,22 @@ func detachMounted(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isLinkable(child *container.Container) bool {
|
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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (daemon *Daemon) isNetworkHotPluggable() bool {
|
func (daemon *Daemon) isNetworkHotPluggable() bool {
|
||||||
return false
|
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"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/daemon/links"
|
"github.com/docker/docker/daemon/links"
|
||||||
"github.com/docker/docker/pkg/fileutils"
|
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/mount"
|
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
|
|
@ -63,39 +61,6 @@ func (daemon *Daemon) setupLinkedContainers(container *container.Container) ([]s
|
||||||
return env, nil
|
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) {
|
func (daemon *Daemon) getIpcContainer(container *container.Container) (*container.Container, error) {
|
||||||
containerID := container.HostConfig.IpcMode.Container()
|
containerID := container.HostConfig.IpcMode.Container()
|
||||||
c, err := daemon.GetContainer(containerID)
|
c, err := daemon.GetContainer(containerID)
|
||||||
|
|
@ -174,54 +139,6 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
|
||||||
|
|
||||||
return nil
|
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 {
|
func killProcessDirectly(container *container.Container) error {
|
||||||
if _, err := container.WaitStop(10 * time.Second); err != nil {
|
if _, err := container.WaitStop(10 * time.Second); err != nil {
|
||||||
// Ensure that we don't kill ourselves
|
// Ensure that we don't kill ourselves
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"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"
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
networktypes "github.com/docker/docker/api/types/network"
|
networktypes "github.com/docker/docker/api/types/network"
|
||||||
|
|
@ -78,6 +81,10 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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()
|
imgID = img.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,14 +267,14 @@ func (daemon *Daemon) verifyNetworkingConfig(nwConfig *networktypes.NetworkingCo
|
||||||
for _, v := range nwConfig.EndpointsConfig {
|
for _, v := range nwConfig.EndpointsConfig {
|
||||||
if v != nil && v.IPAMConfig != nil {
|
if v != nil && v.IPAMConfig != nil {
|
||||||
if v.IPAMConfig.IPv4Address != "" && net.ParseIP(v.IPAMConfig.IPv4Address).To4() == 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 != "" {
|
if v.IPAMConfig.IPv6Address != "" {
|
||||||
n := net.ParseIP(v.IPAMConfig.IPv6Address)
|
n := net.ParseIP(v.IPAMConfig.IPv6Address)
|
||||||
// if the address is an invalid network address (ParseIP == nil) or if it is
|
// 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
|
// an IPv4 address (To4() != nil), then it is an invalid IPv6 address
|
||||||
if n == nil || n.To4() != nil {
|
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)
|
l = append(l, k)
|
||||||
}
|
}
|
||||||
err := fmt.Errorf("Container cannot be connected to network endpoints: %s", strings.Join(l, ", "))
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
|
|
@ -12,9 +15,17 @@ import (
|
||||||
"github.com/docker/docker/layer"
|
"github.com/docker/docker/layer"
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/parsers/kernel"
|
"github.com/docker/docker/pkg/parsers/kernel"
|
||||||
|
"github.com/docker/docker/pkg/sysinfo"
|
||||||
"github.com/docker/docker/reference"
|
"github.com/docker/docker/reference"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
nwconfig "github.com/docker/libnetwork/config"
|
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>
|
//#include <zone.h>
|
||||||
|
|
@ -27,12 +38,50 @@ const (
|
||||||
solarisMaxCPUShares = 65535
|
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 {
|
func (daemon *Daemon) cleanupMountsByID(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSecurityOpt(container *container.Container, config *containertypes.HostConfig) error {
|
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) {
|
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 {
|
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
|
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
|
// verifyPlatformContainerSettings performs platform-specific validation of the
|
||||||
// hostconfig and config structures.
|
// hostconfig and config structures.
|
||||||
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.HostConfig, config *containertypes.Config, update bool) ([]string, error) {
|
||||||
warnings := []string{}
|
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
|
return warnings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,6 +318,16 @@ func (daemon *Daemon) platformReload(config *Config) map[string]string {
|
||||||
|
|
||||||
// verifyDaemonSettings performs validation of daemon config struct
|
// verifyDaemonSettings performs validation of daemon config struct
|
||||||
func verifyDaemonSettings(config *Config) error {
|
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
|
// checkSystem validates platform-specific requirements
|
||||||
return nil
|
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) {
|
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
|
// 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
|
// conditionalMountOnStart is a platform specific helper function during the
|
||||||
// container start to call mount.
|
// container start to call mount.
|
||||||
func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
|
func (daemon *Daemon) conditionalMountOnStart(container *container.Container) error {
|
||||||
return nil
|
return daemon.Mount(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
// conditionalUnmountOnCleanup is a platform specific helper function called
|
// conditionalUnmountOnCleanup is a platform specific helper function called
|
||||||
|
|
@ -171,13 +528,6 @@ func setupDaemonProcess(config *Config) error {
|
||||||
return nil
|
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 {
|
func (daemon *Daemon) setupSeccompProfile() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !solaris
|
||||||
|
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,!solaris
|
||||||
|
|
||||||
package daemon
|
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"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
|
"github.com/docker/docker/pkg/mount"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -44,6 +45,37 @@ func GetFSMagic(rootpath string) (FsMagic, error) {
|
||||||
return 0, nil
|
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
|
// Mounted checks if the given path is mounted as the fs type
|
||||||
//Solaris supports only ZFS for now
|
//Solaris supports only ZFS for now
|
||||||
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
|
func Mounted(fsType FsMagic, mountPath string) (bool, error) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build linux freebsd
|
// +build linux freebsd solaris
|
||||||
|
|
||||||
package graphtest
|
package graphtest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
|
"github.com/docker/docker/api/types/versions/v1p19"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/daemon/exec"
|
"github.com/docker/docker/daemon/exec"
|
||||||
)
|
)
|
||||||
|
|
@ -13,8 +14,8 @@ func setPlatformSpecificContainerFields(container *container.Container, contJSON
|
||||||
}
|
}
|
||||||
|
|
||||||
// containerInspectPre120 get containers for pre 1.20 APIs.
|
// containerInspectPre120 get containers for pre 1.20 APIs.
|
||||||
func (daemon *Daemon) containerInspectPre120(name string) (*types.ContainerJSON, error) {
|
func (daemon *Daemon) containerInspectPre120(name string) (*v1p19.ContainerJSON, error) {
|
||||||
return daemon.containerInspectCurrent(name, false)
|
return &v1p19.ContainerJSON{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func addMountPoints(container *container.Container) []types.MountPoint {
|
func addMountPoints(container *container.Container) []types.MountPoint {
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,19 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"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"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
clustertypes "github.com/docker/docker/daemon/cluster/provider"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
"github.com/docker/libnetwork"
|
"github.com/docker/libnetwork"
|
||||||
networktypes "github.com/docker/libnetwork/types"
|
networktypes "github.com/docker/libnetwork/types"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -236,7 +238,7 @@ func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string
|
||||||
|
|
||||||
if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
|
if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
|
||||||
err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
|
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
|
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. If either cannot be found, an err is returned. If the
|
||||||
// network cannot be set up, an err is returned.
|
// network cannot be set up, an err is returned.
|
||||||
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
|
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)
|
container, err := daemon.GetContainer(containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -346,6 +351,9 @@ func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName strin
|
||||||
// DisconnectContainerFromNetwork disconnects the given container from
|
// DisconnectContainerFromNetwork disconnects the given container from
|
||||||
// the given network. If either cannot be found, an err is returned.
|
// the given network. If either cannot be found, an err is returned.
|
||||||
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error {
|
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)
|
container, err := daemon.GetContainer(containerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if force {
|
if force {
|
||||||
|
|
@ -401,7 +409,7 @@ func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
|
||||||
|
|
||||||
if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
|
if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
|
||||||
err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
|
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 {
|
if err := nw.Delete(); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,183 @@
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
"github.com/docker/docker/oci"
|
"github.com/docker/docker/oci"
|
||||||
|
"github.com/docker/libnetwork"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"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) {
|
func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
|
||||||
s := oci.DefaultSpec()
|
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
|
return (*specs.Spec)(&s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"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"
|
||||||
containertypes "github.com/docker/docker/api/types/container"
|
containertypes "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/container"
|
"github.com/docker/docker/container"
|
||||||
|
|
@ -21,7 +21,7 @@ import (
|
||||||
// ContainerStart starts a container.
|
// ContainerStart starts a container.
|
||||||
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error {
|
func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, validateHostname bool, checkpoint string, checkpointDir string) error {
|
||||||
if checkpoint != "" && !daemon.HasExperimental() {
|
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)
|
container, err := daemon.GetContainer(name)
|
||||||
|
|
@ -35,7 +35,7 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
|
||||||
|
|
||||||
if container.IsRunning() {
|
if container.IsRunning() {
|
||||||
err := fmt.Errorf("Container already started")
|
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.
|
// Windows does not have the backwards compatibility issue here.
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !windows
|
||||||
|
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -3,6 +3,7 @@ package daemon
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -19,6 +20,9 @@ import (
|
||||||
// ContainerStats writes information about the container to the stream
|
// ContainerStats writes information about the container to the stream
|
||||||
// given in the config object.
|
// given in the config object.
|
||||||
func (daemon *Daemon) ContainerStats(ctx context.Context, prefixOrName string, config *backend.ContainerStatsConfig) error {
|
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)
|
// Remote API version (used for backwards compatibility)
|
||||||
apiVersion := config.Version
|
apiVersion := config.Version
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
|
// TODO(amitkris): We need to split this file for solaris.
|
||||||
|
|
||||||
package daemon
|
package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -11,6 +13,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/docker/container"
|
"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"
|
||||||
"github.com/docker/docker/volume/drivers"
|
"github.com/docker/docker/volume/drivers"
|
||||||
"github.com/docker/docker/volume/local"
|
"github.com/docker/docker/volume/local"
|
||||||
|
|
@ -165,3 +169,50 @@ func (daemon *Daemon) verifyVolumesInfo(container *container.Container) error {
|
||||||
}
|
}
|
||||||
return nil
|
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)
|
windows)
|
||||||
DOCKERFILE='Dockerfile.windows'
|
DOCKERFILE='Dockerfile.windows'
|
||||||
;;
|
;;
|
||||||
|
solaris)
|
||||||
|
DOCKERFILE='Dockerfile.solaris'
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@ for platform in $DOCKER_CROSSPLATFORMS; do
|
||||||
export GOOS=${platform%/*}
|
export GOOS=${platform%/*}
|
||||||
export GOARCH=${platform##*/}
|
export GOARCH=${platform##*/}
|
||||||
|
|
||||||
|
if [ "$GOOS" != "solaris" ]; then
|
||||||
|
# TODO. Solaris cannot be cross build because of CGO calls.
|
||||||
if [ -z "${daemonSupporting[$platform]}" ]; then
|
if [ -z "${daemonSupporting[$platform]}" ]; then
|
||||||
# we just need a simple client for these platforms
|
# we just need a simple client for these platforms
|
||||||
export LDFLAGS_STATIC_DOCKER=""
|
export LDFLAGS_STATIC_DOCKER=""
|
||||||
|
|
@ -39,5 +41,6 @@ for platform in $DOCKER_CROSSPLATFORMS; do
|
||||||
source "${MAKEDIR}/binary-client"
|
source "${MAKEDIR}/binary-client"
|
||||||
source "${MAKEDIR}/binary-daemon"
|
source "${MAKEDIR}/binary-daemon"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
)
|
)
|
||||||
done
|
done
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,19 @@ bundle_test_unit() {
|
||||||
else
|
else
|
||||||
TEST_PATH=./${TESTDIRS}
|
TEST_PATH=./${TESTDIRS}
|
||||||
fi
|
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 \
|
pkg_list=$(go list -e \
|
||||||
-f '{{if ne .Name "github.com/docker/docker"}}
|
-f '{{if ne .Name "github.com/docker/docker"}}
|
||||||
{{.ImportPath}}
|
{{.ImportPath}}
|
||||||
|
|
@ -34,6 +47,8 @@ bundle_test_unit() {
|
||||||
| grep -v github.com/docker/docker/vendor \
|
| grep -v github.com/docker/docker/vendor \
|
||||||
| grep -v github.com/docker/docker/man \
|
| grep -v github.com/docker/docker/man \
|
||||||
| grep -v github.com/docker/docker/integration-cli)
|
| grep -v github.com/docker/docker/integration-cli)
|
||||||
|
fi
|
||||||
|
|
||||||
go test -cover -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS $pkg_list
|
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
|
# if windows use a zip, not tgz
|
||||||
BUNDLE_EXTENSION=".zip"
|
BUNDLE_EXTENSION=".zip"
|
||||||
IS_TAR="false"
|
IS_TAR="false"
|
||||||
|
elif [ "$GOOS" == "solaris" ]; then
|
||||||
|
# Solaris bypasses cross due to CGO issues.
|
||||||
|
continue
|
||||||
else
|
else
|
||||||
BUNDLE_EXTENSION=".tgz"
|
BUNDLE_EXTENSION=".tgz"
|
||||||
IS_TAR="true"
|
IS_TAR="true"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
package libcontainerd
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -12,7 +10,6 @@ import (
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
containerd "github.com/docker/containerd/api/grpc/types"
|
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/ioutils"
|
||||||
"github.com/docker/docker/pkg/mount"
|
"github.com/docker/docker/pkg/mount"
|
||||||
"github.com/golang/protobuf/ptypes"
|
"github.com/golang/protobuf/ptypes"
|
||||||
|
|
@ -124,87 +121,6 @@ func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendly
|
||||||
return int(resp.SystemPid), nil
|
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 {
|
func (clnt *client) SignalProcess(containerID string, pid string, sig int) error {
|
||||||
clnt.lock(containerID)
|
clnt.lock(containerID)
|
||||||
defer clnt.unlock(containerID)
|
defer clnt.unlock(containerID)
|
||||||
|
|
@ -340,28 +256,6 @@ func (clnt *client) getContainerdContainer(containerID string) (*containerd.Cont
|
||||||
return nil, fmt.Errorf("invalid state response")
|
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 {
|
func (clnt *client) UpdateResources(containerID string, resources Resources) error {
|
||||||
clnt.lock(containerID)
|
clnt.lock(containerID)
|
||||||
defer clnt.unlock(containerID)
|
defer clnt.unlock(containerID)
|
||||||
|
|
@ -627,27 +521,6 @@ func (clnt *client) Restore(containerID string, attachStdio StdioCallback, optio
|
||||||
return clnt.setExited(containerID, uint32(255))
|
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 {
|
func (clnt *client) CreateCheckpoint(containerID string, checkpointID string, checkpointDir string, exit bool) error {
|
||||||
clnt.lock(containerID)
|
clnt.lock(containerID)
|
||||||
defer clnt.unlock(containerID)
|
defer clnt.unlock(containerID)
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,17 @@ type client struct {
|
||||||
clientCommon
|
clientCommon
|
||||||
|
|
||||||
// Platform specific properties below here.
|
// 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 {
|
func (clnt *client) AddProcess(ctx context.Context, containerID, processFriendlyName string, specp Process, attachStdio StdioCallback) (int, error) {
|
||||||
return nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (clnt *client) Create(containerID string, checkpoint string, checkpointDir string, spec Spec, options ...CreateOption) (err error) {
|
func (clnt *client) SignalProcess(containerID string, pid string, sig int) error {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (clnt *client) Signal(containerID string, sig int) error {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,8 +36,25 @@ func (clnt *client) Stats(containerID string) (*Stats, error) {
|
||||||
return nil, nil
|
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
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,3 +73,15 @@ func (clnt *client) UpdateResources(containerID string, resources Resources) err
|
||||||
// but we should return nil for enabling updating container
|
// but we should return nil for enabling updating container
|
||||||
return nil
|
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
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
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
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
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
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -5,18 +7,19 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
goruntime "runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
containerd "github.com/docker/containerd/api/grpc/types"
|
containerd "github.com/docker/containerd/api/grpc/types"
|
||||||
"github.com/tonistiigi/fifo"
|
"github.com/tonistiigi/fifo"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
var fdNames = map[int]string{
|
var fdNames = map[int]string{
|
||||||
syscall.Stdin: "stdin",
|
unix.Stdin: "stdin",
|
||||||
syscall.Stdout: "stdout",
|
unix.Stdout: "stdout",
|
||||||
syscall.Stderr: "stderr",
|
unix.Stderr: "stderr",
|
||||||
}
|
}
|
||||||
|
|
||||||
// process keeps the state for both main container process and exec process.
|
// 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 := &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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -58,8 +61,10 @@ func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if !terminal {
|
if goruntime.GOOS == "solaris" || !terminal {
|
||||||
io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stderr), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build linux solaris
|
||||||
|
|
||||||
package libcontainerd
|
package libcontainerd
|
||||||
|
|
||||||
import "sync"
|
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
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -9,6 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
goruntime "runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -22,7 +25,6 @@ import (
|
||||||
"github.com/docker/docker/utils"
|
"github.com/docker/docker/utils"
|
||||||
"github.com/golang/protobuf/ptypes"
|
"github.com/golang/protobuf/ptypes"
|
||||||
"github.com/golang/protobuf/ptypes/timestamp"
|
"github.com/golang/protobuf/ptypes/timestamp"
|
||||||
rsystem "github.com/opencontainers/runc/libcontainer/system"
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
|
@ -374,15 +376,19 @@ func (r *remote) runContainerdDaemon() error {
|
||||||
// Start a new instance
|
// Start a new instance
|
||||||
args := []string{
|
args := []string{
|
||||||
"-l", fmt.Sprintf("unix://%s", r.rpcAddr),
|
"-l", fmt.Sprintf("unix://%s", r.rpcAddr),
|
||||||
"--shim", "docker-containerd-shim",
|
|
||||||
"--metrics-interval=0",
|
"--metrics-interval=0",
|
||||||
"--start-timeout", "2m",
|
"--start-timeout", "2m",
|
||||||
"--state-dir", filepath.Join(r.stateDir, containerdStateDir),
|
"--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 != "" {
|
if r.runtime != "" {
|
||||||
args = append(args, "--runtime")
|
args = append(args, "--runtime")
|
||||||
args = append(args, r.runtime)
|
args = append(args, r.runtime)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if r.debugLog {
|
if r.debugLog {
|
||||||
args = append(args, "--debug")
|
args = append(args, "--debug")
|
||||||
}
|
}
|
||||||
|
|
@ -398,7 +404,7 @@ func (r *remote) runContainerdDaemon() error {
|
||||||
// redirect containerd logs to docker logs
|
// redirect containerd logs to docker logs
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true, Pdeathsig: syscall.SIGKILL}
|
cmd.SysProcAttr = setSysProcAttr(true)
|
||||||
cmd.Env = nil
|
cmd.Env = nil
|
||||||
// clear the NOTIFY_SOCKET from the env when starting containerd
|
// clear the NOTIFY_SOCKET from the env when starting containerd
|
||||||
for _, e := range os.Environ() {
|
for _, e := range os.Environ() {
|
||||||
|
|
@ -428,27 +434,6 @@ func (r *remote) runContainerdDaemon() error {
|
||||||
return nil
|
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.
|
// WithRemoteAddr sets the external containerd socket to connect to.
|
||||||
func WithRemoteAddr(addr string) RemoteOption {
|
func WithRemoteAddr(addr string) RemoteOption {
|
||||||
return rpcAddr(addr)
|
return rpcAddr(addr)
|
||||||
|
|
@ -1,11 +1,25 @@
|
||||||
package libcontainerd
|
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.
|
// Process contains information to start a specific application inside the container.
|
||||||
type Process struct {
|
type Process struct {
|
||||||
// Terminal creates an interactive terminal for the container.
|
// Terminal creates an interactive terminal for the container.
|
||||||
Terminal bool `json:"terminal"`
|
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 specifies the binary and arguments for the application to execute.
|
||||||
Args []string `json:"args"`
|
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.
|
// Stats contains a stats properties from containerd.
|
||||||
|
|
@ -19,7 +33,11 @@ type StateInfo struct {
|
||||||
CommonStateInfo
|
CommonStateInfo
|
||||||
|
|
||||||
// Platform specific StateInfo
|
// Platform specific StateInfo
|
||||||
|
OOMKilled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources defines updatable container resource values.
|
// Resources defines updatable container resource values.
|
||||||
type Resources struct{}
|
type Resources struct{}
|
||||||
|
|
||||||
|
// Checkpoints contains the details of a checkpoint
|
||||||
|
type Checkpoints containerd.ListCheckpointResponse
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package libcontainerd
|
package libcontainerd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"syscall"
|
||||||
|
|
||||||
containerd "github.com/docker/containerd/api/grpc/types"
|
containerd "github.com/docker/containerd/api/grpc/types"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
@ -50,3 +52,11 @@ func convertRlimits(sr []specs.Rlimit) (cr []*containerd.Rlimit) {
|
||||||
}
|
}
|
||||||
return
|
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
|
package oci
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultSpec returns default oci spec used by docker.
|
// DefaultSpec returns default oci spec used by docker.
|
||||||
func DefaultSpec() specs.Spec {
|
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
|
return s
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ func TestIsArchivePathDir(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsArchivePathInvalidFile(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()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
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) {
|
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()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
t.Fatalf("Fail to create an archive file for test : %s.", output)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -203,6 +204,9 @@ func TestTarWithBlockCharFifo(t *testing.T) {
|
||||||
|
|
||||||
// TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows
|
// TestTarUntarWithXattr is Unix as Lsetxattr is not supported on Windows
|
||||||
func TestTarUntarWithXattr(t *testing.T) {
|
func TestTarUntarWithXattr(t *testing.T) {
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
origin, err := ioutil.TempDir("", "docker-test-untar-origin")
|
origin, err := ioutil.TempDir("", "docker-test-untar-origin")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,16 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHardLinkOrder(t *testing.T) {
|
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"}
|
names := []string{"file1.txt", "file2.txt", "file3.txt"}
|
||||||
msg := []byte("Hey y'all")
|
msg := []byte("Hey y'all")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,10 @@ func max(x, y int) int {
|
||||||
|
|
||||||
func copyDir(src, dst string) error {
|
func copyDir(src, dst string) error {
|
||||||
cmd := exec.Command("cp", "-a", src, dst)
|
cmd := exec.Command("cp", "-a", src, dst)
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
cmd = exec.Command("gcp", "-a", src, dst)
|
||||||
|
}
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -256,8 +260,9 @@ func TestChangesWithChangesGH13590(t *testing.T) {
|
||||||
func TestChangesDirsEmpty(t *testing.T) {
|
func TestChangesDirsEmpty(t *testing.T) {
|
||||||
// TODO Windows. There may be a way of running this, but turning off for now
|
// TODO Windows. There may be a way of running this, but turning off for now
|
||||||
// as createSampleDir uses symlinks.
|
// as createSampleDir uses symlinks.
|
||||||
if runtime.GOOS == "windows" {
|
// TODO Should work for Solaris
|
||||||
t.Skip("symlinks on Windows")
|
if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
|
||||||
|
t.Skip("symlinks on Windows; gcp failure on Solaris")
|
||||||
}
|
}
|
||||||
src, err := ioutil.TempDir("", "docker-changes-test")
|
src, err := ioutil.TempDir("", "docker-changes-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -364,8 +369,9 @@ func mutateSampleDir(t *testing.T, root string) {
|
||||||
func TestChangesDirsMutated(t *testing.T) {
|
func TestChangesDirsMutated(t *testing.T) {
|
||||||
// TODO Windows. There may be a way of running this, but turning off for now
|
// TODO Windows. There may be a way of running this, but turning off for now
|
||||||
// as createSampleDir uses symlinks.
|
// as createSampleDir uses symlinks.
|
||||||
if runtime.GOOS == "windows" {
|
// TODO Should work for Solaris
|
||||||
t.Skip("symlinks on Windows")
|
if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
|
||||||
|
t.Skip("symlinks on Windows; gcp failures on Solaris")
|
||||||
}
|
}
|
||||||
src, err := ioutil.TempDir("", "docker-changes-test")
|
src, err := ioutil.TempDir("", "docker-changes-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -425,8 +431,9 @@ func TestChangesDirsMutated(t *testing.T) {
|
||||||
func TestApplyLayer(t *testing.T) {
|
func TestApplyLayer(t *testing.T) {
|
||||||
// TODO Windows. There may be a way of running this, but turning off for now
|
// TODO Windows. There may be a way of running this, but turning off for now
|
||||||
// as createSampleDir uses symlinks.
|
// as createSampleDir uses symlinks.
|
||||||
if runtime.GOOS == "windows" {
|
// TODO Should work for Solaris
|
||||||
t.Skip("symlinks on Windows")
|
if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
|
||||||
|
t.Skip("symlinks on Windows; gcp failures on Solaris")
|
||||||
}
|
}
|
||||||
src, err := ioutil.TempDir("", "docker-changes-test")
|
src, err := ioutil.TempDir("", "docker-changes-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -165,7 +165,7 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
|
||||||
if err := system.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
|
|
@ -179,8 +179,8 @@ func TestChrootTarUntarWithSymlink(t *testing.T) {
|
||||||
|
|
||||||
func TestChrootCopyWithTar(t *testing.T) {
|
func TestChrootCopyWithTar(t *testing.T) {
|
||||||
// TODO Windows: Figure out why this is failing
|
// TODO Windows: Figure out why this is failing
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
|
||||||
t.Skip("Failing on Windows")
|
t.Skip("Failing on Windows and Solaris")
|
||||||
}
|
}
|
||||||
tmpdir, err := ioutil.TempDir("", "docker-TestChrootCopyWithTar")
|
tmpdir, err := ioutil.TempDir("", "docker-TestChrootCopyWithTar")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -284,7 +284,7 @@ func TestChrootUntarPath(t *testing.T) {
|
||||||
if err := system.MkdirAll(src, 0700); err != nil {
|
if err := system.MkdirAll(src, 0700); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := prepareSourceDirectory(10, src, true); err != nil {
|
if _, err := prepareSourceDirectory(10, src, false); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
dest := filepath.Join(tmpdir, "dest")
|
dest := filepath.Join(tmpdir, "dest")
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,20 @@ func TestRunCommand(t *testing.T) {
|
||||||
t.Skip("Needs porting to Windows")
|
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.Assert(t, Expected{})
|
||||||
|
|
||||||
result = RunCommand("doesnotexists")
|
result = RunCommand("doesnotexists")
|
||||||
expectedError := `exec: "doesnotexists": executable file not found`
|
expectedError := `exec: "doesnotexists": executable file not found`
|
||||||
result.Assert(t, Expected{ExitCode: 127, Error: expectedError})
|
result.Assert(t, Expected{ExitCode: 127, Error: expectedError})
|
||||||
|
|
||||||
result = RunCommand("ls", "-z")
|
result = RunCommand(cmd, "-z")
|
||||||
result.Assert(t, Expected{
|
result.Assert(t, Expected{
|
||||||
ExitCode: 2,
|
ExitCode: 2,
|
||||||
Error: "exit status 2",
|
Error: "exit status 2",
|
||||||
|
|
@ -90,11 +96,19 @@ func TestRunCommandWithStdoutStderrError(t *testing.T) {
|
||||||
switch runtime.GOOS {
|
switch runtime.GOOS {
|
||||||
case "windows":
|
case "windows":
|
||||||
expected = "ls: unknown option"
|
expected = "ls: unknown option"
|
||||||
|
case "solaris":
|
||||||
|
expected = "gls: invalid option"
|
||||||
default:
|
default:
|
||||||
expected = "ls: invalid option"
|
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{
|
result.Assert(t, Expected{
|
||||||
Out: None,
|
Out: None,
|
||||||
Err: expected,
|
Err: expected,
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,10 @@ func TestRunCommandPipelineWithOutputErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunCommandPipelineWithOutput(t *testing.T) {
|
func TestRunCommandPipelineWithOutput(t *testing.T) {
|
||||||
|
//TODO: Should run on Solaris
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
cmds := []*exec.Cmd{
|
cmds := []*exec.Cmd{
|
||||||
// Print 2 characters
|
// Print 2 characters
|
||||||
exec.Command("echo", "-n", "11"),
|
exec.Command("echo", "-n", "11"),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build !windows
|
// +build !windows,!solaris
|
||||||
|
|
||||||
package mount
|
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
|
package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !solaris
|
||||||
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// +build !solaris
|
||||||
|
|
||||||
package registry
|
package registry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,11 @@ func TestDecodeContainerConfig(t *testing.T) {
|
||||||
image string
|
image string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//TODO: Should run for Solaris
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
if runtime.GOOS != "windows" {
|
if runtime.GOOS != "windows" {
|
||||||
image = "ubuntu"
|
image = "ubuntu"
|
||||||
fixtures = []f{
|
fixtures = []f{
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
package runconfig
|
package runconfig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/pkg/sysinfo"
|
"github.com/docker/docker/pkg/sysinfo"
|
||||||
)
|
)
|
||||||
|
|
@ -11,7 +8,7 @@ import (
|
||||||
// DefaultDaemonNetworkMode returns the default network stack the daemon should
|
// DefaultDaemonNetworkMode returns the default network stack the daemon should
|
||||||
// use.
|
// use.
|
||||||
func DefaultDaemonNetworkMode() container.NetworkMode {
|
func DefaultDaemonNetworkMode() container.NetworkMode {
|
||||||
return container.NetworkMode("default")
|
return container.NetworkMode("bridge")
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPreDefinedNetwork indicates if a network is predefined by the daemon
|
// IsPreDefinedNetwork indicates if a network is predefined by the daemon
|
||||||
|
|
@ -23,15 +20,6 @@ func IsPreDefinedNetwork(network string) bool {
|
||||||
// network settings are valid.
|
// network settings are valid.
|
||||||
func ValidateNetMode(c *container.Config, hc *container.HostConfig) error {
|
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
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// +build linux freebsd
|
// +build linux freebsd solaris
|
||||||
|
|
||||||
package utils
|
package utils
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,10 +164,9 @@ func TestValidateName(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateWithOpts(t *testing.T) {
|
func TestCreateWithOpts(t *testing.T) {
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" || runtime.GOOS == "solaris" {
|
||||||
t.Skip()
|
t.Skip()
|
||||||
}
|
}
|
||||||
|
|
||||||
rootDir, err := ioutil.TempDir("", "local-volume-test")
|
rootDir, err := ioutil.TempDir("", "local-volume-test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue